本人小白一枚,文章如有问题还请各位大神评论区指出。整体实现是参考SuperMap iClient3D for Cesium的通视分析功能源码~
文章目录
前言
SuperMap iClient3D for Cesium中的Sightline类提供了根据观察者点位和目标点建立视线分析,并在场景中分析得到结果的功能。具体下方代码都有详细注释。
一、主要功能
效果图:
通过点击“添加观察点”按钮添加观测点,然后点击“添加目标点”按钮可添加多个目标点,生成的视线绿色表示可见,红色表示被遮挡。
二、具体实现
1.HTML主要结构
<div class="btnBox">
<el-button type="primary" @click="addViewPoint">添加观察点</el-button>
<el-button type="primary" @click="addTargetPoint">添加目标点</el-button>
<el-button type="primary" @click="clear">清 除</el-button>
</div>
2.javascript
<script setup>
//#region
//var viewer = window.viewer;
var scene = viewer.scene;
if (!viewer.scene.pickPositionSupported) {
alert("不支持深度纹理,通视分析功能无法使用(无法添加观测点目标点)!");
}
var sightline = new Cesium.Sightline(scene); //视线分析,即通视分析,根据观察者点位和目标点建立视线分析,并在场景中分析得到结果。
sightline.build(); //执行通视分析。
var addViewFlag = false; //当前点击状态是否是 添加观察点
var addTargetFlag = false; //当前点击状态是否是 添加目标点
var num = 0; //添加的目标点的点号
var couldRemove = false; //是否能移除目标点
var handlerPoint = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Point); //绘制处理器对象类。
handlerPoint.drawEvt.addEventListener(function (result) {
//添加观察点
if (addViewFlag) {
var point = result.object;
// point.show = false;
var position = result.object.position;
//将获取的点的位置转化成经纬度
var cartographic = Cartesian2toDegrees(position);
//设置观察点
sightline.viewPosition = cartographic;
addViewFlag = false;
}
handlerPoint.deactivate();
});
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas); //处理用户输入事件。可以添加自定义功能,以便在用户输入时执行。
//添加观察点
function addViewPoint() {
addViewFlag = true;
if (handlerPoint.active) {
return;
}
viewer.entities.removeAll();
if (couldRemove) {
sightline.removeAllTargetPoint();
}
handlerPoint.activate(); //激活handler。
}
//添加目标点
function addTargetPoint() {
addViewFlag = false;
addTargetFlag = true;
if (addViewFlag || addTargetFlag) {
viewer.enableCursorStyle = false;
viewer._element.style.cursor = "";
}
//鼠标点击事件,添加点
handler.setInputAction(function (e) {
var position = scene.pickPosition(e.position);
addTarget(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动事件,更新点
handler.setInputAction(function (evt) {
//鼠标移动,更新最后一次添加的目标点的位置
var position = scene.pickPosition(evt.endPosition);
if (num > 0) {
sightline.removeTargetPoint("point0");
var cartographic = Cartesian2toDegrees(position);
var flag = sightline.addTargetPoint({
position: cartographic,
name: "point0",
});
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//鼠标右键事件,结束
handler.setInputAction(function () {
viewer.enableCursorStyle = true;
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//清除
function clear() {
addViewFlag = false;
addTargetFlag = false;
handlerPoint.clear();
num = 0;
viewer.entities.removeAll();
if (couldRemove) {
sightline.removeAllTargetPoint();
couldRemove = false;
}
viewer.enableCursorStyle = true;
}
//添加通视点
function addTarget(CartesianPosition) {
if (addViewFlag === false && addTargetFlag) {
num += 1;
//将获取的点的位置转化成经纬度
var cartographic = Cartesian2toDegrees(CartesianPosition);
//添加目标点
var name = "point" + num;
var flag = sightline.addTargetPoint({
position: cartographic,
name: name,
});
couldRemove = true;
}
}
//笛卡尔转换为经纬度
function Cartesian2toDegrees(position) {
var cartographic = Cesium.Cartographic.fromCartesian(position);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
return [longitude, latitude, height];
}
//#endregion
</script>
总结
以上代码仅实现基本的通视分析功能,相较官方示例去掉了一些场景设置及鼠标绘制样式的代码,有需要的朋友可以自己加上,包括线形、颜色等样式都可以参考API文档中的方法进行设置。