[vtkusers] Re: vtkusers Digest, Vol 20, Issue 12
L.J. van Ruijven
L.J.vanRuijven at amc.uva.nl
Mon Dec 12 16:34:00 EST 2005
Hello vtk developers,
When tried to replace a part of my program with a call to
vtkTriangle::EvaluatePosition, this resulted in bad results. So I tried
to find the differences between the VTK code and my program. I still
use VTK 4.2 so I am not sure whether the following still applies.
The function vtkTriangle::EvaluatePosition uses
vtkLine::DistanceToLine. This function seems strange, because it does
not always assign a value to the variable t. So, in some cases the
return value of t is simply the value it had before the function was
called. Also, when a value is assigned, this value is not always in the
interval [0,1]. I cannot oversee all the consequences when this
behavior is changed, but if it is changed the function
vtkTriangle::EvaluatePosition can be made much shorter.
Also the precision of vtkLine::DistanceToLine can be improved very
simply for the case where all the points are located far away from the
origin. My suggestion for vtkLine::DistanceToLine is:
float NewDistanceToLine(float x[3], float p1[3], float p2[3],
float &t, float closestPoint[3])
{
float p21[3], x1[3], denom, num;
float x0[3] = {0,0,0};
float *closest;
float tolerance;
//
// Determine appropriate vectors
//
x1[0] = x[0]- p1[0];
x1[1] = x[1]- p1[1];
x1[2] = x[2]- p1[2];
p21[0] = p2[0]- p1[0];
p21[1] = p2[1]- p1[1];
p21[2] = p2[2]- p1[2];
//
// Get parametric location
//
num = vtkMath::Dot(p21,x1);
denom = vtkMath::Dot(p21,p21);
// trying to avoid an expensive fabs
tolerance = VTK_TOL*num;
if (tolerance < 0.0)
{
tolerance = -tolerance;
}
if ( -tolerance < denom && denom < tolerance ) //numerically bad!
{
closest = x0; //arbitrary, point is (numerically) far away
t = 0.0;
}
//
// If parametric coordinate is within 0<=p<=1, then the point is
closest to
// the line. Otherwise, it's closest to a point at the end of the
line.
//
else if ( (t=num/denom) < 0.0 )
{
closest = x0;
t = 0.0;
}
else if ( t > 1.0 )
{
closest = p21;
t = 1.0;
}
else
{
closest = p21;
p21[0] *= t;
p21[1] *= t;
p21[2] *= t;
}
closestPoint[0] = p1[0] + closest[0];
closestPoint[1] = p1[1] + closest[1];
closestPoint[2] = p1[2] + closest[2];
return vtkMath::Distance2BetweenPoints(closest,x1);
}
The effect on the precision can be seen with the program:
int _tmain(int argc, _TCHAR* argv[])
{
int i,j;
float x[3]={0.1972,0.1020,0.3015}; // point coordinates
float p1[3]={0.1002,0.1999,0.4010}; // endpoints of the line
float p2[3]={0.2000,0.1000,0.3000};
const int N = 200; // call
DistanceToLine N times
float Closest_old[3],Closest_new[3];
float t;
double d_old[N],d_new[N]; // the
distances calculated from the points x[i] to the line
double mean_old=0,mean_new=0; // and their means
for (i=0;i<N;i++) {
float xi[3],p1i[3],p2i[3];
float d[3];
for (j=0;j<3;j++) { // translate the points over a
large distance
d[j]= rand()%50;
xi[j] = x[j]+d[j];
p1i[j] = p1[j]+d[j];
p2i[j] = p2[j]+d[j];
}
float dis1 = vtkLine::DistanceToLine
(xi,p1i,p2i,t,Closest_old);
float dis2 = DistanceToLine(xi,p1i,p2i,t,Closest_new);
d_old[i] = sqrt(dis1); // store the results of both
functions
d_new[i] = sqrt(dis2);
mean_old+=d_old[i];
mean_new+=d_new[i];
}
mean_old/=N; mean_new/=N;
// Now calculate the standard deviations of the distances
double square_old=0, square_new=0;
for (int i=0;i<N;i++) {
d_old[i]-=mean_old; square_old+=d_old[i]*d_old[i];
d_new[i]-=mean_new; square_new+=d_new[i]*d_new[i];
printf("%4d: olddist - mean = %12.8f, newdist - mean = %
12.8f\n",i,d_old[i],d_new[i]);
}
float SD_old = sqrt(square_old/N);
float SD_new = sqrt(square_new/N);
printf("\n");
printf(" Mean Dist ( SD Dist ) :\n");
printf("old: %12.8f (%12.8f)\n",mean_old,SD_old);
printf("new: %12.8f (%12.8f)\n",mean_new,SD_new);
return 0;
}
If you decide to change vtkLine::DistanceToLine, please let me know.
Then I will also propose a new version for
vtkTriangle::EvaluatePosition.
Leo van Ruijven.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ljvanruijven.vcf
Type: text/x-vcard
Size: 262 bytes
Desc: Card for "L.J. van Ruijven" <L.J.vanRuijven at amc.uva.nl>
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20051212/8df09074/attachment.vcf>
More information about the vtkusers
mailing list