-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdist2poly.m
151 lines (119 loc) · 3.92 KB
/
dist2poly.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
function L = dist2poly(p,edgexy,lim)
% Find the minimum distance from the points in P to the polygon defined by
% the edges in EDGEXY. LIM is an optional argument that defines an upper
% bound on the distance for each point.
% Uses (something like?) a double sweep-line approach to reduce the number
% of edges that are required to be tested in order to determine the closest
% edge for each point. On average only size(EDGEXY)/4 comparisons need to
% be made for each point.
if nargin<3
lim = [];
end
np = size(p,1);
ne = size(edgexy,1);
if isempty(lim)
lim = inf*ones(np,1);
end
% Choose the direction with the biggest range as the "y-coordinate" for the
% test. This should ensure that the sorting is done along the best
% direction for long and skinny problems wrt either the x or y axes.
dxy = max(p)-min(p);
if dxy(1)>dxy(2)
% Flip co-ords if x range is bigger
p = p(:,[2,1]);
edgexy = edgexy(:,[2,1,4,3]);
end
% Ensure edgexy(:,[1,2]) contains the lower y value
swap = edgexy(:,4)<edgexy(:,2);
edgexy(swap,:) = edgexy(swap,[3,4,1,2]);
% Sort edges
[i,i] = sort(edgexy(:,2)); % Sort edges by lower y value
edgexy_lower = edgexy(i,:);
[i,i] = sort(edgexy(:,4)); % Sort edges by upper y value
edgexy_upper = edgexy(i,:);
% Mean edge y value
ymean = 0.5*( sum(sum(edgexy(:,[2,4]))) )/ne;
% Alloc output
L = zeros(np,1);
% Loop through points
tol = 1000.0*eps*max(dxy);
for k = 1:np
x = p(k,1);
y = p(k,2);
d = lim(k);
if y<ymean
% Loop through edges bottom up
for j = 1:ne
y2 = edgexy_lower(j,4);
if y2>=(y-d)
y1 = edgexy_lower(j,2);
if y1<=(y+d)
x1 = edgexy_lower(j,1);
x2 = edgexy_lower(j,3);
if x1<x2
xmin = x1;
xmax = x2;
else
xmin = x2;
xmax = x1;
end
if xmin<=(x+d) && xmax>=(x-d)
% Calculate the distance along the normal projection from [x,y] to the jth edge
x2mx1 = x2-x1;
y2my1 = y2-y1;
r = ((x-x1)*x2mx1+(y-y1)*y2my1)/(x2mx1^2+y2my1^2);
if r>1.0 % Limit to wall endpoints
r = 1.0;
elseif r<0.0
r = 0.0;
end
dj = (x1+r*x2mx1-x)^2+(y1+r*y2my1-y)^2;
if (dj<d^2) && (dj>tol)
d = sqrt(dj);
end
end
else
break
end
end
end
else
% Loop through edges top down
for j = ne:-1:1
y1 = edgexy_upper(j,2);
if y1<=(y+d)
y2 = edgexy_upper(j,4);
if y2>=(y-d)
x1 = edgexy_upper(j,1);
x2 = edgexy_upper(j,3);
if x1<x2
xmin = x1;
xmax = x2;
else
xmin = x2;
xmax = x1;
end
if xmin<=(x+d) && xmax>=(x-d)
% Calculate the distance along the normal projection from [x,y] to the jth edge
x2mx1 = x2-x1;
y2my1 = y2-y1;
r = ((x-x1)*x2mx1+(y-y1)*y2my1)/(x2mx1^2+y2my1^2);
if r>1.0 % Limit to wall endpoints
r = 1.0;
elseif r<0.0
r = 0.0;
end
dj = (x1+r*x2mx1-x)^2+(y1+r*y2my1-y)^2;
if (dj<d^2) && (dj>tol)
d = sqrt(dj);
end
end
else
break
end
end
end
end
L(k) = d;
end
end % dist2poly()