三种空间数据的聚合算法

原始数据分布

给老外做的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.hqwc.cn/news/623588.html

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

相关文章

MongoDB分片部署(windows)

OS&#xff1a;win10 MongoDB&#xff1a;4.4.24 分片架构 从图中可以看出&#xff0c;分片集群中主要由三个部分组成&#xff0c;即分片服务器&#xff08; Shard &#xff09;、路由服务器 &#xff08; Mongos &#xff09;以及配置服务器&#xff08; Config Server &am…

vue-treeselect 的基本使用

vue-treeselect 的基本使用 1. 效果展示2. 安装 插件3. 引入组件4. 代码 1. 效果展示 2. 安装 插件 vue-treeselect是一个树形的下拉菜单&#xff0c;至于到底有多少节点那就要看你的数据源有多少层了&#xff0c;挺方便的。下面这个这个不用多说吧&#xff0c;下载依赖 npm in…

文件分发软件有哪些?最值得推荐的文件分发软件

文件分发软件有哪些&#xff1f;最值得推荐的文件分发软件 文件分发软件通常用于在企业或个人之间高效、安全地分发大量文件或软件包。文件分发软件在功能、安全、兼容性上各有差异&#xff0c;以下是一些文件分发软件的列举&#xff0c;以及它们的特点或优势&#xff0c;希望…

【电控笔记2.3】速度回路+系统延迟

2.3.1速度回路pi控制器设计 pi伯德图近似设计(不考虑延时理想情况下) Tl:负载转矩 PI控制器的转折频率:Ki/Kp

如何获取淘宝商品网页上的内嵌视频

如何获取淘宝商品网页上的内嵌视频 1.打开视频所在网页&#xff0c;按下F12&#xff08;或者打开“开发者工具”&#xff09; 2.在开发者工具中选择“网络”&#xff0c;并刷新页面。 3.这时你会看到一些资源&#xff0c;找到视频格式的资源&#xff0c;在新标签页中打开 4.好…

C#学习笔记11:winform上位机与西门子PLC网口通信_下篇

今日终于到了winform上位机与西门子PLC网口通信的系列收为阶段了&#xff0c;一直没一口气更新完&#xff0c;手头上也没有可以测试用的PLC设备&#xff0c;虚拟仿真用到的博图软件也不想下载&#xff08;会让我电脑变卡&#xff09;。 于是等了些日子购买西门子PLC&#xff0…

扫雷 【搜索,哈希】

9.扫雷 - 蓝桥云课 (lanqiao.cn) #include<bits/stdc.h> using namespace std; #define int long long const int N1e5100; int n,m,res0; struct pt{int x,y,r; }; typedef pair<int,int> pii; map <pii,int> a;//炸雷的map,键是x,y,值是r map <pii,int&…

探索Python中的生成器:让数据流动起来

文章目录 1. 生成器1.1 基础1.2 工作原理1.3 表达式1.4 高级应用 2. 生成器是不是相当于函数中的return3. 生成器为什么叫yield 在Python面试中&#xff0c;深入了解生成器是关键。这一特性通过延迟计算优化内存使用&#xff0c;广泛应用于数据流处理和异步编程&#xff0c;对提…

常用WEB测试用例

1、登录 ①用户名和密码都符合要求&#xff08;格式上的要求&#xff09; ②用户名和密码都不符合要求&#xff08;格式上的要求&#xff09; ③用户名符合要求&#xff0c;密码不符合要求&#xff08;格式上的要求&#xff09; ④密码符合要求&#xff0c;用户名不符合要求…

Spring开发:动态代理的艺术与实践

1. 背景 动态代理是一种强大的设计模式&#xff0c;它允许开发者在运行时创建代理对象&#xff0c;用于拦截对真实对象的方法调用。这种技术在实现面向切面编程&#xff08;AOP&#xff09;、事务管理、权限控制等功能时特别有用&#xff0c;因为它可以在不修改原有代码结构的前…

【Android】重温Activity生命周期

前言 Android中用得最多的组件是Activity&#xff0c;而它的生命周期也是最基础的知识&#xff0c;从刚接触Android到工作中会频繁依赖这部分知识。可能大多数人能说出页面新建到页面关闭会走的生命周期&#xff1a;onCreate、onStart、onResume、onPause、onStop、onDestory&…

汽车车灯用肖特基二极管,选什么型号好?

肖特基二极管种类繁多&#xff0c;有低压降肖特基二极管、通用型肖特基二极管、快速恢复型肖特基二极管、高功率肖特基二极管、汽车级肖特基二极管等等&#xff0c;其中低压降肖特基二极管和汽车级肖特基二极管是二极管厂家东沃电子的核心优势产品。关于东沃电子推出的低压降肖…