We can use vtkImplicitPolyDataDistance to calculate the distance from a point to the target polydata. It’s better than calculating the distance by iterating to the search point.
The following example puts a sphere that radius is 1 and origin is (0, 0, 0) in the renderer. Our test point is (1.5, 0, 0), so the ideal distance is 0.5, but the resolution of the sphere can bring impact to the final result.
#include <vtkVersion.h>
#include <vtkImplicitPolyDataDistance.h>
#include <vtkActor.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkLineSource.h>
#include "../share/tool.h"
int main(int, char *[])
{
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(1.0f);
sphereSource->Update();
vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection( sphereSource->GetOutputPort() );
sphereMapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> sphereActor =
vtkSmartPointer<vtkActor>::New();
sphereActor->SetMapper( sphereMapper );
sphereActor->GetProperty()->SetOpacity(.3);
sphereActor->GetProperty()->SetColor(1,0,0);
vtkSmartPointer<vtkImplicitPolyDataDistance> implicitPolyDataDistance =
vtkSmartPointer<vtkImplicitPolyDataDistance>::New();
implicitPolyDataDistance->SetInput(sphereSource->GetOutput());
PointStruct pt0( 1.5, 0, 0 ), closetPoint;
double signedDistance = implicitPolyDataDistance->EvaluateFunctionAndGetClosestPoint( pt0.point,
closetPoint.point );
vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
lineSource->SetPoint1( pt0.point );
lineSource->SetPoint2( closetPoint.point );
lineSource->Update();
vtkSmartPointer<vtkPolyDataMapper> lineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
lineMapper->SetInputData( lineSource->GetOutput() );
vtkSmartPointer<vtkActor> lineActor = vtkSmartPointer<vtkActor>::New();
lineActor->SetMapper( lineMapper );
cout << "signedDistance: " << signedDistance << endl;
cout << "closetPoint: " << closetPoint;
// ========= compare with test result =========
vtkPolyData *sPd = sphereSource->GetOutput();
double absDis = VTK_DOUBLE_MAX;
for( int i = 0; i < sPd->GetNumberOfPoints(); ++i )
{
PointStruct pt( sPd->GetPoint( i ) );
PointStruct vec = pt - pt0;
if( absDis > vec.Length() )
{
absDis = vec.Length();
}
}
cout << "absDis: " << absDis << endl;
// ======== finish: compare ==========
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddViewProp(sphereActor);
renderer->AddActor( lineActor );
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renWinInteractor->SetRenderWindow( renderWindow );
renderWindow->Render();
renWinInteractor->Start();
return EXIT_SUCCESS;
}
Output:
signedDistance: 0.525072
closetPoint: PointStruct [0.974928, 0, 0]
absDis: 0.570277
If the input data for vtkImplicitPolyDataDistance object is a curve, we can compute every distance from the target point to the point on the curve and choose the minimum one as the final distance.
[…] to calculate the distance from a point to the target points set in the post Calculate Distance From A Point To PolyData In VTK. We will try a new way using KD-Tree to find the closest point to the test point. The following […]