VTK拾取网格模型上的可见点

消隐与Z-Buffer

  使用缓冲器记录物体表面在屏幕上投影所覆盖范围内的全部像素的深度值,依次访问屏幕范围内物体表面所覆盖的每一像素,用深度小(深度用z值表示,z值小表示离视点近)的像素点颜色替代深度大的像素点颜色可以实现消隐,称为深度缓冲器算法。深度缓冲器算法也称为Z-Buffer算法,在物体空间内不对物体表面的可见性进行检测,在图像空间中根据每个像素的深度值确定最终绘制到屏幕的物体表面上各个像素的颜色。

  下面的例子中从读入一个简单的8个顶点的立方体STL模型,用vtkSelectVisiblePoints类过滤可见点,并输出相关信息。

  VTK: vtkSelectVisiblePoints Class Reference: extract points that are visible (based on z-buffer calculation).  vtkSelectVisiblePoints is a filter that selects points based on whether they are visible or not. Visibility is determined by accessing the z-buffer of a rendering window. (The position of each input point is converted into display coordinates, and then the z-value at that point is obtained. If within the user-specified tolerance, the point is considered visible.) Points that are visible are passed to the output. Associated data attributes are passed to the output as well.

   鼠标左键旋转到不同视角,点击右键观察输出的信息:

#!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()

    # 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 SetVisibleFilter(self, vis):
        self.VisibleFilter = vis
        
    def RightButtonPressEvent(self,obj,event):
        self.VisibleFilter.Update()
                
        print "number of visible points: ", self.VisibleFilter.GetOutput().GetNumberOfPoints() 
        
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputData(self.VisibleFilter.GetOutput())
        actor =vtk.vtkActor()
        actor.SetMapper(mapper)
        actor.GetProperty().SetPointSize(15)
          self.GetDefaultRenderer().AddActor(actor)

        # Forward events
        self.OnRightButtonDown()
        return
    

    
def CreateScene():
    # Create a rendering window and renderer
    renWin = vtk.vtkRenderWindow()
    ren = vtk.vtkRenderer()
    # Set background color
    ren.GradientBackgroundOn()
    ren.SetBackground(.1, .1, .1)
    ren.SetBackground2(0.8,0.8,0.8)
    # Set window size
    renWin.SetSize(600, 600)
    renWin.AddRenderer(ren)
     
    # Create a renderwindowinteractor
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    style = MyInteractor()
    style.SetDefaultRenderer(ren)
    iren.SetInteractorStyle(style)
    
    # load STL file 
    mesh = loadSTL("cube.stl")
    mapper = vtk.vtkPolyDataMapper() 
    mapper.SetInputData(mesh)         # maps polygonal data to graphics primitives
    actor = vtk.vtkLODActor() 
    actor.SetMapper(mapper)
    ren.AddActor(actor)

    visPts = vtk.vtkSelectVisiblePoints()
    visPts.SetInputData(mesh)
    visPts.SetRenderer(ren)
    style.SetVisibleFilter(visPts)
    
    # Enable user interface interactor
    iren.Initialize()
    iren.Start()
    

if __name__ == "__main__":
    CreateScene()
View Code

 

 

 

 


   使用vtkCellPicker可以拾取模型上可见的面和点的信息(vtkCellPicker will shoot a ray into a 3D scene and return information about the first object that the ray hit),而用vtkPointPicker拾取点时会选择离射线距离最近的点,因此所选的点可能位于不可见的表面上。

#!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()
            
            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
            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(sphereSource.GetOutputPort())
            
            actor = vtk.vtkActor()
            actor.SetMapper(mapper)
            actor.GetProperty().SetColor(1.0, 0.0, 0.0)
            
            self.GetDefaultRenderer().AddActor(actor)

        # Forward events
        self.OnRightButtonDown()
        return
    

    
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("Suzanne.stl")
    mapper = vtk.vtkPolyDataMapper() 
    mapper.SetInputData(mesh)         # maps polygonal data to graphics primitives
    actor = vtk.vtkLODActor() 
    actor.SetMapper(mapper)
    actor.GetProperty().EdgeVisibilityOn()
    actor.GetProperty().SetLineWidth(0.3)
    
    ren.AddActor(actor)

    # Enable user interface interactor
    iren.Initialize()
    iren.Start()
    

if __name__ == "__main__":
    CreateScene()
View Code

 

 

 

 

参考:

VTK拾取相关的类

VTK - Users - point picking problem

VTK: vtkCellPicker Class Reference

VTK: vtkPointPicker Class Reference

VTK修炼之道78:交互与拾取_点拾取

VTK/Examples/Cxx/PolyData/SelectVisiblePoints

Ray Casting with Python and VTK: Intersecting lines/rays with surface meshes

posted @ 2018-06-02 18:14  XXX已失联  阅读(4930)  评论(1编辑  收藏  举报