poly-simplify
Version:
Simplify polyline or polygon vertices in JS
82 lines (64 loc) • 2.29 kB
JavaScript
import { reducePoints, getAngle, getPolyBBox, getPolygonArea, getSquareDistance, detectRegularPolygon, scalePolygon, sortPolygonLeftTopFirst, isClosedPolygon } from './geometry.js';
/**
* "lossless" simplification:
* remove zero length or
* horizontal or vertical segments
* geometry should be perfectly retained
*/
export function simplifyRC(pts) {
//console.log('simplifyRC');
if (pts.length < 3) return pts;
let ptsSmp = [pts[0]];
let pt0 = pts[0];
let pt1, pt2;
let ptL = pts[pts.length-1];
let tolerance = 1;
// First pass: Remove colinear points and collect triangle areas
for (let i = 2, l = pts.length; i < l; i++) {
pt1 = pts[i - 1];
pt2 = pts[i];
// Skip zero-length segments
if (pt1.x === pt2.x && pt1.y === pt2.y) continue;
// Check for vertical/horizontal segments
let isVertical = (pt0.x === pt1.x);
let isHorizontal = (pt0.y === pt1.y);
if (isVertical || isHorizontal) {
let nextVertical = (pt1.x === pt2.x);
let nextHorizontal = (pt1.y === pt2.y);
if (!(nextVertical && isVertical) && !(nextHorizontal && isHorizontal)) {
ptsSmp.push(pt1);
}
// add last point
if(i === l - 1){
ptsSmp.push(pt2);
}
pt0 = pt1;
continue;
}
// Cross product check for colinearity
let dx0 = pt0.x - pt2.x;
let dy0 = pt0.y - pt2.y;
let dx1 = pt0.x - pt1.x;
let dy1 = pt0.y - pt1.y;
let cross = Math.abs(dx0 * dy1 - dy0 * dx1);
// Dynamic tolerance based on segment length
let squareDistance = getSquareDistance(pt1, pt2);
tolerance = squareDistance / 50;
if (cross > tolerance) {
if (i === l - 1) {
// last point
ptsSmp.push(pt1, pt2);
} else {
ptsSmp.push(pt1);
}
}
pt0 = pt1;
}
// first and last points coincide
pt0 = ptsSmp[0];
if(pt0.x===ptL.x && pt0.y===ptL.y){
ptsSmp.pop();
}
//console.log('pts RC:', ptsSmp);
return ptsSmp;
}