我们在上一篇👉2025前端webgis开发实习岗面试题+答案中我们绍了cesium矢量单体化,实现了建筑单体化功能。
本篇我们介绍一下如何通过倾斜摄影模型单体化。

一、倾斜摄影模型单体化实现逻辑
基于倾斜摄影 3DTiles 数据,完成:
-
精准绘制楼栋轮廓,获取空间坐标;
-
实现楼栋与整体模型的 "单体剥离";
-
为单体楼栋绑定基础属性,支撑后续扩展。
二、核心代码实现
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 遍历绘制点集:
Cartographic.fromCartesian将笛卡尔坐标转换为弧度制地理坐标Math.toDegrees将经度/纬度转为度数- 输出包含经度、纬度、高度的三维数组
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 开发技能!