I was able to put together a Programmable Filter that uses vtkStaticCellLocator’s FindClosestPoint method to project my query point to the surface. After that, the probe worked as expected, giving me a valid point.
I assumed the name FindClosestPoint implied that it returned one of the vertices of the input dataset, but it says right there in the docs for that method “the closest point is somewhere on a cell, it need not be one of the vertices of the cell.” This post was helpful in figuring out that FindClosestPoint does indeed handle projection.
In case it’s helpful for future readers, I put together a programmable filter to project multiple points onto a surface. The script looks like:
import vtk
src = self.GetInputDataObject(0, 0)
query = self.GetInputDataObject(0, 1)
loc = vtk.vtkStaticCellLocator()
loc.SetDataSet(src)
loc.BuildLocator()
nearPt = [0.0]*3
cellId = vtk.reference(0)
subId = vtk.reference(0)
dist2 = vtk.reference(0.0)
nq = query.GetNumberOfPoints()
pts = vtk.vtkPoints()
pts.Allocate(nq)
for i in range(nq):
loc.FindClosestPoint(query.GetPoint(i), nearPt, cellId, subId, dist2)
pts.InsertNextPoint(nearPt)
out = self.GetOutput()
out.SetPoints(pts)
out.AllocateExact(nq, nq)
pids = vtk.vtkIdList()
pids.SetNumberOfIds(1)
for i in range(nq):
pids.SetId(0, i)
out.InsertNextCell(vtk.VTK_VERTEX, pids)
Once the projection is done, I can ResampleWithDataset to probe the surface data at all those points.