/* 引入Cesium */ // import * as Cesium from 'Cesium'; /** * 剖切 */ class GeologyClipPlan { /** * 默认初始化 * @param {Object} viewer 三维场景 */ constructor(viewer) { if (!viewer) throw new Cesium.DeveloperError('no viewer object!'); this._viewer = viewer; this._camera = this._viewer.camera; this._scene = this._viewer.scene; this.tileset = undefined; this.targetY = 0.0; this.planeEntities = []; this._mouseHandler(); } /** * @ignore 忽略注释,注释不生成Doc */ _mouseHandler() { let _self = this; let viewer = _self._viewer; let scene = _self._scene; let selectedPlane; let downHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); // 监听鼠标按下时,选择平面并设置样式 downHandler.setInputAction(function(movement) { let pickedObject = scene.pick(movement.position); if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id) && Cesium.defined(pickedObject.id.plane)) { // 获取选中平面对象 selectedPlane = pickedObject.id.plane; // 选中时修改平面的材质透明度 selectedPlane.material = Cesium.Color.RED.withAlpha(0.05); selectedPlane.outlineColor = Cesium.Color.RED; // 当鼠标选中平面后,禁止场景的拖拽 scene.screenSpaceCameraController.enableInputs = false; } }, Cesium.ScreenSpaceEventType.LEFT_DOWN); // 监听鼠标向上释放时,平面设置样式 let upHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); upHandler.setInputAction(function() { if (Cesium.defined(selectedPlane)) { // 鼠标松开时复原平面的材质透明度 selectedPlane.material = Cesium.Color.RED.withAlpha(0.1); selectedPlane.outlineColor = Cesium.Color.RED; selectedPlane = undefined; } // 当鼠标松开选中平面后,开启场景的拖拽 scene.screenSpaceCameraController.enableInputs = true; }, Cesium.ScreenSpaceEventType.LEFT_UP); // 监听鼠标选中移动时,设置平面 let moveHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); moveHandler.setInputAction(function(movement) { //当存在选中平面时执行 if (Cesium.defined(selectedPlane)) { // 移动起点的高度减去移动终点的高度 let deltaY = movement.startPosition.y - movement.endPosition.y; // 目标高度 _self.targetY += deltaY; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); } /** * 修改平面的高度 * @ignore 忽略注释,注释不生成Doc */ _createPlaneUpdateFunction(plane) { let _self = this; return function() { plane.distance = _self.targetY; return plane; }; } } /** * 通用对外公开函数 */ Object.assign(GeologyClipPlan.prototype, /** @lends GeologyClipPlan.prototype */ { /** * @param {Object} tileset * @param {Object} options */ activate(tileset, options) { let _self = this; options = options || {}; let viewer = _self._viewer; // 创建裁剪平面 let distance = 100000; //从原点到平面的最短距离。距离的符号决定了原点在平面的哪一边。如果距离为正,原点在法线方向的半空间中;如果是负的,原点在与法线相对的半空间中;如果为零,平面穿过原点。 // 定义一个ClippingPlaneCollection类,用来存储裁剪面 let clippingPlanes = new Cesium.ClippingPlaneCollection({ // modelMatrix: Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(0.0, -500, Math.abs(2))), // modelMatrix: Cesium.Matrix4.IDENTITY, //一组ClippingPlane对象,用于选择性地禁用每个平面外部的渲染。 planes: [ // ClippingPlane对象数组集合 // 裁剪面两个参数的:第一个为平面法向量,第二个为原点到平面的垂直距离 new Cesium.ClippingPlane( // 裁切面 //笛卡尔3:表示为三维空间的平面的法向量,x表示为该法向量在x轴上的分量,y表示为该法向量在y轴上的分量,z表示为该法向量在z轴上的分量 new Cesium.Cartesian3(0.0, 0.0, -1.0), // 法线 // new Cesium.Cartesian3(1, 0, 0), // new Cesium.Cartesian3(0.0, 1.0, 0), distance, //原点到平面的最短距离,设置0就好 ), ], //应用于裁剪对象的边缘的高光的宽度(以像素为单位) edgeWidth: 1.0, //模型被裁切部分的截面线宽 }); _self.tileset = tileset; tileset.clippingPlanes = clippingPlanes; //切割面 tileset.debugShowBoundingVolume = false; //打开包围卷 // tileset.modelMatrix = Cesium.Matrix4.fromArray( // [0.9972458032561666, 0.04372029028528979, 0.05991113506964879, 0, // -0.03623787897545647, 0.9920229449104262, -0.12073646051879428, 0, // -0.06471185374661931, 0.11823287609043515, 0.9908750491338749, 0, // -663.0794944260269, 1211.490494620055, 2974.1003134818748, 1 // ]); // 当模型准备好时执行 return tileset.readyPromise .then(function() { let boundingSphere = tileset.boundingSphere; //外包球 let radius = boundingSphere.radius; //外包球半径 if ( !Cesium.Matrix4.equals( // Cesium.Matrix4.equals(a,b)判断两个四维矩阵是否相等 tileset.root.transform, // 整个根节点模型矩阵,该tileSet=>世界坐标系 Cesium.Matrix4.IDENTITY // 单位矩阵,对角线值为1.0的4*4矩阵 ) ) { // The clipping plane is initially positioned at the tileset's root transform. // Apply an additional matrix to center the clipping plane on the bounding sphere center. // 获取模型的世界坐标(笛卡尔) // Cesium.Matrix4.getTranslation 通过仿射变换矩阵获取该tileSet的世界坐标 const transformCenter = Cesium.Matrix4.getTranslation( tileset.root.transform, new Cesium.Cartesian3() ); // 将笛卡尔坐标转换为WGS84经纬度坐标(模型的) const transformCartographic = Cesium.Cartographic.fromCartesian( transformCenter ); // 将笛卡尔坐标转换为WGS84经纬度坐标(截面的) const boundingSphereCartographic = Cesium.Cartographic.fromCartesian( tileset.boundingSphere.center ); const height = boundingSphereCartographic.height - transformCartographic.height; // 从一个Cartesian3对象生成Matrix4变换矩阵(裁切面的) clippingPlanes.modelMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(0.0, 0.0, height)); } //中心点 // let entity = viewer.entities.add({ // position: Cartesian33, // point: { // pixelSize: 10, // color: new Cesium.Color.fromCssColorString("red"), // outlineColor: new Cesium.Color.fromCssColorString("blue"), // outlineWidth: 2, // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //指定高度相对于什么的属性。 // disableDepthTestDistance: Number.POSITIVE_INFINITY, //指定距离相机的距离,在这个距离上禁用深度测试。 // } // }); // 定位到模型,并设置相机的俯仰角和距离 viewer.zoomTo( tileset, new Cesium.HeadingPitchRange(0.5, -0.2, radius / 10) ); // Cesium.Matrix4.multiplyByPoint(tileset.root.transform, boundingSphere.center, new Cesium.Cartesian3(0, 0, 0)) // clippingPlanes.modelMatrix = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(0.0, radius/10, 0)); // const redPlane = viewer.entities.add({ // name: "Red plane with black outline", // position:Cartesian33, // plane: { // plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Y, 0.0), // dimensions: new Cesium.Cartesian2(200.0, 200.0), // material: Cesium.Color.RED.withAlpha(0.5), // outline: true, // outlineColor: Cesium.Color.BLACK, // }, // }); // const outlineOnly = viewer.entities.add({ // name: "Yellow plane outline", // position: Cartesian33, // plane: { // plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_Z, 0.0), // dimensions: new Cesium.Cartesian2(200.0, 200.0), // fill: false, // outline: true, // outlineColor: Cesium.Color.YELLOW, // }, // }); let cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); //将弧度转为度的十进制度表示 let lng = Cesium.Math.toDegrees(cartographic.longitude); let lat = Cesium.Math.toDegrees(cartographic.latitude); let alt = cartographic.height; //模型高度 var Cartesian33 = Cesium.Cartesian3.fromDegrees(lng, lat, 105) // 遍历添加裁切面模型 for (let i = 0; i < clippingPlanes.length; ++i) { let plane = clippingPlanes.get(i); let planeEntity = viewer.entities.add({ // 笛卡儿坐标系的原点位置为模型外接圆的圆心 position: Cartesian33, plane: { // 范围 dimensions: new Cesium.Cartesian2( radius / 10, radius / 20 ), // dimensions: new Cesium.Cartesian2( // 200, // 200 // ), //设置材质透明度 material: Cesium.Color.RED.withAlpha(0.1), //使用回调函数,动态改变模型位置 plane: new Cesium.CallbackProperty( _self._createPlaneUpdateFunction(plane), false ), // 轮廓 outline: true, //轮廓颜色 outlineColor: Cesium.Color.RED, }, }); _self.planeEntities.push(planeEntity); } return tileset; }) }, /** * 移除裁切面 */ toggleClipping() { let _self = this; // // if (_self.isShowTileSet) { // _self.tileset._clippingPlanes = null; // // _self.isShowTileSet = false; // // } else { // // _self.tileset._clippingPlanes = _self.clippingPlanes; // // _self.isShowTileSet = true; // // } for (let i = 0; i < _self.planeEntities.length; i++) { _self._viewer.entities.remove(_self.planeEntities[i]); } _self.planeEntities = []; _self.targetY = 0.0; let boundingSphere = _self.tileset.boundingSphere; _self._camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(Cesium.Math.toRadians(120.0), Cesium.Math.toRadians(-10), boundingSphere.radius * 2.5)) _self._camera.lookAtTransform(Cesium.Matrix4.IDENTITY) }, // Track and create the bindings for the view model reset() { // viewer.entities.removeAll(); // viewer.scene.primitives.remove(tileset); this.planeEntities = []; this.targetY = 0.0; // tileset = undefined; } }); export default GeologyClipPlan;