目标
使用java搭建的后端,cesium.js已有的接口来实现视域分析,最起码要实现Arcgis Pro的功能,在其基础上最好可以实现进一步的灵活计算空间体积等其他功能。
启动项目
把前后端框架搭建好,启动服务。
搭建spring boot框架
参考网址:https://blog.csdn.net/bsegebr/article/details/126081107
- 新建项目,选择文件夹,项目名称,生成器等等
- 选择Spring Boot的版本,以及所需依赖项(也可以后面在项目中用到什么加什么)
测试启动
- 在application.properties配置启动端口
server.port=8088
2. 右击com.example.cesiumviewability编写一个控制类controller,注意它的命名规范
3.在新建的软件包下,新建一个“Hello World”软件类,进行编写
4. 编写pom依赖项(第一次的时候可能需要右击“maven”重新加载项目)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
cesium服务
前端的服务可以在static文件下自己建一个网页内完成,这样一启动8088服务,即可访问index.html。
cesium的js和css都使用在线服务。当然,后面也可以引用本地的cesium的js和css文件。
第二种方法是将网页写在“templates文件夹下,在”HelloWorld.java“文件中去编写访问它。
准备好研究区域
- 删除不必要的控件
var viewer = new Cesium.Viewer('cesiumContainer',{
animation:false, //左下角的动画仪表盘
baseLayerPicker:true, //右上角的图层选择按钮
geocoder:false, //搜索框
homeButton:false, //home按钮
sceneModePicker:false, //模式切换按钮
timeline:false, //底部的时间轴
navigationHelpButton:false, //右上角的帮助按钮,
fullscreenButton:false //右下角的全屏按钮
});
viewer._cesiumWidget._creditContainer.style.display="none"; //删除版权信
息
- 设置好高度,聚焦河海大学江宁校区
//聚焦河海校区,设置高度
let initialPosition = new Cesium.Cartesian3.fromDegrees(118.781,
31.916, 3000);
let homeCameraView = {
destination: initialPosition,
};
viewer.scene.camera.setView(homeCameraView);
3. 更换默认图层为OSM
//修改默认图层为OSM
viewer.baseLayerPicker.viewModel.selectedImagery=viewer.baseLayerPic
ker.viewModel.imageryProviderViewModels[9];
赋予地形并建模
赋予地形
这个也不知道正不正确,尝试按着步骤去做。参考网址:https://blog.csdn.net/weixin_35782148/article/details/112119825
地形裁剪
具体这个步骤参考大二的“面向实际地理问题的空间建模”的第一次实验报告。
这里注意一点,以往地理配准起码要三点,但因为一些原因,点选多了反而使得影像数据变形。打开“自动校正” 然后选取两个点(距离远一点)效果最好。
数据转换
将裁剪好的dem数据转换为cesium可以处理的terrain数据。参考文章:
- https://www.jianshu.com/p/01304a961266
- https://zhuanlan.zhihu.com/p/40913210
转换的结果:
地形数据发布
访问地形数据需要访问服务器数据,一种是在线数据,一种是本地数据发布到本地地址上。前者的在线
数据似乎已失效,而且无法定制。故选择第二种方法。据说QGIS也可以完成切片,可以之后尝试一下。
参考网址:
- Cesium本地地形制作与发布
- tomcat发布应用资源
- 深夜总结:使用QGIS切片并用Cesium完成调用
- 先把文件放到tomact的webapps文件夹下,并命名为“HHUTerrain”
- 打开bin文件夹,点击startup.bat启动服务
- 这边有个大坑
- 切片数据通过Tomact发布,是在8080端口。同时,Cesium项目占用了8088端口。8088去访问8080的必然涉及到跨域问题。最简单的是加入“@CrossOrigin”。但是在第一次尝试中,这个方法 失败了。
@CrossOrigin
@SpringBootApplication(scanBasePackages="com.example.cesiumviewability")
@Controller
public class HelloWorld {
@RequestMapping("/Cesium")
public String helloWorld(){
return "Cesium";
}
}
第二种办法是从Tomact 下手,修改其web.xml文件等。
参考这篇博客“Tomcat发布瓦片TMS数据,Cesium加载显示:还是跨域处理”
坑在于,重启服务后,依旧未见效,网页控制台报错“跨域问题”,但其实问题已经解决了。重启电脑即可(不仅仅是重启服务)。
问题的关键可能是需要在“任务管理器”中把Tomact的后台进程(服务)完全关闭。仅仅退出再进入并没有真正的重启Tomact服务。
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filterclass>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Accept, Origin, X-Requested-With, Content-Type,
Last-Modified</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
渲染结果
重启服务后,可以看到地图已经有了起伏,例如牛首山出,是确实有高度的。并且道路有一定的变形
其他
上述的所有成果都是在Google浏览器运行的,如果换个浏览器(例如Edge 或者 360) 网页控制台会无端报错“Cesium.Ion.defaultAccessToken”未被定义。解决办法是 把在线的Cesium资源转换为本地。并且本地的资源也可以对冲 在线资源崩溃的风险。
<script src="../Build/Cesium/Cesium.js"></script>
<link href="../Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- <script src="http://localhost:8080/Build/Cesium/Cesium.js"></script>-
->
<!-- <link href="http://localhost:8080/Build/Cesium/Widgets/widgets.css"
rel="stylesheet">-->
<!--在线资源-->
<!-- <script
src="https://cesiumjs.org/releases/1.54/Build/Cesium/Cesium.js"></script>-->
<!-- <link
href="https://cesiumjs.org/releases/1.54/Build/Cesium/Widgets/widgets.css" r
修改完成后 会接着引发另一个错误,就是本地的cesium.js访问在线服务器的时候会出错(404),有一个不停请求而无法获得的endpoint请求。其中一个解决办法是不引用Cesium的在线底图服务。引用其他服务商的(例如ArcGIS)或者自己本地做瓦片地图。
- vue+cesium离线地图关网报错不加载底图:
- Cesium避免endPoint请求
- cesium离线加载瓦片影像图和DEM高程图
这里选择引用其他服务商已有的服务,之后可以继续实现一下自己切片(大二实现过)的效果。
因为为了避免引用Cesium在线的js资源,而去引用其他的在线地图,无异于“拆东墙补西墙” 本质上还在引用在线公有云服务。无法避免在线资源的不稳定性。
在线资源:http://map.geoq.cn/arcgis/rest/services/
imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
url:"http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetWarm/MapServer"
,
}),//设置默认底图
//修改默认图层
viewer.baseLayerPicker.viewModel.selectedImagery=viewer.baseLayerPicker.viewM
odel.ArcGisMapServerImageryProvider;
最终还是改成了本地的切片服务
- 用工具进行切片,将切片结果放在对应的目录下
- 修改代码,让程序的底图引用本地数据
imageryProvider:new Cesium.UrlTemplateImageryProvider({
url:'../OSM/roadmap/{z}/{x}/{y}.png',
fileExtension:"jpg"
}),
建模
这个就更难了,而且参考资料似乎不多。有两种方法,离线和在线。尝试使用离线的方法,因为这样更稳定一点。这边参考一些文章尝试去实现。
- 离线:https://www.jianshu.com/p/064c42cc105f
- 在线:https://www.cnblogs.com/xi12/p/15921600.html
- 解释:https://www.itdaan.com/blog/2018/06/07/309b269fec11457a2339968e3578dd2d.html
- 总览:https://www.itdaan.com/keywords/cesium+%E5%8A%A0%E8%BD%BDshp%E6%A0%BC%E5%BC%8F%E7%9A%84%E7%99%BD%E6%A8%A1%E5%BB%BA%E7%AD%91.html
- 在ArcMap中给每个建筑物加高度
- 使用CesiumLab3对数据进行切片,这里的高度字段可以自己选择为在ArcMap新设的属性字段Height。
- 下载后的数据是b3dm格式的,关于b3dm格式数据的讲解可以参考以下链接。下载后的数据中有一个是“scenetree.json”,打开它后可以发现它存储的就是之前的shp的属性表数据。将数据和之前的dem数据一样,放在apache的webapps文件夹下,然后启动Tomact服务器。
- b3dm格式讲解:https://www.cnblogs.com/mazhenyu/p/14929552.html
- 它与3dTiles的关系:https://zhuanlan.zhihu.com/p/546861569
- 加载b3dm:https://blog.csdn.net/du_5pet/article/details/95961311?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
- 赋予白膜后的效果
最后
不是要实现三维通视性分析吗? 怎么前面一直在搭建服务?
因为对于初学者来说 搭建服务是最难的,至于如何改进Cesium的PickFromRay算法,实现三维的 定量通视分析 可以去看这篇论文
[1]高超杰,芮小平.基于改进PickFromRay算法的通视性定量分析[J].地理与地理信息科学,2024,40(03):8-13.