123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /* 引入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;
|