版本简介:
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
1. Cesium的使用
-
场景初始化与渲染
function onload(Cesium) {Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI...';var viewer = new Cesium.Viewer('Container');viewer.scenePromise.then(function(scene){init(Cesium, scene, viewer);});
}
Cesium.Ion.defaultAccessToken
: Cesium Ion是用于访问Cesium中的3D地形、卫星影像等服务。在这里,初始化时提供了Ion的访问密钥。Cesium.Viewer
: 创建Cesium的3D场景,并绑定到Container
这个div元素。这个viewer负责加载Cesium的地形、影像等基础资源。scenePromise
:Cesium.Viewer
会返回一个scene
对象,表示当前Cesium的场景。之后我们通过init
函数进一步对场景进行设置。
-
影像图层添加
var labelImagery = new Cesium.TiandituImageryProvider({mapStyle: Cesium.TiandituMapsStyle.CIA_C,token: '04e319956d6385dcdf25089104eb8b5b' });
- 这里使用了Cesium的
TiandituImageryProvider
来添加天地图中文标注图层,配合Cesium的地形渲染,使地图更加丰富。
- 这里使用了Cesium的
-
光源和环境光设置
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);
- 设置了环境光和定向光(
DirectionalLight
)以增强场景的光照效果。
- 设置了环境光和定向光(
-
天际线分析和场景状态判断
if (!scene.pickPositionSupported) {alert('不支持深度纹理,天际线分析功能无法使用!'); }
- 使用Cesium的
pickPositionSupported
来判断浏览器是否支持深度纹理,这对天际线分析是必须的。
- 使用Cesium的
2. SuperMap的使用
-
天际线分析功能(Skyline)
var skyline = new SuperMap3D.Skyline(scene);
- 使用
SuperMap3D.Skyline
来初始化SuperMap的天际线分析工具,这是SuperMap提供的高级空间分析功能,用于分析城市建筑物等的天际线轮廓。
- 使用
-
绘制限高体
var polygonHandler = new SuperMap3D.DrawHandler(viewer, SuperMap3D.DrawMode.Polygon); polygonHandler.drawEvt.addEventListener(function (result) {skyline.removeLimitbody("limitBody");var polygon = result.object;polygon.show = false;var pos = polygon.positions;var positions = [];for (var i = 0, len = pos.length; i < len; i++) {var cartographic = Ceisum.Cartographic.fromCartesian(pos[i]);var longitude = Ceisum.Math.toDegrees(cartographic.longitude);var latitude = Ceisum.Math.toDegrees(cartographic.latitude);positions.push([longitude, latitude]);}positions = unique(positions);var arr = [];for (var i = 0, len = positions.length; i < len; i++) {arr.push(positions[i][0]);arr.push(positions[i][1]);}skyline.addLimitbody({position: arr,name: "limitBody"}); });
- 这里使用了
SuperMap3D.DrawHandler
来进行多边形绘制,完成后调用skyline.addLimitbody
来添加限高体,这是SuperMap提供的另一个分析功能。
- 这里使用了
-
加载S3M场景
var promise = scene.open(URL_CONFIG.SCENE_CBD); SuperMap3D.when(promise, function (layers) {scene.camera.setView({destination: SuperMap3D.Cartesian3.fromDegrees(116.4465, 39.9066, 47.9552),orientation: {heading: 0.34395448573153864,pitch: -0.0538346996932666,roll: 6.2831853071795685}});for (var i = 0; i < layers.length; i++) {layers[i].selectEnabled = false;} }, function (e) {var title = '加载SCP失败,请检查网络连接状态或者url地址是否正确?';widget.showErrorPanel(title, undefined, e); });
- 使用
scene.open()
加载SuperMap的S3M模型数据,并在加载完成后通过Cesium的setView
来调整相机位置。
- 使用
3. 前端按钮交互
-
通过按钮与用户交互,调用不同的功能。
-
提取天际线
$('#chooseView').click(function () {var cartographic = scene.camera.positionCartographic;var longitude = Ceisum.Math.toDegrees(cartographic.longitude);var latitude = Ceisum.Math.toDegrees(cartographic.latitude);var height = cartographic.height;skyline.viewPosition = [longitude, latitude, height];skyline.pitch = Ceisum.Math.toDegrees(scene.camera.pitch);skyline.direction = Ceisum.Math.toDegrees(scene.camera.heading);skyline.radius = 10000;skyline.build(); });
- 点击
chooseView
按钮后,会获取当前相机的经纬度和高度,并使用SuperMap的skyline
对象来构建天际线分析。
- 点击
-
绘制限高体
$('#setLimitBody').click(function () {if (polygonHandler.active) {return;}polygonHandler.activate(); });
- 通过点击
setLimitBody
按钮,激活多边形绘制功能(由SuperMap提供),绘制完成后会自动调用skyline.addLimitbody
来添加限高体。
- 通过点击
-
清除
$('#clear').click(function () {viewer.entities.removeAll();skyline.clear();polygonHandler.clear(); });
- 通过
clear
按钮清除场景中的所有实体(Cesium)和天际线分析数据(SuperMap)。
- 通过
-
二维天际线
$('#getSkyline2D').click(function () {skyline.getSkyline2DAsync().then(object => {var myChart = echarts.init(document.getElementById("map"));var option = { ... };myChart.setOption(option);}); });
- 获取天际线的二维数据(由SuperMap提供),并使用
Echarts
库在前端绘制图表。
- 获取天际线的二维数据(由SuperMap提供),并使用
6.代码部分:
<!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"><link href="../css/skyline.css" rel="stylesheet"><script type="text/javascript" src="../js/jquery.min.js"></script><script type="text/javascript" src="../js/echarts.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="chooseView" class="button black">提取天际线</button><button type="button" id="getSkyline2D" class="button black">二维天际线</button><button type="button" id="setLimitBody" class="button black">绘制限高体</button><button type="button" id="getSkylineArea" class="button black">拉伸闭合体</button><button type="button" id="clear" class="button black">清除</button></div><div id="map" style="position : absolute;right : 5%; bottom : 5%;width:450px;height:400px;"></div><script type="text/javascript">function onload(Cesium) {Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlZjRiNDQyMi1mZDBhLTQxYTAtYWU4NC1hZDY4YzhjNWU3ZGEiLCJpZCI6MjMyMDI3LCJpYXQiOjE3MjI1MDEzMTd9.3lFzziTrt3ggC3pfiVmNRbSidI52EL4CsOqWKgYxHkM'var viewer = new Cesium.Viewer('Container');viewer.scenePromise.then(function(scene){init(Cesium, scene, viewer);});}function init(Cesium, scene, viewer) {viewer.resolutionScale = window.devicePixelRatio;var labelImagery = new Cesium.TiandituImageryProvider({mapStyle: Cesium.TiandituMapsStyle.CIA_C,//天地图全球中文注记服务token: '04e319956d6385dcdf25089104eb8b5b' //由天地图官网申请的密钥});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);if (!scene.pickPositionSupported) {alert('不支持深度纹理,天际线分析功能无法使用!');}var skyline = new SuperMap3D.Skyline(scene);//创建天际线分析对象var polygonHandler = new SuperMap3D.DrawHandler(viewer, SuperMap3D.DrawMode.Polygon);var widget = viewer.Widget;try {var promise = scene.open(URL_CONFIG.SCENE_CBD);SuperMap3D.when(promise, function (layers) {scene.camera.setView({//图层加载完成,设置相机位置destination: SuperMap3D.Cartesian3.fromDegrees(116.4465, 39.9066, 47.9552),orientation: {heading: 0.34395448573153864,pitch: -0.0538346996932666,roll: 6.2831853071795685}});for (var i = 0; i < layers.length; i++) {layers[i].selectEnabled = false;}}, 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);}}try {// 绘制多边形结束的回调事件polygonHandler.drawEvt.addEventListener(function (result) {// 清除之前的限高体对象skyline.removeLimitbody("limitBody");var polygon = result.object;polygon.show = false;var pos = polygon.positions;var positions = [];// 遍历多边形,取出所有点for (var i = 0, len = pos.length; i < len; i++) {//转化为经纬度,并加入至临时数组var cartographic = Cesium.Cartographic.fromCartesian(pos[i]);var longitude = Cesium.Math.toDegrees(cartographic.longitude);var latitude = Cesium.Math.toDegrees(cartographic.latitude);positions.push([longitude, latitude]);}//去除重复点positions = unique(positions);var arr = [];//再次遍历转化为接口所需的数组格式for (var i = 0, len = positions.length; i < len; i++) {arr.push(positions[i][0]);arr.push(positions[i][1]);}//添加限高体对象skyline.addLimitbody({position: arr,name: "limitBody"});});//去重函数unique = function (arr) {var res = [];var json = {};for (var i = 0; i < arr.length; i++) {if (!json[arr[i]]) {res.push(arr[i]);json[arr[i]] = 1;}}return res;};function mousestyle() { //鼠标样式viewer.enableCursorStyle = false;viewer._element.style.cursor = '';$('body').removeClass('drawCur').addClass('drawCur');}$('#chooseView').click(function () {var cartographic = scene.camera.positionCartographic;var longitude = Cesium.Math.toDegrees(cartographic.longitude);var latitude = Cesium.Math.toDegrees(cartographic.latitude);var height = cartographic.height;//天际线分析的视口位置设置成当前相机位置skyline.viewPosition = [longitude, latitude, height];//设置俯仰和方向skyline.pitch = Ceisum.Math.toDegrees(scene.camera.pitch);skyline.direction = Ceisum.Math.toDegrees(scene.camera.heading);skyline.radius = 10000; // 天际线分析半径设置为10000米skyline.build();$("#getSkyline2D").show();$("#setLimitBody").show();$("#map").hide();});$('#setLimitBody').click(function () {mousestyle();if (polygonHandler.active) {return;}polygonHandler.activate();});$('#clear').click(function () {viewer.entities.removeAll();skyline.clear();polygonHandler.clear();$("#map").hide();});$('#getSkylineArea').click(function () {var cartographic = scene.camera.positionCartographic;var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);var height = cartographic.height;var points = skyline.getSkyline3D();var pointArr = new Array();var cameraPoint = SuperMap3D.Cartesian3.fromDegrees(longitude, latitude, height);pointArr.push(cameraPoint);for (var i = 0; i < points.x.length; i++) {var point = SuperMap3D.Cartesian3.fromDegrees(points.x[i], points.y[i], points.z[i]);pointArr.push(point);}viewer.entities.add({polygon: {extrudedHeight: 30,hierarchy: pointArr,perPositionHeight: true,material: SuperMap3D.Color.ORANGE.withAlpha(1.0)}})});$('#getSkyline2D').click(function () {//获取二维天际线对象,兼容webgpuskyline.getSkyline2DAsync().then(object=>{//用echarts绘制二维天际线var myChart = echarts.init(document.getElementById("map"));var option = {backgroundColor: "rgba(73,139,156,0.9)",title: {text: "二维天际线"},tooltip: {trigger: "axis"},calculable: true,xAxis: [{type: "category",boundaryGap: false,data: object.x,show: false}],yAxis: [{type: "value",min: 0,max: 1}],series: [{name: "",type: "line",data: object.y}]};myChart.setOption(option);$("#map").show();});});}catch (e) {if (scene.context.depthTexture) {swal("天际线分析", "该浏览器不支持深度纹理检测", "warning");}}$("#toolbar").show();$('#loadingbar').remove();}if (typeof SuperMap3D !== 'undefined') {window.startupCalled = true;onload(SuperMap3D);}</script></body></html>