UNPKG

@orca-fe/painter

Version:
124 lines (119 loc) 2.87 kB
/** * square distance between 2 points * @param {[number, number]} p1 * @param {[number, number]} p2 * @returns {number} */ function getSqDist(p1, p2) { var dx = p1[0] - p2[0]; var dy = p1[1] - p2[1]; return dx * dx + dy * dy; } /** * square distance from a point to a segment * * @param {[number, number]} p * @param {[number, number]} p1 * @param {[number, number]} p2 * @returns {number} */ function getSqSegDist(p, p1, p2) { var x = p1[0]; var y = p1[1]; var dx = p2[0] - x; var dy = p2[1] - y; var t; if (dx !== 0 || dy !== 0) { t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy); if (t > 1) { x = p2[0]; y = p2[1]; } else if (t > 0) { x += dx * t; y += dy * t; } } dx = p[0] - x; dy = p[1] - y; return dx * dx + dy * dy; } /** * basic distance-based simplification * * @param points * @param sqTolerance * @returns {*[]} */ function simplifyRadialDist(points, sqTolerance) { var prevPoint = points[0]; var newPoints = [prevPoint]; var i = 1; var n = points.length; var point; for (i; i < n; i++) { point = points[i]; if (getSqDist(point, prevPoint) > sqTolerance) { newPoints.push(point); prevPoint = point; } } if (prevPoint !== point) { newPoints.push(point); } return newPoints; } /** * * @param points * @param first * @param last * @param sqTolerance * @param simplified */ function simplifyDPStep(points, first, last, sqTolerance, simplified) { var maxSqDist = sqTolerance; var i = first + 1; var sqDist; var index; for (i; i < last; i++) { sqDist = getSqSegDist(points[i], points[first], points[last]); if (sqDist > maxSqDist) { index = i; maxSqDist = sqDist; } } if (maxSqDist > sqTolerance) { if (index - first > 0) simplifyDPStep(points, first, index, sqTolerance, simplified); simplified.push(points[index]); if (last - index > 0) simplifyDPStep(points, index, last, sqTolerance, simplified); } } /** * simplification using Ramer-Douglas-Peucker algorithm * * @param points * @param sqTolerance * @returns {*[]} */ function simplifyDouglasPeucker(points, sqTolerance) { var last = points.length - 1; var simplified = [points[0]]; simplifyDPStep(points, 0, last, sqTolerance, simplified); simplified.push(points[last]); return simplified; } /** * both algorithms combined for awesome performance * * @param points * @param tolerance * @param highestQuality * @returns {number[]} */ export function simplify(points, tolerance, highestQuality) { if (points.length <= 4) return points; var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1; var newPoints = highestQuality ? points : simplifyRadialDist(points, sqTolerance); newPoints = simplifyDouglasPeucker(newPoints, sqTolerance); return newPoints; }