| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- .pragma library
- /*
- (c) 2013, Vladimir Agafonkin
- Simplify.js, a high-performance JS polyline simplification library
- mourner.github.io/simplify-js
- */
- '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
- function getSqDist(p1, p2) {
- var dx = p1.x - p2.x,
- dy = p1.y - p2.y;
- return dx * dx + dy * dy;
- }
- // square distance from a point to a segment
- function getSqSegDist(p, p1, p2) {
- var x = p1.x,
- y = p1.y,
- dx = p2.x - x,
- dy = p2.y - y;
- if (dx !== 0 || dy !== 0) {
- var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
- if (t > 1) {
- x = p2.x;
- y = p2.y;
- } else if (t > 0) {
- x += dx * t;
- y += dy * t;
- }
- }
- dx = p.x - x;
- dy = p.y - y;
- return dx * dx + dy * dy;
- }
- // rest of the code doesn't care about point format
- // basic distance-based simplification
- function simplifyRadialDist(points, sqTolerance) {
- 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, first, last, sqTolerance, simplified) {
- 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, 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
- function simplify(points, tolerance, highestQuality) {
- 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;
- }
- /*
- // export as AMD module / Node module / browser or worker variable
- if (typeof define === 'function' && define.amd) define(function() { return simplify; });
- else if (typeof module !== 'undefined') module.exports = simplify;
- else if (typeof self !== 'undefined') self.simplify = simplify;
- else window.simplify = simplify;
- })();
- */
|