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

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

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

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

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

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

  2. 实现楼栋与整体模型的 "单体剥离";

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

二、核心代码实现

1. 基础环境搭建

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

javascript 复制代码
<!-- 引入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库初始化一个三维地球场景。

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

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

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

javascript 复制代码
// 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();

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

  • 激活绘图事件监听(如鼠标点击/移动、触摸事件)
  • 重置绘图状态(如清除历史绘制数据)
  • 初始化绘图画布或地图交互层
javascript 复制代码
// 3. 初始化绘制核心变量
let drawPoints = []; // 存储绘制的楼栋轮廓顶点坐标
// 启动楼栋绘制,开始单体化操作
startBuildingDraw();

5.绘制楼栋轮廓

javascript 复制代码
// 实时预览绘制的楼栋轮廓
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 遍历绘制点集:

  1. Cartographic.fromCartesian 将笛卡尔坐标转换为弧度制地理坐标
  2. Math.toDegrees 将经度/纬度转为度数
  3. 输出包含经度、纬度、高度的三维数组
javascript 复制代码
    // 右键确认:完成楼栋轮廓绘制,生成单体化楼栋
    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 开发技能!

相关推荐
悟能不能悟2 小时前
前端如何重定向
前端
三小河2 小时前
React 插槽(Slot)完全指南:从基础到实战的灵活组件通信方案
前端·javascript·面试
布茹 ei ai2 小时前
1、基于 GEE 的 NDVI 交互式时序可视化与趋势分析工具
javascript·gee·遥感图像处理·谷歌云平台
```???2 小时前
666666999999
javascript·tcp/ip·node.js
ghfdgbg2 小时前
12. AOP(记录日志)
前端
我命由我123452 小时前
微信小程序 - 页面返回并传递数据(使用事件通道、操作页面栈)
开发语言·前端·javascript·微信小程序·小程序·前端框架·js
一水鉴天2 小时前
整体设计 定稿 备忘录仪表盘方案 之1 初稿之8 V5版本的主程序 之2: 自动化导航 + 定制化服务 + 个性化智能体(豆包助手)
前端·人工智能·架构
vortex53 小时前
【Web开发】从WSGI到Servlet再到Spring Boot
前端·spring boot·servlet
于谦3 小时前
git提交信息也能自动格式化了?committier快速体验
前端·javascript·代码规范