郑禄喜 罗立宏
关键词:三维地图;定位;实时导航;Web平台;Cesium
0 引言
随着经济的不断发展,高楼大厦拔地而起,道路桥梁不断增加,因此城市的面貌日新月异。现在人们来到一座陌生的城市,不再像以前那样记住显眼的标志,摸索着走几段路就能到达目的地。通常都有着目的地就在附近的想法,但怎么都到达不了目的地,询问当地居民才得知正确的路线。因现今的道路越发复杂,所以电子地图成为出行必备的应用。但对于一些方向感较弱的人来说,当前的电子地图应用给予的地理位置信息还不是很直观,他们仍然会发生到达不了目的地的可能性。
三维可视化技术能够给人们带来强烈的视觉感受,即相比于平面地图和哥伦布地图,三维地图能够提供更为直观的地理位置信息。国内外对于三维地图领域相关的研究力度很大,黄娟娟等[1]在Unity3D上实现景区的可视化,然后利用改进隐性马尔科夫模型的地图匹配算法解决了三维地图定位精度低的问题;田风勋[2]基于现有的PF等数字摄影测量系统生产平台,利用3DMax等建模工具,通过C#语言辅以SkyLine开发包开发实景三维地图;王亚美[3]、孙伟[4]各自的团队都利用OpenGL ES在Android平台上实现了三维地图的可视化系统;문성태等[5]提出使用Kinect等深度相机生成三维地图以及利用相机拍摄的2D图像在三维地图中进行位姿跟踪,解决了室内无法接收GPS信号定位当前位置生成三维地图的问题;Hildebrandt等[6]提出了面向服务的、交互式的大规模3D城市模型三维可视化系统架构,该架构为大规模3D城市模型的安全、稳健分布和交互式呈现提供了一种解决方案。
上述研究都通过不同的方法完成了三维地图的构建,但都需要安装相应的插件或软件进行开发,难以实现跨平台使用,并且研发产品可能在不同的平台会不兼容。若基于Web平台开发三维地图,就能实现跨平台的效果。由于以前各种条件的限制,在Web上渲染的3D图形和三维交互的效果都不如在PC和嵌入式设备上的效果,所以很少基于Web平台开发三维应用。但3D绘图标准WebGL的出现,加上浏览器的性能越来越强,如今网页上也能够绘制和渲染复杂、精美的3D图形。WebGL技术标准不需要安装插件,只用一个文本编辑器和支持WebGL的浏览器就可以开发具有复杂3D图形的网站或3D网页游戏。因此,多种基于JavaScript 封装WebGL API 的3D 引擎逐渐出现,如Babylon.js、Three.js和Cesium.js等,而Cesium.js很适合作为在三维地形、仿真和GIS等领域进行可视化的图形库,如袁凌等[7]将地形数据切片,利用Cesium加载地形、谷歌影像和风力发电机模型等要素构建三维场景,实现了风电场地形的三维可视化,能够辅助风电场的建设和风机运行状态监测;苏昊翔等[8]在Cesium平台上开发了卫星载荷可视化的仿真系统,该系统解决了跨平台使用,无须使用特定软件进行展示的问题,有利于仿真结果的可视化共享;GRAEME F.CLARK等[9]使用CesiumJS结合大数据开发一款基于Web的澳大利亚海洋碎片数据库可视化工具,给专业和民间科学家提供多种方式探索海洋数据;Kilsedar,CE 等[10]利用CityGML和CesiumJS进行三维地理空间数据可视化并模拟洪水发生的过程,达到帮助有关适应措施和减轻洪水影响的知情决策过程的目的;毕硕本等[11]在模拟洪水灾害过程的基础上,还将热带气旋路径、所致损失等其他灾害信息整合于Cesium的三维地球中。因此,本文通过Cesium.js结合高德地图的Web服务API实现Web平台的三维地图实时导航服务。
1 Cesium 简介
Cesium是用于创建强大的3D地理空间应用程序的基础开放平台,也是一款开源的基于JavaScript的3D 地图框架。Cesium 开发平台上有着Cesium Ion、ICoens是ium一JS个、C提e供siu3mDfoTrileUsn和rea地l三理空个间主数要据平的台平。台C,e它siu有m3D Tiles流式传输的最快的管道,可以把3D数据上传到Cesium Ion中,在使用CesiumJS开发时可以通过申请的access token 直接访问Cesium Ion 中的数据源;CesiumJS是一个开放源代码JavaScript 库,用于创建具有最佳性能、精度、视觉质量和易用性的3D地球和地图;Cesium for Unreal是游戏引擎中的第一个高精度地球仪,将Cesium的真实世界的细节和准确性带入了模拟环境。
CesiumJS是一个三维可视化引擎,底层核心基于WebGL技术构建,以WebGL技术作为其图形渲染引擎,所以可以在支持WebGL的浏览器上运行,包括手机、平板、电脑的浏览器,所以它具有跨平台的特点[12]。它有可精确分析的高精度WGS84地球仪,并提供了与地理空间坐标相关的计算功能;支持绘制几何图形;能够加载KML、GeoJSON、CZML和terrain等多种类型的空间数据文件;支持3D Tiles、glTF模型、时间动态数据;可自由切换2D、2.5D、3D视图模式。
一个完整的Cesium应用程序由五层组成,自下而上分别是核心层(Core) 、渲染器层(Renderer) 、场景层(Scene) 、数据源层(DataSources) 、部件层(Widgets) 。核心层主要是数学运算类,例如笛卡尔坐标运算、地理坐标运算和四元数运算等;渲染器层是WebGL的高级抽象和GLSL库;场景层囊括了地形和影像引擎、三维模型、几何图形、矢量数据和摄像机等对象;数据源层是一个高级Entity API,封装了场景类型和时间动態属性;部件层是场景中的一些小部件,如动画、视图模式切换、全屏等控件。
2 关键技术
2.1 WGS84坐标与笛卡尔坐标的转换
Cesium项目中经常涉及坐标转换,如加载模型时的初始位置、模型或实体的空间位置变换等,在执行这些操作时,位置信息几乎都是输入经纬度坐标,但Cesium最终都会把坐标转换为笛卡尔坐标来表达空间位置信息。Cesium中有两种坐标系,分别是WGS84 坐标系(以下简称为84坐标)和墨卡托投影坐标系。本文使用的是84坐标,但Cesium中没有84坐标相对应的类,所以用弧度表示经纬度,可以通过式(1)求得经纬度的弧度形式,R 表示弧度,D 表示经纬度角度。
84坐标转换为笛卡尔坐标[13]:已知84坐标中椭球中 的 长 半 轴 a = 6378137.0、短 半 轴 b = 6356752.3142451793、纬度B、经度L、海拔H。根据式(2)求得笛卡尔坐标(X,Y,Z),式(2)中e1为椭球的第一偏心率,N 为椭圆曲率半径,它们分别可根据式(3)求得:
笛卡尔坐标转换为84坐标:将式(2)进行反向推导,可得到式(4),通过式(5)可将笛卡尔坐标转换为84 坐标,但求得的84坐标是弧度形式,可通过式(2)推导出转换为经纬度形式的式(5)。
2.2 偏移路线检测
在导航过程中,判断当前位置是否偏离了规划的路线是很重要的,若偏离了路线,则需要重新根据当前位置作为起点重新规划路线。本文采用了点是否在多边形内作为判断当前位置是否偏离路线的方法,点在多边形外则表示偏离了路线。当前位置以点表示,构成该点是当前位置的经纬度坐标,规划的路线是以曲线表示,构成该曲线是该路线的经纬度坐标集合。以曲线为中心,计算一个半径为2 m的缓冲区作为多边形,该多边形是由点集P={(xi,y≤ i) | 1≤i≤n, n≥3}构成。当2 i≤n-1时,Pi分别与相邻的两个点Pi-1、Pi+1相互连接构成一条折线,最后P1与Pn连接形成闭合而构成一个多边形。判断点P0(x0, y0)是否在多边形内的过程如下:
1) 判断点P0是否在多边形的边界框bbox内。计算点集P 中x、y 的最值Xmin、Xmax、Ymin、Ymax,从这些最值中可组合成四个点,分别是点A(Xmin,Ymax)、B(Xmax,Y( max)、C Xmax,Ymin)、D(Xmin,Ymin)、这四个点可构成一个边界框bbox (图1 a),然后判断点P0 是否在bbox里面,即Xmin≤x0≤ Xmax 且Ymin≤y0≤Ymax。若不在bbox范围内,表示点P0在多边形外,否则跳到步骤2)。
2) 利用射线法判断点P0与多边形的关系。从任意一点绘制一条到达点P0的直线(图1 b),统计该条直线与多边形相交的边数k,通过式(6)计算出k 的奇偶性,点P0与多边形的关系可用式(7)表示[14]。因为有一种点P0刚好就在多边形的边上,但k 为偶数的特殊情况,所以当k 为偶数时,还需要判断点P0是否落在多边形的边上,跳到步骤3)。
3) 利用叉积法判断点P0与多边形的边的关系。多边形的边集是它的点集中相邻两点和首尾两点连接而构成的边,只要点P0在边集上任一条边上,则点P0就是在多边形的边上。可用叉积判断点P0与边P1P2的关系,边P1 P2是由点P1(x1, y1)和点P2(x2, y2)连接而成,通过式(8)可求得点P0与边P1 P2的叉积Pc,若Pc = 0,则点P0与边P1 P2共线[15]。
2.3 相机模式
2.3.1 相机跟随
在三维地图的实时导航中,场景中的相机需要一直跟随表示当前位置的标志,所以需要实现相机跟随的效果。Cesium中有很多函数可以改变相机的位置,但这些函数要么只能改变相机的视角,没有平滑的跟随效果,要么只有跟随效果,相机的视角却是固定的,所以需要将两者结合起来,实现相机的视角始终跟随在目标的后面。
Viewer中有一个trackedEntity的属性,一旦给该属性赋值,相机将一直跟随该属性中的目标,它的实现原理是通过式(10)计算出相机的新位置T,其中C 表示被跟随目标的当前位置,D 表示相机的偏移量。
虽然trackedEntity解决了相机平滑的跟随,但带来了相机视角固定在一个方向的问题,即相机视角不会随着跟随目标的方向变化而变化,所以需要在这的基础上,使相机的方向随着跟随目标的方向变化而变化。实现方法如下:一旦跟随目标的位置发生改变,就通过式(11)、式(12)计算目标之前的位置点P(L1, B1) 和当前位置点Q(L2, B2)的方位角A(点P、Q 坐标中的L、B 分别表示经度、纬度),然后利用式(5)把方位角A 转换成角度形式,最后对方位角A 取模360求得最终的方位角A,其中点P、Q的经纬度是以弧度来表示[16],一旦方位角A>5,就使相机绕Z轴旋转A 度。
2.3.2 第一人称视角
相机模式设为第一人称视角,相当于把相机当成人的眼睛,即相机的朝向能够和人的视线一样变换,通过监听DeviceOrientationEvent事件获取设备的物理旋转信息作为相机朝向改变的数据源实现和人的视线一样变换。它的事件属性有α、β、γ 三个属性,分别表示设备绕Z、X、Y轴旋转的角度,利用α 表示视线左右摇摆,β 表示上下摇摆。实现第一人称视角的功能只需α、β 两个属性,当设备指向正北时α=0,设备逆时针旋转,则α 值增加,α 的范围为[0,360];当设备水平摆放时β=0,设备顶部向上方倾斜则β 值增加,β 的范围为[-180,180]。
通过α 控制相机左右两侧的朝向和导航标志模型的朝向,β 控制相机上下两方的朝向。基于用户手持设备的习惯,相机上下两方的朝向需要做一定的限制,即β=0时,相机朝向为地面;β=45时,相机朝向为水平方向;β=90時,相机朝向为天空。假设相机上下旋转角度A'的最佳配置为:A'=-90表示地面;A'=0表示水平方向;A'=30表示天空,通过式(13)可获得最终的旋转角度A'。
3 功能实现
3.1 开发前的准备
把项目中需要加载的资源上传到Cesium Ion中(需要在Cesium官网中注册账号并申请一个Access Token) ,如3D Tiles、模型和图片等资源,并获得资源的accessId;还需要在高德开放平台注册为开发者并创建一个Web服务应用,得到该应用的Key。
3.2 搭建Cesium 场景
3.3 路径规划
在页面中添加关于路径规划功能的控件,如起点、终点的输入框、右键菜单、规划路线的信息显示框等控件,并根据情况控制它们的显示和隐藏,这些前提准备完成之后,就可以进行路径规划功能的实现,该功能的流程图如图2所示。
1) 获取起点和终点的经纬度。获取经纬度的方式有两种,一是在起点、终点输入框中输入地址,利用高德的地理编码服务将该地址转化为经纬度;二是单击鼠标右键弹出菜单,点击菜单中的起点、终点来标记起点和终点,通过右键点击的屏幕坐标转化为笛卡尔坐标,再将笛卡尔坐标转化为经纬度,最后需要将84坐标系的经纬度转化为高德地图坐标系的经纬度,Cesium 中的viewer.camera.pickEllipsoid()函数可将屏幕坐标转化为笛卡尔坐标。
2) 路径规划。通过ajax请求高德的路径规划服务接口,如驾车路径规划请求的url:https://restapi.amap.com/v3/direction/driving?origin=longo,lato&destination=longd,latd&key=keyString。url中的参数origin、destination分別是起点和终点的经纬度(longo, lato) , (longd, latd),keyString是用户申请的Web服务应用key,这些参数是必填项。除了驾车路径的接口外,还有公交路径规划和步行路径规划的接口,它们的url分别是: tegrat①ed?hptatpras:m//eretestrasp;i. amap. com/v3/direction/transit/in⁃②https://restapi.amap.com/v3/direction/walking?pa⁃rameters。parameters表示请求中的参数,根据控件中选择查询的方式分别向这些url发起请求。
3) 封装信息。把返回的json数据中的必要信息封装到一个对象中,如路线的起点和终点经纬度、路线的详细信息、路线的经纬度数据等。路线的经纬度数据的值在结果中多个经纬度拼接成的字符串,需要对其进行分割用数组储存,而且结果中的经纬度用于84坐标会有一定的偏差,需要对其转化为84坐标下的经纬度。
4) 绘制路线。把路线的经纬度数据作为数据源,利用GroundPrimitive类来绘制紧贴地形的线段,即路线,并且通过路线的数据创建一个SampledPosition⁃ tPrraocpkeErtnyti的ty使实相例机赋沿值着到该一条个路实线体进上行,漫即游可。通过viewer.
路径规划功能的效果如图3所示。
3.4 实时导航
在实时导航的过程中,需要获得用户的当前的经纬度位置,并需要持续返回用户移动时更新的经纬度位置,根据获得的经纬度位置来更新导航标志模型的位置和检测当前是否偏离了规划的路线。若偏离了路线,则需要根据当前位置重新规划路线。一旦自行结束导航或抵达目的地则导航结束。该功能的流程图如图4所示。
1)Positin获事取件当能前够位持置续。获H得5地用理户定移位动功时能的中位的置w,这atc一h⁃特性恰好符合持续获得用户位置的需求,所以需要监听该事件获得导航过程中用户的当前位置,而该事件的位置信息是以经纬度坐标形式返回,所以可通过式(1)、式(2)把经纬度坐标转换为笛卡尔坐标,然后把该笛卡尔坐标设为导航标志模型的新位置。
2) 检测是否偏离路线。在绘制路径的同时,也会绘制一个路径的缓冲区。该缓冲区是以路径为中心绘制半径2m的多边形,如图5中的线段表示路径,椭圆部分表示路径的缓冲区。在获得新位置坐标后,需要检测新坐标是否在该缓冲区的bbox范围内,若在bbox区域外,则表示当前已经偏离了路线;若在bbox 区域内,则需要通过射线法检测该坐标是否在缓冲区内,若在缓冲区外,则表示当前已经偏离了路线。
3) 偏离路线。若当前位置偏离了路线,则需要以当前位置为起点重新规划路线。在重新规划路径前需要清空之前路径的相关信息,包括路径途径点、导航信息和路径缓冲区等信息。
4 结束语
本文通过结合Cesium与高德Web服务API实现了Web平台的三维地图实时导航服务、路径规划、路径漫游等基础功能,研究了经纬度坐标与笛卡尔坐标转换、点线面的关系、相机模式等关键技术,达到了在不同的操作系统下都可以通过浏览器访问三维地图的效果,完成了跨平台需求。本次研究中的城市模型是白模,这方面有极大的优化空间,接下来将尝试使用倾斜摄影技术构建一个更为真实的城市模型。三维地图实时导航在交通出行、城市规划、景区、高校、商业圈等区域的导航和宣传等领域都有一定的应用价值。