/* 引入Cesium */ // import * as Cesium from 'Cesium'; import CreateRemindertip from "../common/ReminderTip.js"; import CoordTransform from "../common/CoordTransform.js"; /** * 视线分析 通视分析 透视分析 */ class SightLine { /** * 默认初始化 * @param {Object} viewer 三维场景 */ constructor(viewer) { if (!viewer) throw new Cesium.DeveloperError('no viewer object!'); this._viewer = viewer; this._resultObject = { viewPoint: undefined, //通视分析起点 targetPoints: [], //通视分析目标点集合 targetPoint: undefined, //当前目标点 objectExclude: [], //射线排除集合 entities: [], //创建的Entity对象 }; } /** * 空间两点间距离 * @ignore 忽略注释,注释不生成Doc * @param {Object} point1 * @param {Object} point2 */ _distance(point1, point2) { let point1cartographic = Cesium.Cartographic.fromCartesian(point1); let point2cartographic = Cesium.Cartographic.fromCartesian(point2); /**根据经纬度计算出距离**/ let geodesic = new Cesium.EllipsoidGeodesic(); geodesic.setEndPoints(point1cartographic, point2cartographic); let s = geodesic.surfaceDistance; //返回两点之间的距离 s = Math.sqrt( Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2) ); return s; } /** * 检测程序运行环境 * @return {SightLine.RuntimeEnvironment} */ _checkAppOrWeb() { if (window.navigator.userAgent.match( /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i )) { return SightLine.RuntimeEnvironment.App; } else { return SightLine.RuntimeEnvironment.Web; } } /** * 是否是运行于App * @ignore */ _isRuntimeApp() { if (this._checkAppOrWeb() === SightLine.RuntimeEnvironment.App) { return true; } return false; } /** * 是否是运行于App * @ignore */ _isRuntimeWeb() { if (this._checkAppOrWeb() === SightLine.RuntimeEnvironment.Web) { return true; } return false; } /** * @ignore * 创建操作的主容器 */ _createOperationMainDom() { //创建画布 let buttonDiv = document.createElement('div'); buttonDiv.id = "drawButtonDiv"; buttonDiv.style.width = '80px'; buttonDiv.style.backgroundColor = 'rgba(5, 45, 155, 0.7)'; buttonDiv.style.borderRadius = '5px'; buttonDiv.style.display = 'flex'; buttonDiv.style.flexDirection = 'column'; buttonDiv.style.padding = '8px'; buttonDiv.style.justifyContent = 'center'; buttonDiv.style.position = 'absolute'; buttonDiv.style.bottom = '150px'; buttonDiv.style.right = '10px'; // let btnUndo = document.createElement('button'); // btnUndo.id = "btnDrawBackout"; // btnUndo.style.height = '30px'; // btnUndo.style.marginBottom = '8px'; // btnUndo.style.backgroundColor = 'rgba(52, 137, 255, 1.0)'; // btnUndo.style.color = 'rgb(255, 255, 255)'; // btnUndo.style.border = '0px solid red'; // btnUndo.style.borderRadius = '5px'; // btnUndo.innerHTML = '回退'; // btnUndo.style.fontSize = '13px'; // btnUndo.style.cursor = 'pointer'; // buttonDiv.appendChild(btnUndo); let btnCompletion = document.createElement('button'); btnCompletion.id = "btnDrawComplete"; btnCompletion.style.height = '30px'; btnCompletion.style.backgroundColor = 'rgba(88, 185, 45, 1.0)'; btnCompletion.style.color = 'rgb(255, 255, 255)'; btnCompletion.style.border = '0px solid red'; btnCompletion.style.borderRadius = '5px'; btnCompletion.innerHTML = '完成'; btnCompletion.style.fontSize = '13px'; btnCompletion.style.cursor = 'pointer'; buttonDiv.appendChild(btnCompletion); /* 加入到页面 */ document.body.appendChild(buttonDiv); } /** * 创建顶部弹出提示消息 1秒后自动消失 * @ignore * @param {String} message 消息内容 */ _showTooltipMessage(message) { let msgMainDom = document.getElementById('messageMainDom'); if (msgMainDom !== null && msgMainDom !== undefined) { document.body.removeChild(msgMainDom); } msgMainDom = document.createElement('div'); msgMainDom.style.width = '30%'; msgMainDom.style.backgroundColor = 'rgba(237, 248, 230, 1.0)'; msgMainDom.style.height = '45px'; msgMainDom.style.border = 'solid 2px rgb(219, 241, 208)'; msgMainDom.style.borderRadius = '8px'; msgMainDom.style.display = 'flex'; msgMainDom.style.alignItems = 'center'; msgMainDom.style.paddingLeft = '10px'; msgMainDom.style.color = 'rgb(91, 188, 48)'; msgMainDom.style.fontSize = '14px'; msgMainDom.style.fontWeight = '600'; msgMainDom.style.position = 'absolute'; msgMainDom.style.left = '35%'; msgMainDom.style.transition = 'transform 1s'; msgMainDom.style.transform = 'translateY(-90px)'; msgMainDom.style.top = '0px'; msgMainDom.style.zIndex = 1000; document.body.appendChild(msgMainDom); let strHtml = ''; strHtml += "
"; strHtml += "
" + message + "
"; msgMainDom.innerHTML = strHtml; msgMainDom.addEventListener('transitionend', function() { setTimeout(function() { document.body.removeChild(msgMainDom); }, 1000); }, false); setTimeout(function() { msgMainDom.style.transform = 'translateY(50px)'; }, 100) } } /** * 通用对外公开函数 */ Object.assign(SightLine.prototype, /** @lends SightLine.prototype */ { /** * 开启通视分析 */ startSightLine() { let _self = this; _self.clearAll(); let toolTip = "左键单击创建视角起点"; if (this._isRuntimeApp()) { toolTip = "单击创建视角起点"; _self._showTooltipMessage(toolTip); } _self.handler = new Cesium.ScreenSpaceEventHandler(_self._viewer.canvas); _self.handler.setInputAction((event) => { let loc = CoordTransform._transfromFromScreenPoint(_self._viewer, event.position); toolTip = "左键创建视角终点,右键结束通视分析"; if (this._isRuntimeApp()) { toolTip = "再次单击创建视角终点"; _self._showTooltipMessage(toolTip); } if (!Cesium.defined(loc.sLocation)) return; let cartesian = loc.sLocation; if (!_self._resultObject.viewPoint) { _self._resultObject.viewPoint = cartesian; let pointEntity = _self._viewer.entities.add({ position: cartesian, point: { color: Cesium.Color.YELLOW, pixelSize: 5, }, //文字标签 label: { text: "观察位置", font: '12px sans-serif', fillColor: new Cesium.Color(255 / 255, 255 / 255, 255 / 255, 1.0), outlineColor: new Cesium.Color(0, 154 / 255, 94 / 255, 1.0), style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 1.0, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -28), showBackground: true, backgroundColor: new Cesium.Color(0, 0, 0, 0.6), disableDepthTestDistance: Number.POSITIVE_INFINITY, }, }); _self._resultObject.objectExclude.push(pointEntity); _self._resultObject.entities.push(pointEntity); } else { _self._resultObject.targetPoint = cartesian; let pointEntity = _self._viewer.entities.add({ position: cartesian, point: { color: Cesium.Color.YELLOW, pixelSize: 5, }, //文字标签 label: { text: "目标位置", font: '12px sans-serif', fillColor: new Cesium.Color(255 / 255, 255 / 255, 255 / 255, 1.0), outlineColor: new Cesium.Color(0, 154 / 255, 94 / 255, 1.0), style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 1.0, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -28), showBackground: true, backgroundColor: new Cesium.Color(0, 0, 0, 0.6), disableDepthTestDistance: Number.POSITIVE_INFINITY, }, }); _self._resultObject.objectExclude.push(pointEntity); _self._resultObject.entities.push(pointEntity); let direction = Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract( _self._resultObject.targetPoint, _self._resultObject.viewPoint, new Cesium.Cartesian3() ), new Cesium.Cartesian3() ); let ray = new Cesium.Ray(_self._resultObject.viewPoint, direction); let result = _self._viewer.scene.pickFromRay(ray, _self._resultObject.objectExclude); // 计算交互点,返回第一个 if (result) { let dis0 = _self._distance( _self._resultObject.viewPoint, _self._resultObject.targetPoint ); let dis1 = _self._distance( _self._resultObject.viewPoint, result.position ); let dis2 = _self._distance( result.position, _self._resultObject.targetPoint ); console.log(dis0, dis1, dis2); if (dis0 > dis1) { let _poly0 = _self._viewer.entities.add({ polyline: { positions: [_self._resultObject.viewPoint, result.position], material: Cesium.Color.GREEN, width: 3, }, }); _self._resultObject.entities.push(_poly0); let _poly1 = _self._viewer.entities.add({ polyline: { positions: [result.position, _self._resultObject.targetPoint], material: Cesium.Color.RED, width: 3, }, }); _self._resultObject.entities.push(_poly1); _self._resultObject.targetPoints.push({ targetPoint: cartesian, visual: false, //如果dis2足够小,其实他是可视的 distance: [dis0, dis1, dis2], //[初始点和终点,初始点和交点,交点和终点] }); } else { let _poly2 = _self._viewer.entities.add({ polyline: { positions: [ _self._resultObject.viewPoint, _self._resultObject.targetPoint, ], material: Cesium.Color.GREEN, width: 3, }, }); _self._resultObject.entities.push(_poly2); _self._resultObject.targetPoints.push({ targetPoint: cartesian, visual: true, //如果dis2足够小,其实他是可视的 distance: [dis0, dis1, dis2], //[初始点和终点,初始点和交点,交点和终点] }); } } } if (_self._resultObject.objectExclude.length === 2) { if (this._isRuntimeApp()) { //创建按钮 _self._createOperationMainDom(); //完成绘制 document.getElementById("btnDrawComplete").onclick = () => { CreateRemindertip(toolTip, event.endPosition, false); _self.handler.destroy(); let buttonDiv = document.getElementById("drawButtonDiv"); if (buttonDiv) { //从页面移除 document.body.removeChild(buttonDiv); } } } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); _self.handler.setInputAction(function(move) { if (_self._isRuntimeApp()) return; CreateRemindertip(toolTip, move.endPosition, true); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); _self.handler.setInputAction((event) => { CreateRemindertip(toolTip, event.endPosition, false); _self.handler.destroy(); }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, /** * 清除视域分析 */ clearAll() { this._resultObject.entities.forEach((element) => { this._viewer.entities.remove(element); }); this._resultObject = { viewPoint: undefined, //通视分析起点 targetPoints: [], //通视分析目标点集合 targetPoint: undefined, //当前目标点 objectExclude: [], //射线排除集合 entities: [], //创建的Entity对象 }; if (this.handler) { this.handler.destroy(); } let buttonDiv = document.getElementById("drawButtonDiv"); if (buttonDiv) { //从页面移除 document.body.removeChild(buttonDiv); } } }); /** * 运行环境类型 */ SightLine.RuntimeEnvironment = Object.freeze(({ App: 'app', Web: 'web' })) export default SightLine;