Advertisement

Finding the point on a line a given distance from another line

Started by November 11, 2002 02:31 AM
4 comments, last by CGameProgrammer 22 years, 3 months ago
This is dealing with 3D, not 2D. And I theoretically have the solution but it doesn''t work. Let''s say I have these two lines - for simplicity they are intersecting as opposed to skewed (as most 3D lines would be). The two lines intersect at the point O. I must find the point P that is X units away from the red line. The way I''m currently attempting to get the point P is through the following: Get the distance between the two lines like so: float Distance( line A, line B ) { vector SinAngle = B.dir cross A.dir; if( SinAngle != vector(0,0,0) ) return fabsf((A.pos - B.pos) dot SinAngle); else // They are parallel. return Distance( A, B.pos ); } That last bit calls the line-point distance equation which I won''t get into. Besides, in my application parallel lines would have already been discarded. Of course in the above picture the distance is just zero. Now given that distance, I try to find the point P this way: vector PointAt( line A, line B, float X ) { float Distance = Distance( A, B ); float Length = sqrtf( (X*X) - (Distance*Distance) ); Length /= Magnitude(A.dir cross B.dir); return NearestPoint( A, B ) - (A.dir * Length); } The nearest point equation is this: float NearestPoint( line A, line B ) { vector SinAngle; float Length; SinAngle = (A.dir cross B.dir) cross B.dir; Length = ((B.pos - A.pos) dot SinAngle) / (A.dir dot SinAngle); return A.pos + (A.dir * Length); } Somehow this doesn''t always work. I check it by finding the distance from the point and the red line. "X" in my case is supposed to be 16. What it ends up being is exactly 16 only if the two lines are perpendicular - if the magnitude of their cross product is 1, in other words. Otherwise the value tends to be between 16 and 16.5. This error is significant. ~CGameProgrammer( );
~CGameProgrammer( ); Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
i would solve it like this
1- get the Cos(angle) between the two line = x/hyp
2- Segment OP = x/Cos(angle)
3- New Point P = Point O + Length of OP

Note: if Cos(angle) = Zero , then the two line are perpendicular so
2- New Point P = Point 0 + Length of OP

[edited by - Sa6ry on November 11, 2002 4:50:33 AM]
Advertisement
No, the cosine is incorrect - you need the sine.

A dot B = |A||B|cos(angle)
|A cross B| = |A||B|sin(angle)

In theory my approach should work. In reality it basically does but not perfectly. The error is relatively minor - it should return a distance of 16, it ends up returning between 16 and 16.5. But because my collision detection... well why don''t I just describe my situation.

Basically, the blue line is the movement vector of an entity and the red line is the edge of a polygon. I''m colliding with the edge. Now my collision works perfectly if the movement vector is perpendicular to the edge vector, but not if it isn''t. Since it is true that my code above does not work accurately for non-perpendicular cases, I assume it is the source of the error.

~CGameProgrammer( );
~CGameProgrammer( ); Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
quote:
Original post by CGameProgrammer
float Distance( line A, line B )
{
vector SinAngle = B.dir cross A.dir;
if( SinAngle != vector(0,0,0) )
return fabsf((A.pos - B.pos) dot SinAngle);
else // They are parallel.
return Distance( A, B.pos );
}

You should look up the distance formula once more. This can not be right.
Hey, thanks, whoever you are. I think I got that distance formula from Flipcode but their tutorials have certainly been wrong before.

I did another search for the distance formula and found this PDF which stated that I had to divide by the magnitude of the cross-product as well. Since the magnitude is 1 when they are perpendicular, that explains why it worked in the perpendicular case but not the others!

That solved the error! Thanks again. The new distance formula is:

return ((A.pos - B.pos) dot SinAngle) / magnitude(SinAngle);

~CGameProgrammer( );
~CGameProgrammer( ); Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
It truly is a thing of beauty seeing the collision in action. This bug has been plaguing me for the past five days and it''s great to finally be free of it. Whew.

~CGameProgrammer( );
~CGameProgrammer( ); Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.

This topic is closed to new replies.

Advertisement