如题,基于Cesium,探索三维webgis的实现思路,个人总结,如有错误,欢迎指正
目录
目标概述:
成果预览:
数据和软件准备:
实现过程:
1、搭建三维场景页面
2、Cesium对三维要素的基本操作
3、加载三维建筑数据
3.1 准备3D tiles数据
3.1.1 方法一:其他三维数据转换
3.1.2 方法二:二维转三维(白模)
3.1.3 方法三:倾斜摄影数据
3.2 加载数据方法
4、模型的单体化显示
目标概述:
搭建一个web端的三维场景,无需第三方软件,在浏览器上查看仿真三维场景,包括地形,房屋建筑等,同时点击建筑能够展示建筑楼栋信息,细分到户的房屋信息。
成果预览:
分楼栋选取
分户选取
数据和软件准备:
软件:
1、geoserver:发布二维shp数据,提供wms接口,包括建筑底座轮廓数据,分户平面数据
2、 qgjs:shp数据处理,属性补充,坐标系转换
3、cesiumlab:cesium官方提供的数据转换软件,本次主要用于将二维shp数据转换为三维数据
数据:
倾斜摄影数据(3dtiles格式),建筑底座轮廓数据(shp格式),建筑平面分户数据(shp格式,包含层数和高度字段)
实现过程:
1、搭建三维场景页面
cesium,是目前web3d技术领域最流行的技术框架,市场占有率高,技术相对成熟,最重要的是开源免费。
首先,下载cesium框架,下载地址 csdn - 安全中心csdn - 安全中心csdn - 安全中心
在cesium官网注册账号,并申请一个自己的token
cesium官方文档中文 版地址---------Index - Cesium Documentation
cesium官方文档提供几千种种接口,类,方,看起来非常复杂,不过搭建基本的三维场景需要用到的也就那几个
参照官方文档,搭建一个三维地球的页面,也就是new一个Viewer,Viewer也是操作三维场景最常用的一个类,并根据需求设置初始化参数,选择是否屏蔽默认控件,等,这里,我没有用cesium的默认影像,把地球的影像设置为arcgjs提供的影像,arcgjs的影像更加清晰,现势性更好。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>新建地球</title> <script src="Build/Cesium/Cesium.js"></script> <link rel="stylesheet" href="Build/Cesium/Widgets/widgets.css"> <style> html,body{ height: 100%; margin: 0px; padding: 0px; } </style> </head> <body> <div id="cesiumContainer"></div> <script> Cesium.Ion.defaultAccessToken='你的密钥'; //配置自定义影像突出,以arcgis图层为例 const esri = new Cesium.ArcGisMapServerImageryProvider({ url: 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer', enablePickFeatures: false }); var viewer = new Cesium.Viewer('cesiumContainer',{ imageryProvider: esri,//显示自定义影像 animation: false, // 是否显示动画控件 baseLayerPicker: true, // 是否显示图层选择控件 vrButton: false, // 是否显示VR控件 geocoder: false, // 是否显示地名查找控件 timeline: false, // 是否显示时间线控件 sceneModePicker: false, // 是否显示投影方式控件 navigationHelpButton: false, // 是否显示帮助信息控件 navigationInstructionsInitiallyVisible: true, // 帮助按钮,初始化的时候是否展开 infoBox: true, // 是否显示点击要素之后显示的信息 fullscreenButton: true, // 是否显示全屏按钮 selectionIndicator: true, // 是否显示选中指示框 homeButton: false, // 是否显示返回主视角控件 scene3DOnly: true, // 如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源 terrainProvider: Cesium.createWorldTerrain({ // 光照阴影 requestVertexNormals: true, // 水流效果 requestWaterMask: true }), // 显示地形 }); //viewer.cesiumWidget. .style.display = "none"; 控制界面下方logo等信息 </script> </body>
打开页面,可以看到一个三维地球 ,第一个三维场景搭建完成
调整视角,可以查看全世界任何地方 ,并且由于开启了地形,能够展示非常真实的局部世界场景
喜马拉雅山的地形起伏
2、Cesium对三维要素的基本操作
Cesium提供了添加三维要素的方法,通过viewer.entities.add 方法在场景内能够构建三维要素,包括点,线,面,多面体,球体等,单个三维要素以entity实例的形式创建和添加,创建entity实例时声明实例的类型,实例的位置,包括经纬度,海拔高度,大小,颜色,透明度等基本属性,然后通过viewer.entities.add 方法,将创建好的实例添加到场景中。这是cesium操作三维场景要素的基本用法
以点要素为例,
同时, Cesium还支持加载第三方数据,支持包括shp,geojson,kml等常用的地理数据格式
3、加载三维建筑数据
基本场景搭建好了,我们的目的是在场景中立体的展示某地的建筑物,因此我们接下来要考虑两个问题,一是怎么准备好这个建筑物的三维数据,二这个数据要怎么添加到场景中。
3.1 准备3D tiles数据
3D tiles数据是 Cesium官方支持的三维模型数据格式, 3D tiles数据去去哪里弄呢,通过查阅资料,找到三种方法
3.1.1 方法一:其他三维数据转换
首先3D tiles数据支持与多种其他三维数据格式的转换,如3dmax数据,maya数据,点云数据等,但是这些数据我也是没有的,这个办法放弃;
3.1.2 方法二:二维转三维(白模)
将二维shp数据转换成三维数据,这个方法是最简单的,怎么转呢?Cesium官方提供了数据转换工具Cesiumlab ,原理就是将建筑物的轮廓平面,向上拉伸一个高度,形成立体模型,这个高度可以统一固定高度,也可以是shp属性本身包含的高度字段。操作如下。
1、首先,在网上可以下载全国各大城市的建筑轮廓的shp数据,如高德,百度,水经注等, 这个建筑轮廓的shp属性需要包含每栋建筑的高度
2、下载并安装Cesiumlab ,需要注册和登陆。(推荐用2.3.4版本,其他版本我试了好多转换的时候一直失败 ,具体原因没找到,不知道是不是软件bug)
3、打开软件,点击数据处理,选择通用模型处理,选择shp格式文件,找到准备好的建筑物轮廓shp数据,添加到任务中,并选择输出格式为“散列”
4、点击任务上面的选项按钮,在造型参数上面,设置转换三维模型的高度,可以设置固定高度值10米,这样我们转换出来的建筑物模型高度都是一样的。如果shp属性包含高度字段,也可以选择高度字段,这样生成的建筑模型高度就根据自身高度属性动态生成,或者如果建筑物属性里包含层数,也可以选择层数字段,然后乘以层高的参数。设置完成点击确定
5、选择输出路径,点击输出,即可完成数据转换,并可以对数据进行预览
6、叠加到cesium 场景中的效果,由于这种方式生成的三维数据相当于白模,没有材质,并且与地面的影像风格差异,看起来效果不真实,但也是实现加载三维建筑数据的一种方式。
3.1.3 方法三:倾斜摄影数据
倾斜摄影测量技术通常使用特殊设计的航空相机或无人机(UAV)搭载多个倾斜角度相机,同时采集多个角度的图像。这些图像可以在后续的处理过程中通过图像匹配、三维点云生成和建模软件来生成高精度的三维模型。
倾斜摄影数据一般是osgb格式,也可以通过cesiumlab进行格式转换,加载三维倾斜摄影数据,能够最大程度真实反应建筑物及其环境的真实材质纹理,效果最好,但是也存在缺点。这个后面再说。数据怎么获取呢,下载香港地区倾斜摄影数据地址:
Planning Department Hong Kong 3D Photo-realistic Model 規劃署 香港三維實景模型 规划署 香港三维实景模型
3.2 加载数据方法
cesium提供的3dtiles加载方法 viewer.scene.primitives.add
url:指向3dtiles的入口文件
4、模型的单体化显示
三维建筑数据加载完了,接下来要做的是,实现在场景中点击建筑模型时,模型高亮,并展示楼栋信息。也就是模型的单体化显示。
我们先来说说什么是“单体化”。“单体化”其实指的就是每一个我们想要单独管理的对象,是一个个单独的、可以被选中的实体(Entity);即用鼠标点击时可以显示为不同颜色(称为“高亮”)显示,可以附加属性,可以被查询统计等等。只有具备了“单体化”的能力,数据才可以被管理,而不仅仅是被用来查看。
在3.1.2中,我们通过给二维平面赋予高度的方法,将二维shp数据转换为3dtiles数据,这种办法生成的模型数据,每个模型都是独立的单体,并且每个模型都继承了shp的属性,如果要做单体高亮显示和信息展示就很简单。点击模型时可以直接获取模型上的属性数据,同时改变模型的颜色就可以了,这个很容易理解。
但是在3.1.3中,我们加载的是倾斜摄影的模型数据,倾斜摄影数据存在一个很大的缺点,因为它是将无人机通过倾斜摄影拍摄得到的很多张图片通过软件建模处理生成的三维模型,建模算法并不会把建筑、地面、树木等地物区分出来,因此构建出来的是一个连续的Tin网。也就是说整个场景的模型是一个整体,包括地面,植物,建筑,都相当于是一张皮连在一起的,不存在单体的概念,因此不能针对某一部分单独操作,也不存在单体的属性。因此这是我们要解决的主要问题。
查阅资料了解到,目前对于这种倾斜摄影模型单体化的问题,主要有三种解决思路
单体化方法 | 技术思路 | 预处理时间 | 模型效果 | 功能 | 小结 |
---|---|---|---|---|---|
切割单体化 | 预先物理切割把地物分离开 | 长 | 差,锯齿感明显 | 弱 | 非特殊情况不推荐使用 |
ID单体化 | 给对应地物的模型赋予相同ID | 一般 | 一般 | 一般 | 在不支持动态渲染的环境中使用 |
动态单体化 | 叠加矢量底图,动态渲染出地物单体化效果 | 无需 | 好,模型边缘和屏幕分辨率一致 | 强,所有GIS功能都能实现 | 推荐使用 |
目前主流的办法还是采用动态单体化的方式,这种方式的原理就是,在场景中,点击某一栋建筑的时候,围绕着这栋建筑生成一个实体,并为这个实体设置高亮的颜色和一定的透明度,然后将它覆盖在这栋建筑上。类似于一个保鲜膜从上到下完整的把对应建筑等物体的模型包裹起来,从而实现可被单独选中的效果。这种解决办法虽然并不是真正的单体化,但是与单体化看起来的效果是一样的,由于不受三维模型本身的限制,功能的可扩展性也很强。具体实现步骤如下:
1、将二维的建筑轮廓shp数据,在geoserver中进行发布,提供一个查询建筑数据的wms接口,接口返回内容包括shp图形的坐标点,shp图形的属性信息。
2、在场景页面添加点击事件,点击模型时,获取点击位置的坐标经纬度,以经纬度作为查询条件,调用上面发布的wms接口,查询当前位置的建筑物底座轮廓的坐标和建筑属性,拿到建筑物底座轮廓以及属性中的建筑物高度,就具备生成一个柱体的条件,这个柱体的位置,高度,与场景中点击的模型完全一样,将这个柱体设置好需要的颜色和透明度,覆盖在场景中,就完成了倾斜摄影场景中楼栋模型的高亮显示。同时,也可以将获取到的建筑物属性信息,展示在信息面板中。
3、关于分户单体化显示,基本逻辑与楼栋的单体化显示一样,不同的是,分户单体化需要有分户平面图作为获取轮廓的数据支持,另外分户图属性上需要有每一层的地面高度和屋顶高度(或者是层高和层数)。 这样场景中点击某一户时,可根据点击位置的经纬度和海拔,锁定到哪一户,根据这户的位置和高度,在场景中生成柱体,覆盖在模型的对应位置,即完成了精确到户的单体化显示。
参考文档:
扫荡倾斜摄影单体化难题_IT冰是睡着的水的博客-CSDN博客
纯代码方式实现cesium倾斜摄影单体化和楼栋分层_cesium 单体化_敲代码的小江江的博客-CSDN博客
cesium自定义的弹窗 Popup弹窗(可随球放大缩小,移动)_cesium popup_GIS-CL的博客-CSDN博客
CesiumLab V1.4 分类3dtiles生成(倾斜单体化、楼层房间交互)_Cesium实验室的博客-CSDN博客
https://www.cnblogs.com/onsummer/p/12082584.html
cesium 3dtiles模型单体化点击高亮效果_GIS之家的博客-CSDN博客文章来源:https://www.toymoban.com/news/detail-754521.html
cesium加载倾斜摄影模型_cesium 倾斜摄影_devil-J的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-754521.html
到了这里,关于基于Cesium,探索实景三维webgis的实现过程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!