模型师要失业了?无需建模!Cesium根据数据自定义生成真实道路

448 阅读4分钟

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

效果预览

55758bc9528540c4bb198fc816576cfd~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pS75Z-O5biI5LiN5rWq_q75.gif

前言

通常一个数字孪生类项目,建模成本是非常高的,因为建模是体力活,这个成本很难压下。

因此,如何能最大程度上减少建模的成本,同时还能保证项目的美观,也成为了众多研发创作者一直在探索的道路。

今天,我们就来聊一下,如何在Cesium中根据道路数据自动生成美观的道路,从而减少建模成本,同时本技术方案代码开源,源码请文末自取!

场景实现原理

该场景的核心原理是通过GeoJSON道路数据结合Cesium三维地球引擎与Turf.js地理空间分析库,实现多层道路可视化效果。具体流程如下:

  1. 数据加载:读取包含道路线段的GeoJSON数据(hefei-road.json);

  2. 坐标转换:将经纬度坐标转换为Cesium三维笛卡尔坐标系(Cesium.Cartesian3.fromDegrees);

  3. 缓冲区生成:利用turf.buffer创建不同宽度的道路缓冲区:

    • 最外层:灰色路基(30米宽)
    • 中间层:带纹理的柏油路面
    • 内层:黑白虚线分隔线
    • 最内层:黄色中心线
  4. 三维渲染:通过Cesium的Polygon实体分层渲染缓冲多边形

关键代码解析

数据加载与坐标转换

axios.get("/json/hefei-road.json").then((response) => {
  response.data.features.forEach((k) => {
    k.geometry.coordinates.forEach((m) => {
      if(m.length > 5) {
        let arr = [];
        m.forEach((mm) => {
          arr.push(Cesium.Cartesian3.fromDegrees(mm[0], mm[1], 10)); // 坐标转换
        });
        initRoad(arr); // 初始化道路
      }
    });
  });
});
  • 通过axios加载GeoJSON数据

  • 使用Cesium.Cartesian3.fromDegrees将经纬度转换为三维坐标

  • 筛选有效路径(长度>5的线段)

缓冲区生成核心逻辑

// 生成路基缓冲区(最宽层)
var buffered = turf.buffer(linestring1, (luKuan/15)*15, {units: "meters"});

// 生成柏油路面
var buffered1 = turf.buffer(linestring1, (luKuan/15)*14.3, {units: "meters"});
var buffered2 = turf.buffer(linestring1, (luKuan/15)*14, {units: "meters"});

// 生成分隔线
var buffered3 = turf.buffer(linestring1, (luKuan/15)*7.5, {units: "meters"});
var buffered4 = turf.buffer(linestring1, (luKuan/15)*6.8, {units: "meters"});
  • luKuan定义基准路宽(30米)

  • 通过比例系数实现多层嵌套缓冲区:

    • 路基:100%宽度(30m)
    • 柏油路面:95.3%-93.3%宽度(28.6m-28m)
    • 分隔线:50%-45.3%宽度(15m-13.6m)

Cesium实体渲染

// 路基渲染
__viewer.entities.add({
  polygon: {
    hierarchy: Cesium.Cartesian3.fromDegreesArray(kkk1),
    material: new Cesium.Color(81/255, 81/255, 81/255, 1) // 灰色材质
  }
});

// 柏油路面(带纹理)
__viewer.entities.add({
  polygon: {
    hierarchy: {
      positions: Cesium.Cartesian3.fromDegreesArray(kkkk1),
      holes: [{
        positions: Cesium.Cartesian3.fromDegreesArray(kkkk2)
      }]
    },
    material: new Cesium.ImageMaterialProperty({
      image: "/images/qqq.png", // 路面纹理
      repeat: new Cesium.Cartesian2((50/luKuan)*15, (50/luKuan)*15)
    })
  }
});
  • 使用polygon实体创建多边形

  • 通过hierarchy定义带孔多边形实现嵌套效果

  • ImageMaterialProperty实现纹理贴图

  • repeat参数控制纹理重复密度

核心技术

  1. 多级缓冲区算法:通过turf.buffer生成不同宽度的嵌套缓冲区,模拟真实道路结构

  2. 坐标系转换

    • WGS84转笛卡尔坐标系(Cesium.Cartesian3.fromDegrees

    • 高程处理(cartographic.height

  3. 性能优化

    • 使用holes属性减少多边形渲染量

    • 通过纹理贴图(qqq.png/3333.jpg)替代复杂几何体

  4. 视觉增强

    • 分层颜色区分(灰->黑->黄)

    • 动态纹理重复(Cesium.Cartesian2控制UV)

后期规划

  • 交互增强:添加Primitive实现道路点击事件,获取相关道路信息;

好了,通过以上解析,我们可以看到如何将地理空间数据与三维引擎结合,实现具有真实感的道路可视化效果。核心在于Turf.js的空间分析与Cesium的高效渲染的完美结合。

最后

源码地址】:github.com/jiawanlong/…

不浪的【Cesium案例集合源码】:github.com/tingyuxuan2…

如果开源对您有帮助,也欢迎帮我们点一个免费的star,以鼓励和支持我们开源更多案例!

不会Cesium的基础,也很难做出更高级的效果,所以可以了解下不浪的教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,课程也在不断更新迭代中,想了解+作者:brown_7778(备注来意)。

有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意)。