opengl-demo.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import os
  2. import vtk
  3. import pyvista as pv
  4. # -----------------------------------------------------------------------------
  5. # 1. 配置:要展示的文件夹路径(改成你自己的)
  6. # -----------------------------------------------------------------------------
  7. ROOT_FOLDER = r"./" # 示例:当前目录
  8. MAX_DEPTH = 3 # 限制深度,防止太密
  9. NODE_SPACING_X = 2.0
  10. NODE_SPACING_Y = 1.5
  11. # -----------------------------------------------------------------------------
  12. # 2. 递归遍历文件夹,生成树形结构数据
  13. # -----------------------------------------------------------------------------
  14. class TreeNode:
  15. def __init__(self, name, path, depth=0):
  16. self.name = name
  17. self.path = path
  18. self.depth = depth
  19. self.children = []
  20. self.x = 0.0
  21. self.y = 0.0
  22. def build_tree(folder, depth=0, max_depth=MAX_DEPTH):
  23. node = TreeNode(os.path.basename(folder) or folder, folder, depth)
  24. if depth >= max_depth:
  25. return node
  26. try:
  27. entries = sorted(os.listdir(folder))
  28. except PermissionError:
  29. return node
  30. for entry in entries:
  31. full = os.path.join(folder, entry)
  32. if os.path.isdir(full):
  33. child = build_tree(full, depth + 1, max_depth)
  34. node.children.append(child)
  35. return node
  36. # -----------------------------------------------------------------------------
  37. # 3. 树布局算法(简单层级横向布局)
  38. # -----------------------------------------------------------------------------
  39. def layout_tree(node: TreeNode, x=0.0, y=0.0):
  40. node.y = y
  41. node.x = x
  42. child_x = x - (len(node.children) - 1) * NODE_SPACING_X / 2
  43. for child in node.children:
  44. layout_tree(child, child_x, y - NODE_SPACING_Y)
  45. child_x += NODE_SPACING_X
  46. # -----------------------------------------------------------------------------
  47. # 4. 收集所有节点、边用于 VTK 绘制
  48. # -----------------------------------------------------------------------------
  49. def collect_geometry(node):
  50. points = []
  51. lines = []
  52. labels = []
  53. stack = [node]
  54. while stack:
  55. n = stack.pop()
  56. points.append([n.x, n.y, 0.0])
  57. labels.append(n.name)
  58. for child in n.children:
  59. points.append([child.x, child.y, 0.0])
  60. labels.append(child.name)
  61. lines.append(2) # 每个线段有两个点
  62. lines.append(len(points)-2) # 父节点的索引
  63. lines.append(len(points)-1) # 子节点的索引
  64. stack.append(child)
  65. return points, lines, labels
  66. # -----------------------------------------------------------------------------
  67. # 5. PyVista + VTK 绘制树
  68. # -----------------------------------------------------------------------------
  69. if __name__ == "__main__":
  70. tree = build_tree(ROOT_FOLDER)
  71. layout_tree(tree)
  72. points, lines, labels = collect_geometry(tree)
  73. # 构建点线云
  74. cloud = pv.PolyData(points)
  75. cloud.lines = lines
  76. cloud["label"] = labels
  77. # 绘图
  78. plotter = pv.Plotter(window_size=(1200, 800))
  79. plotter.add_mesh(cloud, color="#66ccff", point_size=12, render_lines_as_tubes=True, line_width=3)
  80. plotter.add_point_labels(cloud, "label", font_size=8, shape_color="white")
  81. plotter.add_text(
  82. f"Folder Tree: {ROOT_FOLDER}\nMax Depth: {MAX_DEPTH}",
  83. font_size=10, color="blue"
  84. )
  85. plotter.camera_position = "xy"
  86. plotter.show()