cesium 3dtile ClippingPlanes 多边形挖洞ClippingPlaneCollection

原理就是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 中,ClippingPlaneClippingPlaneCollection 通常用于控制哪些部分的场景或模型是可见的。通过切割面(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 单位以内的部分。


其他可能的应用场景:

  1. Skybox(天空盒) clippingPlanes 也可用于裁剪 天空盒,这在某些需要动态裁剪天空内容的应用中有用。

  2. Custom Primitives(自定义原始几何体) 如果你自己创建了自定义几何体,可以通过 clippingPlanes 使其进行裁剪,减少计算负担或者实现特定的可视化效果。

  3. Ground Clipping (地面裁剪) 对于需要动态控制地面显示的场景,clippingPlanes 可以用来裁剪地面,或者将其与其他场景元素进行交互。


总结

ClippingPlanesCesium 中是一个非常灵活的工具,可以应用于以下对象:

  • 3D Tiles(如城市模型)
  • Primitives(如几何体)
  • Models(如 glTF 模型)
  • Terrain(地形)
  • Imagery(影像图层)
  • Skybox(天空盒)
  • Custom Primitives(自定义几何体)

这些对象可以通过 ClippingPlaneCollection 结合多个切割面来实现不同的裁剪效果,从而动态地控制场景中的可见部分。

相关推荐
mm_exploration9 小时前
halcon三维点云数据处理(九)create_shape_model_3d_ignore_part_polarity
图像处理·3d·halcon·点云处理
winxp-pic11 小时前
从 2D 图像中学习 3D 人机交互关系
学习·3d·人机交互
万物得其道者成13 小时前
在高德地图上加载3DTilesLayer图层模型/天地瓦片
前端·javascript·3d
成功之路必定艰辛13 小时前
【Mars3D项目实战开发】加载水系河流,加载植被,加载区划街道社区吊牌,点击加载对应社区倾斜摄影
vue·cesium·mars3d
cxr82813 小时前
如何制定有效的微调策略
llama·cesium·unsloth
老K(郭云开)18 小时前
最新版Chrome浏览器加载ActiveX控件之SolidWorks 3D控件
前端·javascript·chrome·安全·3d·firefox
jndingxin18 小时前
OpenCV相机标定与3D重建(51)对 3x3 矩阵进行 RQ 分解(RQ Decomposition)函数RQDecomp3x3()的使用
opencv·3d
mirrornan18 小时前
3D扫描建模有哪些优势和劣势?
3d·3d建模·3d模型·三维建模·三维扫描·3d扫描仪
AI生成未来18 小时前
ECCV`24 | 首次解决文本到3D NeRFs分解问题!港中文等提出DreamDissector
3d·eccv·3d生成·eccv2024
鲤鱼不懂18 小时前
绘制人体3D关键点
3d