I would recommend using readily available VTK filters for point sampling, such as vtkPoissonDiskSampler and vtkPolyDataPointSampler. They produce approximately uniform grid even if the surface is uneven.
Full example:
modelNode = getNode('model')
# Sample points on the surface
sampler = vtk.vtkPoissonDiskSampler()
sampler.SetInputConnection(modelNode.GetPolyDataConnection())
sampler.SetRadius(10.0)
sampler.Update()
sampler.GetOutput().GetNumberOfPoints()
# Get point coordinates as numpy array
import vtk.util.numpy_support
pointData = sampler.GetOutput().GetPoints().GetData()
coordsArray = vtk.util.numpy_support.vtk_to_numpy(pointData)
# Create a markup point list
markupPointList = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsFiducialNode')
markupPointList.CreateDefaultDisplayNodes()
displayNode = markupPointList.GetDisplayNode()
displayNode.SetPointLabelsVisibility(False)
markupPointList.SetLocked(True)
# Set sampled point coordinates into the markup point list
updateMarkupsControlPointsFromArray(markupPointList, coordsArray)
Note that in the very latest Slicer Preview Release (that you download on 2022-09-03 or later) I’ve made some performance improvements in updateMarkupsControlPointsFromArray
completes immediately instead in tens of seconds (if you have many points).
If you want to place points only in a specific part of the surface then you can clip the model using Dynamic Modeler module (Curve cut
, Boundary cut
, or Select by points
tool) before you project.
You may also find this discussion useful: How to project points to Polydata? - #6 by will.schroeder - Support - VTK