利用Cesium和JS实现地点点聚合功能

引言

在实现基于地图的业务场景时,当地图上需要展示过多的标记点时,大量的分散点会使地图上显得杂乱无章,导致标记点对地图上的其他重要信息造成遮挡和混淆,降低地图整体的可读性。

标记点的聚合就很好的解决了这些痛点的同时,还可以清晰的展示数据的分布模式和主要区域,便于用户直观的理解,提高地图的加载和交互的效率,便于对数据镜像更深层次的开阔和分析。

CesiumAPI 中本身自带聚合的方法,但是提供的聚合场景只适用于一些简单的标记点或者 POI 中使用

在实际的开发过程中,我们需要展示的标记点样式大多较为复杂甚至是视频等自定义的样式,标记点内实际会使用到点击、显示隐藏、调整等交互。

那么怎样利用 JSCesium 实现地图点位的聚合呢?

本文将在实际的业务使用场景中,带大家了解如何利用 cesiumJS 实现地图标记点位的聚合实现原理及方法。

实现思路:

  1. 首先是实现标记点的实现,通过监听相机角度的变化,达到的效果的地图的拖动缩放,标记点都会根据固定的点位移动;

  2. 通过简单的算法实现聚合,达到两个标记点通过放大和缩小,显示成具体的标记点数量

完成效果:



具体实现:

1.引入cesium,并初始化数据;

 //引入cesium文件
<script src="/Cesium/Cesium.js"></script>
//初始化cesium
Const viewerGis = new BIMCC_GIS_Base.Viewer('container');

2.监听相机视角变化

//开启相机视角变化
viewerGis.MouseCustomEvent.registerCameraChange();
// 监听相机视角变化事件
viewerGis.on('cameraChange', () => {
//相机视角变化调用下一步的方法获取屏幕坐标
});

3.经纬度坐标转换为屏幕坐标

经纬度坐标转换是实现聚合的最核心的一步。

Cesium 中,将经纬度坐标转换为屏幕坐标的过程主要涉及到相机视图矩阵和模型矩阵的计算。

其实现原理是将 3D世界坐标 转换为 2D画布坐标

其原理是通过Uniform(统一变量)将当前的模型视图投影矩阵应用到指定的世界坐标上,进而得到屏幕坐标。

最后将屏幕坐标转换为画布坐标系中的位置。

//假设viewer是Cesium的Viewer实例,worldPosition是一个Cesium.Cartesian实例,表示世界坐标中的一个经纬度坐标点
var canvasCoordinates = viewerGis.Coordinate?.getCanvasByWgs(worldPosition);
// 如果转换成功,canvasCoordinates将是一个包含x和y属性的对象,表示在画布上的位置
if (canvasCoordinates){console.log(`画布坐标: (${canvasCoordinates.x}, ${canvasCoordinates.y})`)
}

在实际开发中,我们是对 Cesium 进行了二次开发,调用的方法名有所变化,但是其原理是一样的。

获取到屏幕坐标我们就可以很容易地将标记点放入到指定的位置。

并通过上一步的监听相机位置变化,获取到每次缩放拖动后的屏幕坐标。

4.标记的聚合实现

标记的聚合实现主要算法有很多,参考高德地图,主要的算法有:直接网格法网格距离法直接距离法K-D树方法

这里我们使用直接距离法,初始时没有任何已知聚合点,然后对每个点进行迭代,计算一个点的外包正方形

若此点的外包正方形与现有的聚合点的外包正方形不相交,则新建聚合点(这里不是计算点与点间的距离,而是计算一个点的外包正方形,正方形的变长由用户指定或程序设置一个默认值)

若相交,则把该点聚合到该聚合点中,若点与多个已知的聚合点的外包正方形相交,则计算该点到到聚合点的距离,聚合到距离最近的聚合点中

如此循环,直到所有点都遍历完毕。

每个缩放级别都重新遍历所有原始点要素。

优点:运算速度相对较快,每个原始点只需计算一次,可能会有点与点距离计算,聚合点较精确的反映了所包含的原始点要素的位置信息。

缺点:速度不如完全基于网格的速度快,此法还有个缺点,就是各个点迭代顺序不同导致最终结果不同。

因此涉及到制定迭代顺序的问题。

//处理聚合数据,传参data是所有标记点
const collectMakers = (data) => {collectList.value = [];data.forEach((maker) => {let flag = false;collectList.value.forEach((item) => {if (flag) return;item.forEach((i) => {if (i.id == maker.id) {flag = true;return;}});});if (flag) return;const filterList = data.filter((item) => Math.abs(maker.style.left - item.style.left) < maker.style.width && Math.abs(maker.style.top - item.style.top) < maker.style.height);//filterList就是聚合的数据collectList.value.push(filterList);});
}

通过以上几步就可以通过 JSCesium 上实现标记以及聚合的效果。

– 欢迎点赞、关注、转发、收藏【我码玄黄】,gonghao同名

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

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

相关文章

[大模型]XVERSE-MoE-A4.2B Transformers 部署调用

XVERSE-MoE-A4.2B介绍 XVERSE-MoE-A4.2B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;使用混合专家模型&#xff08;MoE&#xff0c;Mixture-of-experts&#xff09;架构&#xff0c;模型的总参数规模为 258 亿…

apt-get update和apt-get upgrade的区别

apt-get update apt-get update 命令用于更新本地软件包列表。具体来说&#xff0c;做了以下事情&#xff1a; ①从 /etc/apt/sources.list 文件和 /etc/apt/sources.list.d/ 目录下的所有文件中读取软件源配置。 ②连接到这些软件源&#xff0c;并下载最新的软件包列表。 ③将…

springcloud入门与实践

Spring Cloud 是一个基于 Spring Boot 的框架&#xff0c;专注于微服务架构下的常见问题&#xff0c;如服务发现、负载均衡、断路器、分布式配置、消息驱动的微服务等。以下是 Spring Cloud 的入门指南和实践示例。 1. 环境准备 首先&#xff0c;确保你已经安装了以下工具&am…

Python 潮流周刊#56:NumPy 2.0 里更快速的字符串函数

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&am…

Mysql(一):深入理解Mysql索引底层数据结构与算法

众所众知&#xff0c;MySql的查询效率以及查询方式&#xff0c;基本上和索引息息相关&#xff0c;所以&#xff0c;我们一定要对MySql的索引有一个具体到数据底层上的认知。 这一次也是借着整理的机会&#xff0c;和大家一起重新复习一下MySql的索引底层。 本节也主要有一下的…

AOSP : Android编译记录

Android编译记录 1、关注编译配置文件2、编译记录2.1 设置构建环境2.2 记录 1、关注编译配置文件 Android.bp 或 Android.mk Android.bp 文件格式 2、编译记录 2.1 设置构建环境 source build/envsetup.sh lunch product_name-release-build_variant查看当前的启动设置&#…

【PL理论】(25) C- 语言:表达式求值的推理规则 | 执行语句的推理规则 | 语句执行的推理规则

&#x1f4ad; 写在前面&#xff1a;本章我们将继续更新我们的 "C-" 语言&#xff0c;更新表达式求值的推理规则、执行语句的推理规则以及语句执行的推理规则。 目录 0x00 C- 语言更新&#xff1a;表达式求值的推理规则 0x01 C- 语言更新&#xff1a;执行语句的推…

网页五子棋对战项目测试(selenium+Junit5)

目录 网页五子棋对战项目介绍 网页五子棋对战测试的思维导图​ 网页五子棋对战的UI自动化测试 测试一&#xff1a;测试注册界面 测试二&#xff1a;测试登陆界面 测试三&#xff1a;测试游戏大厅界面 测试四&#xff1a;测试游戏房间界面以及观战房间界面 测试五&#…

【技巧】Leetcode 67. 二进制求和【简单】

二进制求和 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 示例 1&#xff1a; 输入:a “11”, b “1” 输出&#xff1a;“100” 示例 2&#xff1a; 输入&#xff1a;a “1010”, b “1011” 输出&#xff1a;“10101” 解题思路 …

软考-架构设计师-综合知识总结(试卷:2009~2022)(下篇)

说明 本文档对2009到2022年试卷的综合知识进行了归纳总结&#xff0c;同时对叶宏主编的《系统架构设计师教程》划分重点。 第十七章&#xff1a;通信系统架构设计 17.2 考题总结 第十八章&#xff1a;安全架构设计 18.1 重要知识点 18.2 考题总结 第十九章&#xff1a;大数据…

传统后端SQL数据层替代解决方案: 内置数据源+JdbcTemplate+H2数据库 详解

内置数据源 我们回顾一下druid数据源的配置方式 通过type属性指定数据源的类型 导入依赖 starter就使用了spring的自动装配功能 格式二是在引入druid的依赖的基础上 进行的一种配置方式 Tomcat内部也可以进行数据源的配置 轻量级中最快的数据源对象 我们切换德鲁伊连接池 我…

OpenDevin 环境配置及踩坑指南

不惧怕任何环境配置 首先 clone 项目&#xff0c;然后查看开发者文档&#xff1a;https://github.com/OpenDevin/OpenDevin/blob/main/Development.md make setup-config 自定义 LLM 配置 首先这个 devin 写的是支持自定义的 LLM 配置&#xff0c;并且提供了交互式命令供我们…

DzzOffice集成功能最丰富的开源PHP+MySQL办公系统套件

DzzOffice是一套开源办公套件&#xff0c;旨在为企业和团队提供类似“Google企业应用套件”和“微软Office365”的协同办公平台。以下是对DzzOffice的详细介绍&#xff1a; 主要功能和应用&#xff1a; 网盘&#xff1a;支持企业、团队文件的集中管理&#xff0c;提供文件标签…

app-ios 内嵌h5的缓存问题

在iOS应用中内嵌H5页面时&#xff0c;可能会遇到缓存问题&#xff0c;导致页面更新不及时。以下是一些解决策略和方法&#xff1a; 目录 方法1&#xff1a;Nginx配置 方法2&#xff1a;使用版本号 方法1&#xff1a;Nginx配置 通过Nginx服务器配置来控制缓存行为。例如&#…

Python开发示例——使用Python实现炫酷的数据动态图

前言 数据可视化是通过图形、图表、地图等可视元素将数据呈现出来&#xff0c;以便更容易理解、分析和解释。它是将抽象的数据转化为直观形象的过程&#xff0c;有助于发现数据中的模式、趋势和关系。数据可视化对于数据科学、商业分析、决策制定等领域都至关重要。当我们想用…

UniApp+Vue3使用Vant-微信小程序组件

第一步&#xff1a;打开创建好的UniappVue3的项目 第二步&#xff1a;下载Vant-Weapp npm i vant/weapp -S --production 第三步&#xff1a;修改目录名称 wxcomponents 必须是wxcomponents 第四步&#xff1a;将下载好的vant中的dist目录剪切到当前wxcomponents目录下 第五…

在 Linux 上刷新 DNS 缓存:告别过时解析,提升网络访问效率

引言 在 Linux 系统中&#xff0c;DNS&#xff08;域名系统&#xff09;缓存对于提高网络访问速度和效率至关重要。然而&#xff0c;当 DNS 记录发生更改或需要更新时&#xff0c;旧的缓存条目可能会导致访问问题或连接到错误的服务器。因此&#xff0c;了解如何在 Linux 上刷…

leetcode打卡#day51 300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

300. 最长递增子序列 class Solution { public:int lengthOfLIS(vector<int>& nums) {if (nums.size() < 1) return nums.size();vector<int> dp(nums.size(), 1);int result 0;for (int i 1; i < nums.size(); i) {for (int j 0; j < i; j) {if …

牛客网金九银十最新版互联网Java高级工程师面试八股文出炉!面面俱到,太全了

前言 作为一个 Java 程序员&#xff0c;你平时总是陷在业务开发里&#xff0c;每天噼里啪啦忙敲着代码&#xff0c;上到系统开发&#xff0c;下到 Bug 修改&#xff0c;你感觉自己无所不能。然而偶尔的一次聚会&#xff0c;你听说和自己一起出道的同学早已经年薪 50 万&#x…

hive split 特殊用法

日常使用 split(字符串&#xff0c;分割符) &#xff0c;如 split(abcd],dd[,as,,) 则按照分隔符逗号进行分割 但是日常数据处理过程中&#xff0c;还会遇到在某个字符后面的后者某个字符前面的分割符&#xff0c;则此时需要加入正则表达式&#xff1a; 正向前瞻断言 ,(?[)…