Cesium:模型裁切
关于平面裁切,官网有两个例子,3D Tiles裁切和地形裁切。
本文实现的功能:由两点确定一条直线,给定裁切位置,对3D Tiles数据做裁切。
裁切效果:

要实现平面裁切,首先需要创建裁切平面
1、ClippingPlane
new Cesium.ClippingPlane(normal, distance)
名称 | 默认值 |
---|---|
normal | 平面的法线方向。 |
distance | 原点到平面的最短距离。距离符号决定了原点在平面的哪一侧。如果距离为正,则原点在法向的半空间中;如果距离为负,则原点在法向反方向的半空间中;如果距离为零,则平面通过原点。 |
平面法向所在坐标系是以正东方为x轴正方向,正北方为y轴正方向,正上面为z轴正方向的座标系。(局部坐标)
平面法向确定了裁切面的方向,距离通过原点到平面的距离控制,原点在tileset中就是模型的原点。

然后,创建裁切平面集合,
2、ClippingPlaneCollection
new Cesium.ClippingPlaneCollection(options)
名称 | 默认值 | 描述 |
---|---|---|
planes | ClippingPlane,用于在每个平面的外部选择性地禁用渲染 的对象数组。 | |
enabled | true | 确定剪切平面是否处于活动状态。 |
modelMatrix | 4x4变换矩阵,指定相对于剪裁平面原始座标系的附加变换。 | |
unionClippingRegions | false | 如果为true,则位于任何平面外部的区域将被剪裁,即取并集。否则,位于每个平面的外部区域才会被剪裁,即取交集。 |
edgeColor | Color.WHITE | 用于突出显示裁剪对象的边缘的颜色。 |
edgeWidth | 0 | 剪裁对象的边缘的高光的宽度(以像素为单位)。 |
核心代码:
function clipPlane(viewer, tileset) {
this.viewer = viewer;
this.tileset = tileset;
this.clipPlane;
this.origin;
this.size;
this.init();
}
clipPlane.prototype.init = function() {
// 根据两个点的坐标计算方向向量
var point1 = new Cesium.Cartesian3(1214947.495184834,-4736223.627644073,4081719.8535693167);
var point2 = new Cesium.Cartesian3(1215009.7319983065, -4736271.158724633, 4081646.6675580707);
//中点坐标
var midpoint = new Cesium.Cartesian3((point1.x + point2.x) / 2, (point1.y + point2.y) / 2, (point1.z + point2.z) / 2);
// 计算连线向量
var vector = Cesium.Cartesian3.subtract(point2, point1, new Cesium.Cartesian3());
//椭球面单位法向量
var normalVector = Cesium.Cartesian3.cross(midpoint, vector, new Cesium.Cartesian3());
var unitVector = Cesium.Cartesian3.normalize(normalVector, new Cesium.Cartesian3());
//模型包围盒中心点坐标
this.origin = this.tileset.boundingSphere.center;
//包围盒半径,用于确定绘制的裁切面大小
this.size = this.tileset.boundingSphere.radius;
//局部坐标到世界坐标的转换矩阵
var northeastup = Cesium.Transforms.eastNorthUpToFixedFrame(this.origin);
//取逆得世界坐标到局部坐标的转换矩阵
var inverse;
//为了应对某些数据root的变换为单位阵的情况
var rootTransform = this.tileset.root.transform;
if (rootTransform.equals(Cesium.Matrix4.IDENTITY)) {
rootTransform = northeastup;
inverse = Cesium.Matrix4.inverse(northeastup, new Cesium.Matrix4);
}else{
inverse = Cesium.Matrix4.inverse(rootTransform, new Cesium.Matrix4);
}
//计算距离
let line = new Cesium.Cartesian3(this.origin.x - point1.x, this.origin.y - point1.y, this.origin.z - point1.z);
let distance = Cesium.Cartesian3.dot(line, unitVector);
//tileset模型用的是局部坐标,所以给的方向也要时局部坐标系下的
let direction = Cesium.Matrix4.multiplyByPointAsVector(inverse, unitVector, new Cesium.Cartesian3());
//创建裁切平面
this.clipPlane = new Cesium.ClippingPlane(direction, distance);
//创建裁切平面集合
var clippingPlanes = new Cesium.ClippingPlaneCollection({
planes: [
this.clipPlane
],
edgeWidth: 1.0
});
//添加面
this.planeEntity = this.viewer.entities.add({
position: this.origin,
plane: {
dimensions: new Cesium.Cartesian2(
this.size * 2,
this.size * 2
),
material: Cesium.Color.WHITE.withAlpha(0.3),
plane: clippingPlanes.get(0),
outline: true,
outlineColor: Cesium.Color.WHITE,
},
});
//添加点
viewer.entities.add({
position: point1,
point: {
pixelSize: 5
}
})
viewer.entities.add({
position: point2,
point: {
pixelSize: 5
}
})
//添加线
var lineEntity = viewer.entities.add({
polyline: {
positions: [point1, point2],
width: 2,
material: Cesium.Color.RED
}
});
this.tileset.clippingPlanes = clippingPlanes;
}
参考:Cesium——平面裁切
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具