123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- /* 引入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 += "<div style='"
- strHtml += "background-color: rgb(88, 185, 45);";
- strHtml += "color: rgb(255, 255, 255);";
- strHtml += "height: 24px;";
- strHtml += "width: 24px;";
- strHtml += "border-radius: 20px;";
- strHtml += "display: flex;";
- strHtml += "justify-content: center;";
- strHtml += "align-items: center;";
- strHtml += "font-size: 14px;";
- strHtml += "margin-right: 18px;";
- strHtml += "'>✓</div>";
- strHtml += "<div>" + message + "</div>";
- 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;
|