三种空间数据的聚合算法

原始数据分布

给老外做的Demo,所以是英文界面。
原始数据分布情况如下:
在这里插入图片描述
geojson文本内容:
在这里插入图片描述

三种方法基本原理

三种聚合算法来做一个例子(500条记录)。
方法1:按Ol默认方法进行聚类,使用Openlayers默认聚类方法,将任何特征聚合为满足最小距离的种子数据
方法2:按所属区域属性进行聚类,根据元素的属性进行聚合,即具有相同Name_2属性的元素的聚合
方法3:按所属空间网格进行聚类,将所有元素所在的区域划分为多个网格,在网格的中心创建特征,并将网格中的特征聚合到该网格中

上代码

JavaScript

var myMap = null;
var vectorLayerForOrginalMap = null;
var clusterLayerByOLMethod = null;
var clusterLayerByBelongsRegion = null;
var clusterLayerByBelongsGrid = null;
var lastSelectedFeature = null;
const initMap = () => {const raster = new ol.layer.Tile({source: new ol.source.OSM(),});const map = new ol.Map({layers: [raster],target: "map",view: new ol.View({center: [-137702.88482159126, 7165549.988880951],zoom: 6,}),});myMap = map;showTip();
};
const removeAllVecLayers = () => {if (!myMap) return;vectorLayerForOrginalMap && myMap.removeLayer(vectorLayerForOrginalMap);clusterLayerByOLMethod && myMap && myMap.removeLayer(clusterLayerByOLMethod);clusterLayerByBelongsRegion && myMap.removeLayer(clusterLayerByBelongsRegion);clusterLayerByBelongsGrid && myMap.removeLayer(clusterLayerByBelongsGrid);
};
const loadData = () => {removeAllVecLayers();const vectorSource = createVectorSource();const vectorLayer = new ol.layer.Vector({source: vectorSource,});vectorLayerForOrginalMap = vectorLayer;myMap && myMap.addLayer(vectorLayer);
};
// 方法一★★★★★★
const loadDataClusterOl = () => {removeAllVecLayers();const clusterSource = new ol.source.Cluster({distance: 100,minDistance: 80,source: createVectorSource(),});const styleCache = {};clusterLayerByOLMethod = new ol.layer.Vector({source: clusterSource,style: function (feature) {const size = feature.get("features").length;let style = styleCache[size];if (!style) {style = createStyle(15 + size / 20.0, `${size.toString()}`);styleCache[size] = style;}return style;},});myMap && myMap.addLayer(clusterLayerByOLMethod);
};
// 方法二★★★★★★
const loadDataClusterRegion = () => {removeAllVecLayers();const vectorSource = createVectorSource();const styleCache = {};clusterLayerByBelongsRegion = new ol.layer.Vector({source: vectorSource,style: function (feature) {let size = feature.features && feature.features.length;!size && (size = 15);let style = styleCache[size];if (!style) {style = createStyle(15 + size / 2.0, `${size.toString()}`);styleCache[size] = style;}return style;},});myMap && myMap.addLayer(clusterLayerByBelongsRegion);vectorSource.on("featuresloadend", function () {loadDataClusterRegionLoaded(vectorSource);});
};
const loadDataClusterRegionLoaded = (vectorSource) => {const fsMap = new Map();const fs = vectorSource.getFeatures();for (let i = 0; i < fs.length; i++) {const region = fs[i].getProperties()["NAME_2"];if (fsMap.has(region)) {fsMap.get(region).push(fs[i]);fs[i].del = true;continue;}if (!fs[i].features && !fs[i].del) {fs[i].features = [fs[i]];fsMap.set(region, fs[i].features);continue;}}for (let i = fs.length - 1; i >= 0; i--) {if (fs[i].del) {vectorSource.removeFeature(fs[i]);}}
};
// 方法三★★★★★★
const loadDataClusterGrid = () => {removeAllVecLayers();const vectorSource = createVectorSource();const styleCache = {};clusterLayerByBelongsGrid = new ol.layer.Vector({source: vectorSource,style: function (feature) {let size = feature.features && feature.features.length;!size && (size = 15);let style = styleCache[size];if (!style) {style = createStyle(size, `${size.toString()}`);styleCache[size] = style;}return style;},});myMap && myMap.addLayer(clusterLayerByBelongsGrid);vectorSource.on("featuresloadend", function () {loadDataClusterGridLoaded(vectorSource);});
};
const loadDataClusterGridLoaded = (vectorSource) => {const fs = vectorSource.getFeatures();const ext = vectorSource.getExtent();const disX = 200000,disY = 200000;const minX = ext[0],minY = ext[1];const maxX = ext[2],maxY = ext[3];for (let i = minX; i <= maxX; i += disX) {for (let j = minY; j <= maxY; j += disY) {const centerX = i + disX / 2,centerY = j + disY / 2;var feature = new ol.Feature();feature.features = [];feature.setGeometry(new ol.geom.Point([centerX, centerY]));for (let k = 0; k < fs.length; k++) {if (fs[k].del) continue;const geometry = fs[k].getGeometry();const coordinates = geometry.getCoordinates();const x = coordinates[0],y = coordinates[1];if (x <= i || x > i + disX) continue;if (y <= j || y > j + disY) continue;fs[k].del = true;feature.features.push(fs[k]);}feature.features.length > 0 && vectorSource.addFeature(feature);}}for (let i = fs.length - 1; i >= 0; i--) {vectorSource.removeFeature(fs[i]);}
};
const createVectorSource = () => {return new ol.source.Vector({url: "./data/postcodes.json.geojson",format: new ol.format.GeoJSON(),});
};
const createStyle = (size, text) => {size < 10 && (size = 9);let fillColors = {0: "pink",1: "#0c0",2: "#cc0",3: "#f00",4: "#f0f",5: "#0ff",6: "#00f",};return new ol.style.Style({image: new ol.style.Circle({radius: size,stroke: new ol.style.Stroke({color: "#fff",}),fill: new ol.style.Fill({color: fillColors[`${Math.floor(size / 10)}`],}),}),text: new ol.style.Text({text: text,fill: new ol.style.Fill({color: "#fff",}),}),});
};
const showTip = () => {myMap.on("pointermove", function (event) {var feature = myMap.forEachFeatureAtPixel(event.pixel, function (feature) {return feature;});lastSelectedFeature && lastSelectedFeature.setStyle();if (feature) {lastSelectedFeature = feature;lastSelectedFeature.setStyle(new ol.style.Style());const tooltip = document.getElementById("info");// Get the feature informationconst fs = feature.features || feature.getProperties()["features"];const date = new Date();const options = {weekday: "long",year: "numeric",month: "long",day: "numeric",hour: "numeric",minute: "numeric",second: "numeric",};const stringDate = date.toLocaleDateString("en-US", options);if (!fs) {tooltip.innerHTML = `${stringDate} : <br>not clustered`;return;}const infos = [];for (let i = 0; i < fs.length; i++) {const f = fs[i];infos.push(JSON.stringify({id: f.getProperties()["id"],NAME_2: f.getProperties()["NAME_2"],}));}tooltip.innerHTML = `${stringDate}<br>Clustered Features : <br>${infos.join("<br>")}`;}});
};

HTML 页面

<!DOCTYPE html>
<html><head><title>Cluster UK Postcodes </title><link rel="stylesheet" href="style.css"><link rel="stylesheet" href="libs/ol.css"><script src="./libs/ol.js" type="text/javascript"></script><script src="do.js" type="text/javascript"></script>
</head><body><div class="mcontainer"><div class="leftPanel"><div><button onclick="loadData();">Load Data Directly</button><span>Load data directly</span></div><div><button onclick="loadDataClusterOl();">Method 1:Cluster By Ol Default Method</button><span>Use Openlayers default cluster method,Aggregating any feature as seed data that satisfies theminimum distance</span></div><div><button onclick="loadDataClusterRegion();">Method 2:Cluster By Belonging Region Attribute</button><span>Aggregation based on the attributes of elements, i.e. aggregation of elements with the same Name_2attribute</span></div><div><button onclick="loadDataClusterGrid();">Method 3:Cluster By Belonging Spatial Grid</button><span>Divide the area where all elements are located into several grids, create features at the centerof the grid, and aggregate the features in the grid to that grid</span></div><div id="info"></div></div><div class="rightPanel"><div id="map"></div></div></div><script type="text/javascript">initMap();</script>
</body></html>

CSS

html,
body {margin: 0;padding: 0;height: 100%;
}
.mcontainer {display: flex;height: 100%;
}
.leftPanel {width: 25%;height: 100%;display: flex;flex-direction: row;flex-flow: column;overflow-y: auto;box-shadow: -5px 0px 0px 0px black, 5px 0px 0px 0px black;
}
.rightPanel {width: 75%;height: 100%;
}
#map {width: 100%;height: 100%;
}
.leftPanel div {display: flex;flex-direction: row;flex-flow: column;overflow-y: auto;border-top: 1px solid #ccc;
}
button {display: block;width: 80%;align-self: center;margin-top:.5rem;
}
#info {border-top: 1px solid #ccc;
}

效果图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

可见光相机曝光方式

可见光摄影中的曝光方式主要包括两种&#xff1a;卷帘曝光和全局曝光。它们之间的区别在于曝光过程中传感器或胶片感光部分的工作方式不同&#xff0c;这直接影响到图像捕获的效果和特性。 卷帘曝光&#xff08;Rolling Shutter&#xff09;&#xff1a; 工作原理&#xff1a;在…

对一个全局变量进行多线程并发 -- 或者 ++ 操作是否是安全的??是否是原子的??

1.结论&#xff1a; 不是安全的&#xff0c;不是原子的 2.原因&#xff1a; 2.1 不是原子性的原因&#xff1a; 一个线程将一个全局变量--&#xff08;减减&#xff09;时候&#xff0c;需要以下几个步骤 第一步&#xff1a;将全局变量读到cpu的寄存器中&#xff0c; 第二步…

3D目标检测实用技巧(三)- 生成虚拟点

一、引言 本次参考的是VirConv生成虚拟点的方法&#xff1a; VirConv/tools/PENet at master hailanyi/VirConv GitHubVirtual Sparse Convolution for Multimodal 3D Object Detection - VirConv/tools/PENet at master hailanyi/VirConvhttps://github.com/hailanyi/Vir…

腾讯文档推出智能白板创新品类,自研开物引擎支持全端应用

4月18日&#xff0c;“腾讯文档&#xff0c;打开想象”2024产品发布会在线上举办。腾讯社交协作产品部总经理、腾讯文档负责人鄢贤卿在会上&#xff0c;正式发布智能白板创新品类、双核编辑“开物引擎”、云加端解决方案等产品矩阵。他表示&#xff0c;在自研文档品类和自研双核…

ctfshow web入门 SQl注入web171--web179

从这里开始SQl建议大家去看这篇文章学习一下先 MySQl web171 法一联合查询 题目 $sql "select username,password from user where username !flag and id ".$_GET[id]." limit 1;";爆数据库名 -1 union select 1,database(),3 -- 爆表名 -1 union s…

数据结构 - 栈

概述 计算机科学中,stack是一种线性的数据结构,只能在其一段添加和移除数据. 习惯来说,这一端称之为栈顶,另一端不能操作数据的称之为栈底,就如同生活中的一摞书 先提供一个接口: public interface Stack <E>{/*** 向栈顶压入元素* param value -- 待压入值* returns…

✌粤嵌—2024/4/18—旋转链表✌

代码实现&#xff1a; 方法一&#xff1a;在原链表中找到旋转之后的首尾&#xff0c;改变指向 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* rotateRight(struct ListNode *head, int k) {i…

线程安全问题的原因和解决方案

目录 原因分析 解决线程安全问题——加锁 synchroized&#xff08;&#xff09; 死锁 死锁的四个必要条件 线程安全是指多个线程同时访问共享资源时&#xff0c;不会产生不正确的结果。线程安全问题的主要原因是多个线程对共享数据进行读写操作时的并发性。这可能导致竞态…

制作直通网线和交叉网线

制作直通网线和交叉网线 1. 网络直通线2. 网络交叉线References 双绞线的连接方法有两种&#xff1a;直通连接和交叉连接 。 直通连接是将双绞线的两端分别都依次按白橙、橙、白绿、蓝、白蓝、绿、白棕、棕色的顺序 (国际 EIA/TIA 568B 标准) 压入 RJ45 水晶头内。这种方法制作…

壁纸、软件、电子书、音乐资源、数据库资源,囤一囤

资源网站我真的有很多&#xff01;&#xff01;下面这十几个都是壁纸资源、软件资源、电子书资源、音乐资源、数据库资源等等&#xff0c;感兴趣的囤一囤&#xff01; 一、壁纸资源 1、PEXELS 网址&#xff1a; https://www.pexels.com/zh-cn/ 一个专门分享无版权图片的网站…

Windows突然蓝屏解决办法

Windows突然蓝屏&#xff0c;然后重复开机没有用&#xff0c;但是能进入bios系统&#xff0c;证明内存和磁盘没事&#xff0c;用大白菜制作了PE系统盘制作过程&#xff08;之前一直都是用官方镜像制作&#xff0c;但是发现用大白菜制作可以对系统之前的磁盘里面重要的信息拷贝到…

Python用于比较数据结构并生成差异报告的工具库之data-diff使用详解

概要 Python的data-diff库是一个用于比较数据结构并生成差异报告的工具。它可以处理各种数据类型,如字典、列表、集合等,使得开发者能够快速识别数据之间的差异。 安装 通过pip可以轻松安装data-diff: pip install data-diff特性 支持多种数据类型:能够比较字典、列表、…

tokio 学习

Rust Async 异步编程 简易教程 理解tokio核心(1): runtime Rust 中的异步编程 Rust 中的 async 和线程 OS 线程&#xff1a; 适用于少量任务&#xff0c;有内存和 CPU 开销&#xff0c;且线程生成和线程间切换非常昂贵线程池可以降低一些成本允许重用同步代码&#xff0c;…

新手做抖音小店,最易爆单的几大类目分享,抓紧收藏!

大家好&#xff0c;我是电商糖果 新手做抖店没有经验&#xff0c;不了解市场&#xff0c;很多人都担心类目选错了&#xff0c;很难起店。 毕竟电商行业有一句话&#xff0c;类目大于一切&#xff0c;选择大于努力。 类目没有选对&#xff0c;再折腾也没用。 糖果做抖音小店…

eclipse配置SVN和Maven插件

3、 安装SVN插件 使用如下方法安装 Help–Install New Software 注意&#xff1a;目前只能安装1.8.x这个版本的SVN&#xff0c;如果使用高版本的SVN&#xff0c;在安装SVN和maven整合插件的时候就会报错&#xff0c;这应该是插件的bug。 点击Add name: subclipse location…

五款3dmax常用插件推荐(含云渲染工具)

在三维建模和动画设计领域&#xff0c;3ds Max软件因其强大功能和灵活性而广受欢迎。为了进一步提升工作效率和创作质量&#xff0c;有许多插件可供选择。本文推荐五款常用3ds Max插件&#xff0c;帮助你更好实现复杂的模型和动效创作。 五款3dmax常用插件推荐 1、Kitchen Cab…

Linux gcc 6

本章开始学习工具 什么是工具&#xff1f; 本质也是指令 yum 命令 小火车 sudo yum install sl&#xff08;安装sl&#xff09; sudo yum install -y sl //直接yes就不提示了 yum list //将yum源上的软件都穷举出来 yum search sl //结果不友好&#xff0c;不推荐 yum lis…

活动报名 | 如何进行全增量一体的异构数据库实时同步

伴随着新技术的不断涌现&#xff0c;市场竞争也在不断开辟新的角斗场——新的业务需求&#xff0c;新的应用设想都在这里迸发。 面对如此日新月异的竞争环境&#xff0c;企业的当务之急&#xff0c;是为新应用扎根准备好随时可取、准确一致的高质量数据土壤。在这样的背景下&a…

(二十八)Flask之wtforms库【上手使用篇】

目录&#xff1a; 每篇前言&#xff1a;用户登录验证&#xff1a;用户注册验证&#xff1a;使用示例&#xff1a; 抽象解读使用wtforms编写的类&#xff1a;简单谈一嘴&#xff1a;开始抽象&#xff1a; 每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【…

Docker 磁盘占用过多问题处理过程记录

一、问题描述 突然发现服务器磁盘使用超过95%了&#xff08;截图时2.1 和 2.2 已经执行过了&#xff09; 二、问题分析与解决 2.1&#xff0c;docker 无用镜像占用磁盘 # 使用 docker images 查看服务的镜像 docker images# 可以手动删除一些很大不用的 docker rmi ***## 也…