VTK 平面裁剪

Posted Sam Fang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VTK 平面裁剪相关的知识,希望对你有一定的参考价值。

有些时候需要显示零件内部情况,所有会对零件显示进行平面裁剪,这里用到了vtkPlane和vtkClipPolyData。

vtkPlane是定义一个平面,vtkClipPolyData使用vtkPlane定义的平面进行裁剪。

下面列出主要的代码,其他Qt框架代码参考前面文章。

QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

vtkNew<vtkRenderer> renderer;
vtkNew<vtkNamedColors> colors;

//定义球
vtkNew<vtkSphereSource> sphereSource;
sphereSource->SetRadius(10);
sphereSource->SetCenter(0, 0, 0);

//定义平面
vtkNew<vtkPlane> plane;
plane->SetOrigin(3,0,0);
plane->SetNormal(-1, 0, 0);

//定义裁剪
vtkNew<vtkClipPolyData> clipper;
clipper->SetInputConnection(sphereSource->GetOutputPort());
clipper->SetClipFunction(plane);

vtkNew<vtkDataSetMapper> clipMapper;
clipMapper->SetInputConnection(clipper->GetOutputPort());

vtkNew<vtkActor> clipActor;
clipActor->SetMapper(clipMapper);
clipActor->GetProperty()->SetDiffuseColor(colors->GetColor4d("Tomato").GetData());
clipActor->GetProperty()->EdgeVisibilityOn(); //显示线框
    
renderer->AddActor(clipActor);

renderer->SetBackground(colors->GetColor3d("SteelBlue").GetData());

vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("RenderWindowNoUIFile");
ui.vtk_main->setRenderWindow(renderWindow);

 显示如下:

 

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()
View Code

 

   立体网格:

 

 

 

参考:

Dijkstra算法(一)之 C语言详解

VTKExamples/Cxx/Graphs/ShortestPath

VTKExamples/Cxx/PolyData/DijkstraGraphGeodesicPath

VTK: vtkDijkstraGraphGeodesicPath Class Reference

vtkDijkstraGraphGeodesicPath在曲面上寻找最短路径的应用

以上是关于VTK 平面裁剪的主要内容,如果未能解决你的问题,请参考以下文章

# ThreeJS学习7_裁剪平面(clipping)

基于局部轴的平面局部裁剪

裁剪平面附近的 OpenGL

VTK计算网格模型上的最短路径

如何在三个js中将多个纹理裁剪为多边形

平面反射