mirror of
https://github.com/Turfjs/turf.git
synced 2026-01-25 16:07:00 +00:00
* Migrate isobands and isolines grid lib files * simplifyjs * great-circle already migrated to upstream arc npm package * Migrate js files in unkink-polygon, this felt kinda rough * Migrate astar lib to typescript * Remove heuristic option to fix typings
118 lines
2.8 KiB
TypeScript
118 lines
2.8 KiB
TypeScript
/*
|
|
(c) 2013, Vladimir Agafonkin
|
|
Simplify.js, a high-performance JS polyline simplification library
|
|
mourner.github.io/simplify-js
|
|
*/
|
|
|
|
// 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
|
|
function getSqDist(p1: number[], p2: number[]) {
|
|
var dx = p1[0] - p2[0],
|
|
dy = p1[1] - p2[1];
|
|
|
|
return dx * dx + dy * dy;
|
|
}
|
|
|
|
// square distance from a point to a segment
|
|
function getSqSegDist(p: number[], p1: number[], p2: number[]) {
|
|
var x = p1[0],
|
|
y = p1[1],
|
|
dx = p2[0] - x,
|
|
dy = p2[1] - y;
|
|
|
|
if (dx !== 0 || dy !== 0) {
|
|
var 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;
|
|
}
|
|
// rest of the code doesn't care about point format
|
|
|
|
// basic distance-based simplification
|
|
function simplifyRadialDist(points: number[][], sqTolerance: number) {
|
|
var prevPoint = points[0],
|
|
newPoints = [prevPoint],
|
|
point;
|
|
|
|
for (var i = 1, len = points.length; i < len; i++) {
|
|
point = points[i];
|
|
|
|
if (getSqDist(point, prevPoint) > sqTolerance) {
|
|
newPoints.push(point);
|
|
prevPoint = point;
|
|
}
|
|
}
|
|
|
|
if (prevPoint !== point) newPoints.push(point!);
|
|
|
|
return newPoints;
|
|
}
|
|
|
|
function simplifyDPStep(
|
|
points: number[][],
|
|
first: number,
|
|
last: number,
|
|
sqTolerance: number,
|
|
simplified: number[][]
|
|
) {
|
|
var maxSqDist = sqTolerance,
|
|
index;
|
|
|
|
for (var i = first + 1; i < last; i++) {
|
|
var sqDist = getSqSegDist(points[i], points[first], points[last]);
|
|
|
|
if (sqDist > maxSqDist) {
|
|
index = i;
|
|
maxSqDist = sqDist;
|
|
}
|
|
}
|
|
|
|
if (maxSqDist > sqTolerance) {
|
|
if (index! - first > 1)
|
|
simplifyDPStep(points, first, index!, sqTolerance, simplified);
|
|
simplified.push(points[index!]);
|
|
if (last - index! > 1)
|
|
simplifyDPStep(points, index!, last, sqTolerance, simplified);
|
|
}
|
|
}
|
|
|
|
// simplification using Ramer-Douglas-Peucker algorithm
|
|
function simplifyDouglasPeucker(points: number[][], sqTolerance: number) {
|
|
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
|
|
export function simplify(
|
|
points: number[][],
|
|
tolerance: number,
|
|
highestQuality: boolean
|
|
) {
|
|
if (points.length <= 2) return points;
|
|
|
|
var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
|
|
|
|
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
|
|
points = simplifyDouglasPeucker(points, sqTolerance);
|
|
|
|
return points;
|
|
}
|