原理就是3dtiles里面的属性clippingPlanes
采用ClippingPlaneCollection,构成多边形来挖洞。
其次就是xyz法向量挖洞
javascript
clippingPlanes: new this.ffCesium.Cesium.ClippingPlaneCollection({
unionClippingRegions: true, // true 表示多个切割面能合并为一个有效的切割区域
planes: [
new this.ffCesium.Cesium.ClippingPlane(
new this.ffCesium.Cesium.Cartesian3(0.0, 0.0, -1.0), // 法向量
23.0 // 切割平面到原点的距离(高度)
)
]
})
以下是多边形裁剪
javascript
import * as Cesium from 'cesium'
class tileSetClipByPolygon {
constructor(options) {
this.tileSet = options.tileSet || null //3dtiles
this.originPositions = options.originPositions || [] //点
this.unionClippingRegions = !options.unionClippingRegions ? options.unionClippingRegions : true
this.enabled = !options.enabled ? options.enabled : true
this.edgeColor = options.edgeColor || Cesium.Color.WHITE
this.edgeWidth = options.edgeWidth || 0.0
}
isClockwise(polygon) {
var area = 0
var length = polygon.length
for (var i = 0; i < length; i++) {
var j = (i + 1) % length
area += polygon[i][0] * polygon[j][1] - polygon[j][0] * polygon[i][1]
}
return area < 0
}
getInverseTransform() {
let transform
let tmp = this.tileSet.root.transform
if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
// 如果root.transform不存在,则3DTiles的原点变成了boundingSphere.center
transform = Cesium.Transforms.eastNorthUpToFixedFrame(this.tileSet.boundingSphere.center)
} else {
transform = Cesium.Matrix4.fromArray(this.tileSet.root.transform)
}
return Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4())
}
clippingByPositions(clipping) {
// debugger
console.log('this.tileSet', this.tileSet)
this.tileSet.clippingPlanes = null
const Cartesian3 = Cesium.Cartesian3
const pointsLength = clipping.length
const clockwise = this.isClockwise(clipping)
//所有的裁切面
const clippingPlanes = []
let positions
if (clockwise) {
//如果为逆,则需要对数组取反
positions = clipping.reverse()
} else {
positions = clipping
}
positions = clipping
const inverseTransform = this.getInverseTransform()
for (let i = 0; i < pointsLength; ++i) {
const nextIndex = (i + 1) % pointsLength
const next = Cesium.Matrix4.multiplyByPoint(inverseTransform, Cesium.Cartesian3.fromDegrees(positions[nextIndex][0], positions[nextIndex][1]), new Cesium.Cartesian3())
const now = Cesium.Matrix4.multiplyByPoint(inverseTransform, Cesium.Cartesian3.fromDegrees(positions[i][0], positions[i][1]), new Cesium.Cartesian3())
// 定义一个垂直向上的向量up
let up = new Cesium.Cartesian3(0, 0, 10)
//得到指向下一个点的向量
let right = Cartesian3.subtract(next, now, new Cartesian3())
right = Cartesian3.normalize(right, right)
let normal = Cartesian3.cross(right, up, new Cartesian3())
Cartesian3.normalize(normal, normal)
//将法向量进行反向
if (this.unionClippingRegions) {
Cartesian3.negate(normal, normal)
}
//由于已经获得了法向量和过平面的一点,因此可以直接构造Plane,并进一步构造ClippingPlane
let planeTmp = Cesium.Plane.fromPointNormal(now, normal)
const clipPlane = Cesium.ClippingPlane.fromPlane(planeTmp)
clippingPlanes.push(clipPlane)
}
let the = this
const clipPlanes = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes,
edgeWidth: the.edgeColor,
edgeColor: the.edgeColor,
enabled: the.enabled,
unionClippingRegions: the.unionClippingRegions
})
console.log('clipPlanes', clipPlanes)
this.tileSet.clippingPlanes = clipPlanes
}
removeTilesetClip() {
this.tileSet.clippingPlanes.enabled = false
}
}
export default tileSetClipByPolygon
使用
javascript
this.CeiumPolygonClipA = new CeiumPolygonClip({
tileSet: photographyTileset.value,
originPositions: clipping,
unionClippingRegions: false
})
this.CeiumPolygonClipA.clippingByPositions(clipping)
在 CesiumJS 中,ClippingPlane
和 ClippingPlaneCollection 通常用于控制哪些部分的场景或模型是可见的。通过切割面(ClippingPlanes),你可以裁剪或隐藏指定区域的内容。clippingPlanes
主要应用于以下几种对象:
1. 3D Tiles
3D Tiles 是一种用于存储和传输大规模 3D 场景的格式,它可以通过 clippingPlanes
进行裁剪。这是一个非常常见的应用,尤其是在城市建模和大规模场景可视化中。
clippingPlanes
可以直接应用于Cesium3DTileset
对象,以裁剪掉 3D Tiles 模型的一部分。
示例:
javascript
const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: 'path/to/your/3dtiles/tileset.json',
clippingPlanes: new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(Cesium.Cartesian3.UNIT_Z, 100.0)
]
})
}));
在这个例子中,Cesium3DTileset
会被切割,只显示离 Z 轴 100 单位以内的区域。
2. Primitive(原始几何体)
clippingPlanes
也可以用于 Primitive 对象(如几何体、模型等),这是最基础的 3D 对象类型。通过将 ClippingPlaneCollection
赋值给 Primitive
,可以在渲染时裁剪它的几何体。
- 这种方法适用于自定义的几何体或其他静态几何体,例如:球体、立方体等。
示例:
javascript
const sphereGeometry = new Cesium.SphereGeometry({
radius: 100.0
});
const sphere = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: sphereGeometry,
modelMatrix: Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(0.0, 0.0, 0.0)),
}),
appearance: new Cesium.MaterialAppearance({
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.RED
})
}),
clippingPlanes: new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(Cesium.Cartesian3.UNIT_Z, 50.0) // 裁剪半径为 50 的球体
]
})
});
viewer.scene.primitives.add(sphere);
在这个例子中,创建了一个球体并将其裁剪,裁剪面距离原点 50 单位,隐藏球体超过该高度的部分。
3. Models(3D 模型)
ClippingPlanes 也可以应用于 3D 模型 (如 glTF 模型)。在 Cesium.Model
中,clippingPlanes
可以用来裁剪模型的一部分。
示例:
javascript
const model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
url: 'path/to/your/model.glb',
clippingPlanes: new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(Cesium.Cartesian3.UNIT_Z, 50.0)
]
})
}));
这段代码将对加载的 glTF 模型应用切割面,裁剪掉离 Z 轴 50 单位以上的部分。
4. Terrain(地形)
对于 Cesium 中的地形数据(例如使用 3D Tiles 数据源的地形),可以通过切割面进行裁剪。地形通常是通过 Cesium.CesiumTerrainProvider
加载的,而切割面可以用来限制地形的显示。
这种应用场景通常适用于大规模的地形可视化,用户可以通过切割面查看地形的特定部分,或从不同的切割角度进行分析。
5. Imagery(影像图层)
clippingPlanes
还可以用于影像图层,特别是当你想要切割或限制影像图层的显示时。通过使用 clippingPlanes
,你可以将某些区域的影像数据裁剪掉,以使其他数据更加突出。
示例:
javascript
const imageryLayer = viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
url : 'https://your-imagery-url/{z}/{x}/{y}.png'
}));
imageryLayer.clippingPlanes = new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(Cesium.Cartesian3.UNIT_Z, 100.0)
]
});
在这个例子中,影像图层会被切割,只显示离 Z 轴 100 单位以内的部分。
其他可能的应用场景:
-
Skybox(天空盒)
clippingPlanes
也可用于裁剪 天空盒,这在某些需要动态裁剪天空内容的应用中有用。 -
Custom Primitives(自定义原始几何体) 如果你自己创建了自定义几何体,可以通过
clippingPlanes
使其进行裁剪,减少计算负担或者实现特定的可视化效果。 -
Ground Clipping (地面裁剪) 对于需要动态控制地面显示的场景,
clippingPlanes
可以用来裁剪地面,或者将其与其他场景元素进行交互。
总结
ClippingPlanes
在 Cesium 中是一个非常灵活的工具,可以应用于以下对象:
- 3D Tiles(如城市模型)
- Primitives(如几何体)
- Models(如 glTF 模型)
- Terrain(地形)
- Imagery(影像图层)
- Skybox(天空盒)
- Custom Primitives(自定义几何体)
这些对象可以通过 ClippingPlaneCollection
结合多个切割面来实现不同的裁剪效果,从而动态地控制场景中的可见部分。