对于此类拖动滑动条切割物体的案例,我发现有两种思路可以达到该效果。

vtkClipPolyData

使用vtkClipPolyData来处理原始的polydata,利用ClipFunction切割polydata,生成切割后的new polydata。
每一次滑动,通过改变ClipFunction,间接改变了actor的polydata。所以就有了动态切割的效果。

python code:

#!/usr/bin/env python

import vtk

cone = vtk.vtkConeSource()
cone.Update()

ren1= vtk.vtkRenderer()
ren1.SetBackground( 0, 0, 0 )

renWin = vtk.vtkRenderWindow()
renWin.AddRenderer( ren1 )

# selection part - green color part
plane = vtk.vtkPlane()
clipper = vtk.vtkClipPolyData()
clipper.SetInputConnection( cone.GetOutputPort() )
clipper.SetClipFunction( plane )
clipper.InsideOutOn()

selectMapper = vtk.vtkPolyDataMapper()
selectMapper.SetInputConnection( clipper.GetOutputPort() )

selectActor = vtk.vtkLODActor()
selectActor.SetMapper(selectMapper)
selectActor.GetProperty().SetColor(0, 1, 0)
selectActor.SetScale(1.01, 1.01, 1.01)

ren1.AddActor( selectActor )
# selection part end

renWinInteractor = vtk.vtkRenderWindowInteractor()
renWinInteractor.SetRenderWindow( renWin )

def myCallback(obj, event):
    #print(type(obj))
    global plane, selectActor
    obj.GetPlane(plane)

# ImplicitPlaneWidget - outlines and plane
planeWidget = vtk.vtkImplicitPlaneWidget()
planeWidget.SetInteractor( renWinInteractor )
planeWidget.SetPlaceFactor(1)
planeWidget.SetInputConnection( cone.GetOutputPort() )
planeWidget.PlaceWidget()
planeWidget.AddObserver("InteractionEvent", myCallback)
planeWidget.On()
# ImplicitPlaneWidget end

renWinInteractor.Start()

这个和http://weiy.org/2018/10/25/%e3%80%90vtk%e3%80%91vtkclippolydata-example/ 是类似的。

vtkThreshold

使用vtkThreshold给点集增加“属性”。然后通过设定的属性值进行过滤,也能达到切割的效果。
给STL文件的polydata增加属性数组:

void Widget::AddThresholdArray()
{
    vtkPolyData *pd = m_STLReader->GetOutput();
    vtkPoints *points = pd->GetPoints();
    vSPNew( ZValues, vtkDoubleArray );
    ZValues->SetNumberOfComponents( 1 );
    ZValues->SetName( "ZValues" );
    int count = points->GetNumberOfPoints();
    for( int i = 0; i < count; ++i )
    {
        PointStruct pt( points->GetPoint( i ) );
        ZValues->InsertNextValue( pt[2] );
    }
    pd->GetPointData()->AddArray( ZValues );
    m_STLReader->Update();
}

使用vtkThreshold对象进行点过滤。

    m_Threshold->SetInputData( m_STLReader->GetOutput() );
//... 
    // If point's z value is smaller than Z, shows it.
    m_Threshold->ThresholdByLower( Z );
    m_Threshold->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "ZValues" );
    m_Threshold->Update();

    vtkUnstructuredGrid *thresholdPd = m_Threshold->GetOutput();
    m_SurfaceFilter->SetInputData( thresholdPd );
    m_SurfaceFilter->Update();

    m_ArchMapper->SetInputData( m_SurfaceFilter->GetOutput() );
//...

以这样的方式同样可以达到目的。
样例工程:https://github.com/theArcticOcean/ArchClip
可查看分支:Threshold

 

分类: C plus plusPython

发表评论

电子邮件地址不会被公开。 必填项已用*标注