vtkAppendPolyData - performance increase?

Hello there,

I’m trying to visualize a highly dense mesh. I have the coordinates and the connectivity of said coordinates.

I have already succeeded in showing the mesh, however, after my initial testing, I received a substantially larger mesh, containing roughly 350,000 elements. It looks great and all that, however, when trying to interact with the scene, rotation, panning, and stuff, everything is lagging and it is near impossible to work with.

This is the code I have right now, where I have simply included some dummy coordinates and connectivity for allowing the code to run

import vtk

surfaces = [[[0, 0, 0], [2, 0, 0], [1, 2, 0]], [[2, 0, 0], [3, 0, 0], [3, 2, 0], [1, 2, 0]]]

append_data = vtk.vtkAppendPolyData()
for vertices in surfaces:
    # Draw one surface at the time.
    points = vtk.vtkPoints()
    cell = vtk.vtkCellArray()
    surface = vtk.vtkPolygon()
    surface.GetPointIds().SetNumberOfIds(len(vertices))
    for index, vertex in enumerate(vertices):
        points.InsertNextPoint(vertex)
        surface.GetPointIds().SetId(index, index)

    cell.InsertNextCell(surface)

    polydata = vtk.vtkPolyData()
    polydata.SetPoints(points)
    polydata.SetPolys(cell)
    polydata.Modified()

    append_data.AddInputData(polydata)
# Update and clean the polydata.
append_data.Update()
clean_filter = vtk.vtkCleanPolyData()
clean_filter.SetInputConnection(append_data.GetOutputPort())
clean_filter.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(clean_filter.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)

renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)
renderer.AddActor(actor)

render_window.Render()
interactor.Start()`:

This is good and all, but as I said, come hundreds of thousands of elements, this is not efficient anymore.

I was thinking about forming this as an UnstructedGrid, and working on it right now (It requires some input changes). However, I don’t know if that will help me, performance-wise.

I’m no shark at Vtk just yet, so I am wondering if any of you could have any ideas of how I could speed things up?

What graphics card do you have and what VTK version do you use? On an average computer, rendering of a mesh of 350k cells should be very fast.

Try
mapper.SetInput(clean_filter.GetOutput())

This will prevent a pipeline check for each render.

Thanks for the answer.

I’m running VTK 8.1.0 and I have a Nvidia Quadro M2200 graphics card.

On an average computer, rendering of a mesh of 350k cells should be very fast.

Thats why I’m confident my coding must be wrongful.

This did the trick.

I’m going to find some information regarding the differences. Everything is running smoothly now, thanks a lot.

Going out on a limb here, maybe you can answer one more question?

In addition to this mesh, I’m trying to show some specific points. In the aforementioned example, we are talking roughly 60,000 points.

These points are interacted with, individually, as they carry information (a caption box is displayed when the actor is picked). This leads me to think that they should be displayed as individual actors, like spheres.

Again, this proves incredibly slow:

import vtk
import numpy as np

renderer = vtk.vtkRenderer()
render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(render_window)

sphere = vtk.vtkSphereSource()
sphere.SetRadius(0.05)
sphere.SetThetaResolution(32)
sphere.SetPhiResolution(32)

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(sphere.GetOutputPort())
mapper.Update()
mapper.StaticOn()

for i in range(60000):
    new_sphere = vtk.vtkActor()
    new_sphere.SetMapper(mapper)
    new_sphere.GetProperty().BackfaceCullingOn()
    new_sphere.SetPosition(20 * np.random.random(3))
    renderer.AddActor(new_sphere)

render_window.Render()
interactor.Start()

I can create these points as glyphs. But doing so I lose the individual interaction option.

points = vtk.vtkPoints()
p_data = vtk.vtkPolyData()
for i in range(60000):
    points.InsertNextPoint(20 * np.random.random(3))

p_data.SetPoints(points)

glyph = vtk.vtkVertexGlyphFilter()
glyph.SetInputData(p_data)
glyph.Update()

poly_data = vtk.vtkPolyData()
poly_data.ShallowCopy(glyph.GetOutput())

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(poly_data)

actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetPointSize(5)
renderer.AddActor(actor)

Again, is there anything I am missing, or is Vtk not made for something like this?

@Mskovmand What did the trick?

Showing 60k points is easy, it should be work without any extra effort at screen refresh rate.

Interacting with 60k points is a completely different story. You can certainly not use a separate actor for each point as it would be extremely slow. You need to use a glyph filter or mapper and take care of point interactions yourself, since existing interactive VTK widgets use a few actors for each interactive handle. There is an implementation of point and curve widgets in 3D Slicer that allow interaction with thousands of points (interaction starts to become less fluid when you reach about 10k, because we stopped optimizing performance when everything was fluid at 1k). See some more details in this post: picking glyphs vtkGlyph3DMapper - #2 by lassoan.

Once again, thank you for your answer.

I’d given it a look but seems far too complicated for my skills right now. I achieved something useful in Pick and highlight glyphs.