公司有个需求须要实时绘制扫地机的清洁路径,可是上报的点几千个后,svg绘制就会很卡,决定使用抽稀算法减小些定位点,优化性能。算法
util.js数组
// 计算两点间距离 export const calculationDistance = (point1, point2) => { const x1 = point1.x; const y1 = point1.y; const x2 = point2.x; const y2 = point2.y; const xy = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); return xy; }; // 计算点pX到点pA和pB所肯定的直线的距离 export const distToSegment = (start, end, center) => { const a = Math.abs(calculationDistance(start, end)); const b = Math.abs(calculationDistance(start, center)); const c = Math.abs(calculationDistance(end, center)); const p = (a + b + c) / 2.0; const s = Math.sqrt(Math.abs(p * (p - a) * (p - b) * (p - c))); return s * 2.0 / a; }; // 递归方式压缩轨迹 export const compressLine = (coordinate, result, start, end, dMax) => { if (start < end) { let maxDist = 0; let currentIndex = 0; const startPoint = coordinate[start]; const endPoint = coordinate[end]; for (let i = start + 1; i < end; i++) { const currentDist = distToSegment(startPoint, endPoint, coordinate[i]); if (currentDist > maxDist) { maxDist = currentDist; currentIndex = i; } } if (maxDist >= dMax) { // 将当前点加入到过滤数组中 // console.warn(maxDist); result.push(coordinate[currentIndex]); // 将原来的线段以当前点为中心拆成两段,分别进行递归处理 compressLine(coordinate, result, start, currentIndex, dMax); compressLine(coordinate, result, currentIndex, end, dMax); } } return result; }; export const douglasPeucker = (coordinate, dMax = 10) => { if (!coordinate || !(coordinate.length > 2)) { return null; } coordinate.forEach((item, index) => { item.id = index; }); const result = compressLine(coordinate, [], 0, coordinate.length - 1, dMax); result.push(coordinate[0]); result.push(coordinate[coordinate.length - 1]); const resultLatLng = result.sort((a, b) => { if (a.id < b.id) { return -1; } else if (a.id > b.id) return 1; return 0; }); resultLatLng.forEach((item) => { item.id = undefined; }); return resultLatLng; };
datas= douglasPeucker(newData,10);
优化前svg
优化后性能