Skip to content

Commit f65129c

Browse files
committed
more precise segment to axis-aligned box distance calculation
Makes the concave phase much faster on large point sets. Total time for 1 million points went from 6.3s to 2.7s.
1 parent 8e39de6 commit f65129c

File tree

1 file changed

+86
-3
lines changed

1 file changed

+86
-3
lines changed

index.js

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,23 @@ function compareDist(a, b) {
124124

125125
// square distance from a segment bounding box to the given one
126126
function sqSegBoxDist(a, b, bbox) {
127-
var dx = Math.max(bbox[0] - Math.max(a[0], b[0]), Math.min(a[0], b[0]) - bbox[2], 0);
128-
var dy = Math.max(bbox[1] - Math.max(a[1], b[1]), Math.min(a[1], b[1]) - bbox[3], 0);
129-
return dx * dx + dy * dy;
127+
if (inside(a, bbox) || inside(b, bbox)) return 0;
128+
var d1 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[1], bbox[2], bbox[1]);
129+
if (d1 === 0) return 0;
130+
var d2 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[1], bbox[0], bbox[3]);
131+
if (d2 === 0) return 0;
132+
var d3 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[2], bbox[1], bbox[2], bbox[3]);
133+
if (d3 === 0) return 0;
134+
var d4 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[3], bbox[2], bbox[3]);
135+
if (d4 === 0) return 0;
136+
return Math.min(d1, d2, d3, d4);
137+
}
138+
139+
function inside(a, bbox) {
140+
return a[0] >= bbox[0] &&
141+
a[0] <= bbox[2] &&
142+
a[1] >= bbox[1] &&
143+
a[1] <= bbox[3];
130144
}
131145

132146
// check if the edge (a,b) doesn't intersect any other edges
@@ -254,3 +268,72 @@ function sqSegDist(p, p1, p2) {
254268

255269
return dx * dx + dy * dy;
256270
}
271+
272+
// segment to segment distance, ported from http://geomalgorithms.com/a07-_distance.html by Dan Sunday
273+
function sqSegSegDist(x0, y0, x1, y1, x2, y2, x3, y3) {
274+
var ux = x1 - x0;
275+
var uy = y1 - y0;
276+
var vx = x3 - x2;
277+
var vy = y3 - y2;
278+
var wx = x0 - x2;
279+
var wy = y0 - y2;
280+
var a = ux * ux + uy * uy;
281+
var b = ux * vx + uy * vy;
282+
var c = vx * vx + vy * vy;
283+
var d = ux * wx + uy * wy;
284+
var e = vx * wx + vy * wy;
285+
var D = a * c - b * b;
286+
287+
var sc, sN, tc, tN;
288+
var sD = D;
289+
var tD = D;
290+
291+
if (D === 0) {
292+
sN = 0;
293+
sD = 1;
294+
tN = e;
295+
tD = c;
296+
} else {
297+
sN = b * e - c * d;
298+
tN = a * e - b * d;
299+
if (sN < 0) {
300+
sN = 0;
301+
tN = e;
302+
tD = c;
303+
} else if (sN > sD) {
304+
sN = sD;
305+
tN = e + b;
306+
tD = c;
307+
}
308+
}
309+
310+
if (tN < 0.0) {
311+
tN = 0.0;
312+
if (-d < 0.0) sN = 0.0;
313+
else if (-d > a) sN = sD;
314+
else {
315+
sN = -d;
316+
sD = a;
317+
}
318+
} else if (tN > tD) {
319+
tN = tD;
320+
if ((-d + b) < 0.0) sN = 0;
321+
else if (-d + b > a) sN = sD;
322+
else {
323+
sN = -d + b;
324+
sD = a;
325+
}
326+
}
327+
328+
sc = sN === 0 ? 0 : sN / sD;
329+
tc = tN === 0 ? 0 : tN / tD;
330+
331+
var cx = (1 - sc) * x0 + sc * x1;
332+
var cy = (1 - sc) * y0 + sc * y1;
333+
var cx2 = (1 - tc) * x2 + tc * x3;
334+
var cy2 = (1 - tc) * y2 + tc * y3;
335+
var dx = cx2 - cx;
336+
var dy = cy2 - cy;
337+
338+
return dx * dx + dy * dy;
339+
}

0 commit comments

Comments
 (0)