在已知的二维坐标里找到最接近的点
一、业务场景
最近在研发的项目,在做可视化层,在全球地图上,对我们的国家的陆地地图经纬度按照步长为1的间隔做了二维处理。在得到一组整数的点位信息后,需要将我们已有的数据库数据(业务项目)按照地址的经纬度,映射到这些点位上,找到对应的id建立联系。简化后的处理逻辑如下:

参考上图:
纬度为y轴,跨度为35,间距为1
经度为x轴,跨度为61,间距为1
橙色的点为业务项目对应的经纬度信息(x’,y’)
需要计算出二维坐标中整数点上最靠近的点(利用三角形三边公式)
MIN(aa + bb)
第一层:粉色层
第二层:灰色层
…
由于我们国家的地图存在边界,并不是一个规规矩矩的4方形,且我国的内陆海渤海的包围圈,海洋地区并不计入在二维坐标中,跨度为1的情况下,会出现项目对应的坐标点,需要一层一层对外查找的情况。

二、点位数据
CREATE TABLE `china_grid_map` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主见',`lng` decimal(20,6) NOT NULL COMMENT '经度',`lat` decimal(20,6) NOT NULL COMMENT '纬度',PRIMARY KEY (`id`),KEY `idx_lat` (`lng`),KEY `idx_lng` (`lat`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自定义中国陆地地图网格经纬度信息';
部分示例数据
INSERT INTO china_grid_map (id, lng, lat) VALUES (1, 74.000000, 39.000000),(3, 74.000000, 40.000000),(4, 75.000000, 37.000000),(5, 75.000000, 38.000000),(7, 75.000000, 39.000000),(9, 75.000000, 40.000000),(11, 76.000000, 37.000000),(13, 76.000000, 38.000000),(15, 76.000000, 39.000000),(17, 76.000000, 40.000000),(18, 77.000000, 36.000000),(20, 77.000000, 37.000000),(22, 77.000000, 38.000000),(24, 77.000000, 39.000000),(26, 77.000000, 40.000000),(28, 77.000000, 41.000000),(30, 78.000000, 36.000000),(32, 78.000000, 37.000000),(34, 78.000000, 38.000000),(36, 78.000000, 39.000000),(38, 78.000000, 40.000000),(40, 78.000000, 41.000000),(42, 79.000000, 32.000000),(44, 79.000000, 34.000000),(46, 79.000000, 35.000000),...
(1911, 131.000000, 44.000000),(1913, 131.000000, 45.000000),(1915, 131.000000, 46.000000),(1917, 131.000000, 47.000000),(1920, 132.000000, 46.000000),(1922, 132.000000, 47.000000),(1925, 133.000000, 46.000000),(1927, 133.000000, 47.000000),(1929, 133.000000, 48.000000),(1930, 134.000000, 47.000000),(1932, 134.000000, 48.000000);
三、实现方式
v1.0 版本 MySQL-直取数据
假设要求的项目坐标点为:
{“lat”: “31.231706”, “lng”: “121.472644”}
第一版本:
直接利用sql,查找出最靠近的四个点,然后再计算距离。
select id, lng, lat
from china_grid_map
where lat <= (select lat as latright from china_grid_map where lat >= 31.231706 order by lat limit 1)and lat >= (select lat as latleft from china_grid_map where lat <= 31.231706 order by lat desc limit 1)and lng <= (select lng as lngright from china_grid_map where lng >= 121.472644 order by lng limit 1)and lng >= (select lng as lngLeft from china_grid_map where lng <= 121.472644 order by lng desc limit 1);
如果查到了点 就求出最小的距离对应的点
如果没查到,重复上面点查询,扩大点数
存在的问题:
1.SQL复杂,如果点位正好在边界上,无论扩充多少层都查不到数据
2.耗时久
v2.0 版本 redis-Zset
{“lat”: “31.231706”, “lng”: “121.472644”}
已经知道步长为1,所以最靠近的点,如图1中所示,直接对x’,y’向下向上取整,组合。
利用redis缓存,使用Zset模型
key存储序列化后的信息,score用经度值
利用Zset的对经度范围取值,score (x,x+1)
对返回的数据再挨个查找,找出映射的id
存在的问题:
1.耗时久,因为按照经度 (x,x+1)取值 还是会得到很多数据,需要循环对比数据 才能得到对应的id
2.批量导入数据时,需要反反复复的从redis中取数据
v3.0 版本 内存-HashMap
Map<String,Long> CACHE = new HashMap<>();
key = lat + “-” + lng
value = id
按照步骤二的模式获取到点列表后,从map中get(key);
如果第一层4个点未命中,扩大到第二层
存在的问题:
1.存在内存中,分布式系统部署,每台服务器上的内存各自独立[好在该点位信息一旦生成后不会修改,在项目初始化后,不存在插入、删除相关的操作,只要考虑查询的时间效率]
2.791个点,消耗的存储比较大:113944
v4.0 版本 内存-二维数组 long[][]
由于点位是提前知道不会变动,且是步长为1的有规则的数据
经度数据区间 : 74 - 134 总个数 61
纬度数据区间 : 19 - 53 总个数 35
private static long[][] GRID_ARRAY = new long[61][35];
在项目启动时初始化缓存数据
public void initCacheByArray() {//先获取到所有的点位数据List<GridMapDO> mapDOS = baseMapper.listAllDO();if (CollectionUtil.isEmpty(mapDOS)) {return;}//循环将数据放入到缓存中for (GridMapDO grid : mapDOS) {int arrayLng = getArrayLng(grid.getLng());int arrayLat = getArrayLat(grid.getLat());if (arrayLng == -1 || arrayLat == -1) {//存在越界的点位log.info(">>>>>>>>>存在越界点位[经度:{},纬度:{}],跳过缓存<<<<<<<", grid.getLng(), grid.getLat());continue;}//找到对应的位置 将id存储为数组的值GRID_ARRAY[arrayLng][arrayLat] = grid.getId();}log.info(">>>> 缓存结束,缓存内容:[{}] <<<<<<", JSONObject.toJSONString(GRID_ARRAY));}private int getArrayLng(BigDecimal lng) {//防止数组下标越界int intLng = lng.intValue();if (intLng < 74 || intLng > 134) {return -1;}return lng.intValue() - 74;}private int getArrayLat(BigDecimal lat) {int intLat = lat.intValue();if (intLat < 19 || intLat > 53) {return -1;}return lat.intValue() - 19;}
用的时候 只需要计算出点位,直接从数组中取对应的下标即可。
如果 GRID_ARRAY[x][y] == 0L 说明点位不是中国的大陆地图
如果 GRID_ARRAY[x][y] != 0L 计算出该点的距离平方
存在的问题:
1.存在内存中,分布式系统部署,每台服务器上的内存各自独立[好在该点位信息一旦生成后不会修改,在项目初始化后,不存在插入、删除相关的操作,只要考虑查询的时间效率]
2.791个点,消耗的存储比V3.0版本减少了1个数量级,但是数组用的是连续的存储空间
四、总结
可以多尝试,找出最合适项目的,结合数据的规律,空间换时间 等等
只有实践了 才能找到最佳的吧…
相关文章:
在已知的二维坐标里找到最接近的点
一、业务场景 最近在研发的项目,在做可视化层,在全球地图上,对我们的国家的陆地地图经纬度按照步长为1的间隔做了二维处理。在得到一组整数的点位信息后,需要将我们已有的数据库数据(业务项目)按照地址的经纬度,映射到…...
spring boot 八、 sharding-jdbc 分库分表 按月分表
在项目resources目录下新建com.jianmu.config.sharding.DateShardingAlgorithm 文件 新增yaml配置 数据源 spring:shardingsphere:props:sql:#是否在日志中打印 SQLshow: true#打印简单风格的 SQLsimple: truedatasource:names: pingxuanlogpingxuanlog:type: com.alibaba.dru…...
Java 8 中Stream流的一些用法
public class Djmxlist {private String dxmc;private Integer sl;public String getDxmc() {return dxmc;}public void setDxmc(String dxmc) {this.dxmc dxmc;}public Integer getSl() {return sl;}public void setSl(Integer sl) {this.sl sl;} }插入一下数据 List<Djm…...
Elasticsearch 8.10 中引入查询规则 - query rules
作者:Kathleen DeRusso 我们很高兴宣布 Elasticsearch 8.10 中的查询规则! 查询规则(query rules)允许你根据正在搜索的查询词或根据作为搜索查询的一部分提供的上下文信息来更改查询。 什么是查询规则? 查询规则&…...
Windows PostgreSql 创建多个数据库目录
1 使用默认用户Administrator 1.1初始化数据库目录 E:\Program Files\PostgreSQL\13> .\bin\initdb -D G:\DATA\pgsql\data3 -W -A md5 1.2连接数据库 这时User为Administrator,密码就是你刚才设置的,我设置的为123456,方便测试。 2 添加…...
Java AOP Framework概述
Java AOP Framework概述 1. AspectJ1.1 使用AspectJ进行切面编程 2. Spring AOP2.1 使用Spring AOP进行切面编程2.2 如何决定使用哪种动态代理2.3 如何通过配置指定代理方式2.4 Spring AOP和AspectJ的关系 3. Spring Boot AOP4. 扩展4.1 AspectJ织入方式详解 参考 Java常用的AO…...
220V转12V芯片-交流45v-265v输入,固定12v输出峰值电流600MA
标题:220V转12V芯片,实现宽电压输入和固定12V输出 摘要:本文介绍了一款具备宽电压输入范围(45V-265V)和固定12V输出的220V转12V芯片。该芯片内置了650V高压MOS管,并通过CS电阻调节输出电流,最大…...
TOGAF架构开发方法—初步阶段
本章描述了满足新企业体系结构业务指令所需的准备和启动活动,包括组织特定体系结构框架的定义和原则的定义。 一、目标 初步阶段的目标是: 确定组织所需的体系结构功能: 审查进行企业架构的组织背景确定受体系结构功能影响的企业组织的元素并确定其范围确定与架构功能相交的…...
软件定制APP开发步骤分析|小程序
软件定制APP开发步骤分析|小程序 软件定制开发步骤: 1.需求分析: 这是软件定制开发的第一步,也是最关键的一步。在这个阶段,软件开发团队需要与客户进行沟通,了解客户的具体需求和期望。通过讨论和交流,确…...
postman接口传参案例
目录 案例1: 接口A 接口B 案例2: //断言 案例1: 接口A 根据返回值需要从返回值中提取userid值,在Tests标签栏下编写脚本 //获取返回的响应值,并转化为json格式 var jsonData pm.response.json(); // 获取返回…...
【2023华为杯A题】WLAN网络信道接入机制建模(代码、思路.....)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
CFCA企业版通配符SSL证书
CFCA是中国CFCA企业版通配符SSL证书金融认证中心的缩写,即China Financial Certification Authority。它是一家经过中国人民银行和国家信息安全机构批准成立的国家级权威安全认证机构,也是国际CA浏览器联盟组织(CA/Browser Forum)…...
基于ASCON的AEAD
1. 引言 前序博客: ASCON:以“慢而稳”赢得NIST轻量级加密算法标准密码学中的AEAD(authenticated encryption with associated data) 对称密钥加密过去数年来已发生改变,具体为: 当今主要使用stream ciphers,因其比…...
汇编宏伪指令介绍
1、汇编宏伪指令介绍 .macro macname macargs .endm(1)“.macro"和”.endm"表示宏定义的开始和结束; (2) “.macro"后面接着宏定义的名字,然后是参数,参数后面的宏定义的实现…...
优化系统报错提示信息,提高人机交互(一)
1、常规报错及处理 package com.example.demo.controller;import com.example.demo.service.IDemoService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.w…...
FPGA纯verilog实现8路视频拼接显示,提供工程源码和技术支持
目录 1、前言版本更新说明免责声明 2、我已有的FPGA视频拼接叠加融合方案3、设计思路框架视频源选择OV5640摄像头配置及采集静态彩条视频拼接算法图像缓存视频输出 4、vivado工程详解5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他注意事项 6、上板调试验证并演示…...
spring boot项目一次性能测试的总结
满足标准:并发大于等于100 ,平均响应时间小于等于3秒 项目在压测过程中并发数只有50,在并发数100的情况下有很多请求链接是失败的 我们该如何入手去处理这些问题并提高并发数呢? 1、首先从压测结果入手,对不满足标准…...
10分钟设置免费海外远程桌面
前言 本教程将向您介绍如何使用 Amazon Lightsail 服务的免费套餐轻松搭建属于您的远程桌面。依托于 Amazon 全球可用区,您可以在世界各地搭建符合您配置需求的远程桌面。 本教程需要先拥有亚马逊云科技海外账户。现在注册亚马逊云科技账户可以享受12个月免费套餐…...
基于复旦微的FMQL45T900全国产化ARM核心模块(100%国产化)
TES745D是一款基于上海复旦微电子FMQL45T900的全国产化ARM核心板。该核心板将复旦微的FMQL45T900(与XILINX的XC7Z045-2FFG900I兼容)的最小系统集成在了一个87*117mm的核心板上,可以作为一个核心模块,进行功能性扩展,能…...
2023.9.11 关于传输层协议 UDP和TCP 详解
目录 UDP协议 TCP协议 TCP十大核心机制 确认应答 超时重传 连接管理(三次握手 四次挥手) 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 面向字节流 粘包问题 TCP 中的异常处理 经典面试题 对比 TCP 和 UDP 如何使用 UDP 实现可靠传…...
从用户态到内核态:Linux Hook技术的全景实践与攻防解析
1. Linux Hook技术入门:从概念到实践 第一次接触Hook技术是在十年前的一个安全分析项目中,当时需要监控某个可疑进程的行为。那时候我才明白,原来Linux系统里藏着这么多可以"截胡"程序执行的秘密通道。简单来说,Hook技术…...
居家办公网络优化指南:从Wi-Fi原理到实战部署
1. 居家隔离如何压垮了我们的家庭Wi-Fi网络如果你在2020年初也经历过居家办公或学习,大概率会对某个场景记忆犹新:视频会议卡成PPT、在线课程频繁掉线、追剧时那个转不完的缓冲圈。这不是你一个人的问题,而是全球无数家庭网络在特定时期承受的…...
基于宏观通胀预测模型的利率预期重定价:华尔街降息路径为何出现系统性回撤?CPI成为关键校准变量
摘要:本文通过宏观通胀预测模型,结合利率预期曲线重定价算法与市场情绪迁移分析,对当前美通胀路径、CPI数据影响及华尔街降息预期变化进行系统性建模,分析利率政策预期从宽松交易向数据依赖模式切换的结构性原因。一、市场情绪迁移…...
智能网联汽车窄路车流预测与协同通行【附仿真】
✨ 长期致力于智能网联汽车、窄路段、短时车流量预测、协同通行研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)窄路车流时空异质图特征构建ÿ…...
初次使用Taotoken模型广场进行选型与切换的直观体验
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 初次使用Taotoken模型广场进行选型与切换的直观体验 对于开发者而言,接入大模型API后,面对的第一个现实问题…...
告别手动建造:TEdit免费地图编辑器如何10倍提升泰拉瑞亚创作效率
告别手动建造:TEdit免费地图编辑器如何10倍提升泰拉瑞亚创作效率 【免费下载链接】Terraria-Map-Editor TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also l…...
告别调参焦虑!用Matlab Regression Learner App快速搞定你的第一个回归模型(附三维曲面拟合实战)
告别调参焦虑!用Matlab Regression Learner App快速搞定你的第一个回归模型(附三维曲面拟合实战) 在科研和工程领域,数据建模是绕不开的核心技能。但传统建模流程往往令人望而生畏:从数据清洗到特征工程,从…...
短视频矩阵系统技术选型:从自研到 SaaS 的成本与收益分析
前言在短视频运营规模化的今天,几乎所有有一定规模的团队都面临着一个关键的技术决策:是自研矩阵管理系统,还是选择成熟的 SaaS 解决方案。很多团队在初期都会选择自研,认为这样可以更好地满足个性化需求,但最终往往陷…...
工作5年的Go程序员,转大模型开发3个月,我踩过的所有坑
文章目录前言一、第一个大坑:以为大模型就是调API,结果连面试门都没入二、第二个大坑:技术栈转换,从Go的天堂掉进Python的地狱三、第三个大坑:Go调用大模型推理,踩不完的性能和内存坑四、第四个大坑&#x…...
k8s——RBAC认证中心
一、整体流程:认证 → 授权 → 准入控制在 Kubernetes 中,所有操作都要通过 API Server。当你(或某个程序)想对集群做任何事(比如创建一个 Pod),必须经过三步检查:认证:你…...
