SuperMap iClient3D for WebGL 影像数据可视范围控制

在共享同一影像底图的服务场景中,如何基于用户权限体系实现差异化的数据可视范围控制?SuperMap iClient3D for WebGL提供了自定义区域影像裁剪的方法。让我们一起看看吧!

一、数据制作

对于上述视频中的地图制作,此处不做讲述,如有需要可访问:Online 开发者中心

可视化案例中提供了详细的代码、数据下载链接及数据制作过程。

二、实现思路

影像数据可视范围控制的实现思路如下图所示:

三、关键代码

遍历Geojson数据获取坐标数组关键代码如下:

javascript 复制代码
if (data.type === "MultiPolygon") {
    // 处理 MultiPolygon 类型的数据,可能包含多个多边形
    for (let i = 0; i < data.coordinates.length; i++) {
        for (let j = 0; j < data.coordinates[i].length; j++) {
            // 获取当前多边形的坐标数组
            let positions = data.coordinates[i][j];
            // 用于存储转换后的笛卡尔坐标
            let superMapPositions = [];
            for (let k = 0; k < positions.length; k++) {
                // 将经纬度坐标转换为地理坐标对象,高度设为 0
                var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[k][0], positions[k][1], 0);
                // 将地理坐标对象转换为笛卡尔坐标
                var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
                superMapPositions.push(cartesian);
            }
            // 转换为经纬度和高度数组
            let finalPositions = [];
            for (let k = 0, len = superMapPositions.length; k < len; k++) {
                // 将笛卡尔坐标转换为地理坐标对象
                var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[k]);
                // 将弧度制的经度转换为角度制
                var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
                // 将弧度制的纬度转换为角度制
                var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
                // 获取高度值
                var h = cartographic.height;
                // 将经纬度和高度值依次添加到数组中
                finalPositions.push(longitude);
                finalPositions.push(latitude);
                finalPositions.push(h);
            }
            // 将当前多边形的位置信息添加到 allPositions 数组中
            allPositions = allPositions.concat(finalPositions);
        }
    }
} else if (data.type === "Polygon") {
    // 处理 Polygon 类型的数据,只包含一个多边形
    let positions = data.coordinates[0];
    let superMapPositions = [];
    for (let i = 0; i < positions.length; i++) {
        var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[i][0], positions[i][1], 0);
        var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
        superMapPositions.push(cartesian);
    }
    // 转换为经纬度和高度数组
    let finalPositions = [];
    for (let i = 0, len = superMapPositions.length; i < len; i++) {
        var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[i]);
        var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
        var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
        var h = cartographic.height;
        finalPositions.push(longitude);
        finalPositions.push(latitude);
        finalPositions.push(h);
    }
    // 将当前多边形的位置信息赋值给 allPositions 数组
    allPositions = finalPositions;
}

四、示例完整代码

javascript 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义区域影像裁剪</title>
    <link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
    <link href="./css/pretty.css" rel="stylesheet">
    <script src="./js/jquery.min.js"></script>
    <script src="./js/spectrum.js"></script>
    <script src="./js/config.js"></script>
    <script src="./js/tooltip.js"></script>
    <script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
</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">
        <div class="param-item">
            <select id="citySelector" style="width: 150px">
                <option value="" selected disabled hidden>请选择所属区域</option>
                <option value="guiyang_city">贵阳市</option>
                <option value="anshun_city">安顺市</option>
                <option value="bijie_city">毕节市</option>
                <option value="liupanshui_city">六盘水市</option>
                <option value="tongren_city">铜仁市</option>
                <option value="zunyi_city">遵义市</option>
                <option value="qiandongnan_prefecture">黔东南</option>
                <option value="qiannan_prefecture">黔南</option>
                <option value="qianxinan_prefecture">黔西南</option>
            </select>
        </div>
    </div>
    <script>
        // 定义各城市中心点经纬度信息
        const cityCenters = {
            "guiyang_city": [106.713478, 26.578341],
            "anshun_city": [105.934854, 26.224645],
            "bijie_city": [105.291238, 27.302327],
            "liupanshui_city": [104.831343, 26.590612],
            "tongren_city": [109.188523, 27.704321],
            "zunyi_city": [106.932211, 27.707422],
            "qiandongnan_prefecture": [107.983421, 26.587345],
            "qiannan_prefecture": [107.501234, 26.234567],
            "qianxinan_prefecture": [104.902345, 25.098765]
        };

        // 页面加载完成后执行的函数,初始化 SuperMap3D 地图
        function onload(SuperMap3D) {
            // 通过 config.js 中的 getEngineType 函数,获取引擎类型(EngineType),用于设置启动方式
            let EngineType = getEngineType();
            // 创建一个 SuperMap3D 的 Viewer 实例,将其显示在 id 为 'Container' 的容器中
            let viewer = new SuperMap3D.Viewer('Container', {
                contextOptions: {
                    // 设置 WebGL 上下文类型,Webgl2 对应值为 2,WebGPU 对应值为 3
                    contextType: Number(EngineType),
                }
            });

            // 当场景加载完成后,调用 init 函数进行初始化操作
            viewer.scenePromise.then(function (scene) {
                init(SuperMap3D, scene, viewer);
            });
        }

        // 初始化地图场景的函数
        function init(SuperMap3D, scene, viewer) {
            // 设置地图的分辨率比例,根据设备的像素比进行调整
            viewer.resolutionScale = window.devicePixelRatio;
            $('#loadingbar').remove();

            // 存储添加的影像图层
            let tmpLayer = viewer.imageryLayers.addImageryProvider(
                new SuperMap3D.SuperMapImageryProvider({
                    url: "http://localhost:8090/iserver/services/map-GuiZhou/rest/maps/%E8%B4%B5%E5%B7%9E%E7%9C%81%E5%9C%B0%E5%BD%A2%E5%9B%BE",
                })
            );
            // 设置所加载的影像背景透明,将白色背景设为透明
            tmpLayer.transparentBackColor = SuperMap3D.Color.fromCssColorString('#ffffff');
            // 设置透明背景的容差,即与指定颜色相近的颜色也会被视为透明
            tmpLayer.transparentBackColorTolerance = Number(0.1);
            // 让地图飞到影像所在的位置,以便用户能看到影像
            viewer.flyTo(tmpLayer);

            // 监听城市选择框的 change 事件,当用户选择不同的城市时触发
            $('#citySelector').change(function () {
                // 获取用户选择的城市的值
                var selectedCity = $(this).val();
                if (selectedCity) {
                    // 根据选择的城市加载对应的 JSON 边界数据文件
                    $.getJSON('./data/json/' + selectedCity + '.json', function (data) {
                        // 用于存储所有多边形的位置信息
                        let allPositions = [];

                        if (data.type === "MultiPolygon") {
                            // 处理 MultiPolygon 类型的数据,可能包含多个多边形
                            for (let i = 0; i < data.coordinates.length; i++) {
                                for (let j = 0; j < data.coordinates[i].length; j++) {
                                    // 获取当前多边形的坐标数组
                                    let positions = data.coordinates[i][j];
                                    // 用于存储转换后的笛卡尔坐标
                                    let superMapPositions = [];
                                    for (let k = 0; k < positions.length; k++) {
                                        // 将经纬度坐标转换为地理坐标对象,高度设为 0
                                        var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[k][0], positions[k][1], 0);
                                        // 将地理坐标对象转换为笛卡尔坐标
                                        var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
                                        superMapPositions.push(cartesian);
                                    }
                                    // 转换为经纬度和高度数组
                                    let finalPositions = [];
                                    for (let k = 0, len = superMapPositions.length; k < len; k++) {
                                        // 将笛卡尔坐标转换为地理坐标对象
                                        var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[k]);
                                        // 将弧度制的经度转换为角度制
                                        var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
                                        // 将弧度制的纬度转换为角度制
                                        var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
                                        // 获取高度值
                                        var h = cartographic.height;
                                        // 将经纬度和高度值依次添加到数组中
                                        finalPositions.push(longitude);
                                        finalPositions.push(latitude);
                                        finalPositions.push(h);
                                    }
                                    // 将当前多边形的位置信息添加到 allPositions 数组中
                                    allPositions = allPositions.concat(finalPositions);
                                }
                            }
                        } else if (data.type === "Polygon") {
                            // 处理 Polygon 类型的数据,只包含一个多边形
                            let positions = data.coordinates[0];
                            let superMapPositions = [];
                            for (let i = 0; i < positions.length; i++) {
                                var cartographic = SuperMap3D.Cartographic.fromDegrees(positions[i][0], positions[i][1], 0);
                                var cartesian = SuperMap3D.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height);
                                superMapPositions.push(cartesian);
                            }
                            // 转换为经纬度和高度数组
                            let finalPositions = [];
                            for (let i = 0, len = superMapPositions.length; i < len; i++) {
                                var cartographic = SuperMap3D.Cartographic.fromCartesian(superMapPositions[i]);
                                var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
                                var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
                                var h = cartographic.height;
                                finalPositions.push(longitude);
                                finalPositions.push(latitude);
                                finalPositions.push(h);
                            }
                            // 将当前多边形的位置信息赋值给 allPositions 数组
                            allPositions = finalPositions;
                        }
                        // 移除之前的裁剪区域,避免重叠
                        viewer.scene.globe.removeImageryClipRegion("clip", [tmpLayer]);
                        // 添加新的裁剪区域,根据选择的城市边界对影像进行裁剪
                        viewer.scene.globe.addImageryClipRegions({
                            position: allPositions,
                            layers: [tmpLayer],
                            name: "clip"
                        });

                        // 获取所选城市的中心点坐标
                        const [lon, lat] = cityCenters[selectedCity];
                        // 创建地理坐标对象
                        const center = SuperMap3D.Cartographic.fromDegrees(lon, lat);
                        // 创建笛卡尔坐标对象
                        const centerCartesian = SuperMap3D.Cartesian3.fromRadians(center.longitude, center.latitude, 530000);
                        // 让地图飞到城市中心点
                        viewer.camera.flyTo({
                            destination: centerCartesian,
                            duration: 3 // 飞行时间,单位为秒
                        });
                    });
                }
            });
        }

        // 检查 SuperMap3D 是否已经定义,如果已经定义则调用 onload 函数进行初始化
        if (typeof SuperMap3D!== 'undefined') {
            onload(SuperMap3D);
        }
    </script>
</body>

</html>
相关推荐
伶俜Monster12 小时前
Threejs 光照教程,为 3D 场景注入灵魂
前端·3d·webgl·threejs
2201_7596465613 小时前
Three.js 引领时代的 三维可视化技术
开发语言·前端·javascript·3d·webgl
efvv3 天前
使用CSS3DRenderer/CSS2DRenderer给模型上面添加html标签
前端·javascript·webgl·threejs
伶俜Monster3 天前
Threejs教程一【三要素】
前端·3d·webgl
贵州数擎科技有限公司5 天前
使用 Three.js 实现流光特效
前端·webgl
GAMESLI-GIS5 天前
【WebGL】fbo双pass案例
前端·javascript·webgl
图导物联7 天前
基于WebGIS技术的校园地图导航系统架构与核心功能设计
系统架构·智慧校园·gis·webgl·地图导航·电子地图·校园地图导航
匹马夕阳8 天前
(十七)WebGL中 图像处理的初识
图像处理·人工智能·webgl
2201_759646569 天前
three.js 通用 shaderToy着色器使用,切换
开发语言·前端·javascript·ecmascript·webgl·着色器