VTK计算网格模型上的最短路径
Dijkstra algorithm to compute the graph geodesic.Takes as input a polygonal mesh and performs a single source shortest path calculation. Dijkstra's algorithm is used.
用鼠标右键拾取平面网格上的点,观察输出路径:
#!usrbinenv python import vtk def loadSTL(filenameSTL): readerSTL = vtk.vtkSTLReader() readerSTL.SetFileName(filenameSTL) # 'update' the reader i.e. read the .stl file readerSTL.Update() polydata = readerSTL.GetOutput() print "Number of Cells:", polydata.GetNumberOfCells() print "Number of Points:", polydata.GetNumberOfPoints() # If there are no points in 'vtkPolyData' something went wrong if polydata.GetNumberOfPoints() == 0: raise ValueError("No point data could be loaded from " + filenameSTL) return None return polydata # Customize vtkInteractorStyleTrackballCamera class MyInteractor(vtk.vtkInteractorStyleTrackballCamera): def __init__(self,parent=None): self.AddObserver("RightButtonPressEvent", self.RightButtonPressEvent) def RightButtonPressEvent(self,obj,event): clickPos = self.GetInteractor().GetEventPosition() print "Picking pixel: " , clickPos # Pick from this location picker = self.GetInteractor().GetPicker() picker.Pick(clickPos[0], clickPos[1], 0, self.GetDefaultRenderer()) # If CellId = -1, nothing was picked if(picker.GetCellId() != -1): print "Pick position is: " , picker.GetPickPosition() print "Cell id is:", picker.GetCellId() print "Point id is:", picker.GetPointId() pathList.append(picker.GetPointId()) point_position = mesh.GetPoint(picker.GetPointId()) # Create a sphere sphereSource = vtk.vtkSphereSource() sphereSource.SetCenter(point_position) #sphereSource.SetRadius(0.2) sphereSource.SetRadius(0.02) # Create a mapper and actor sphereMapper = vtk.vtkPolyDataMapper() sphereMapper.SetInputConnection(sphereSource.GetOutputPort()) sphereActor = vtk.vtkActor() sphereActor.SetMapper(sphereMapper) sphereActor.GetProperty().SetColor(1.0, 0.0, 0.0) self.GetDefaultRenderer().AddActor(sphereActor) # find the shortest path if len(pathList) > 1: dijkstra.SetStartVertex(pathList[-2]) dijkstra.SetEndVertex(pathList[-1]) dijkstra.Update() # Get the vertex ids (of the input polydata) on the shortest path IdList = dijkstra.GetIdList() # store in pathList for i in range(IdList.GetNumberOfIds()-1, 0, -1): pathList.insert(-1, IdList.GetId(i)) self.drawPath() # Forward events self.OnRightButtonDown() return def drawPath(self): points = vtk.vtkPoints() for i in range(0, len(pathList)): points.InsertNextPoint(mesh.GetPoint(pathList[i])) # draw intermediate points # pointsPolydata = vtk.vtkPolyData() # pointsPolydata.SetPoints(points) # vertexFilter = vtk.vtkVertexGlyphFilter() # vertexFilter.SetInputData(pointsPolydata) # vertexFilter.Update() # polydata = vtk.vtkPolyData() # polydata.ShallowCopy(vertexFilter.GetOutput()) # mapper = vtk.vtkPolyDataMapper() # mapper.SetInputData(polydata) # polydataActor = vtk.vtkActor() # polydataActor.SetMapper(mapper) # polydataActor.GetProperty().SetPointSize(5) # self.GetDefaultRenderer().AddActor(polydataActor) # draw path polyLine = vtk.vtkPolyLine() polyLine.GetPointIds().SetNumberOfIds(len(pathList)) for i in range(0, len(pathList)): polyLine.GetPointIds().SetId(i,i) #Create a cell array to store the lines in and add the lines to it cells = vtk.vtkCellArray() cells.InsertNextCell(polyLine) # Create a polydata to store everything in polyLine = vtk.vtkPolyData() polyLine.SetPoints(points) # Add the points to the dataset polyLine.SetLines(cells) # Add the lines to the dataset # Setup mapper polyLineMapper = vtk.vtkPolyDataMapper() polyLineMapper.SetInputData(polyLine) # Create an actor to represent the polyline polyLineActor = vtk.vtkActor() polyLineActor.SetMapper(polyLineMapper) polyLineActor.GetProperty().SetColor(0,0,1) polyLineActor.GetProperty().SetLineWidth(2) self.GetDefaultRenderer().AddActor(polyLineActor) def CreateScene(): # Create a rendering window and renderer renWin = vtk.vtkRenderWindow() # Set window size renWin.SetSize(600, 600) ren = vtk.vtkRenderer() # Set background color ren.GradientBackgroundOn() ren.SetBackground(.1, .1, .1) ren.SetBackground2(0.8,0.8,0.8) renWin.AddRenderer(ren) # Create a renderwindowinteractor iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) style = MyInteractor() style.SetDefaultRenderer(ren) iren.SetInteractorStyle(style) # vtkCellPicker will shoot a ray into a 3D scene and return information about # the first object that the ray hits. cellPicker = vtk.vtkCellPicker() iren.SetPicker(cellPicker) # load STL file global mesh mesh = loadSTL("untitled.stl") global dijkstra global pathList pathList = [] dijkstra = vtk.vtkDijkstraGraphGeodesicPath() dijkstra.SetInputData(mesh) mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(mesh) # maps polygonal data to graphics primitives actor = vtk.vtkLODActor() actor.SetMapper(mapper) actor.GetProperty().EdgeVisibilityOn() actor.GetProperty().SetColor(0.0,0.9,0.9) actor.GetProperty().SetLineWidth(0.3) ren.AddActor(actor) # Enable user interface interactor iren.Initialize() iren.Start() if __name__ == "__main__": CreateScene()
立体网格:
参考:
VTKExamples/Cxx/Graphs/ShortestPath
VTKExamples/Cxx/PolyData/DijkstraGraphGeodesicPath