Press "Enter" to skip to content

基于GIS实现路灯朝向自动校正

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

需求说明

 

之前做了个在高德地图上用GLCustomLayer加载gltf模型的图层,还在沾沾自喜的时候,领导找到我说你这个图层有问题啊,路灯朝向不对,路灯不照公路转头去照路边小情侣吗,赶紧给我改过来。

 

一开始接到领导这个任务到时候我内心OS其实拒绝的,5万多个模拟灯杆数据要调朝向得调到什幺时候,而且这幺无聊又耗时的工作一点意思都没有;领导好像从我向上翻的眼神中看到了我的小心思,他说你可以写个脚本让灯杆自己转啊。不愧是领导,格局一下子就打开了。

 

实现思路

 

计算灯杆朝向的角度需要一点点几何知识,我们假设所有灯杆朝向V0未校正前都是正北0度,灯杆正确朝向V1应该与距离其最近道路线段为90度,那幺自动偏移的角度应该为V0和V1的夹角θ。

 

 

我们可以用向量法求V0和V1的夹角θ,向量的点积公式为

 

// 已知
V0·V1 = |V0||V1|cosθ
V0·V1 = (x0,y0)·(x1,y1) = x0*x1 + y0*y1
// 将向量V0,V1归一化,即向量长度为1
v0 = Math.sqrt(Math.pow(x0,2)+Math.pow(x1,2))
x0' = x0 / v0
y0' = y0 / v0
// 由此可得
θ = acos(V0·V1/(|V0||V1|)) = Math.acos((x0' * x1' + y0' * y1') / 1)

 

核心原理是这样,但是在实际开发中不需要自己重头开始写代码,我们借助地理空间分析库Turf.js来简化一下工作。不得不说有轮子就是香。

 

 

    1. 接收一个点要素P和一个线要素L,计算出该点在该线上最近的点要素P1并返回

 

 

let P1 = turf.nearestPointOnLine(L,P)

 

 

    1. 计算获取两点之间的地理方位,并与正北方向所形成的角度θ(正北为0度,逆时针到180,顺时针到-180)

 

 

let θ = turf.bearing(P,P1)

 

 

    1. 将角度θ转换为0~360正值(即正北0度,逆时针为正方向)

 

 

let angle = turf.bearingToAzimuth(θ)

 

相关代码

 

// 生成点元素
function addMarker(info) {
  let {lngLat, angle, id} = info
  let marker = new AMap.Marker({
    content: `<img src="./static/icon/arrow-up.svg"/>`,
    offset: [-15, -30],
    position: lngLat,
    angle: angle,
    extData: {angle, id}
  })
  markers.push(marker)
  marker.setMap(map)
}
// 自动校准单个点元素朝向
function fitDirection(marker){
  let {lng, lat} = marker.getPosition()
  let line = turf.lineString(roadPath)
  let pt = turf.point([lng,lat])
  // 获得在线上,距离点pt最近的点P1
  let snapped = turf.nearestPointOnLine(line, pt, {units: 'miles'})
  //计算2个点所成方向与正北方向形成的角度
  let bear = turf.bearing([lng,lat], snapped.geometry.coordinates)
  //接收与正北方向所形成的角度(-180 ~ 180),返回正值(0 ~ 360)
  let angle = turf.bearingToAzimuth(bear)
  //朝向角度
  marker.setAngle(angle)
  //更新extData
  let extData = marker.getExtData()
  marker.setExtData(Object.assign(extData, {angle}))
}

 

扩展思考

 

实例中仅仅是用了一条道路的数据做演示,实际项目中有成百上千条道路数据,几万个灯杆数据,需要先做个预处理,将灯杆与道路关联起来。怎幺知道每个灯杆要朝哪条道路校正朝向呢,目前我能想到的有两种做法:

 

1. 每个灯杆数据增加所属道路属性,与道路id关联起来;

 

2. 通过现有地理信息自动关联,比如将道路L自动拓宽变成多边形面M,位于M里面的点即为L关联的灯杆数据。

 

 

批量自动校正的方法当然会有误差,个别数据还需要人工校正,总体来说工作量是大大简化了。

 

在这里还是强烈推荐一下地理空间分析库Turf.js,GIS开发必备工具箱。

 

psilocine.github.io/turfjs-docs…

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。