SourceTermAnalysisSystem_vue/node_modules/ol-ext/geom/visvalingam.js
2026-05-15 10:22:44 +08:00

185 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import ol_geom_LineString from 'ol/geom/LineString.js'
import { ol_coordinate_equal } from './GeomUtils';
(function () {
/**
* Visvalingam polyline simplification algorithm, adapted from http://bost.ocks.org/mike/simplify/simplify.js
* This uses the [VisvalingamWhyatt](https://en.wikipedia.org/wiki/Visvalingam%E2%80%93Whyatt_algorithm) algorithm.
* @param {Object} options
* @param {number} [area] the tolerance area for simplification
* @param {number} [dist] a tolerance distance for simplification
* @param {number} [ratio=.8] a ratio of points to keep
* @param {number} [minPoints=2] minimum number of points to keep
* @param {boolean} [keepEnds] keep line ends
* @return { LineString } A new, simplified version of the original geometry.
* @api
*/
ol_geom_LineString.prototype.simplifyVisvalingam = function (options) {
var points = this.getCoordinates();
if (options.minPoints && options.minPoints >= points.length) {
return new ol_geom_LineString(points);
}
var heap = minHeap(),
maxArea = 0,
triangle,
triangles = [];
points = points.map(function (d) { return d.slice(0,2); });
for (var i = 1, n = points.length - 1; i < n; ++i) {
triangle = points.slice(i - 1, i + 2);
if (triangle[1][2] = area(triangle)) {
triangles.push(triangle);
heap.push(triangle);
}
}
for (i = 0, n = triangles.length; i < n; ++i) {
triangle = triangles[i];
triangle.previous = triangles[i - 1];
triangle.next = triangles[i + 1];
}
while (triangle = heap.pop()) {
// If the area of the current point is less than that of the previous point
// to be eliminated, use the latters area instead. This ensures that the
// current point cannot be eliminated without eliminating previously-
// eliminated points.
if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
else maxArea = triangle[1][2];
if (triangle.previous) {
triangle.previous.next = triangle.next;
triangle.previous[2] = triangle[2];
update(triangle.previous);
} else {
triangle[0][2] = triangle[1][2];
}
if (triangle.next) {
triangle.next.previous = triangle.previous;
triangle.next[0] = triangle[0];
update(triangle.next);
} else {
triangle[2][2] = triangle[1][2];
}
}
function update(triangle) {
heap.remove(triangle);
triangle[1][2] = area(triangle);
heap.push(triangle);
}
// Get area to remove
var w = options.area;
if (options.dist) w = options.dist * options.dist / 2;
// If no area
if (w === undefined || options.minPoints) {
// Get ordered weights
var weights = points.map(function (d) { return d.length < 3 ? Infinity : d[2] += Math.random(); /* break ties */ });
weights.sort(function (a, b) {
return b - a;
});
if (w) {
// Check min points
if (weights[options.minPoints] < w) {
w = weights[options.minPoints]
}
} else {
var pointsToKeep = options.minPoints;
// Calculate ratio
if (!pointsToKeep) {
var ratio = options.ratio || .8
pointsToKeep = Math.round(points.length * ratio);
}
pointsToKeep = Math.min(pointsToKeep, weights.length -1);
w = weights[pointsToKeep]
}
}
var result = points.filter(function (d) {
return d[2] > w;
});
if (options.keepEnds) {
if (!ol_coordinate_equal(result[0], points[0])) result.unshift(points[0]);
if (!ol_coordinate_equal(result[result.length-1], points[points.length-1])) result.push(points[points.length-1]);
}
return new ol_geom_LineString(result);
};
function compare(a, b) {
return a[1][2] - b[1][2];
}
function area(t) {
return Math.abs((t[0][0] - t[2][0]) * (t[1][1] - t[0][1]) - (t[0][0] - t[1][0]) * (t[2][1] - t[0][1]));
}
function minHeap() {
var heap = {},
array = [];
heap.push = function() {
for (var i = 0, n = arguments.length; i < n; ++i) {
var object = arguments[i];
up(object.index = array.push(object) - 1);
}
return array.length;
};
heap.pop = function() {
var removed = array[0],
object = array.pop();
if (array.length) {
array[object.index = 0] = object;
down(0);
}
return removed;
};
heap.size = function () {
return array.length;
};
heap.remove = function(removed) {
var i = removed.index,
object = array.pop();
if (i !== array.length) {
array[object.index = i] = object;
(compare(object, removed) < 0 ? up : down)(i);
}
return i;
};
function up(i) {
var object = array[i];
while (i > 0) {
var up = ((i + 1) >> 1) - 1,
parent = array[up];
if (compare(object, parent) >= 0) break;
array[parent.index = i] = parent;
array[object.index = i = up] = object;
}
}
function down(i) {
var object = array[i];
for (;;) {
var right = (i + 1) * 2,
left = right - 1,
down = i,
child = array[down];
if (left < array.length && compare(array[left], child) < 0) child = array[down = left];
if (right < array.length && compare(array[right], child) < 0) child = array[down = right];
if (down === i) break;
array[child.index = i] = child;
array[object.index = i = down] = object;
}
}
return heap;
}
})();
export default ol_geom_LineString