CesiumJS+SuperMap3D.js混用实现通视分析
版本简介:
cesium:1.99;Supermap3D:SuperMap iClient JavaScript 11i(2023);
官方下载文档链家:SuperMap技术资源中心|为您提供全面的在线技术服务
示例参考:support.supermap.com.cn:8090/webgl/Cesium/examples/webgl/examples.html#analysis
support.supermap.com.cn:8090/webgl/examples/webgl/examples.html
概述:
代码中将Cesium用于场景渲染、光照效果和鼠标交互处理,而SuperMap3D则负责加载3D场景和实现通视分析功能。这种设计让Cesium负责基础的场景渲染,而SuperMap3D负责更高级的功能实现,例如加载特定的SCP文件和处理视线分析。
1. Cesium负责的部分:
场景的初始化与渲染
Cesium.Ion.defaultAccessToken = 'your token';
var viewer = new Cesium.Viewer('Container', {
selectionIndicator: false,
infoBox: false,
terrainProvider: Cesium.createWorldTerrain()
});
这段使用了Cesium来创建场景。Cesium.Viewer
用于初始化Cesium的Viewer,并且指定了不显示选择指示器、信息框,同时使用了Cesium自带的世界地形Cesium.createWorldTerrain()
。
场景配置与光照
scene.shadowMap.darkness = 1.275;
scene.hdrEnabled = false;
scene.sun.show = true;
scene.lightSource.ambientLightColor = new Cesium.Color(0.65, 0.65, 0.65, 1);
var position1 = new Cesium.Cartesian3.fromDegrees(116.261209157595, 39.3042238956531, 480);
这段代码使用了Cesium的场景相关配置,包括设置阴影、光照、HDR效果等。另外,通过Cesium.Cartesian3.fromDegrees()
将经纬度转换为三维笛卡尔坐标,添加了光源。
鼠标交互处理
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (e) {
scene.pickPositionAsync(e.position).then((position)=>{
addTarget(position);
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Cesium的ScreenSpaceEventHandler
用于处理鼠标事件,这里通过鼠标点击事件获取场景中的点,并调用pickPositionAsync()
来计算点击位置的三维坐标。
2. SuperMap3D负责的部分:
场景加载与配置
var promise = scene.open('http://www.supermapol.com/realspace/services/3D-CBD-2/rest/realspace');
SuperMap3D.when.all(promise, function (layer) {
scene.camera.setView({
destination: new SuperMap3D.Cartesian3.fromDegrees(116.44621857300415, 39.899281526734555, 216.7793905027196),
orientation: {
heading: 0.41348036210986194,
pitch: -0.13636490404291735,
roll: 6.283185307179563
}
});
for (var i = 0; i < layer.length; i++) {
layer[i].selectEnabled = false;
}
sightline.build();
}, function (e) {
widget.showErrorPanel(title, undefined, e);
});
这里通过SuperMap3D的scene.open()
加载了SuperMap的3D场景,并且通过SuperMap3D.Cartesian3.fromDegrees()
设定相机视角。加载完成后,调用setView
调整相机角度。
通视分析功能
var sightline = new Cesium.Sightline(scene);
sightline.viewPosition = cartographic;
sightline.addTargetPoint({
position: cartographic,
name: name
});
虽然Sightline
是通过Cesium创建的,但功能实现是通过SuperMap3D管理的,特别是addTargetPoint
函数,该函数负责通视分析中添加目标点。
3.具体代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>通视分析</title>
<link href="../../public/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
<link href="../css/pretty.css" rel="stylesheet">
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/config.js"></script>
<script type="text/javascript" src="../../public/SuperMap3D/SuperMap3D.js"></script>
<script src="../../../Cesium-1.99/Build/Cesium/Cesium.js"></script>
<link href="../../../Cesium-1.99/Build/Cesium/Widgets/widgets.css">
</head>
<body>
<div id="Container"></div>
<div id='loadingbar' class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
<div id='toolbar' class="param-container tool-bar">
<button type="button" id="addViewPoint" class="button black">添加观察点</button>
<button type="button" id="addTargetPoint" class="button black">添加目标点</button>
<button type="button" id="clear" class="button black">清除</button>
</div>
<script type="text/javascript">
function onload(Cesium) {
Cesium.Ion.defaultAccessToken = 'your token'
var viewer = new Cesium.Viewer('Container', {
selectionIndicator: false,
infoBox: false,
terrainProvider: Cesium.createWorldTerrain()
});
viewer.scenePromise.then(function(scene){
init(Cesium, scene, viewer);
});
}
function init(Cesium, scene, viewer) {
viewer.resolutionScale = window.devicePixelRatio;
if (!viewer.scene.pickPositionSupported) {
alert('不支持深度纹理,通视分析功能无法使用(无法添加观测点目标点)!');
}
$("#toolbar").show();
$('#loadingbar').remove();
var scene = viewer.scene;
scene.shadowMap.darkness = 1.275; //设置第二重烘焙纹理的效果(明暗程度)
scene.debugShowFramesPerSecond = false;
scene.hdrEnabled = false;
scene.sun.show = true;
// 01设置环境光的强度-新处理CBD场景
scene.lightSource.ambientLightColor = new Cesium.Color(0.65, 0.65, 0.65, 1);
// 添加光源
var position1 = new Cesium.Cartesian3.fromDegrees(116.261209157595, 39.3042238956531, 480);
//光源方向点
var targetPosition1 = new Cesium.Cartesian3.fromDegrees(116.261209157595, 39.3042238956531, 430);
var dirLightOptions = {
targetPosition: targetPosition1,
color: new Cesium.Color(1.0, 1.0, 1.0, 1),
intensity: 0.55
};
directionalLight_1 = new Cesium.DirectionalLight(position1, dirLightOptions);
scene.addLightSource(directionalLight_1);
var sightline = new Cesium.Sightline(scene);
var widget = viewer.cesiumWidget;
try {
var promise = scene.open('http://www.supermapol.com/realspace/services/3D-CBD-2/rest/realspace');
SuperMap3D.when.all(promise, function (layer) {
scene.camera.setView({
destination: new SuperMap3D.Cartesian3.fromDegrees(116.44621857300415, 39.899281526734555, 216.7793905027196),
orientation: {
heading: 0.41348036210986194,
pitch: -0.13636490404291735,
roll: 6.283185307179563
}
});
for (var i = 0; i < layer.length; i++) {
layer[i].selectEnabled = false;
}
sightline.build();
}, function (e) {
if (widget._showRenderLoopErrors) {
var title = '加载SCP失败,请检查网络连接状态或者url地址是否正确?';
widget.showErrorPanel(title, undefined, e);
}
});
} catch (e) {
if (widget._showRenderLoopErrors) {
var title = '渲染时发生错误,已停止渲染。';
widget.showErrorPanel(title, undefined, e);
}
}
var addViewFlag = false;//当前点击状态是否是 添加观察点
var addTargetFlag = false;//当前点击状态是否是 添加目标点
var num = 0;//添加的目标点的点号
var couldRemove = false;//是否能移除目标点
var handlerPoint = new SuperMap3D.DrawHandler(viewer, SuperMap3D.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 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];
}
$("#addViewPoint").on("click", function () {
handler.removeInputAction(SuperMap3D.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(SuperMap3D.ScreenSpaceEventType.LEFT_CLICK);
addViewFlag = true;
if (handlerPoint.active) {
return;
}
viewer.entities.removeAll();
if (couldRemove) {
sightline.removeAllTargetPoint();
}
handlerPoint.activate();
if (addViewFlag || addTargetFlag) {
viewer.enableCursorStyle = false;
viewer._element.style.cursor = '';
$('body').removeClass('drawCur').addClass('drawCur');
}
})
$("#addTargetPoint").on("click", function () {
addViewFlag = false;
addTargetFlag = true;
if (addViewFlag || addTargetFlag) {
viewer.enableCursorStyle = false;
viewer._element.style.cursor = '';
$('body').removeClass('drawCur').addClass('drawCur');
}
//鼠标点击事件,添加点
handler.setInputAction(function (e) {
scene.pickPositionAsync(e.position).then((position)=>{
addTarget(position);
})
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动事件,更新点
handler.setInputAction(function (evt) {
//鼠标移动,更新最后一次添加的目标点的位置
scene.pickPositionAsync(evt.endPosition).then((position)=>{
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;
$('body').removeClass('drawCur');
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
})
$("#clear").on("click", function () {
addViewFlag = false;
addTargetFlag = false;
handlerPoint.clear();
num = 0;
viewer.entities.removeAll();
if (couldRemove) {
sightline.removeAllTargetPoint();
couldRemove = false;
}
viewer.enableCursorStyle = true;
$('body').removeClass('drawCur');
})
}
if (typeof SuperMap3D !== 'undefined') {
window.startupCalled = true;
onload(SuperMap3D);
}
</script>
</body>
</html>
记得更改成自己的token