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——平面裁切

posted @   MARSHBAN  阅读(1689)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示