const DouglasPeucker = { getProcessPoints: function (points, tolerance) { /// 获取处理后的点 /// 包含点的数组 /// 取样临界值 /// if (!Array.isArray(points) || !points.length) { //当points不是数组或没有值时,直接返回一个空数组 return []; } if (points.length < 3) return points; //小于3个点时不抽稀,因为1个或2个点无法进行抽稀 let firstPoint = 0, lastPoint = points.length - 1; //取开始点与结束点的下标 let pointIndexsToKeep = []; //保存需要点下标的数组 pointIndexsToKeep.push(firstPoint); pointIndexsToKeep.push(lastPoint); //开始与结束不进行处理,直接保留 while (points[firstPoint] == points[lastPoint]) { //处理闭合情况,闭合时,强制断开 lastPoint--; } this.reduce(points, firstPoint, lastPoint, tolerance, pointIndexsToKeep); //抽稀 let resultPoints = []; //返回的点数组 pointIndexsToKeep.sort(function (a, b) { //排序,这个可排可不排 return a - b; }); for (let i = 0; i < pointIndexsToKeep.length; i++) { resultPoints.push(points[pointIndexsToKeep[i]]); } return resultPoints; }, reduce: function (points, firstPoint, lastPoint, tolerance, pointIndexsToKeep) { /// 抽稀处理 /// 待抽稀的数组 /// 起点 /// 终点 /// 取样临界值 /// 保留点下标的数组 let maxDis = 0, idxFarthest = 0; //定义最大长度及最远点的下标 for (let i = firstPoint, dis; i < lastPoint; i++) { dis = this.perpendicularDistance(points[firstPoint], points[lastPoint], points[i]); //获取当前点到起点与 if (dis > maxDis) { //保存最远距离 maxDis = dis; idxFarthest = i; } } if (maxDis > tolerance && idxFarthest != 0) { //如果最远距离大于临界值 pointIndexsToKeep.push(idxFarthest); this.reduce(points, firstPoint, idxFarthest, tolerance, pointIndexsToKeep); this.reduce(points, idxFarthest, lastPoint, tolerance, pointIndexsToKeep); } }, perpendicularDistance: function (beginPoint, endPoint, comparePoint) { /// 计算给出的comparePoint到beginPoint与endPoint组成的直线的垂直距离 /// 起始点 /// 结束点 /// 比较点 /// //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle //Base = v((x1-x2)2+(y1-y2)2) *Base of Triangle* //Area = .5*Base*H *Solve for height //Height = Area/.5/Base let area = Math.abs(0.5 * (beginPoint.x * endPoint.y + endPoint.x * comparePoint.y + comparePoint.x * beginPoint.y - endPoint.x * beginPoint.y - comparePoint.x * endPoint.y - beginPoint.x * comparePoint.y)); let bottom = Math.sqrt(Math.pow(beginPoint.x - endPoint.x, 2) + Math.pow(beginPoint.y - endPoint.y, 2)); let height = area / bottom * 2; return height; } }; export default DouglasPeucker;