处理前
处理后
直接上代码
注意points 格式 [{lng:120,lat:34}.....]
注意 threshold 一般 0.005 自己调
/**
* 密度抽稀算法(Point Density Simplification)对这些点进行过滤
* 基本思路是在计算点密度(每个点周围一定距离内点的数量),并根据设定的阈值来决定是否保留该点。
* 具体实现有许多种方法,其中一种比较常见的方法是使用 Douglus-Peucker 算法,
* 这是一种广泛应用于曲线平滑和抽稀的算法,其基本原理是通过一系列递归操作,将曲线中的一些不必要的点去掉,
* 从而使得抽稀后的曲线与原曲线之间的误差最小。
* @param {*} points
* @param {*} threshold
* @returns
*/
const getPointBySimplify = (points, threshold) => {
return simplify(points, threshold);
function simplify(points, threshold) {
if (points.length <= 2) {
return points;
}
// 计算起点和终点距离
const dMax = findMaxDistance(points);
// 如果最大距离小于阈值,则直接连接起点和终点
if (dMax <= threshold) {
return [points[0], points[points.length - 1]];
}
// 找到最大距离对应的点
const index = findMaxDistanceIndex(points);
// 对左边和右边的点列表分别进行递归操作
const leftPoints = points.slice(0, index + 1);
const rightPoints = points.slice(index);
const leftSimplified = simplify(leftPoints, threshold);
const rightSimplified = simplify(rightPoints, threshold);
// 合并抽稀后的左右两部分,中间保留最大距离对应的点
return leftSimplified.slice(0, leftSimplified.length - 1)
.concat(rightSimplified);
}
function findMaxDistance(points) {
let dMax = 0;
for (let i = 1; i < points.length - 1; i++) {
const d = getPerpendicularDistance(points[i], points[0], points[points.length - 1]);
if (d > dMax) {
dMax = d;
}
}
return dMax;
}
function findMaxDistanceIndex(points) {
let dMax = 0;
let index = -1;
for (let i = 1; i < points.length - 1; i++) {
const d = getPerpendicularDistance(points[i], points[0], points[points.length - 1]);
if (d > dMax) {
dMax = d;
index = i;
}
}
return index;
}
function getPerpendicularDistance(point, start, end) {
const {
lng: x,
lat: y
} = point;
const {
lng: startX,
lat: startY
} = start;
const {
lng: endX,
lat: endY
} = end;
const A = x - startX;
const B = y - startY;
const C = endX - startX;
const D = endY - startY;
const dot = A * C + B * D;
const lenSquared = C * C + D * D;
let param = -1;
if (lenSquared !== 0) {
param = dot / lenSquared;
}
let xx, yy;
if (param < 0) {
xx = startX;
yy = startY;
} else if (param > 1) {
xx = endX;
yy = endY;
} else {
xx = startX + param * C;
yy = startY + param * D;
}
const dx = x - xx;
const dy = y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
}
export default {
getPointBySimplify
}