I have replaced vtkCellLocator and introduced vtkSMP. It made it 2 orders of magnitude faster. Below is a snippet from a new vtkDisplacementFilter, where both distance and directions are computed in parallell.
namespace
{
class DisplacementOp
{
private:
vtkDisplacementPolyDataFilter* Self;
vtkDoubleArray* OutputScalar;
vtkDoubleArray* OutputVector;
vtkImplicitPolyDataDistance* Imp;
vtkPolyData* Dst;
public:
DisplacementOp(vtkDisplacementPolyDataFilter* self, vtkImplicitPolyDataDistance* imp,
vtkPolyData* dst, vtkDoubleArray* outputScalar, vtkDoubleArray* outputVector)
: Self(self)
, Imp(imp)
, Dst(dst)
, OutputScalar(outputScalar)
, OutputVector(outputVector) {}
void Initialize() {}
void operator()(vtkIdType begin, vtkIdType end)
{
vtkImplicitPolyDataDistance* imp = this->Imp;
vtkTypeBool signedDistance = Self->GetSignedDistance();
vtkTypeBool negateDistance = Self->GetNegateDistance();
for (vtkIdType ptId = begin; ptId < end; ptId++)
{
double pt[3];
Dst->GetPoint(ptId, pt);
double closestPoint[3];
double val = imp->EvaluateFunctionAndGetClosestPoint(pt, closestPoint);
double dist = signedDistance
? (negateDistance ? -val : val) : fabs(val);
double direction[3];
double absDistance = 0.0;
for (int i = 0; i < 3; i++)
{
direction[i] = closestPoint[i] - pt[i];
}
absDistance = std::max<double>(1e-6, fabs(dist));
// Normalize direction
for (int i = 0; i < 3; i++)
{
direction[i] /= absDistance;
}
OutputVector->SetTuple(ptId, direction);
OutputScalar->SetValue(ptId, dist);
}
}
void Reduce() {}
};
and to execute it
vtkImplicitPolyDataDistance* imp = vtkImplicitPolyDataDistance::New();
imp->SetInput(src);
// Calculate distance from points.
int numPts = mesh->GetNumberOfPoints();
vtkDoubleArray* directionArray = vtkDoubleArray::New();
directionArray->SetName("Direction");
directionArray->SetNumberOfComponents(3);
directionArray->SetNumberOfTuples(numPts);
vtkDoubleArray* distanceArray = vtkDoubleArray::New();
distanceArray->SetName("Distance");
distanceArray->SetNumberOfComponents(1);
distanceArray->SetNumberOfTuples(numPts);
// The sign of the functions are the dot product between pseudo normal and the vector
// x-p. The point p is on the target polydata.
DisplacementOp pointFunctor(this, imp, mesh, distanceArray, directionArray);
vtkSMPTools::For(0, numPts, pointFunctor);