Code archives/3D Graphics - Maths/BMAX - Distance from Point to Line

This code has been declared by its author to be Public Domain code.

Download source code

BMAX - Distance from Point to Line by Leon Drake2007
This is some old C code i found and ported it to Bmax. basically the command to run is DistancePointLine it returns True or False if the Point is within the line's segment. but you can access its X Y & Z coordinates on the line by grabbing ix,iy,iz and Distance# is the area distance from the point to the line.
Function Magnitude#( px#,py#,pz#,dx#,dy#,dz# )

 Local vx#,vy#,vz#
 vx# = dx# - px#
 vy# = dy# - py#
 vz# = dz# - pz#
 Return Float(Sqr( vx# * vx# + vy# * vy# + vz# * vz# ))
End Function

Function DistancePointLine( ax#,ay#,az#,bx#,by#,bz#,px#,py#,pz# )
 Local LineMag#,U#
 Local ix#,iy#,iz#
 Local Distance#
 LineMag# = Magnitude( bx#, by#, bz#, ax#, ay#, az# )
 U# = ( ( ( px# - ax# ) * ( bx# - ax# ) ) +( ( py# - ay# ) * ( by# - ay# ) ) +( ( pz# - az# ) * ( bz# - az# ) ) ) /( LineMag# * LineMag# )

 If  U# < 0.0 Or U# > 1.0 Then Return False 
 ' closest point does Not fall within the line segment
 
 ix# = ax# + U# * ( bx# - ax# )
 iy# = ay# + U# * ( by# - ay# )
 iz# = az# + U# * ( bz# - az# )
 Distance# = Magnitude( px#,py#,pz#,ix#,iy#,iz# )
 Return True
End Function

Comments

Derron2007
a bit shorter and about 15% faster (using less locals each time the function is called)

Function Magnitude#( px#,py#,pz#,dx#,dy#,dz# )
  Return Float(Sqr( (dx# - px#)*(dx# - px#) + (dy# - py#)*(dy# - py#) + (dz# - pz#)*(dz# - pz#) ))
End Function

Function DistancePointLine( ax#,ay#,az#,bx#,by#,bz#,px#,py#,pz#, Distance# Var)
 Local LineMag#,U#
 Local ix# = bx# - ax#
 Local iy# = by# - ay#
 Local iz# = bz# - az#
' Local Distance#
 LineMag# = Magnitude( bx#, by#, bz#, ax#, ay#, az# )
 U# = ( ( ( px# - ax# ) * ix# ) +( ( py# - ay# ) * iy# ) +( ( pz# - az# ) * iz# ) ) /( LineMag# * LineMag# )
 If  U# < 0.0 Or U# > 1.0 Then Return False 
 ' closest point does Not fall within the line segment
 
 ix# = ax# + U# * ix#
 iy# = ay# + U# * iy#
 iz# = az# + U# * iz#
 Distance# = Magnitude( px#,py#,pz#,ix#,iy#,iz# )
 Return True
End Function


Disabling the "Distance# var" and enabling the local again cuts the speed to 52/58 instead of 50/58.

Using a^2 instead of a*a is instead a reason to be 300% as slow as the original code.

bye
MB


big10p2007
MichaelB: Won't your Magnitude function be slightly slower, as you're calculating the vector components twice each?

I almost always put calcs into locals if they're needed more than once, as Leon has done. It's easier to read, too.


Derron2007
you may change it without big differences... but this avoids to declare 3 locals each call of "Magnitude".

Magnitude is called twice times in "DistancePointLine".

While the locals ix,iy and iz are declared in "DistancePointLine", I reused them to make the calculation of "U#" shorter and the final calculation of ix,iy and iz faster.

That the original code is much easier to read is without comment... just wanted to make it a bit faster for the copy/paste-user who just wants to have the solution for a problem without learning something from it.



bye
MB


Code Archives Forum