三种空间数据的聚合算法

原始数据分布

给老外做的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 information
      const 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 the
                    minimum 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_2
                    attribute</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 center
                    of 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;
}

效果图

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)

文章目录 一、JavaFx介绍1、JavaFx简介2、可用性3、主要特征4、UI控件 二、JavaFx概述1、JavaFx结构图2、JavaFx组件&#xff08;1&#xff09;舞台&#xff08;2&#xff09;场景① 场景图② 节点 &#xff08;3&#xff09;控件&#xff08;4&#xff09;布局&#xff08;5&a…

网络安全产品---数据库防火墙/审计

数据库防火墙 防火墙的类型繁多&#xff0c;即使下一代防火墙或者说AI防火墙集成功能再多&#xff0c;我觉得waf与数据库防火墙也有其无法被替代的理由&#xff0c;以此记录我对数据库防火墙的理解 what 数据库防火墙是基于数据库协议分析与访问行为控制的数据库安全防护产品…

【QT学习】7.事件,把文本显示在页面中(文本可变),鼠标指针切换,鼠标左键右键按下,qt设置背景样式

0.创建项目&#xff0c;事件的创建 1.事件的位置 2.这就是多态&#xff0c;子类重写父类函数&#xff0c;子类调用子类函数&#xff0c;也可以调用父类函数。但同函数名 1.要求&#xff1a;文本显示在页面中&#xff08;文本可变&#xff09; 1.文本显示在页面的核心代码 主要步…

齐次变换矩阵、欧拉角

齐次变换矩阵 因为老是忘记齐次变换矩阵的含义以及方向&#xff0c;每次推导公式都很费劲&#xff0c;写下这篇文章用于快速回顾齐次变换矩阵。 表示的是&#xff1a;坐标系A到坐标系B的齐次变换矩阵&#xff0c;也是坐标系B在坐标系A下的位姿。 对于这个矩阵&#xff0c;有三…

万兆网络的十字路口:电口还是光模块?

&#x1f335;在构建高速、高效的网络系统时&#xff0c;选择正确的连接技术至关重要。万兆电口&#xff08;10GBASE-T&#xff09;和万兆光模块&#xff08;SFP&#xff09;是目前市场上两种主流的高速网络解决方案。它们各有优势&#xff0c;但在不同的应用场景和需求下&…

[阅读笔记18][CITING]LARGE LANGUAGE MODELS CREATE CURRICULUM FOR INSTRUCTION TUNING

这篇论文是23年10月提交到arxiv上的&#xff0c;也是用大模型蒸馏小模型的思路。 作者在这篇论文中提出了课程指令微调&#xff0c;大体流程如下图所示&#xff0c;教师模型给出一个问题&#xff0c;让学生模型回答一下&#xff0c;这时候学生回答大概率不够准确&#xff0c;这…

多因子模型的因子分组-克隆巴赫α系数

优质博文&#xff1a;IT-BLOG-CN 在建立我们的Alpha模型之前&#xff0c;我们得先知道什么是Alpha&#xff1f;Alpha是一条或者一系列能够预测股票走势的信息资讯组合。而这每一条非随机的信息资讯&#xff0c;我们称之为多因子模型的因子。多因子模型因子的选择需要避免系统性…

Lobechat 的基本使用流程

一、安装 下载lobechart的页面代码 $ git clone https://github.com/lobehub/lobe-chat.git $ cd lobe-chat $ pnpm install $ pnpm run dev注意&#xff1a;node环境要18以上 二、使用本地模型 1.安装ollama 2.通过ollama 下载本地模型 llama2&#xff08;选择合适的本地模型…

基于Springboot的职称评审管理系统

基于SpringbootVue的获取源码 联系方式 &#x1f447;&#x1f3fb;的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 评审条件 论坛信息 系统公告 后台登录…

多模态视觉语言模型:BLIP和BLIP2

1. BLIP BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation BLIP的总体结构如下所示&#xff0c;主要包括三部分&#xff1a; 单模态编码器&#xff08;Image encoder/Text encoder&#xff09;&#xff1a;分别进…

【6】mysql查询性能优化-关联子查询

【README】 0. 先说结论&#xff1a;一般用inner join来改写in和exist&#xff0c;用left join来改写not in&#xff0c;not exist&#xff1b;&#xff08;本文会比较内连接&#xff0c;包含in子句的子查询&#xff0c;exist的性能 &#xff09; 1. 本文总结自高性能mysql 6…

局域网无法连接怎么办?

局域网连接是我们日常生活和工作中常用的方式之一&#xff0c;但有时我们可能会遇到局域网无法连接的问题。这给我们的工作和生活带来了很大的困扰。本文将介绍局域网无法连接的常见原因&#xff0c;并推荐一款名为【天联】的组网产品&#xff0c;它能够解决不同地区间的局域网…

软件设计师软考中项学习(二)之计算机系统基础知识

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 学习目标学习内容学习笔记学习总结 学习目标 计算机系统硬件基本组成 中央处理…

开源博客项目Blog .NET Core源码学习(16:App.Hosting项目结构分析-4)

本文学习并分析App.Hosting项目中前台页面的文章专栏页面和文章详情页面。< 文章专栏页面 文章专栏页面总体上为左右布局&#xff0c;左侧显示文章列表&#xff0c;右侧从上向下为关键词搜索、分类导航、热门文章等内容。整个页面使用了layui中的面包屑导航、表单、模版、流…

【1425】java 外籍人员管理系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 外籍人员管理系统是一套完善的java web信息管理系统 采用serlvetdaobean&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff…

【从浅学到熟知Linux】基础IO第三弹=>文件系统介绍、软链接与硬链接(含磁盘结构、文件系统存储原理、软硬链接的创建、原理及应用详解)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 理解文件系统物理角度认识磁盘逻辑角度认识磁盘磁盘寻址磁盘中的寄存器 磁盘存储管理 软链接与硬链接软链接…

【AI自媒体制作】【AI工具】Midjourney中文站

Midjourney Midjourney中文站, MJ中文站 - 专业AI绘图网站 广场 绘画广场&#xff1a; 包含大量其他用户生成好的图片&#xff0c;可以自由保存。 视频广场&#xff1a; 普通用户目前只支持查看&#xff0c;无法下载 画夹广场&#xff1a; 有很多免费的画夹&#xff0c;比…

JS学习归纳8

这是JS基础学习的最后一部分&#xff0c;我们介绍一下简单数据类型和复杂数据类型。 一、 简单数据类型和复杂数据类型 如果有个变量我们以后打算存储为对象&#xff0c;暂时没想好放啥&#xff0c; 这个时候就给 null 1. 简单数据类型 是存放在栈里面 里面直接开辟一个空间存…

03 华三交换机的基础配置

用户登录设备后,直接进入用户视图。用户视图下可执行的操作主要包括查看操作、调试操作、文件管理操作、设置系统时间、重启设备、FTP和Telnet操作等。 从用户视图可以进入系统视图。系统视图下能对设备运行参数以及部分功能进行配置,例如配置夏令时、配置欢迎…

zabbix自定义监控、自动发现和注册以及代理设置

前言 监控项的定制和新设备的注册往往需要大量手动操作&#xff0c;这会导致维护成本的增加和监控效率的降低。本文将介绍如何利用 Zabbix 的自定义功能&#xff0c;实现监控项的动态发布和新设备的自动注册以及代理设置、从而简化运维工作并实现更高效的监控管理。 Zabbix 监…