-
Notifications
You must be signed in to change notification settings - Fork 0
/
DistBetween2Segment.m
105 lines (90 loc) · 2.8 KB
/
DistBetween2Segment.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
% Computes the minimum distance between two line segments. Code
% is adapted for Matlab from Dan Sunday's Geometry Algorithms originally
% written in C++
% http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm#dist3D_Segment_to_Segment
% Usage: Input the start and end x,y,z coordinates for two line segments.
% p1, p2 are [x,y,z] coordinates of first line segment and p3,p4 are for
% second line segment.
% Output: scalar minimum distance between the two segments.
% Example:
% P1 = [0 0 0]; P2 = [1 0 0];
% P3 = [0 1 0]; P4 = [1 1 0];
% dist = DistBetween2Segment(P1, P2, P3, P4)
% dist =
%
% 1
%
function [distance varargout] = DistBetween2Segment(p1, p2, p3, p4)
u = p1 - p2;
v = p3 - p4;
w = p2 - p4;
a = dot(u,u);
b = dot(u,v);
c = dot(v,v);
d = dot(u,w);
e = dot(v,w);
D = a*c - b*b;
sD = D;
tD = D;
SMALL_NUM = 0.00000001;
% compute the line parameters of the two closest points
if (D < SMALL_NUM) % the lines are almost parallel
sN = 0.0; % force using point P0 on segment S1
sD = 1.0; % to prevent possible division by 0.0 later
tN = e;
tD = c;
else % get the closest points on the infinite lines
sN = (b*e - c*d);
tN = (a*e - b*d);
if (sN < 0.0) % sc < 0 => the s=0 edge is visible
sN = 0.0;
tN = e;
tD = c;
elseif (sN > sD)% sc > 1 => the s=1 edge is visible
sN = sD;
tN = e + b;
tD = c;
end
end
if (tN < 0.0) % tc < 0 => the t=0 edge is visible
tN = 0.0;
% recompute sc for this edge
if (-d < 0.0)
sN = 0.0;
elseif (-d > a)
sN = sD;
else
sN = -d;
sD = a;
end
elseif (tN > tD) % tc > 1 => the t=1 edge is visible
tN = tD;
% recompute sc for this edge
if ((-d + b) < 0.0)
sN = 0;
elseif ((-d + b) > a)
sN = sD;
else
sN = (-d + b);
sD = a;
end
end
% finally do the division to get sc and tc
if(abs(sN) < SMALL_NUM)
sc = 0.0;
else
sc = sN / sD;
end
if(abs(tN) < SMALL_NUM)
tc = 0.0;
else
tc = tN / tD;
end
% get the difference of the two closest points
dP = w + (sc * u) - (tc * v); % = S1(sc) - S2(tc)
distance = norm(dP);
outV = dP;
varargout(1) = {outV}; % vector connecting the closest points
varargout(2) = {p2+sc*u}; % Closest point on object 1
varargout(3) = {p4+tc*v}; % Closest point on object 2
end