当前位置:首页 > 编程技术 > 正文内容

PHP 经纬度坐标相关计算方法

yc8881年前 (2022-12-03)编程技术190

PHP 经纬度坐标相关计算方法

  • 1. 前言

  • 2. 计算经纬度坐标间的距离

  • 3. 根据经纬度坐标距离排序

  • 4. 经纬度范围查询

    1. 前言


    想要测试本文提供的几个功能函数,可以使用下面这个数据表结构及其数据

    CREATE TABLE `user` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',  `name` varchar(60) DEFAULT NULL COMMENT '昵称',  `longitude` varchar(64) DEFAULT NULL COMMENT '经度',  `latitude` varchar(64) DEFAULT NULL COMMENT '纬度',  `remark` varchar(50) DEFAULT NULL COMMENT '备注',  `distance` varchar(20) DEFAULT NULL COMMENT '距离',  PRIMARY KEY (`id`)) ENGINE=InnoDB COMMENT='用户表';INSERT INTO `user` (`name`, `longitude`, `latitude`, `remark`, `distance`) VALUES ('中海九号公馆', '113.899529', '22.60063', '深圳市宝安区中海九号公馆', '3.66km');INSERT INTO `user` (`name`, `longitude`, `latitude`, `remark`, `distance`) VALUES ('平峦山公园', '113.876462', '22.608322', '深圳市宝安区平峦山公园', '2.88km');INSERT INTO `user` (`name`, `longitude`, `latitude`, `remark`, `distance`) VALUES ('铁仔山公园', '113.86359', '22.592355', '深圳市宝安区铁仔山公园', '1.16km');INSERT INTO `user` (`name`, `longitude`, `latitude`, `remark`, `distance`) VALUES ('宝安公园', '113.902671', '22.58621', '深圳市宝安区宝安公园', '3.45km');

    本文内容测试各个功能函数时,使用的当前位置坐标均为:

    // 深圳市宝安区西乡街道九方广场$longitude = '113.869205';//经度$latitude  = '22.583286';//纬度

    2. 计算经纬度坐标间的距离


    计算经纬度坐标间的距离 功能函数 (前四个参数为两组经纬度坐标)

    /** * 计算经纬度坐标间的距离 * @param $lng1 经度 * @param $lat1 纬度 * @param $lng2 经度 * @param $lat2 纬度 * @param $lang 语言 */function get_distance($lng1, $lat1, $lng2, $lat2, $lang = 'en'){    // 地球的近似半径(单位:米)    $earthRadius = 6367000;    // 将这些度数转换为弧度以使用公式    $lat1 = ($lat1 * pi()) / 180;    $lng1 = ($lng1 * pi()) / 180;    $lat2 = ($lat2 * pi()) / 180;    $lng2 = ($lng2 * pi()) / 180;    // 使用 Haversine 公示计算距离    // http://en.wikipedia.org/wiki/Haversine_formula    $calcLongitude = $lng2 - $lng1;    $calcLatitude  = $lat2 - $lat1;    $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);    $stepTwo = 2 * asin(min(1, sqrt($stepOne)));    // 两个经纬度坐标的距离(单位: 米)    $calculatedDistance = round($earthRadius * $stepTwo);    // 距离单位    $language = [        'en' => ['m' => 'm', 'km' => 'km'],        'cn' => ['m' => '米', 'km' => '公里'],    ];    if (!isset($language[$lang])) throw new \Exception('不支持的语言:' . $lang);    foreach ($language[$lang] as $key => $value) $$key = $value;    // 两个坐标间的距离,单位:米    $distance = round($calculatedDistance);    // 距离单位转换:超出 1000m 时单位转为km    if ($distance < 1000) {        $distance .= $m;    } else {        $distance = floatval(number_format($distance / 1000, 2)) . $km;    }    return $distance; // 返回单位转换后的距离}

    使用示例:

    我在 九方广场,手机上的高德地图导航至 中海九号公馆 显示的距离为 3.6公里,计算结果还是很准确的

    // 深圳市宝安区西乡街道九方广场: 113.869205, 22.583286// 深圳市宝安区西乡街道中海九号公馆: 113.899529, 22.60063$distance = get_distance(113.869205, 22.583286, 113.899529, 22.60063);echo $distance; //3.66km

    3. 根据经纬度坐标距离排序


    项目中经常有距离显示数据的场景,根据距离排序,越近越靠前显示;比如: 店铺地址、房源信息等。代码示例:

    // 当前坐标$longitude = '113.869205';$latitude  = '22.583286';// 数据库中经纬度字段分别为:longitude、latitude$field = '*,( 2 * 6378.137 * ASIN( SQRT( POW( SIN( PI() * (' . $longitude . ' - longitude) / 360 ), 2 ) + COS(PI() * ' . $latitude . ' / 180) * COS(latitude * PI() / 180) * POW( SIN( PI() * (' . $latitude . ' - latitude) / 360 ), 2 ) ) ) ) AS juli';// 根据距离升序查询(越近越靠前)$order = 'juli asc,id desc';// 查询数据Db::name('user')->field($field)->order($order)->select();

    4. 经纬度范围查询


    经纬度范围计算 功能函数

    /** * 经纬度范围计算 * @param $longitude 经度 * @param $latitude  纬度 * @param $radius    半径(米) * @return array */function get_around($longitude, $latitude,  $radius){    $PI = 3.14159265;    $degree = (24901 * 1609) / 360.0;    $dpmLat = 1 / $degree;    $radiusLat = $dpmLat * $radius;    $minLat = $latitude - $radiusLat;    $maxLat = $latitude + $radiusLat;    $mpdLng = $degree * cos($latitude * ($PI / 180));    $dpmLng = 1 / $mpdLng;    $radiusLng = $dpmLng * $radius;    $minLng = $longitude - $radiusLng;    $maxLng = $longitude + $radiusLng;    return compact('minLat', 'maxLat', 'minLng', 'maxLng');}

    使用示例

    查询 3 公里内的数据。首先,根据当前位置获取 3 公里内的经纬度范围,然后带上查询条件查询数据库即可

    $longitude = 113.869205; //经度$latitude  = 22.583286; //纬度$radius    = 3000; //单位:米// 经纬度范围$around = get_around($longitude, $latitude, $radius);// 构造查询条件// 数据库经纬度字段分别为:longitude,latitude$where = [    ['longitude', '>=', $around['minLng']],    ['longitude', '<=', $around['maxLng']],    ['latitude', '>=', $around['minLat']],    ['latitude', '<=', $around['maxLat']],];// 按照经纬度范围查询数据// 建议使用 where 的闭包查询(TP6.0)// 因为闭包可以生成以下SQL,标明这几个查询条件是一个整体,便于后期维护// SQL语句示例: SELECT * FROM `user` WHERE ( 经纬度查询条件 ) and 其他条件$data = Db::name('user')    ->where(function ($query) use ($where) {        $query->where($where);    })    ->select();

    本文来自:编程笔记 源码下载

    本站发布的内容若侵犯到您的权益,请邮件联系站长删除,我们将及时处理!


    从您进入本站开始,已表示您已同意接受本站【免责声明】中的一切条款!


    本站大部分下载资源收集于网络,不保证其完整性以及安全性,请下载后自行研究。


    本站资源仅供学习和交流使用,版权归原作者所有,请勿商业运营、违法使用和传播!请在下载后24小时之内自觉删除。


    若作商业用途,请购买正版,由于未及时购买和付费发生的侵权行为,使用者自行承担,概与本站无关。


    本文链接:https://www.10zhan.com/biancheng/10166.html

    标签: php
    分享给朋友:

    “PHP 经纬度坐标相关计算方法” 的相关文章

    【说站】Thymeleaf报错Error resolving template “XXX”

    【说站】Thymeleaf报错Error resolving template “XXX”

    修改了一下开源项目的目录结构访问突然报错Error resolving template “XXX”可能原因有如下三种:第一种可能:原因:在使用springboot的过程中,如果使用thymeleaf...

    【说站】用一句话就可以去除宝塔面板操作上的二次验证

    【说站】用一句话就可以去除宝塔面板操作上的二次验证

    用过宝塔的朋友应该都会发现,现在宝塔面板有些鸡肋的功能,删除文件、删除数据库、删除站点等操作都需要做计算题!不仅加了几秒的延时等待,还无法跳过!这时候就会有朋友在想,如何去除宝塔面板的二次验证,此篇文...

    【说站】利用Webhook实现Java项目自动化部署

    【说站】利用Webhook实现Java项目自动化部署

    用webhook就能实现Java项目自动部署,其实原理很简单。费话不多说,直接往下看教程。1. 创建gitee仓库并初始化2. 在linux安装git3. 在宝塔的软件的商店里下载Webhook4....

    【说站】电脑安装MySQL时出现starting the server失败原因及解决方案

    【说站】电脑安装MySQL时出现starting the server失败原因及解决方案

    今天在安装MySQL时出现starting the server失败,经过查询分析得出以下结论,记录一下操作步骤。原因分析:如果电脑是第一次安装MySQL,一般不会出现这样的报错。如下图所示。star...

    【说站】Java从resources读取文件内容的方法有哪些

    【说站】Java从resources读取文件内容的方法有哪些

    本文主要介绍的是java读取resource目录下文件的方法,比如这是你的src目录的结构├── main│ ├── java│ │ └── ...

    【说站】linux中redis如何以redis用户重启?

    【说站】linux中redis如何以redis用户重启?

    通过上图我们可以看到,目前状态是已经以 redis 用户启动着,我想修改下 redis 的密码,然后怎么以 redis 用户重启呢?redis 是 nologin 用户,不能通过 su redis 切...