Compute the signed distance field from a polygonal mesh

Goal

Compute the signed distance field from points in a data set to a polygonal mesh. The signed distance field has many applications in computational geometry, and can be used, for instance, to find intersections of objects with a polygonal mesh.

Background

A signed distance field is a point-associated field that gives the distance from each point in a data set to some location or object. In this case, we’ll compute the signed distance as the nearest point on a polygonal mesh. The sign of the distance is determined by which side of the polygonal mesh the point is located. Points inside the polygonal mesh (or opposite of the surface normal direction) will have a negative distance while points outside will have a positive distance. Points on the surface will have a distance of 0.

In the image above, a signed distance field with respect to a disk has been computed for several streamline objects. Blue indicates negative distance and red indicates positive distance.

Approach

ParaView does not have a filter to compute a signed distance field. However, one can use the Programmable Filter and a few lines of VTK code to do this.

First, load or create the sources that provide the polygonal mesh and data set on which you want to add the signed distance field. The polygonal mesh must consist of only triangles - to ensure it does, you can add a Triangulate filter to it. Next, select these sources in the Pipeline Browser. The order of selection is important to how you access the sources inside the Programmable Filter, so select the polygonal mesh first, followed by the data set that should have the signed distance field added. Now add a Programmable Filter and set the Script property to the following

mesh = self.GetInputDataObject(0, 0)

import paraview.vtk as vtk

pdd = vtk.vtkImplicitPolyDataDistance()
pdd.SetInput(mesh)

dataset = self.GetInputDataObject(0, 1)
output.CopyStructure(dataset)

numPts = dataset.GetNumberOfPoints()
distArray = vtk.vtkDoubleArray()
distArray.SetName("Distance")
distArray.SetNumberOfComponents(1)
distArray.SetNumberOfTuples(numPts)
for i in xrange(numPts):
  pt = dataset.GetPoint(i)
  distArray.SetValue(i, pdd.EvaluateFunction(pt))

output.GetPointData().AddArray(distArray)

Click Apply and the output of the Programmable Filter will now have a new point data array called “Distance”.

StreamlineIntersection.pvsm (909.4 KB) is a sample state file that can be used to create the image above.

6 Likes

How would I get the programmable filter to update in time, for example if I wanted to animate the plot you’ve created?