I fail to find a way to utilize vtkClipPolyData
and vtkBoxWidget
efficiently for the clipping of a large point cloud. There is no example in docs for clipping with vtkBoxWidget
(or I was unable to find it; there is only transformation example, not clipping). But I assume what I write below in an MRE is correct as it works decently when I change the number of points to ~10000.
However, it is painfully slow for any reasonably big point cloud. I understand that it is because of constant re-rendering. But is there a way to speed that up? Some tricks/workarounds? My point clouds usually have at least 10M points, and that is already after downsampling, so downsampling it further before clipping is not really feasible for the purpose of the application.
import vtk
import random
vtk_points = vtk.vtkPoints()
for _ in range(10_000_000):
vtk_points.InsertNextPoint(
random.uniform(-5, 5), random.uniform(-5, 5), random.uniform(-5, 5)
)
poly_data = vtk.vtkPolyData()
poly_data.SetPoints(vtk_points)
vertex_filter = vtk.vtkVertexGlyphFilter()
vertex_filter.SetInputData(poly_data)
vertex_filter.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(vertex_filter.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetPointSize(3)
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
interactor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
renderer.SetBackground(0.1, 0.1, 0.1)
camera = vtk.vtkCamera()
camera.SetPosition(10, 10, 10)
camera.SetFocalPoint(0, 0, 0)
renderer.SetActiveCamera(camera)
box_widget = vtk.vtkBoxWidget()
box_widget.SetInteractor(interactor)
box_widget.SetPlaceFactor(1.0)
box_widget.SetProp3D(actor)
box_widget.PlaceWidget()
box_widget.SetEnabled(True)
clipper = vtk.vtkClipPolyData()
clipper.SetInputConnection(vertex_filter.GetOutputPort())
clipper.InsideOutOn()
clipped_mapper = vtk.vtkPolyDataMapper()
def update_clipping(caller, event):
planes = vtk.vtkPlanes()
box_widget.GetPlanes(planes)
clipper.SetClipFunction(planes)
clipper.Update()
clipped_mapper.SetInputConnection(clipper.GetOutputPort())
actor.SetMapper(clipped_mapper)
render_window.Render()
box_widget.AddObserver("InteractionEvent", update_clipping)
render_window.Render()
interactor.Start()
Upd: tried also without explicitly calling render_window.Render()
but it seems to have same behavior.