1
votes

I have a line AB. I would like to draw a line BC, perpendicular to AB. I know xyz of the points A and B, I also know the distance N between B and C. How can I find an arbitrary point C which fits into the given parameters? The calculations should be done in 3-D. Any point, perpendicular to AB can be the point C, if its distance to B equals N.

An almost identical question is given here, but I would like to know how the same thing is done in 3-D: How do you find a point at a given perpendicular distance from a line?

The calculation that works for me in 2-D was given in the link above:

dx = A.x-B.x
dy = A.y-B.y
dist = sqrt(dx*dx + dy*dy)
dx /= dist
dy /= dist
C.x = B.x + N*dy
C.y = B.y - N*dx

I tried adding Z axis to it like this:

dz = A.z - B.z 
dist = sqrt(dx*dx + dy*dy + dz*dz) 
dz /=dist 
C.z = .... at this point it becomes a mystery to me

If I put something like "C.z - N*dz" into C.z, the distance is accurate only in some rotation angles, I would like to know the correct solution. I can imagine that in 3-D it is calculated in a completely different manner.

Clarification

  • Point C is not unique. It can be any point on a circle with its centre at B and radius N. The circle is perpendicular to AB
1
If I understand your question correctly, the point C that has distance N from B is not unique. It is actually all the points on a circle that with B as a center and N as radius.Aziz
@Aziz, yes, you are correct. Point C can be any point on that circle.Lori
Do you know enough about 3D vectors to implement the vector algorithm I just gave in my answer?Rory Daulton
@Rory, thank you very much for you answer. It would be helpful if you could show how it's done in the code.Lori

1 Answers

1
votes

If the desired point C can be any of the infinitely-many points fitting your requirements, here is one method.

Choose any vector that is not parallel or anti-parallel to vector AB. You could try the vector (1, 0, 0), and if that is parallel you could use (0, 1, 0) instead. Then take the cross-product of vector AB and the chosen vector. That cross-product is perpendicular to vector AB. Divide that cross-product by its length then multiply by the desired length N. Finally extend that vector from point B to find your desired point C.

Here is code in Python 3 that follows that algorithm. This code is somewhat non-pythonic to make it easier to convert to other languages. (If I really did this for myself I would use the numpy module to avoid coordinates completely and shorten this code.) But it does treat the points as tuples of 3 values: many languages will require you to handle each coordinate separately. Any real-life code would need to check for "near zero" rather than "zero" and to check that the sqrt calculation does not result in zero. I'll leave those additional steps to you. Ask if you have more questions.

from math import sqrt

def pt_at_given_distance_from_line_segment_and_endpoint(a, b, dist):
    """Return a point c such that line segment bc is perpendicular to
    line segment ab and segment bc has length dist.

    a and b are tuples of length 3, dist is a positive float.
    """
    vec_ab = (b[0]-a[0], b[1]-a[1], b[2]-a[2])
    # Find a vector not parallel or antiparallel to vector ab
    if vec_ab[1] != 0 or vec_ab[2] != 0:
        vec = (1, 0, 0)
    else:
        vec = (0, 1, 0)
    # Find the cross product of the vectors
    cross = (vec_ab[1] * vec[2] - vec_ab[2] * vec[1],
             vec_ab[2] * vec[0] - vec_ab[0] * vec[2],
             vec_ab[0] * vec[1] - vec_ab[1] * vec[0])
    # Find the vector in the same direction with length dist
    factor = dist / sqrt(cross[0]**2 + cross[1]**2 + cross[2]**2)
    newvec = (factor * cross[0], factor * cross[1], factor * cross[2])
    # Find point c such that vector bc is that vector
    c = (b[0] + newvec[0], b[1] + newvec[1], b[2] + newvec[2])
    # Done!
    return c

The resulting output from the command

print(pt_at_given_distance_from_line_segment_and_endpoint((1, 2, 3), (4, 5, 6), 2))

is

(4.0, 6.414213562373095, 4.585786437626905)