5
\$\begingroup\$

This function returns the shortest distance from a 3D point P to a line segment defined by two 3D points A and B. It projects P onto the line, then checks if this projected point lies between A and B. If it does, then the distance is calculated using this projected point.

If the projection is outside the line segment, then the distance is calculated to either point A or B, depending on which is closer.

I wanted to get feedback on if this is a clean solution to the problem.

function d = point_seg_dist(P, A, B)
% Returns distance from a 3D point to a line segment
%
% Inputs
%
%   P : vector
%       Position in space
%
%   A : vector
%       Position of line segment endpoint
%
%   B : vector
%       Position of other line segment endpoint
%
% Outputs
%
%   d : double
%       Distance from point to line segment

AP = P - A; % Vector from A to point
AB = B - A; % Vector from A to B

% Project point onto line
P_line = A + dot(AP, AB) / dot(AB, AB) * AB;

if all(A < P_line) && all(P_line < B)
    % The point projected onto the line is in between A and B 

    % Projection of point onto segment is the same 
    % as projection of point onto line
    P_seg = P_line; 
else
    % The point projected onto the line is outside of A and B

    if all(P_line <= A)
        % The projected point is closer to A
        P_seg = A;  
    else
        % The projected point is closer to B
        P_seg = B;
    end
end

d = norm(P - P_seg); % Distance to line segment

end
\$\endgroup\$
6
  • 1
    \$\begingroup\$ hi there - are you able to elaborate more on what is happening here: P_line = A + dot(AP, AB) / dot(AB, AB) * AB; ---> how did you derive that? \$\endgroup\$ Commented May 4, 2017 at 4:28
  • \$\begingroup\$ Hi, I took that code from another stack exchange thread. gamedev.stackexchange.com/questions/72528/… \$\endgroup\$ Commented May 4, 2017 at 4:52
  • \$\begingroup\$ ok i see. i don't like that solution. there are some useful videos on youtube: which show how it can be done via calculus. it's simple enough. \$\endgroup\$ Commented May 4, 2017 at 5:52
  • \$\begingroup\$ follow the links on this post - stackoverflow.com/questions/7142028/… \$\endgroup\$ Commented May 4, 2017 at 6:06
  • 1
    \$\begingroup\$ It seems to me mathworld.wolfram.com/Point-LineDistance3-Dimensional.html is the simplest way to do this. \$\endgroup\$ Commented May 6, 2017 at 13:34

1 Answer 1

1
\$\begingroup\$

Here is the implementation of the solution provided by Wolfram Alpha, as was suggested in the comments of the OP.

The implemented equation is:

$$ d=\frac{|(\mathbf{x}_2-\mathbf{x}_1)\times(\mathbf{x}_1-\mathbf{x}_0)|}{|\mathbf{x}_2-\mathbf{x}_1|} $$

where

$$x_1=(x_1,y_1,z_1)$$ $$x_2=(x_2,y_2,z_2)$$

are two points on the line and \$x_0\$ is a third point.

function d = point_seg_dist(x0, x1, x2)
    
    % Make sure we are in 3D
    if length(x0) == 2
        x1(3) = 0;
        x2(3) = 0;
        x0(3) = 0;
    end
    
    % We want column arrays
    if size(x0,1) < size(x0,2)
         x0 = P';
         x1 = x1';
         x2 = x2';
    end

    d = norm(cross(x2-x1 , x1-x0)) / norm(x2-x1);

Apart from a couple of checks on the input, the calculation is on one line and it does not need projections or checks on the projected point's position.

\$\endgroup\$
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.