开源!3D带地形的区域地图,原来用Cesium几行代码就搞定了!(附源码)

大家好,我是日拱一卒的攻城师不浪,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第57/100篇原创文章。

效果预览

群里经常会有小伙伴抱怨道:我们领导又提了个奇葩的需求,他不想看到整个地球的地形影像,因为其他地区的跟业务无关,没有必要展示。他只想看到只展示某个指定的区域的地形影像,这样会更清晰简洁明了。

其实这个功能就需要对地球进行区域裁剪,那么,今天我们就来一起实现下,其实还蛮简单的。

源码放在了文章末尾,需要的自行领取!

区域地形裁剪的优势

个人认为此功能具备以下几个优势吧:

  • 聚焦分析特定区域,排除无关区域干扰

  • 有利于创建地形剖面,能够更清晰的展示地下结构或地质构造

  • 形成特殊的视觉效果,提升展示的专业性和美观性

应用场景

该功能可以利用在很多场景,例如

  • 地质分析与勘探;

  • 灾害模拟分析:如洪水、滑坡,聚焦于受影响区域,可更精准的分析辅助决策;

  • 矿山工程施工可视化等等

开发原理

首先我们先捋一下,做该功能的原理是啥。

  1. 首先,你得先加载地形吧。

  2. 其次,你得知道你要裁剪的区域吧,你得去下载区域坐标json吧,去哪下呢?这个我们之前已经提过跟多次啦!datav.aliyun.com/portal/scho...

  3. 然后你得知道用Cesium的哪个API去裁吧,ClippingPolygon,是它,就是它。

上手撸

关闭不必要的元素影响

javascript 复制代码
// 添加地形
const addCesiumTerrain = async () => {
  // 加载默认地形
  const terrain = await Cesium.CesiumTerrainProvider.fromIonAssetId(1);
  __viewer.terrainProvider = terrain;
  __viewer.scene.globe.depthTestAgainstTerrain = true;
  // 关闭一些不必要的视觉效果,优化性能
  __viewer.scene.sun.show = false; // 太阳
  __viewer.scene.moon.show = false; // 月亮 
  __viewer.scene.skyBox.show = false; // 天空盒
  __viewer.scene.fog.enabled = false; // 雾
  __viewer.scene.skyAtmosphere.show = false; // 大气
};

裁剪

javascript 复制代码
const start = () => {
  // 加载青岛区域的GeoJSON数据
  axios.get('/json/qingdao.json').then(res => {
    const coors = res.data.features[0].geometry.coordinates[0].flat().flat()
    console.log(coors)
    const areas = new Cesium.ClippingPolygon({
      positions: Cesium.Cartesian3.fromDegreesArray(coors),
    })
    __viewer.scene.globe.clippingPolygons = new Cesium.ClippingPolygonCollection({
      polygons: [areas],
      inverse: true
    })

    // 飞行到青岛区域
    __viewer.camera.flyTo({
      destination: new Cesium.Cartesian3.fromDegrees(120.656037, 36.322163, 30000),
    })
  })
}

拿到区域json数据然后将经纬度多维数组拍平 !将所有的ClippingPolygon都放入到截面集合ClippingPolygonCollection中,决定地形裁剪的范围;

这里注意inverse参数,它负责判断裁剪区域外还是内,当为true,则是裁剪掉区域以外的内容。

性能优化

不过,如果区域点位过多,裁剪完之后运行起来会感觉异常的卡顿,帧率甚至连10都不到,所以需要做性能优化。

这里我采用的方案是多边形简化,缩减区域点位数量 ,利用turf插件库。

js 复制代码
// 性能优化,简化点位
const coors = res.data.features[0].geometry.coordinates[0]
const geojson = turf.polygon(coors)
const simplified = turf.simplify(geojson, {
  tolerance: 0.01,
  highQuality: false, // 是否花费更多时间使用其他算法创建更高质量的简化
})
const areas = 
  new Cesium.ClippingPolygon({
    positions: Cesium.Cartesian3.fromDegreesArray(simplified.geometry.coordinates[0].flat())
  })

__viewer.scene.globe.clippingPolygons = new Cesium.ClippingPolygonCollection({
  polygons: [areas],
  inverse: true
})

简化后的性能就要好很多了,不过裁剪边界就显得没有那么精细了,所以这个简化参数视情况而定。

五、最后

完整源码放在了不浪的开源项目里,觉得有帮助的朋友可以帮忙点一个star,鼓励不浪开源更多案例。

【开源地址】:github.com/tingyuxuan2...

想系统学习Cesium的小伙伴儿,可以了解下不浪的教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,关注公众号:攻城师不浪,即可获取教程介绍,也可+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意)。

相关推荐
青山Coding2 天前
Cesium应用(二):基于heatmap.js 的全球气象可视化实现方案
前端·gis·cesium
不浪brown4 天前
WebGIS必备技能!Cesium坡度坡向分析全解析
cesium
1H1R1M6 天前
同步绘制视锥几何体和实际相机视锥体
前端·javascript·cesium
青山Coding6 天前
Cesium应用(一):解决 Cesium 海量船舶轨迹点渲染难题:轨迹数据池方案实践
gis·cesium
锦岁6 天前
cesium-1.92源码编译
cesium
allenjiao7 天前
Cesium粒子系统模拟风场动态效果
javascript·arcgis·gis·webgl·cesium·三维·风场
GIS瞧葩菜11 天前
Cesium 中拾取 3DTiles 交点坐标
前端·javascript·cesium
刘小筛11 天前
Cesium视锥和航向角,终于被我玩明白了。纯干货,全程无废话。
cesium
不浪brown13 天前
丝滑!Cesium中实现机械模型动作仿真全流程
cesium