三种空间数据的聚合算法

原始数据分布

给老外做的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,一经查实,立即删除!

相关文章

IPC最新发行了新标准:IPC-A-610J, IPC-J-STD-001J, IPC-7711/21D, IPC-2221C, -2024年

2024年伊始&#xff0c;IPC又更新了一些新的标准&#xff0c;大家可以及时去更新了。 ** IPC-A-610J_EN 2024 TOC Acceptability of Electronic Assemblies ** 大家对这个标准都不陌生了吧&#xff0c;从事电子行业的技术人员&#xff0c;应该没有人不知道。 IPC-A-610J是…

可见光相机曝光方式

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

springboot mongodb 数据添加时更改‘_class‘字段

重写beanMappingMongoConverter 修改DefaultMongoTypeMapper /*** 更改默认的 MongoDB 映射转换器,更改_class字段** param factory MongoDB 工厂对象* param context MongoDB 映射上下文* param beanFactory springBean 工厂* return MongoDB 映射转换器*/Beanpublic…

Elasticsearch 创建自定义分析器(4)

一.自定义分析器 当内置分析器不能满足时&#xff0c;可以创建一个自定义分析器&#xff0c;自定义分析器(analyzer)由&#xff1a; 1)0或多个 charactcr filter 字符过滤器 2) 1个 tokenizer 分词器&#xff0c;将文本切分为分词 3)0或多个 token filter 令牌过滤器&#xff…

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

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;不会产生不正确的结果。线程安全问题的主要原因是多个线程对共享数据进行读写操作时的并发性。这可能导致竞态…

GDB调试基础

一.调试环境 一般的GDB调试为本机环境下调试&#xff0c;如在一台Centos6的服务器上编写demo&#xff0c;那么gdb调试时只需要运行gdb工具并指定待调试文件即可开始调试&#xff1b; 如: [xxxcentos6]$ gdb a.out //…… This GDB was configured as "x86_64-redhat-l…

制作直通网线和交叉网线

制作直通网线和交叉网线 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 日期格式化,等日期相关操作

输入日期格式字符串 获取时间戳 构造时间&#xff0c;时间加减等 import time import datetimedef format_time() -> None:""" 日期格式化"""inputStr1: str input("输入一个时间格式的字符串")timeArray time.strptime(inputSt…

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

【Python-第三方库】cv2

作用 一个开源的库平台计算机视觉库。 安装 pip install opencv_python导入 import cv2 as cv函数 cv.imread( ) 用于读取图片文件 image cv.imread(image_path)image_path&#xff1a; 图片路径。 未待完续…

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

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