Probing surface data

I’m trying to use the Probe Location filter on a surface mesh. My dataset is a cylinder of radius 0.5. The cylinder’s axis is through the origin, along the Y axis. I’m trying to probe the dataset at (0.501, 0, 0). That’s not exactly on the surface, but pretty close. No matter what I use for the tolerance, I get vtkValidPointMask=0. That’s shown in ProbeLocation1 in the attached state file.

If I rotate that probe point by 45 degrees, I can set a relatively small tolerance and get a valid point. That’s shown in ProbeLocation2. If you define an angle theta about the azimuth of the cylinder, I’ve noticed that probes near theta=0, 90, 180, and 270 yield invalid points, while probes in between those areas yield valid points.

Why does ProbeLocation1 not return a valid point, even with a huge tolerance. Am I misusing that filter? Is there a filter I can use to project points onto the surface prior to probing? Eventually, I’d like to use the Resample With Dataset filter to probe multiple points, but I thought I would simply things for now by doing one point at a time.

probe_example.pvsm (434.4 KB)
src_dataset.vtu (211.6 KB)

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.