效果:
裁剪前:
裁剪后:
封装方法:
clipTileset(tileset, polygon) {//倾斜摄影裁剪
tileset._clippingPlanes = null;
const viewer = tileset._viewer;
const transform = tileset.root.transform; // 获取模型加载后的矩阵
// 转换矩阵
const inverseTransform = Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4());
// 创建裁剪平面集合
const clippingPlanes = new Cesium.ClippingPlaneCollection({
//一组ClippingPlane对象,用于选择性地禁用每个平面外部的渲染。
planes: [
// 裁剪面两个参数的:第一个为平面法向量,第二个为原点到平面的垂直距离
new Cesium.ClippingPlane(
//笛卡尔3:表示为三维空间的平面的法向量,x表示为该法向量在x轴上的分量,y表示为该法向量在y轴上的分量,z表示为该法向量在z轴上的分量
new Cesium.Cartesian3(0.0, 0.0, -1.0),
1.2//裁剪平面距地面的距离
),
],
});
// 创建裁剪平面
for (let i = 0; i < polygon.length - 1; i++) {
const plane = this.createClippingPlane(polygon[i], polygon[i + 1], inverseTransform);
clippingPlanes.add(plane);
}
// 设置模型的裁剪平面集合
tileset.clippingPlanes = clippingPlanes;
}
createClippingPlane(p1, p2, inverseTransform) {
// 将仅包含经纬度信息的p1,p2,转换为相应坐标系的cartesian3对象
const p1C3 = this.getOriginCoordinateSystemPoint(p1, inverseTransform);
const p2C3 = this.getOriginCoordinateSystemPoint(p2, inverseTransform);
// 定义一个垂直向上的向量up
const up = new Cesium.Cartesian3(0, 0, 10);
// 计算法向量normal
const direction = Cesium.Cartesian3.subtract(p2C3, p1C3, new Cesium.Cartesian3());
const normal = Cesium.Cartesian3.cross(direction, up, new Cesium.Cartesian3());
Cesium.Cartesian3.normalize(normal, normal);
// 创建裁剪平面
const plane = Cesium.Plane.fromPointNormal(p1C3, normal);
return Cesium.ClippingPlane.fromPlane(plane);
}
getOriginCoordinateSystemPoint(point, inverseTransform) {
const val = Cesium.Cartesian3.fromDegrees(point[0], point[1]);
return Cesium.Matrix4.multiplyByPoint(inverseTransform, val, new Cesium.Cartesian3(0, 0, 0));
}
取消裁剪:
cancelClipping(tileset) {//取消裁剪
tileset._clippingPlanes=new Cesium.ClippingPlaneCollection({
//一组ClippingPlane对象,用于选择性地禁用每个平面外部的渲染。
planes: [
// 裁剪面两个参数的:第一个为平面法向量,第二个为原点到平面的垂直距离
new Cesium.ClippingPlane(
//笛卡尔3:表示为三维空间的平面的法向量,x表示为该法向量在x轴上的分量,y表示为该法向量在y轴上的分量,z表示为该法向量在z轴上的分量
new Cesium.Cartesian3(0.0, 0.0, -1.0),
2000 // 我是把裁剪高度抬高到没有倾斜的高度达到取消裁剪效果
),
],
});
}
调用示例:
// 经纬度坐标点(一定要逆时针顺序选点),最后一个坐标点和起点一致形成闭合多边形;(或者找一个顺序转换方法,把顺时针选取的坐标点转成逆时针顺序)
const polygon = [
[122.50659820182338, 40.92167507082603],
[122.50647158464602, 40.92209157639903],
[122.5056436778383, 40.921389892895164],
[122.50590698641585, 40.92120253418978],
[122.50659820182338, 40.92167507082603],
];
// 3DTiles实体对象
const tileset = this.tileset
// 裁剪方法调用
this.clipTileset(tileset, polygon);
我是参考下面两篇文章对裁剪方法进行了封装: