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