计算两个经纬度之间的球面距离(基于Mysql和PHP实现)

计算两个经纬度之间的球面距离

1、MySQL实现方式 - 基于空间函数(ST_Distance_Sphere)实现

前置条件:确保您使用的是 MySQL 8.0 或更高版本,因为较早的版本对地理空间的支持有限。

1.1 创建表和索引

说明:设置 location 为 point 类型

# 建表
CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `location` point NOT NULL,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`),
  SPATIAL KEY `sp_index` (`location`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

# 创建空间索引
CREATE SPATIAL INDEX sp_index ON `test` (location);

1.2 添加模拟数据

方式一:

INSERT INTO test (location,name) VALUES ( ST_GeomFromText('POINT(121.675702 31.281530)'),'恒越荣新广场');

方式二:

INSERT INTO test (location,name) VALUES ( POINT(121.675702,31.281530),'恒越荣新广场');

1.3 根据定位查询与目标位置的距离并排序

定位:121.658889,31.26485

SELECT *, ST_Distance_Sphere(location, Point(121.658889,31.26485)) AS distance
FROM test
ORDER BY distance asc;

查询结果:
说明: distance的单位: 米
在这里插入图片描述

2、MySQL实现方式 - 基于自定义函数实现

2.1 创建表和索引

说明:设置 location 为 varchar 类型,格式: 经度,纬度

# 建表
CREATE TABLE `test1` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `location` varchar(30) NOT NULL,
  `name` varchar(30) NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

# 创建普通索引
ALTER TABLE `test1` ADD INDEX(`location`);

2.2 添加模拟数据

INSERT INTO test1 (location,name) VALUES ('121.675702,31.28153','恒越荣新广场');
INSERT INTO test1 (location,name) VALUES ('121.673772,31.2799','华美新苑');
INSERT INTO test1 (location,name) VALUES ('121.658889,31.26485','金泰广场');

2.3 封装计算函数

CREATE DEFINER = CURRENT_USER FUNCTION `calculate_distance_from_comma_separated`(`loc1` VARCHAR(50), `loc2` VARCHAR(50))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
    DECLARE lon1 DECIMAL(10, 7);
    DECLARE lat1 DECIMAL(9, 6);
    DECLARE lon2 DECIMAL(10, 7);
    DECLARE lat2 DECIMAL(9, 6);
    DECLARE earth_radius DECIMAL(10, 2) DEFAULT 6371.0; -- 地球平均半径,单位:千米
    DECLARE lat1_rad DECIMAL(11, 7);
    DECLARE lon1_rad DECIMAL(11, 7);
    DECLARE lat2_rad DECIMAL(11, 7);
    DECLARE lon2_rad DECIMAL(11, 7);
    DECLARE distance DECIMAL(10, 2);

    SET lon1 = CAST(SUBSTRING_INDEX(loc1, ',', 1) AS DECIMAL(10, 7));
    SET lat1 = CAST(SUBSTRING_INDEX(loc1, ',', -1) AS DECIMAL(9, 6));
    SET lon2 = CAST(SUBSTRING_INDEX(loc2, ',', 1) AS DECIMAL(10, 7));
    SET lat2 = CAST(SUBSTRING_INDEX(loc2, ',', -1) AS DECIMAL(9, 6));

    SET lon1_rad = RADIANS(lon1);
    SET lat1_rad = RADIANS(lat1);
    SET lon2_rad = RADIANS(lon2);
    SET lat2_rad = RADIANS(lat2);

    SET distance = earth_radius * ACOS(SIN(lat1_rad) * SIN(lat2_rad) + COS(lat1_rad) * COS(lat2_rad) * COS(lon2_rad - lon1_rad));

    RETURN distance;
END;

2.4 根据定位查询与目标位置的距离并排序

定位:121.658889,31.26485

SELECT *,(calculate_distance_from_comma_separated(location,'121.658889,31.26485')) AS distance
FROM test1
ORDER BY distance asc;

查询结果:
说明: distance的单位: 千米
在这里插入图片描述

3、PHP实现方式

3.1 函数封装

说明: 单位: 千米

<?php

/**
 * 计算两个定位的球面距离
 * @param $longitude1 string 经度1
 * @param $latitude1 string 纬度1
 * @param $longitude2 string 经度2
 * @param $latitude2 string 纬度2
 * @return float|int
 */
function calculateDistance($latitude1, $longitude1, $latitude2, $longitude2)
{
    $earthRadius = 6371; // 地球平均半径,单位:千米

    $lat1 = deg2rad($latitude1);
    $lon1 = deg2rad($longitude1);
    $lat2 = deg2rad($latitude2);
    $lon2 = deg2rad($longitude2);

    $distance = acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lon2 - $lon1)) * $earthRadius;

    return $distance;
}

$longitude1 = 121.658889;
$latitude1 = 31.26485;
$longitude2 = 121.675702;
$latitude2 = 31.28153;

$distance = calculateDistance($latitude1, $longitude1, $latitude2, $longitude2);
echo sprintf('%.2f', $distance); # 输出: 2.45
?>

4、其他工具

4.1 经纬度查询

https://jingweidu.bmcx.com/

4.2 经纬度距离计算

https://tools.fun/distance.html

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

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

相关文章

驭码CodeRider将亮相世界人工智能大会,AI 产品、重磅分享,真的很City!

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…

Redis 中 Set 和 Zset 类型

目录 1.Set类型 1.1 Set集合 1.2 普通命令 1.3 集合操作 1.4 内部编码 1.5 使用场景 2.Zset类型 2.1 Zset有序集合 2.2 普通命令 2.3 集合间操作 2.4 内部编码 2.5 使用场景 1.Set类型 1.1 Set集合 集合类型也是保存多个字符串类型的元素&#xff0c;但是和列表类型不同的是&…

LVS+Keepalived 实现高可用负载均衡

前言 在业务量达到一定量的时候&#xff0c;往往单机的服务是会出现瓶颈的。此时最常见的方式就是通过负载均衡来进行横向扩展。其中我们最常用的软件就是 Nginx。通过其反向代理的能力能够轻松实现负载均衡&#xff0c;当有服务出现异常&#xff0c;也能够自动剔除。但是负载…

基于Redisson实现分布式锁

基于redisson实现分布式锁 之前背过分布式锁几种实现方案的八股文&#xff0c;但是并没有真正自己实操过。现在对AOP有了更深一点的理解&#xff0c;就自己来实现一遍。 1、分布式锁的基础知识 分布式锁是相对于普通的锁的。普通的锁在具体的方法层面去锁&#xff0c;单体应…

搜维尔科技:详谈ART的工具追踪技术

您的生产流程中是否已经受益于刀具跟踪系统&#xff1f;您是否意识到它们的价值&#xff1f;因为它们可以优化您的装配顺序&#xff0c;从而节省您的时间和金钱。 目前我们提供两种工具跟踪解决方案&#xff1a; 1.ART与 VERPOSE的解决方案——易于使用的图像识别 安装在工…

探索智能合约在医疗健康领域的革新应用

随着区块链技术的发展&#xff0c;智能合约作为其重要应用之一&#xff0c;在医疗健康领域展示了巨大的潜力和革新性。智能合约是一种基于区块链的自动化执行协议&#xff0c;它可以在无需中介的情况下执行和验证合同。在医疗健康领域&#xff0c;智能合约不仅简化了数据管理和…

房屋租赁管理小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;中介管理&#xff0c;房屋信息管理&#xff0c;房屋类型管理&#xff0c;租房订单管理&#xff0c;租房信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信息&a…

ctfshow-web入门-命令执行(web66-web70)

目录 1、web66 2、web67 3、web68 4、web69 5、web70 1、web66 show_source 被禁用 highlight_file 发现 flag 不在 flag.php 里面 先使用 scandir() 进行目录扫描&#xff1a; cprint_r(scandir("./")); 当前目录下只有 index.php 和 flag.php 扫一下根目…

图书商城系统java项目ssm项目jsp项目java课程设计java毕业设计

文章目录 图书商城系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 图书商城系统 一、项目演示 图书商城系统 二、项目介绍 语言: Java 数据库&#xff1a;MySQL 技术栈&#xff1a;SpringS…

「ETL趋势」FDL定时任务区分开发/生产模式、API输入输出支持自定义响应解析

FineDataLink作为一款市场上的顶尖ETL工具&#xff0c;集实时数据同步、ELT/ETL数据处理、数据服务和系统管理于一体的数据集成工具&#xff0c;进行了新的维护迭代。本文把FDL4.1.7最新功能作了介绍&#xff0c;方便大家对比&#xff1a;&#xff08;产品更新详情&#xff1a;…

spark shuffle——shuffle管理

ShuffleManager shuffle系统的入口。ShuffleManager在driver和executor中的sparkEnv中创建。在driver中注册shuffle&#xff0c;在executor中读取和写入数据。 registerShuffle&#xff1a;注册shuffle&#xff0c;返回shuffleHandle unregisterShuffle&#xff1a;移除shuff…

LED显示屏跟COB显示屏有哪些不同?

COB显示屏跟LED显示屏的主要区别在于产品的显示效果、封装技术、耐用性、防护力、维护以及制造成本方面的不同&#xff0c;这里所说的LED显示屏主要指的是使用SMD封装的LED显示屏&#xff0c;今天跟随COB显示屏厂家中品瑞科技一起来详细看看具体分析&#xff1a; 一、封装技术 …

视图库对接系列(GA-T 1400)九、视图库对接系列(本级)机动车数据推送

背景 在上几章中,我们已经可以将视图库的平台写到我们的数据库中了。 换句话说就已经接入我们的平台了,这几期的话,我们就对接设备, 将设备的数据接入到我们平台来。 机动车数据推送 接入机动车数据推送相对比较简单,我们只需要实现对应的接口就ok了。 具体如图: 有增…

77. UE5 RPG 创建角色的技能栏

在前面的文章里&#xff0c;我们实现了角色属性技能和场景。接下来&#xff0c;我们要优化角色显示UI&#xff0c;在屏幕底部显示角色血量&#xff0c;蓝量&#xff0c;技能和经验值。 创建新的用户控件 选择创建新的控件蓝图 父类为我们自定义的RPGUserWidget&#xff0c;这…

这样拼板帮你省近万元,堪称PCB工程师成本终结者!

别再被骗了&#xff0c;打PCB板价格高不是单价高&#xff01;而是你的拼板导致利用率太低了&#xff01; 今天给大家讲个小故事&#xff0c;教大家如何省钱...... 一个爽朗的晴天&#xff0c;我听闻同事说有客户对他吐槽打板子价格太高&#xff0c;说着说着就开始吹起了牛逼...…

【论文阅读】VASA-1: Lifelike Audio-Driven Talking FacesGenerated in Real Time

整体框架。不直接生成视频帧&#xff0c;而是在潜在空间中生成整体面部动态和头部运动&#xff0c;条件是音频和其他信号。给定这些运动潜在编码&#xff0c;通过面部解码器生成视频帧&#xff0c;还接受从输入图像中提取的外观和身份特征作为输入。 构建了一个面部潜在空间并…

【C#】ProgressBar进度条异步编程思想

1.控件介绍 进度条通常用于显示代码的执行进程进度&#xff0c;在一些复杂功能交互体验时告知用户进程还在继续。 在属性栏中&#xff0c;有三个值常用&#xff1a; Value表示当前值&#xff0c;Minimum表示进度条范围下限&#xff0c;Maximum表示进度条范围上限。 2.简单实…

【网络安全】第8讲 网络安全协议(笔记)

一、网络安全协议概述 1、协议 是指两个或多个以上参与者为完成某项特定的任务而采取的一系列步骤。 2、网络协议 是指计算机网络中通信各方关于如何进行数据交换所达成的一致性规则、标准或约定的集合&#xff0c;即由参与通信的各方按确定的步骤做出一系列通信动作&#xff…

Linux系统安装青龙面板结合内网穿透实现使用公网地址远程访问

文章目录 前言一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 …

Embedded Coder生成C代码注释

学习目标 本教程将向您说明如何生成包含以下内容的代码&#xff1a; 在函数前注中包含函数签名和函数帮助文本。包含 MATLAB 源代码&#xff0c;以带有可追溯性标记的注释表示。在代码生成报告中&#xff0c;可追溯性标记链接到对应的 MATLAB 源代码。 前提条件 要完成本教…