对 gps 经纬度点进行抽稀算法处理,不影响整体路线的精度

该算法基于Douglas-Peucker算法,通过对点集计算点密度(每个点周围一定范围内点的数量),并设定阈值来决定是否保留点。当最大距离小于阈值时,直接连接起点和终点。递归地对点集左右两部分进行处理,以减少不必要的点,保持简化后曲线与原始曲线的误差最小。
摘要由CSDN通过智能技术生成

处理前

 

处理后

 

 

 

直接上代码

注意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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值