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

news2025/4/26 2:07:49

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

一、数据制作

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

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

二、实现思路

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

三、关键代码

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

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;
}

四、示例完整代码

<!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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309028.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenHarmony4.1-轻量与小型系统ubuntu开发环境

因OpenHarmony官网提供包含轻量、小型与标准系统的全量代码非常宠大&#xff0c;解包后大概需要70G以上硬盘空间&#xff0c;如要编译标准系统则需要140G以上空间。 如硬盘空间有限与只使用轻量/小型OpenHarmony系统&#xff0c;则可以下载并直接使用本人裁剪源码过的ubuntu硬盘…

秒杀系统的常用架构是什么?怎么设计?

架构 秒杀系统需要单独部署&#xff0c;如果说放在订单服务里面&#xff0c;秒杀的系统压力太大了就会影响正常的用户下单。 常用架构&#xff1a; Redis 数据倾斜问题 第一步扣减库存时 假设现在有 10 个商品需要秒杀&#xff0c;正常情况下&#xff0c;这 10 个商品应该均…

LabVIEW中三种PSD分析VI的区别与应用

在LabVIEW的声音与振动分析工具包中&#xff0c;SVFA Power Spectral Density VI、SVFA Power Spectral Density Subset VI 和 SVFA Zoom Power Spectral Density VI 均用于信号频域分析&#xff0c;但它们在功能、适用场景和操作逻辑上存在显著差异。以下从区别、应用场合、注…

蓝桥杯备考:动态规划入门题目之下楼梯问题

按照动态规划解题顺序&#xff0c;首先&#xff0c;我们要定义状态表示&#xff0c;这里根据题意f[i]就应该表示有i个台阶方案总数 第二步就是 确认状态转移方程&#xff0c;画图分析 所以实际上f[i] 也就是说i个台阶的方案数实际上就是第i-1个格子的方案数第i-2个格子的方案数…

【树莓派学习】树莓派3B+的安装和环境配置

【树莓派学习】树莓派3B的安装和环境配置 文章目录 【树莓派学习】树莓派3B的安装和环境配置一、搭建Raspberry Pi树莓派运行环境1、下载树莓派镜像下载器2、配置wifi及ssh3、SSH访问树莓派1&#xff09;命令行登录2&#xff09;远程桌面登录3&#xff09;VNC登录&#xff08;推…

算法题(83):寄包柜

审题&#xff1a; 需要我们对模拟柜子的数组进行插入数据和打印数据的操作 思路&#xff1a; 首先我们观察题目&#xff0c;发现可以用一个数组表示一个柜子&#xff0c;而数组中每个索引的位置可以看成是一个个格子。但是柜子的数据量是1e5&#xff0c;且格子的数据量是1e5.如…

深入浅出MySQL:概述与体系结构解析

目录 1. 初识MySQL 1.1. 数据库 1.1.1. OLTP&#xff08;联机事务处理&#xff09;1.1.2. OLAP&#xff08;联机分析处理&#xff09; 2. SQL 2.1. 定义2.2. DQL&#xff08;数据查询语言&#xff09;2.3. DML&#xff08;数据操纵语言&#xff09;2.4. DDL&#xff08;数据定…

tin这个单词怎么记

英语单词 tin&#xff0c;一般用作名词&#xff0c;意为“罐头&#xff1b;锡”&#xff1a; tin n.锡&#xff1b;罐头&#xff1b;罐&#xff1b;罐头盒&#xff1b;(盛涂料、胶水等的)马口铁罐&#xff0c;白铁桶&#xff1b;罐装物&#xff1b;金属食品盒&#xff1b;烘焙…

【0005】Python变量详解

如果你觉得我的文章写的不错&#xff0c;请关注我哟&#xff0c;请点赞、评论&#xff0c;收藏此文章&#xff0c;谢谢&#xff01; 本文内容体系结构如下&#xff1a; 任何一个语言编写的程序或者项目&#xff0c;都需要数据的支持&#xff0c;没有数据的项目不能称之为一个…

yolov8_pose模型,使用rknn在安卓RK3568上使用

最近在使用rknn的一些功能,看了看文档以及自己做的一些jni,使用上yolov8_pose的模型. 1.我们先下载一下rknn的模型功能代码,rk有自己做的一套demo 地址:GitHub - airockchip/rknn_model_zooContribute to airockchip/rknn_model_zoo development by creating an account on G…

MCP与RAG:增强大型语言模型的两种路径

引言 近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;在自然语言处理任务中展现了令人印象深刻的能力。然而&#xff0c;这些模型的局限性&#xff0c;如知识过时、生成幻觉&#xff08;hallucination&#xff09;等问题&#xff0c;促使研究人员开发了多种增强技…

ARM 架构下 cache 一致性问题整理

本篇文章主要整理 ARM 架构下&#xff0c;和 Cache 一致性相关的一些知识。 本文假设读者具备一定的计算机体系结构和 Cache 相关基础知识&#xff0c;适合有相关背景的读者阅读 1、引言 简单介绍一下 Cache 和内存之间的关系 在使能 Cache 的情况下&#xff0c;CPU 每次获取数…

tcc编译器教程1 配置tcc编译器环境

TinyCC&#xff08;又名TCC&#xff09;是一款开源小型但超快速的C编译器。下面介绍在windows下使用 1软件下载 tcc编译器官网为 https://www.bellard.org/tcc/ 下载地址为 http://download.savannah.gnu.org/releases/tinycc/ 选择其中tcc-0.9.27-win64-bin.zip进行下载 htt…

安全模块设计:token服务、校验注解(开启token校验、开启签名校验、允许处理API日志)、获取当前用户信息的辅助类

文章目录 引言pom.xmlI 校验注解ApiValidationII token服务TokenService获取当前用户信息的辅助类III 域登录接口响应数据登陆用户信息引言 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/PO…

机器学习:线性回归,梯度下降,多元线性回归

线性回归模型 (Linear Regression Model) 梯度下降算法 (Gradient Descent Algorithm) 的数学公式 多元线性回归&#xff08;Multiple Linear Regression&#xff09;

【弹性计算】弹性裸金属服务器和神龙虚拟化(一):功能特点

弹性裸金属服务器和神龙虚拟化&#xff08;一&#xff09;&#xff1a;功能特点 特征一&#xff1a;分钟级交付特征二&#xff1a;兼容 VPC、SLB、RDS 等云平台全业务特征三&#xff1a;兼容虚拟机镜像特征四&#xff1a;云盘启动和数据云盘动态热插拔特征五&#xff1a;虚拟机…

大模型function calling:让AI函数调用更智能、更高效

大模型function calling&#xff1a;让AI函数调用更智能、更高效 随着大语言模型&#xff08;LLM&#xff09;的快速发展&#xff0c;其在实际应用中的能力越来越受到关注。Function Calling 是一种新兴的技术&#xff0c;允许大模型与外部工具或API进行交互&#xff0c;从而扩…

计算机毕业设计SpringBoot+Vue.js贸易行业CRM系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

图像分类项目2:鸟类图像分类

1 数据集处理 1.1数据集下载 数据集来源&#xff1a;kaggle&#xff0c;网址&#xff1a;https://www.kaggle.com/&#xff0c;点击进入网站&#xff0c;左侧选择Datasets。 进入后搜索栏搜索关键词bird。此时出现很多数据集可以选择&#xff0c;推荐选择第一个或者第三个。…

Redis数据结构-List列表

1.List列表 列表类型适用于存储多个有序的字符串&#xff08;这里的有序指的是强调数据排列顺序的重要&#xff0c;不是升序降序的意思&#xff09;&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;一个列表最多可以存储2^32-1个元素。在R…