@orca-fe/painter
Version:
Konva Painter
130 lines (124 loc) • 2.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.simplify = simplify;
/**
* 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[]}
*/
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;
}