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负责的部分:

场景的初始化与渲染
javascript 复制代码
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()

场景配置与光照
javascript 复制代码
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()将经纬度转换为三维笛卡尔坐标,添加了光源。

鼠标交互处理
javascript 复制代码
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负责的部分:

场景加载与配置
javascript 复制代码
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调整相机角度。

通视分析功能
javascript 复制代码
var sightline = new Cesium.Sightline(scene);
sightline.viewPosition = cartographic;
sightline.addTargetPoint({
    position: cartographic,
    name: name
});

虽然Sightline是通过Cesium创建的,但功能实现是通过SuperMap3D管理的,特别是addTargetPoint函数,该函数负责通视分析中添加目标点。

3.具体代码

javascript 复制代码
<!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

4.实现效果展示:

相关推荐
阿伟来咯~29 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端34 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱37 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
starsongda39 分钟前
科技成果跃然“屏”上,虚拟展厅引领科技展示新风尚
科技·3d·虚拟现实
guai_guai_guai1 小时前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨1 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试