如何从GeoServer加载GeoTIFF数据作为CesiumJS中的3D地形?
从GeoServer加载GeoTIFF作为CesiumJS 3D地形的分步指南
你已经通过WMS成功加载了影像图层,要实现3D地形渲染,需要单独处理带高程信息的DEM数据(注意:RGB影像无法直接作为地形数据源,必须用单波段的高程GeoTIFF),以下是具体步骤:
一、GeoServer端配置
- 确认你的GeoTIFF是单波段DEM数据(数值代表海拔高度),如果之前发布的是影像图层,需要单独发布这个高程数据为新图层
- 开启图层的WCS服务:进入GeoServer图层配置的「发布」标签,找到「WCS设置」,勾选「启用WCS」
- 确保图层坐标系支持Cesium常用的
EPSG:4326(WGS84)或EPSG:3857(Web墨卡托),若原始坐标系不符,需在GeoServer中配置投影转换支持 - (可选)若要提升性能,可使用GeoServer的
gs-terrain插件或gdal2tiles.py工具,将DEM转换成Cesium兼容的地形瓦片格式,部署到静态服务目录
二、CesiumJS端实现方案
方案1:动态请求WCS高程数据(实时渲染)
通过CustomHeightmapTerrainProvider结合GeoServer的WCS服务,动态获取指定区域的高程数据。需引入geotiff.js库解析TIFF数据。
<!-- 先引入geotiff.js --> <script src="https://unpkg.com/geotiff@2.0.7/dist/geotiff.min.js"></script> <script> const viewer = new Cesium.Viewer('cesiumContainer',{ animation : false, }); viewer.imageryLayers.remove(viewer.imageryLayers.get(0)); viewer.timeline.container.style.display="none"; viewer.bottomContainer.style.display = "none"; // 保留原影像加载代码 const url = 'http://localhost:8080/geoserver/cesium/wms'; const imageryProvider = new Cesium.WebMapServiceImageryProvider({ url : url, layers:'cesium:geotiff', parameters: { service: 'WMS', format: 'image/png', transparent: true, } }); viewer.imageryLayers.addImageryProvider(imageryProvider); // 自定义地形提供者 const terrainProvider = new Cesium.CustomHeightmapTerrainProvider({ width: 65, // 必须为2^n +1,比如65、129、257等 height: 65, requestHeightmap: async function(x, y, level) { // 计算当前瓦片的地理范围 const rectangle = Cesium.TileXY.getRectangle(level, x, y, Cesium.Ellipsoid.WGS84); // 构造WCS请求参数,替换为你的高程图层名称(cesium:dem_layer) const wcsUrl = 'http://localhost:8080/geoserver/cesium/wcs'; const requestUrl = `${wcsUrl}?service=WCS&version=2.0.1&request=GetCoverage` + `&coverageId=cesium:dem_layer` + `&format=image/tiff` + `&subset=Long(${rectangle.west},${rectangle.east})` + `&subset=Lat(${rectangle.south},${rectangle.north})` + `&size=65,65`; const response = await fetch(requestUrl); if (!response.ok) throw new Error(`WCS请求失败: ${response.statusText}`); // 解析TIFF为高程数组 const arrayBuffer = await response.arrayBuffer(); const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer); const image = await tiff.getImage(); const raster = await image.readRasters(); // 返回Float32格式的高程数据(单位:米) return new Float32Array(raster[0]); } }); // 替换默认地形 viewer.terrainProvider = terrainProvider; </script>
方案2:加载预生成的地形瓦片(推荐,性能更好)
如果已经预生成了Cesium兼容的地形瓦片,直接用CesiumTerrainProvider加载:
// 替换原地形加载代码 viewer.terrainProvider = new Cesium.CesiumTerrainProvider({ url: 'http://localhost:8080/terrain-tiles', // 地形瓦片的服务地址 requestVertexNormals: true // 可选,开启后支持地形光照效果 });
关键注意事项
- 解决跨域问题:在GeoServer的
web.xml中添加CORS过滤器,否则Cesium无法请求GeoServer数据 - 高程数据单位必须为米,Cesium默认以米作为高程单位
- 影像与地形的坐标系需保持一致,避免出现偏移错位
内容的提问来源于stack exchange,提问作者Zarabotok 04
相关产品推荐
相关产品推荐

