欢迎光临
我们一直在努力

如何用 Cesium 实现楼栋单体化?前端 WebGIS 实战教程

我们在上一篇👉2025前端webgis开发实习岗面试题+答案中我们绍了cesium矢量单体化,实现了建筑单体化功能。

本篇我们介绍一下如何通过倾斜摄影模型单体化。

图片

一、倾斜摄影模型单体化实现逻辑

基于倾斜摄影 3DTiles 数据,完成:

  • 精准绘制楼栋轮廓,获取空间坐标;

  • 实现楼栋与整体模型的 “单体剥离”;

  • 为单体楼栋绑定基础属性,支撑后续扩展。

  • 二、核心代码实现

    1. 基础环境搭建

    在网页中引入CesiumJS库并创建一个三维地球场景容器。

    <!– 引入Cesium核心依赖 –>
    <script src="https://cesium.com/downloads/cesiumjs/releases/1.110/Build/Cesium/Cesium.js"></script>
    <link href="https://cesium.com/downloads/cesiumjs/releases/1.110/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
    <!– 三维场景容器 –>
    <div id="cesiumContainer" style="width: 100vw; height: 100vh;"></div>

    2.初始化 Cesium 基础场景

    使用Cesium库初始化一个三维地球场景。

    // 1. 初始化Cesium场景(搭建三维可视化基础环境)
    const viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain(), // 加载地形,还原真实地理高程
    infoBox: false, // 关闭默认信息框,简化交互逻辑
    selectionIndicator: false
    });

    3.加载倾斜摄影 3DTiles 数据

    使用Cesium库加载倾斜摄影3DTiles数据,并实现相机定位功能。

    // 2. 加载倾斜摄影3DTiles数据(楼栋单体化的数据源基础)
    const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
    url: 'http://localhost:8080/3dtiles/community/', // 替换为实际3DTiles服务地址
    maximumScreenSpaceError: 16 // 平衡加载精度与性能,数值越小精度越高
    }));
    // 相机定位到目标楼栋区域,方便操作
    viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(113.9213, 22.5381, 200),
    duration: 3
    });

    4.初始化绘制变量 + 启动绘制函数

    建筑轮廓绘制功能的初始化,主要用于楼栋单体化建模的准备工作。

    变量声明与作用

    let drawPoints = []; 声明一个空数组用于存储用户绘制的楼栋轮廓顶点坐标。该数组将记录鼠标点击或触摸产生的所有顶点位置,后续用于生成闭合多边形。

    方法调用

    startBuildingDraw(); 触发楼栋绘制模式的启动函数。该函数通常包含以下隐含逻辑:

    • 激活绘图事件监听(如鼠标点击/移动、触摸事件)
    • 重置绘图状态(如清除历史绘制数据)
    • 初始化绘图画布或地图交互层

    // 3. 初始化绘制核心变量
    let drawPoints = []; // 存储绘制的楼栋轮廓顶点坐标
    // 启动楼栋绘制,开始单体化操作
    startBuildingDraw();

    5.绘制楼栋轮廓

    // 实时预览绘制的楼栋轮廓
    function drawPreview() {
        // 清除上一次预览,避免重复渲染
        viewer.entities.removeById('previewPolygon');
        if (drawPoints.length >= 3) { // 多边形至少需要3个顶点
            viewer.entities.add({
                id: 'previewPolygon',
                polygon: {
                    hierarchy: new Cesium.PolygonHierarchy(drawPoints),
                    material: Cesium.Color.RED.withAlpha(0.2), // 预览轮廓半透明样式
                    outline: true
                }
            });
        }
    }
    // 核心:绘制楼栋轮廓的核心函数
    function startBuildingDraw() {
        // 左键点击:添加楼栋轮廓顶点
        viewer.screenSpaceEventHandler.setInputAction((e) => {
            const earthPos = viewer.scene.pickPosition(e.position);
            if (Cesium.defined(earthPos)) {
                drawPoints.push(earthPos); // 收集三维地理坐标
                drawPreview(); // 实时预览绘制效果
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    实时预览绘制的楼栋轮廓 drawPreview()函数用于实时显示用户绘制的楼栋轮廓。 通过viewer.entities.removeById('previewPolygon')清除上一次的预览图形,避免重复渲染。 当drawPoints数组中的顶点数量达到3个或以上时,调用viewer.entities.add()创建一个半透明的红色多边形实体,轮廓线可见。

    绘制楼栋轮廓的核心逻辑 startBuildingDraw()函数通过左键点击事件收集用户输入的顶点坐标。 使用viewer.scene.pickPosition(e.position)将屏幕坐标转换为三维地理坐标,并存入drawPoints数组。 每次点击后调用drawPreview()更新预览效果,实现交互式绘制。

    6.完成楼栋轮廓绘制,生成单体化楼栋

    右键触发校验与绘制 通过 viewer.screenSpaceEventHandler.setInputAction 监听右键点击事件。当顶点数组 drawPoints 中存储的点数量不足3个时直接返回,确保多边形绘制有效性。

    单体化楼栋实体创建 利用 viewer.entities.add 创建高亮显示的楼栋实体:

    • polygon.hierarchy 使用 PolygonHierarchy 封装绘制点集
    • material 设置为半透明红色(透明度0.4)作为填充色
    • outline 启用轮廓线并设置为纯红色
    • properties 附加业务属性如楼栋ID和名称

    坐标转换处理

    笛卡尔坐标转经纬度 通过 map 遍历绘制点集:

  • Cartographic.fromCartesian 将笛卡尔坐标转换为弧度制地理坐标
  • Math.toDegrees 将经度/纬度转为度数
  • 输出包含经度、纬度、高度的三维数组
  •     // 右键确认:完成楼栋轮廓绘制,生成单体化楼栋
        viewer.screenSpaceEventHandler.setInputAction(() => {
            if (drawPoints.length < 3) return; // 校验顶点数量,避免无效绘制

            // 1. 生成单体化楼栋实体(视觉上高亮标识单体楼栋)
            const buildingEntity = viewer.entities.add({
                polygon: {
                    hierarchy: new Cesium.PolygonHierarchy(drawPoints),
                    material: Cesium.Color.RED.withAlpha(0.4), // 单体楼栋高亮样式
                    outline: true,
                    outlineColor: Cesium.Color.RED
                },
                properties: {
                    buildingId: 'BM008', // 楼栋唯一标识
                    buildingName: '光明小区8栋' // 绑定基础属性
                }
            });
            // 2. 转换为经纬度坐标(便于存储和后续业务使用)
            const buildingCoords = drawPoints.map((p) => {
                const carto = Cesium.Cartographic.fromCartesian(p);
                return [
                    Cesium.Math.toDegrees(carto.longitude),
                    Cesium.Math.toDegrees(carto.latitude),
                    carto.height
                ];
            });
            console.log('8栋单体化坐标数据:', buildingCoords);
            // 重置绘制状态,准备下一次绘制
            drawPoints = [];
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }

    在数字不动产、智慧园区等 GIS 核心场景中,Cesium 建筑单体化只是基础。真正的企业级项目要求开发者实现「单体化 + 分户管理 + 业务功能落地」的全流程开发。

    而这整套实战能力,在新中地 GIS 开发特训营的【cesium实战案例-建筑分房分户】中都有全流程讲解—— 从 Cesium 集成 Vue3 的工程化开发,到分层分户全功能落地,再到不动产登记业务对接,手把手带你掌握可直接落地的 GIS 开发技能!

    赞(0)
    未经允许不得转载:171主机测评 » 如何用 Cesium 实现楼栋单体化?前端 WebGIS 实战教程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址