November 25, 2020, 08:20:26 AM

Author Topic: [bb] BMAX - Distance from Point to Line by Leon Drake [ 1+ years ago ]  (Read 666 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : BMAX - Distance from Point to Line
Author : Leon Drake
Posted : 1+ years ago

Description : 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.

Code :
Code: BlitzBasic
  1. Function Magnitude#( px#,py#,pz#,dx#,dy#,dz# )
  2.  
  3.  Local vx#,vy#,vz#
  4.  vx# = dx# - px#
  5.  vy# = dy# - py#
  6.  vz# = dz# - pz#
  7.  Return Float(Sqr( vx# * vx# + vy# * vy# + vz# * vz# ))
  8. End Function
  9.  
  10. Function DistancePointLine( ax#,ay#,az#,bx#,by#,bz#,px#,py#,pz# )
  11.  Local LineMag#,U#
  12.  Local ix#,iy#,iz#
  13.  Local Distance#
  14.  LineMag# = Magnitude( bx#, by#, bz#, ax#, ay#, az# )
  15.  U# = ( ( ( px# - ax# ) * ( bx# - ax# ) ) +( ( py# - ay# ) * ( by# - ay# ) ) +( ( pz# - az# ) * ( bz# - az# ) ) ) /( LineMag# * LineMag# )
  16.  
  17.  If  U# < 0.0 Or U# > 1.0 Then Return False
  18.  ' closest point does Not fall within the line segment
  19.  
  20.  ix# = ax# + U# * ( bx# - ax# )
  21.  iy# = ay# + U# * ( by# - ay# )
  22.  iz# = az# + U# * ( bz# - az# )
  23.  Distance# = Magnitude( px#,py#,pz#,ix#,iy#,iz# )
  24.  Return True
  25. End Function


Comments :


Derron(Posted 1+ years ago)

 a bit shorter and about 15% faster (using less locals each time the function is called)
Code: [Select]
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.byeMB


big10p(Posted 1+ years ago)

 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.


Derron(Posted 1+ years ago)

 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.byeMB [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal