老规矩:直接放效果图,符合就往下看,不符合出门右转。
第一步创建障碍物区域(火场)
如图所示,红色区域为火场区域。路径算用用的是@turf/turf最短路径算法,原有算法是最短路径算法,所以规划的路线离障碍物比较的近,由于业务需求障碍物是火场,所以得保持一定的安全距离绕行。需要缓冲区(蓝色区域)。
缓冲区
参考的 @turf/turf缓冲区算法,可以设置缓冲区距离。
//缓冲区宽度
const BUFFER_WIDTH = 35
const area = polygon([
[
[116.16408088, 40.2609315916],
[116.1658748784, 40.2609680945],
[116.1660412621, 40.2622909901],
[116.1647571874, 40.2627837188],
[116.1632636937, 40.2623205249],
[116.16408088, 40.2609315916],
]
])
const newArea = buffer(area, BUFFER_WIDTH , { units: "metres" })
规划路径
提供起始点、终点,以及配置相关的参数。
const options = {
obstacles:
geometry("Polygon", [
newArea?.geometry.coordinates[0]
]),
resolution: 200,
units: 'metres'
};
const startPoint = point([116.1651967246, 40.2606423497])
const endPoint = point([ 116.1634496569, 40.2625630188])
shortestPath(startPoint, endPoint , options);
最短路径
会有很多的小折线,非常不美观。
去除小折线
//噪点大小
const hotPixelSize = 2
//去掉规划路径中的噪点
REMOVE_HOT_PIXEL(path: any) {
let activePoint: number[], indexs: number[] = []
path.geometry.coordinates.forEach((i: any, j: number) => {
if (activePoint) {
const p1 = point([activePoint[0], activePoint[1]])
const p2 = point([i[0], i[1]])
const d = distance(p1, p2, option)
if (d < hotPixelSize) {
indexs.push(j)
}
}
activePoint = i
})
path.geometry.coordinates = path.geometry.coordinates.filter((i:any, j:number) => !indexs.some(k => k === j))
return path
}
最终的效果
找到小折线规律,距离都很短,所以计算前后两点的距离,取一个阈值,去掉这个阈值内的所有点。
黄色的线为优化后的结果