From f8dff89bdc6f266b74b952ad86dde8d752432115 Mon Sep 17 00:00:00 2001 From: Dylan Praul Date: Fri, 11 Oct 2019 16:59:04 -0400 Subject: [PATCH 1/4] feat: n-dimensional points --- index.d.ts | 3 +- simplify.js | 89 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/index.d.ts b/index.d.ts index b2bf7af..77ec059 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,6 +1,5 @@ interface Point { - x: number; - y: number; + [k: string]: number; } declare function simplify (points: Point[], tolerance?: number, highQuality?: boolean): Point[]; diff --git a/simplify.js b/simplify.js index 339c84f..c06e411 100644 --- a/simplify.js +++ b/simplify.js @@ -6,44 +6,83 @@ (function () { 'use strict'; -// to suit your point format, run search/replace for '.x' and '.y'; -// for 3D version, see 3d branch (configurability would draw significant performance overhead) +/** + * Square distance between 2 points + * + * @param {Point} p1 + * @param {Point} p2 + * @return {{deltas: Point, dimensions: string[]}} + */ +function getDeltas(p1, p2) { + var dimensions = Object.keys(p1); + var deltas = dimensions.reduce(function(out, dim) { + out[dim] = p1[dim] - p2[dim]; + return out; + }, {}); + return { + deltas: deltas, + dimensions: dimensions + }; +} -// square distance between 2 points +/** + * @param {Point} p1 + * @param {Point} p2 + * @return {{distance: number, deltas: Point, dimensions: string[]}} + */ function getSqDist(p1, p2) { - - var dx = p1.x - p2.x, - dy = p1.y - p2.y; - - return dx * dx + dy * dy; + var deltaOut = getDeltas(p1, p2); + var deltas = deltaOut.deltas; + var dimensions = deltaOut.dimensions; + + var distance = dimensions.reduce(function(out, dimension) { + return out + (deltas[dimension] * deltas[dimension]); + }, 0); + return { + deltas: deltas, + dimensions: dimensions, + distance: distance + }; } -// square distance from a point to a segment +/** + * Square distance from a point to a segment + * + * @param {Point} p + * @param {Point} p1 + * @param {Point} p2 + * @return {number} + */ function getSqSegDist(p, p1, p2) { + var sqDistOut = getSqDist(p2, p1); + var segmentDeltas = sqDistOut.deltas; + var segmentDistance = sqDistOut.distance; + var dimensions = sqDistOut.dimensions; - var x = p1.x, - y = p1.y, - dx = p2.x - x, - dy = p2.y - y; + var hasNonZeroDelta = Object.values(segmentDeltas).some(function(d) { + return d !== 0; + }); - if (dx !== 0 || dy !== 0) { + var refPoint; - var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy); + if (hasNonZeroDelta) { + var deltas = getDeltas(p, p1).deltas; + var cumulative = dimensions.reduce(function(sum, dimension) { + return sum + (deltas[dimension] * segmentDeltas[dimension]); + }, 0); + var t = cumulative / segmentDistance; if (t > 1) { - x = p2.x; - y = p2.y; - + refPoint = p2; } else if (t > 0) { - x += dx * t; - y += dy * t; + refPoint = dimensions.reduce(function(out, dim) { + out[dim] = p1[dim] + (segmentDeltas[dim] * t); + return out; + }, {}); } } - dx = p.x - x; - dy = p.y - y; - - return dx * dx + dy * dy; + return getSqDist(p, refPoint).distance; } // rest of the code doesn't care about point format @@ -57,7 +96,7 @@ function simplifyRadialDist(points, sqTolerance) { for (var i = 1, len = points.length; i < len; i++) { point = points[i]; - if (getSqDist(point, prevPoint) > sqTolerance) { + if (getSqDist(point, prevPoint).distance > sqTolerance) { newPoints.push(point); prevPoint = point; } From 528bcf5fda7d0121ab01d4ef71f943e5de79f06d Mon Sep 17 00:00:00 2001 From: Dylan Praul Date: Fri, 11 Oct 2019 17:01:52 -0400 Subject: [PATCH 2/4] don't use Object.values --- simplify.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/simplify.js b/simplify.js index c06e411..dc2854f 100644 --- a/simplify.js +++ b/simplify.js @@ -21,7 +21,7 @@ function getDeltas(p1, p2) { }, {}); return { deltas: deltas, - dimensions: dimensions + dimensions: dimensions, }; } @@ -41,7 +41,7 @@ function getSqDist(p1, p2) { return { deltas: deltas, dimensions: dimensions, - distance: distance + distance: distance, }; } @@ -59,9 +59,10 @@ function getSqSegDist(p, p1, p2) { var segmentDistance = sqDistOut.distance; var dimensions = sqDistOut.dimensions; - var hasNonZeroDelta = Object.values(segmentDeltas).some(function(d) { - return d !== 0; - }); + var hasNonZeroDelta = dimensions + .some(function(dimension) { + return segmentDeltas[dimension] !== 0; + }); var refPoint; From 99affaecb821dc39e15a1444b20d403e0b85521e Mon Sep 17 00:00:00 2001 From: Dylan Praul Date: Fri, 11 Oct 2019 17:11:33 -0400 Subject: [PATCH 3/4] correct default refPoint --- simplify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplify.js b/simplify.js index dc2854f..458ef16 100644 --- a/simplify.js +++ b/simplify.js @@ -64,7 +64,7 @@ function getSqSegDist(p, p1, p2) { return segmentDeltas[dimension] !== 0; }); - var refPoint; + var refPoint = p1; if (hasNonZeroDelta) { var deltas = getDeltas(p, p1).deltas; From b2f079fbddaa3f716000cf548155f01cfd8a1751 Mon Sep 17 00:00:00 2001 From: Dylan Praul Date: Fri, 11 Oct 2019 17:47:28 -0400 Subject: [PATCH 4/4] small optimization --- simplify.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/simplify.js b/simplify.js index 458ef16..f784cf2 100644 --- a/simplify.js +++ b/simplify.js @@ -59,14 +59,9 @@ function getSqSegDist(p, p1, p2) { var segmentDistance = sqDistOut.distance; var dimensions = sqDistOut.dimensions; - var hasNonZeroDelta = dimensions - .some(function(dimension) { - return segmentDeltas[dimension] !== 0; - }); - var refPoint = p1; - if (hasNonZeroDelta) { + if (segmentDistance > 0) { var deltas = getDeltas(p, p1).deltas; var cumulative = dimensions.reduce(function(sum, dimension) { return sum + (deltas[dimension] * segmentDeltas[dimension]);