11

This question has been asked before in reference to 2D. This question extends it to 3D. How do I find the perpendicular intersected point on a line from a point in 3D space?. If my line is defined by points (x1,y1,z1) & (x2,y2,z2) and I have a point (x3,y3,z3) in space.

How do I find the perpendicular intersection of point (x4,y4,z4) on the line from (x3,y3,z3)?

andand
  • 17,134
  • 11
  • 53
  • 79
user1222017
  • 121
  • 1
  • 2
  • 5

4 Answers4

11

For starters, you pretty much need some implementation of a Vector3 class, whether you write your own, find a standalone implementation on the internet somewhere, or use a library that contains one like XNA or Sharp3D.Math.

Typically lines in 3d space are not represented by two points, but by parametric equations and operated on by vectors and not scalars. Your parametric equation would be of the form:

x = x1 + t(x2-x1), y = y1 + t(y2-y1), z = z1 + t(z2-z1)

The vector u is defined by the coefficients of t. <x2-x1, y2-y1, z2-z1>.

The vector PQ is defined by your chosen point Q minus a point P on the line. Any point on the line can be chosen, so it would be simplest to just use the line t = 0, which simplifies to x1, y1, and z1. <x3-x1, y3-y1, z3-z1>

The definition of the shortest distance between a point and a line in 3-space is as follows:

D = ||PQ x u|| / ||u||

Where x is the cross product operator, and || ... || gets the magnitude of the contained vector. Depending on which library you choose, your code may vary, but it should be very similar:

Vector3 u = new Vector3(x2 - x1, y2 - y1, z2 - z1);
Vector3 pq = new Vector3(x3 - x1, y3 - y1, z3 - z1);

float distance = Vector3.Cross(pq, u).Length / u.Length;

Edit: I just realized you wanted the actual point of intersection, and not the distance. The formula to find the actual point is a bit different. You need to use inner product space to get the component of u perpendicular to PQ. To do that, you need to find the component of u in the direction of PQ:

((PQ · u) / ||u||^2) * u

This gets us the w1 component, but we want w2, which is the component between Q and the line:

PQ = w1 + w2

w2 = PQ - w1

From there, we take w2 and add it to the point Q to get the point on the line nearest Q. In code this would be:

Vector3 p1 = new Vector3(x1, y1, z1);
Vector3 p2 = new Vector3(x2, y2, z2);
Vector3 q = new Vector3(x3, y3, z3);

Vector3 u = p2 - p1;
Vector3 pq = q - p1;
Vector3 w2 = pq - Vector3.Multiply(u, Vector3.Dot(pq, u) / u.LengthSquared);

Vector3 point = q - w2;

Where point.X is x4, point.Y is y4, and point.Z is z4.

Community
  • 1
  • 1
Robert Rouhani
  • 14,512
  • 6
  • 44
  • 59
  • This might seem dumb, but I can't locate the Vector3.Scale method in the Xna namespace. Is there another namespace in Xna? I am using Microsoft.Xna.Framework. I see a Vector3.Scale in the Directx namespace, but i did not find anywhere to download that assembly. Need some direction? – user1222017 Feb 21 '12 at 03:48
  • XNA's Vector3 uses `Vector3.Multiply` instead of `Vector3.Scale`: http://msdn.microsoft.com/en-us/library/bb198114.aspx – Robert Rouhani Feb 21 '12 at 04:35
  • Many, Many MyBads I thought this was working at 2:00 last night but now when I check by points, I get the wrong answer. As an example: I have points A:(666.401,-8.421,151.687), B:(666.401,-86.459,154.459), C:(1047, -26.988,133.248) line is: AB and point is C --- Ans I get is: D:(380.60,-33.49,-17.20). Should lie on x axis which is 666.401? – user1222017 Feb 21 '12 at 19:42
  • I just tested out my own code with the points you provided, it looks like `point` should be `q - w2` and not `q + w2`. – Robert Rouhani Feb 21 '12 at 20:36
  • I get D:(1713,-20.49,283.69) If AB is the line, Dx should be 666.401? I assume u.LengthSquared is :u.LengthSquared()? – user1222017 Feb 21 '12 at 21:19
  • yeah, sorry about that. I just realized that I didn't change the code example to subtract w2 from q, make sure you're doing that. Other than that it's hard to say what's wrong. I'm testing this with OpenTK's Vector3 implementation and I got a proper answer of (666.401, -26.31045, 152.3224) , maybe the parameters of a method are flipped somewhere in the XNA implementation. – Robert Rouhani Feb 21 '12 at 21:36
  • I tried both ways with w2& q and got wrong answers. Looks like your answer is correct. I assume then I have some vectors in the wrong order in Xna. I will try to get TK. Thanks for your patience. – user1222017 Feb 21 '12 at 21:43
  • Okey DoKey-- I rechecked and found that in trying different orders that I had reversed a vector. For anyone that may come across this post, the above appears correct and is fairly simple to program. Works in both Xna and TK as is: Thanks for your help!! – user1222017 Feb 22 '12 at 01:18
2

We Can also Use AAS Triangle Method.

A - (x1,y1,z1), B - (x2,y2,z3) , C - (x3,y3,z3)

We need to find the Point D in Line AB which is perpendicular to point C

Now we have Directional Vectors

VectorAC = normalize(A - C),
VectorCA = normalize(C - A),
VectorAB = normalize(A - B),

Lets Consider ADC as a triangle

Dot product gives the angle between 2 vectors

AngleA = Angle Between VectorAC and vectorAB
AngleD = Angle Between VectorDC and vector DA, Always 90 deg, As VectorDC and DA are perpendicular to each other.
AngleC =  180 - (AngleA + AngleD), Angle between VectorCD and VectorCA.

So now we have 3 angle of the Triangle

Use AAS triangle method and find the distance between A and D.

http://www.mathsisfun.com/algebra/trig-solving-aas-triangles.html

 D = (A + (VectorAB * Distance between A and D)).
VivekParamasivam
  • 1,086
  • 2
  • 13
  • 23
2

You're asking, in practice, the calculation of a distance between the point and line, so the Length of the vector from the (x3,y3,z3) point to the line which is orthogonal to the vector. If we immagine the line like a vector, that means that dot-product of both vectors is equal to 0. (this is just to give you a hint) .

Tigran
  • 61,654
  • 8
  • 86
  • 123
1

I did the calculation for the answer marked as Best Answer:
let alpha = [(x3-x1)(x2-x1) + (y3-y1)(y2-y1) + (z3-z1)(z2-z1)] / [(x2-x1)(x2-x1) + (y2-y1)(y2-y1) + (z2-z1)(z2-z1)]
point of intersection = (x1+alpha*(x2-x1), y1+alpha*(y2-y1), z1+alpha*(z2-z1)).

daniel
  • 157
  • 1
  • 1