2
$\begingroup$

I'm doing some simulation work using Blender/Python and I'm stuck on a geometry problem. What I want to do is:

  • Define a line in 3D space based on two points. One of the points will always be the origin.

  • Be able to find the coordinates of the closest point on that line to a given point B.

I've found plenty of information on how to do this in 2 dimensions, but none using 3, at least not that are in python and don't use a bunch of vector math libraries that I'm not familiar with.

I've tried working it out for 3 dimensions based on the 2D examples and I keep getting bogged down in the math.

Anyone have an example of how to do this?

$\endgroup$
4
$\begingroup$

The math you use for two dimensions can translate to three dimensions. You will find what you are looking for in the mathutils module.

mathutils.geometry.intersect_point_line() will give the result you are looking for.

import bpy
from mathutils.geometry import intersect_point_line

line = ((0.0,0.0,0.0), (1.0,1.0,1.0))
point = (0.0,0.2,0.5)

intersect = intersect_point_line(point, line[0], line[1])

print('point is closest to',intersect[0],'on the line')

The result includes the percentage of the line length where the point is located, to get it's distance from either point you can subtract two vectors and get the distance between them in the length property of the resulting vector.

distance1 = (intersect[0] - line[0]).length
distance2 = (intersect[0] - line[1]).length

if distance1 < distance2:
    print('The point is closer to the start of the line')
else:
    print('The point is closer to the end of the line')
$\endgroup$
3
$\begingroup$

You can use the Dot Product for this. Passing a normalized direction vector into the Dot Product along with another vector will resurn a scalar value representing the element of the vector that is in the direction of the direction vector. Multiplying the normalized direction vector by the acalar value will give you your closest point.

Consider 3 points - O (the origin), A (the end point of the line), and B (the point you want to get closest to along the line). You want the point on the line that is closest to B - lets call thay C.

Start with the vector OA and normalize it (make it 1 unit length. The result defines the direction of the line.

Calculate the Dot Product of that Direction Vector with the vector OB to produce the scalar distance to the closest point.

Multiply the Direction Vector by the scalar distance to produce the vector to the closest point - ie, OC.

EDIT : Thanks to @batFINGER for the following example Python code :

from mathutils import Vector
# two points define the line
a, b = Vector((0.0,0.0,0.0)), Vector((1.0,1.0,1.0))
p = Vector((0.0,0.2,0.5))
n = (b - a).normalized()

ap = p - a
t = ap.dot(n)
x =  a + t * n #  x is a point on line
print("point on line  :", x)
print("distance from p:", (p - x).length)

# cross product for distance
d = ap.cross(n).length
print("dist cross prod:", d)

Also see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Vector_formulation

$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.