当前位置: 首页 > news >正文

根据当前门店经纬度,求出1km内的门店

文章目录

  • 前言
  • mysql计算经纬度之间的距离
    • 准备工作
    • 计算距离
    • 正确性检验
  • 其它方式实现
  • 总结


前言

需求:

  1. 公司有一些门店的注册信息,注册信息中有门店详细地址,我们需要通过门店的地址信息获取到地图上的经纬度。

    经纬度可以通过高德或者百度的接口来付费*获取,下面是高德通过地址获取经纬度的文档。
    https://lbs.amap.com/api/webservice/guide/api/georegeo

  2. 使用不同门店的经纬度计算出门店之间的距离。

    其实高德或百度地图本身也有这种api,但是收费比较贵,所以我们采用其它方法来做,我们可以用java的方式来计算出,也可以通过mysq空间函数来计算出,当然这种方式的精确度会有所出入但是不会相差太大,这里我们主要使用mysql来实现。

mysql计算经纬度之间的距离

准备工作

这里我们省略了从地图api获取门店经纬度这一步骤,下面有一些我从高德获取到的经纬度。

测试数据如下:
在这里插入图片描述
生成数据sql:
注意:location 是空间类型字段,并且添加了空间索引

CREATE TABLE `ums_member_company_coordinate` (`id` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT '主键',`company_id` BIGINT ( 20 ) DEFAULT NULL COMMENT '门店ID',`company_name` VARCHAR ( 255 ) DEFAULT NULL,`address_detail` VARCHAR ( 255 ) DEFAULT NULL COMMENT '详细地址\n',`longitude` VARCHAR ( 64 ) DEFAULT NULL COMMENT '经度',`latitude` VARCHAR ( 64 ) DEFAULT NULL COMMENT '维度',`location` point NOT NULL COMMENT '经纬度',PRIMARY KEY ( `id` ) USING BTREE,UNIQUE KEY `index_company_id` ( `company_id` ),
SPATIAL KEY `spatial_index_location` ( `location` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '客户门店高德坐标';

location的类型是空间类型所以需要插入的时候使用POINT 函数

INSERT INTO `ums_member_company_coordinate` ( `company_id`, `company_name`, `address_detail`, `longitude`, `latitude`, `location` )
VALUES(17787,'宁波杭州湾新区春草堂大药房有限公司','宁波市慈溪市浙江省宁波杭州湾新区南洋商城4幢','121.294532','30.290669',POINT (CAST('121.294532' AS DECIMAL ( 12, 6 )),CAST('30.290669' AS DECIMAL ( 12, 6 ))) );
INSERT INTO `ums_member_company_coordinate` ( `company_id`, `company_name`, `address_detail`, `longitude`, `latitude`, `location` )
VALUES(10132,'宁波杭州湾热心大药房有限公司','宁波市慈溪市浙江省宁波杭州湾新区庵东镇海南村中心东路173号','121.298002','30.288234',POINT (CAST('121.298002' AS DECIMAL ( 12, 6 )),CAST('30.288234' AS DECIMAL ( 12, 6 ))) );
INSERT INTO `ums_member_company_coordinate` (`company_id`,`company_name`,`address_detail`,`longitude`,`latitude`,`location`
)
VALUES(1540,'七台河市恒健大药房','黑龙江省七台河市桃山区桃北街125号楼10号商服','131.017754','45.773341',POINT (CAST('131.017754' AS DECIMAL ( 12, 6 )),CAST('45.773341' AS DECIMAL ( 12, 6 ))) );

计算距离

计算距离sql:

SELECTt1.companyId,t1.companyAId,t1.companyBId,t1.companyAName,t1.companyBName,t1.companyALongitude,t1.companyALatitude,t1.companyBLongitude,t1.companyBLatitude,t1.distance --  门店和门店之间的距离FROM(SELECTIF(a.company_id > b.company_id,CONCAT( a.company_id, "-", b.company_id ),CONCAT( b.company_id, "-", a.company_id )) AS companyId,ROW_NUMBER() OVER (PARTITION BY companyId ORDER BY companyId) AS row_num, -- 用来去重的字段a.company_id AS companyAId,b.company_id AS companyBId,a.company_name AS companyAName,b.company_name AS companyBName,a.longitude AS companyALongitude,a.latitude AS companyALatitude,b.longitude AS companyBLongitude,b.latitude AS companyBLatitude,ROUND( ST_DISTANCE_SPHERE ( a.location, b.location ), 2 ) AS distanceFROMums_member_company_coordinate aLEFT JOIN ums_member_company_coordinate b ON ST_INTERSECTS ( a.location, BUFFER ( b.location, 1 ) )WHEREROUND( ST_DISTANCE_SPHERE ( a.location, b.location ), 6 ) < 1000 -- mysql的空间函数,1000是指1000米的距离) t1WHERE 1=1AND t1.row_num = 1  -- 去重and t1.companyAId != t1.companyBId -- 去掉门店和门店自身比较的数据

用的是mysql的空间函数,ROUND( ST_DISTANCE_SPHERE ( a.location, b.location ), 6 ) < 1000 这里的1000是指1000米

正确性检验

通过上面的sql最终计算的结果如下:
在这里插入图片描述
我们可以通过使用高德的工具检验我们结果数据的准确性。

https://lbs.amap.com/demo/jsapi-v2/example/calcutation/calculate-distance-between-two-markers

在这里插入图片描述

其它方式实现

  1. 使用Haversine公式计算:

public static void main(String[] args) {// 传入两个门店的经纬度对比距离double distance = calculateDistance(121.298002, 30.288234, 121.294532, 30.290669);System.out.println("distance = " + distance);}/*** 计算距离* @param lat1 a点纬度* @param lon1 a点经度* @param lat2 b点纬度* @param lon2 b点经度* @return*/public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {// 地球半径,单位:米final double R = 6371000;// 将经纬度转换为弧度double lat1Rad = Math.toRadians(lat1);double lon1Rad = Math.toRadians(lon1);double lat2Rad = Math.toRadians(lat2);double lon2Rad = Math.toRadians(lon2);// 计算经纬度的差值double deltaLat = lat2Rad - lat1Rad;double deltaLon = lon2Rad - lon1Rad;// 使用Haversine公式计算两点间的距离double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)+ Math.cos(lat1Rad) * Math.cos(lat2Rad)* Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));// 计算距离double distance = R * c;return distance;}

2.使用geo来计算距离
geo计算需要导入对应的依赖,我这里使用的gradle作为依赖包的管理我的,下面是我的build.gradle文件

plugins {id("java")
}group = "org.example"
version = "1.0-SNAPSHOT"repositories {mavenCentral().content {excludeModule("javax.media", "jai_core")}maven {url "https://repo.osgeo.org/repository/release/" // GeoTools 仓库}
}dependencies {implementation 'org.geotools:gt-main:25.0' // 使用 GeoTools 25.0 版本作为示例
}tasks.test {useJUnitPlatform()
}
 public static void main(String[] args) {// 创建 GeometryFactory 实例GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();// 创建第一个点Coordinate point1Coordinate = new Coordinate(121.298002, 30.288234); // 经度, 纬度Point point1 = geometryFactory.createPoint(point1Coordinate);// 创建第二个点Coordinate point2Coordinate = new Coordinate(121.294532, 30.290669);Point point2 = geometryFactory.createPoint(point2Coordinate);// 计算两个点之间的直线距离(大圆距离)double distanceInMeters = calculateDistance(point1, point2);System.out.println("两个点之间的直线距离:" + distanceInMeters + " 米");}// 计算两个点之间的直线距离(大圆距离)private static double calculateDistance(Point point1, Point point2) {return point1.distance(point2) * 111000.0; // 将距离从度转换为米,约111千米/度}

总结

不管是java公式Haversine、geo、mysql的实现方式都会与地图api计算出的距离有一些差异的。


文章转载自:

http://MwaNr3o2.kxqfz.cn
http://6QTfj6ZR.kxqfz.cn
http://BtSygsu3.kxqfz.cn
http://fD1beDYP.kxqfz.cn
http://7030r3QO.kxqfz.cn
http://GNn8gCZ7.kxqfz.cn
http://jO6NcdIm.kxqfz.cn
http://4mKl01Y4.kxqfz.cn
http://UWkhiAKm.kxqfz.cn
http://kic0Td8r.kxqfz.cn
http://12teo5U3.kxqfz.cn
http://zYE3a5t1.kxqfz.cn
http://1QCOklcp.kxqfz.cn
http://OqrkZQd5.kxqfz.cn
http://567acjeN.kxqfz.cn
http://2VRh5DKk.kxqfz.cn
http://2kzALk3p.kxqfz.cn
http://6031hI22.kxqfz.cn
http://7Q96J4ES.kxqfz.cn
http://r4woyj2t.kxqfz.cn
http://vZDVmcAC.kxqfz.cn
http://XdnjADaY.kxqfz.cn
http://b5q9GohP.kxqfz.cn
http://enac3kZs.kxqfz.cn
http://Oed2udet.kxqfz.cn
http://T7sBz3B0.kxqfz.cn
http://WW8qdDgA.kxqfz.cn
http://bgDPFVpV.kxqfz.cn
http://Vk3xPh7Q.kxqfz.cn
http://ZPALHxAB.kxqfz.cn
http://www.dtcms.com/a/379757.html

相关文章:

  • java类冲突
  • 线上的Python服务如何部署?
  • ​​Cinema 4D 2026 核心亮点:AI智能驱动 + 无缝实时渲染​
  • 【Pywinauto库】10.7 pywinauto.controls.uia_controls控件
  • Next.js 字体优化:使用 `next/font` 告别布局偏移和性能瓶颈
  • 腾讯滑块---Js逆向酷狗音乐登入
  • 机器学习算法概述
  • zzz‘sJavaweb知识点总结
  • 【STL源码剖析】二叉世界的平衡:从BST 到 AVL-tree 和 RB-tree 的插入逻辑
  • Altium Designer使用精通教程 第四章(PCB封装库绘制)
  • 基于多模态与主动学习的车船飞机图像识别系统研究与应用技术方案
  • cesium的3dtiles模型矫正工具
  • Win7环境中离线安装Visual Studio 2017的相关问题
  • 解决 Typora 0.11.18 版本过期问题
  • 基于R语言机器学习方法在生态经济学领域中的实践技术应用;十大原理、熵权法、随机森林、神经网络、因果推断全解析
  • 数据结构:并查集
  • Unity Addressable System 本地服务器功能验证
  • 用简单的日期类巩固C++类与对象基本知识
  • python+springboot+uniapp微信小程序题库系统 在线答题 题目分类 错题本管理 学习记录查询系统
  • DeepSeek v3.1和DeepSeek R1在编程风格方面的区别
  • kafka启动小脚本
  • AI-调查研究-76-具身智能 当机器人走进生活:具身智能对就业与社会结构的深远影响
  • 机器学习-机器学习模型简介
  • sVLMs之:《SmolVLM: Redefining small and efficient multimodal models》的翻译与解读
  • 【GPT入门】第67课 多模态模型实践: 本地部署文生视频模型和图片推理模型
  • 机器学习-探索性数据分析
  • AVL树旋转全解析:四步让失衡二叉树“华丽转身”
  • 一文学会CMakeLists.txt: CMake现代C++跨平台工程化实战
  • 使用XAMPP一键式快速搭建LAMP的完整环境——且配置上WordPress网站的保姆级教程
  • 【Docker】P2 Docker环境构建准备:MacOS 与 Linux