Cesium 模型裁切(包括单面和多面)

本人使用cesium版本依旧是1.6.1。

现阶段可以实现单面和多面(盒子)裁剪,不多说,直接上代码:

加载模型数据:

m_b3dm = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
                type: "3dtiles",
                url: RootURL + '/Datasource/Model/b3dm/tileset.json'
            }));
viewer.zoomTo(m_b3dm);

单面切割:

var clippingPlanes = m_b3dm.clippingPlanes = loadClip();
            var boundingSphere = m_b3dm.boundingSphere;

            for (var i = 0; i < clippingPlanes.length; ++i) {
                var plane = clippingPlanes.get(i);
                var planeEntity = viewer.entities.add({ //添加平面实体 直观裁切面
                    id: '裁切面' + i,
                    position: boundingSphere.center,// offset, 根据3dtiles同步调整裁切面高度 
                    plane: {
                        dimensions: new Cesium.Cartesian2(150, 150),//(radius * 2.5, radius * 2.5),
                        material: Cesium.Color.WHITE.withAlpha(0.0),
                        plane: new Cesium.CallbackProperty(createPlaneUpdateFunction(plane), false),
                        outline: true,
                        outlineColor: Cesium.Color.WHITE
                    }
                });
            }

方法补充:

function loadClip() {
    clippingPlanes = new Cesium.ClippingPlaneCollection({
        planes: [
            new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0), 0), 
        ],
        edgeColor: Cesium.Color.RED,
        edgeWidth: 1.0,
        unionClippingRegions: true, //true 才能多个切割  
    })
    return clippingPlanes
}

function createPlaneUpdateFunction(plane) {
    return function () {
        if (window.localStorage.getItem('slider')) {
            plane.distance = window.localStorage.getItem('slider');
            return plane;
        }
        plane.distance = 0;
        return plane;
    };
}
var CreateSlider = function (f_id, left, top, max,localStoragename) {
    var fEve = document.getElementById(f_id);
    window.localStorage.setItem(localStoragename, 0);
    var sliderDiv = document.createElement('div');
    sliderDiv.style.position = 'absolute';
    sliderDiv.style.left = left + 'px';
    sliderDiv.style.top = top + 'px';
    sliderDiv.style.zIndex = 99;

    //滑动长条
    var outerDiv = document.createElement('div');
    outerDiv.style.position = 'absolute';
    outerDiv.style.width = max + 'px';
    outerDiv.style.height = '8px';
    outerDiv.style.margin = '6px 0 0 0';
    outerDiv.style.background = '#fff';
    outerDiv.style.border = 'none';
    outerDiv.style.borderRadius = '3px';
    sliderDiv.appendChild(outerDiv);

    //滑动条指针
    var innerDiv = document.createElement('div');
    innerDiv.style.position = 'absolute';
    innerDiv.style.height = '20px';
    innerDiv.style.width = '5px';
    innerDiv.style.left = max / 2 + 'px';
    innerDiv.style.background = 'chocolate';
    innerDiv.style.border = '1px solid';
    innerDiv.style.borderRadius = '3px';

    sliderDiv.appendChild(innerDiv);
    fEve.appendChild(sliderDiv);

    function getPos(ev) {
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        return { x: ev.clientX + scrollLeft, y: ev.clientY + scrollTop };
    }
    function getStyle(obj, name) {
        if (obj.currentStyle) {
            return obj.currentStyle[name];
        }
        else {
            return getComputedStyle(obj, false)[name];
        }
    }

    innerDiv.onmousedown = function (ev) {
        var oEvent = ev || event;
        var pos = getPos(oEvent);
        var disx = pos.x - parseInt(getStyle(innerDiv, 'left'));
        document.onmousemove = function (ev) {
            var oEvent = ev || event;
            var pos = getPos(oEvent);
            var l = pos.x - disx;
            if (l < 0) {
                l = 0;
            }
            if (l > parseInt(getStyle(outerDiv, 'width')) - parseInt(getStyle(innerDiv, 'width'))) {
                l = parseInt(getStyle(outerDiv, 'width')) - parseInt(getStyle(innerDiv, 'width'))
            }
            innerDiv.style.left = l + 'px';

            window.localStorage.setItem(localStoragename, l - max / 2);
        }
        document.onmouseup = function () {
            document.onmousemove = null;
            document.onmouseup = null;
        }
        return false;
    }
}

效果图:

多面(盒子)裁切 :

CreateSlider('MapContainer', 10, 10, 300, 'slider_x');
            CreateSlider('MapContainer', 10, 60, 300, 'slider_y');
            CreateSlider('MapContainer', 10, 110, 300, 'slider_z');
            // return;
            var clippingPlanes = m_b3dm.clippingPlanes = loadClip_box();

            var boundingSphere = m_b3dm.boundingSphere;
            // 创建一个坐标轴,便于测试
            var transform = Cesium.Transforms.eastNorthUpToFixedFrame(boundingSphere.center);
            var modelMatrixPrimitive = viewer.scene.primitives.add(new Cesium.DebugModelMatrixPrimitive({
                modelMatrix: transform,
                length: 40.0
            }));

            var m_box;
            for (var i = 0; i < clippingPlanes.length; ++i) {
                var plane = clippingPlanes.get(i);
                var getPlaneType = getType4Plane(plane);
                var planeEntity = viewer.entities.add({ //添加平面实体 直观裁切面
                    id: 'ClipPlane' + i,
                    position: boundingSphere.center,// 根据3dtiles同步调整裁切面高度 
                    plane: {
                        dimensions: new Cesium.Cartesian2(80, 80),//切面的长和宽
                        plane: new Cesium.CallbackProperty(createPlaneUpdateFunction_box(plane, getPlaneType, boundingSphere.center), false),
                        material: Cesium.Color.WHITE.withAlpha(0),
                        outline: false
                    }
                });
                if (!m_box) {
                    m_box = viewer.entities.add({
                        id: 'ClopBox',
                        modelMatrixPrimitive:modelMatrixPrimitive,
                        position: boundingSphere.center,
                        box: {
                            dimensions: new Cesium.Cartesian3(80, 80, 80),
                            material: Cesium.Color.RED.withAlpha(0.2),
                        }
                    })
                }
            }

方法补充:

//获取切面的type // 上、下、左、右、前、后
function getType4Plane(plane) {
    var m_type;
    var normal = plane._normal;
    var x = normal.x;
    var y = normal.y;
    var z = normal.z;
    if (x == 1 && y == 0 && z == 0) {
        m_type = 'left';
    }
    else if (x == -1 && y == 0 && z == 0) {
        m_type = 'right';
    }
    else if (x == 0 && y == 1 && z == 0) {
        m_type = 'behind';
    }
    else if (x == 0 && y == -1 && z == 0) {
        m_type = 'front';
    }
    else if (x == 0 && y == 0 && z == -1) {
        m_type = 'top';
    }
    return m_type;
}

function loadClip_box() {
    clippingPlanes = new Cesium.ClippingPlaneCollection({
        planes: [
            //前后切割
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 1, 0), 0), //后 
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0, -1, 0), 0),  //前

            // 左右切割
            new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0), 0), //左 
            new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0), 0),  //右

            // 上下切割
            new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0.0, -1), 0),  //上→下
            // new Cesium.ClippingPlane(new Cesium.Cartesian3(0, 0.0, 1), 0),  //下→上
        ],
        edgeColor: Cesium.Color.RED,
        edgeWidth: 1.0,
        unionClippingRegions: true, //true 才能多个切割  
    })
    return clippingPlanes
}

function createPlanePos(origin, x, y, z) {
    var clipbox=viewer.entities.getById('ClopBox');
    if (clipbox) {
        clipbox.position=new Cesium.CallbackProperty(function () {
            return Cesium.Cartesian3.fromDegrees(origin[0] + x, origin[1] + y, +origin[2] + z);//实时返回当前盒子的位置
        }, false);
    }
}

function createPlaneUpdateFunction_box(plane, type, origin) {
    return function () {
        // plane.distance = 40;
        var num_x = window.localStorage.getItem('slider_x') / 100000;
        var num_y = window.localStorage.getItem('slider_y') / 100000;
        var num_z = window.localStorage.getItem('slider_z')/1.5;//读取滑动条值 
        var origin_degree = cartesian3ToDegrees(origin);
        var target_degree_x = [origin_degree[0] + num_x, origin_degree[1], +origin_degree[2]];
        var target_degree_y = [origin_degree[0], origin_degree[1] + num_y, +origin_degree[2]];
        var target_degree_z = [origin_degree[0], origin_degree[1], +origin_degree[2] + num_z];
        var m_dis_x = Cesium.Cartesian3.distance(origin, Cesium.Cartesian3.fromDegrees(target_degree_x[0], target_degree_x[1], target_degree_x[2]));
        var m_dis_y = Cesium.Cartesian3.distance(origin, Cesium.Cartesian3.fromDegrees(target_degree_y[0], target_degree_y[1], target_degree_y[2]));
        var m_dis_z = Cesium.Cartesian3.distance(origin, Cesium.Cartesian3.fromDegrees(target_degree_z[0], target_degree_z[1], target_degree_z[2]));
        createPlanePos(origin_degree, num_x, num_y, num_z);
        if (type == 'left') {
            if (num_x < 0) {
                plane.distance = 40 - (-m_dis_x);                
                return plane;
            } else {
                plane.distance = 40 - m_dis_x      
                return plane;
            }
        }
        else if (type == 'behind') {
            if (num_y < 0) {
                plane.distance = 40 - (-m_dis_y);              
                return plane;
            } else {
                plane.distance = 40 - m_dis_y;               
                return plane;
            }
        }
        else if (type == 'right') {
            if (num_x < 0) {
                plane.distance = 40 - m_dis_x;               
                return plane;
            } else {
                plane.distance = 40 - (-m_dis_x);               
                return plane;
            }
        }
        else if (type == 'front') {
            if (num_y < 0) {
                plane.distance = 40 - m_dis_y;
                return plane;
            } else {
                plane.distance = 40 - (-m_dis_y);
                return plane;
            }
        }
        else if (type == 'top') {
            if (num_z < 0) {
                plane.distance = 40 - m_dis_z;
                return plane;
            } else {
                plane.distance = 40 - (-m_dis_z);
                return plane;
            }
        }
        return plane;
    };
}

效果图:

现阶段效果暂时先这样,如有问题或者建议欢迎提出.......

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页