Upsample vtkPolyData

I have a set of 3d coordinates and their triangulations, which have been pre-computed and this is the start of my pipeline. I also have a colour that corresponds to each of these points. I can visualise the surface as expected, see screenshot below.

However, I would like to smooth out the surface, I suppose by subdividing the triangles. I guess this could be done with vtkSmoothPolyData, but I also need to interpolate the colours associated with each point. How do I do this?

Current code is attached below:

colours = vtk.vtkUnsignedCharArray()
colours.SetNumberOfComponents(3)
colours.SetName("Colors")

points = vtk.vtkPoints()
polys = vtk.vtkCellArray()
vertices = vtk.vtkCellArray()
for i in range(0, t.shape[0]):
    polygon = vtk.vtkPolygon()
    polygon.GetPointIds().SetNumberOfIds(3)
    for j in range(3):
        idx = 3 * i + j
        point = [q[t[i, j]] for q in (x,y,z)]
        id = points.InsertNextPoint(point)
        polygon.GetPointIds().SetId(j, idx)
        vertices.InsertNextCell(1)
        vertices.InsertCellPoint(id)
        if np.isnan(color[i]):
            colours.InsertNextTuple(50, 50, 50)
        else:
            colours.InsertNextTuple([q * 255 for q in final_col[int(255 * (color[i] / color.max()))][:3]])
    polys.InsertNextCell(polygon)
polydata = vtk.vtkPolyData()
polydata.SetPoints(points)
polydata.SetPolys(polys)
# polydata.SetVerts(vertices)
polydata.GetPointData().SetScalars(colours)

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polydata)
mapper.SetColorModeToDefault()
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetPointSize(5)

# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()

Use vtkWindowedSincPolyDataFilter for smoothing. It’s much faster and gives better results than the Laplacian-based vtkSmoothPolyDataFilter.

I believe that you are assigning colors to each cell (i.e., using cell data to color the surface). If so, you can either 1) assign colors at points instead, and if that’s not possible, 2) use the vtkCellDataToPointData filter to create point data by averaging the cell data values connected to each point to produce the point data.

Hi @will.schroeder, thanks for the suggestion. Setting the colours per-point rather than per-triangle meant that VTK automatically linearly interpolates across the triangles, and the results are much better.

Would you be able to expand on your second suggestion? I guess that vtkWindowedSincPolyDataFilter will alter the x,y,z coordinates (or add more of them) to smooth the surface. I still don’t fully understand how I would then modify the colours to match the moved/extra points.

Yes, the smoothing filters move points around. In many cases the distance moved is small, so users just live with the fact that the attribute values are “close enough”. However, if you want to update the data attributes, you have to reproject the new points (i.e., the smoothed points) onto the old mesh using something like the probe filter. However I can tell you that this projection is a fraught process, because the smoothed points may be located well off of the original mesh, and it is not clear how to assign new attribute values in this case. Another option: maybe you have an analytical function, or you are smoothing within the domain of a 3D volume, so can resample the smoothed points into the function or volume rather than reprojecting - this would be much more robust).

Another approach: don’t smooth. Just use vtkCellDataToPointData as before, and then generate surface normals (e.g., vtkPolyDataNormals). Rendering with normals may give you the appearance of smoothness that is adequate for your application.