php教程 php手册 php根据地址的经纬度查询周围的城市例子

php根据地址的经纬度查询周围的城市例子

May 26, 2016 am 08:19 AM

目前的工作是需要对用户的一些数据进行分析,每个用户都有若干条记录,每条记录中有用户的一个位置,是用经度和纬度表示的.

还有一个给定的数据库,存储的是一些已知地点以及他们的经纬度,内有43W多条的数据,现在需要拿用户的经纬度和已知地点进行距离匹配,如果它们之间的距离小于一定的数据,比如说500米,就认为用户是在这个地点.

MYSQL本身是支持空间索引的,但是在5.x的版本中,取消了对Distance()和Related()的支持,无法使用空间的距离函数去直接去查询距离在一定范围内的点,所以,我首先想到的是,对每条记录,去进行遍历,跟数据库中的每一个点进行距离计算,当距离小于500米时,认为匹配,这样做确实能够得到结果,但是效率极其低下,因为每条记录都要去循环匹配40W条数据,其消耗的时间可想而知,经过记录,发现每条记录处理的时间消耗达到1700ms,针对每天上亿的数据量,这样一个处理速度,让人情何以堪啊.

我自己也有个想法,就是找到每条记录所在点的经纬度周围的一个大概范围,比方说正方形的四个点,然后使用mysql的空间计算,使用MBR去得出点在这个矩形内的已知记录,然后进行匹配,可惜,自己没想出能计算到四个点经纬度的方法.

意外的查询到了一个关于这个计算附近地点搜索初探,里面使用python实现了这个想法.

所以参考了一下原文中的算法,使用PHP进行了实现,实现原理也是很相似的,先算出该点周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录.

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围

参考wiki百科上的一些球面计算公式:

Great-circle distance

Haversine formula

假设已知点的经纬度分别为$lng, $lat

先实现经度范围的查询,在haversin公式中令φ1 = φ2,可得,用PHP进行计算,就是,代码如下:

//$lat 已知点的纬度 

$dlng =  2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat))); 

$dlng = rad2deg($dlng);//转换弧度 

然后是纬度范围的查询,在haversin公式中令 Δλ = 0,可得,在PHP中进行计算,就是代码如下:

$dlat = $distance/EARTH_RADIUS;//EARTH_RADIUS地球半径 

$dlat = rad2deg($dlat);//转换弧度 

最后,就可以得出四个点的坐标:

left-top : (lat + dlat, lng – dlng) 
right-top : (lat + dlat, lng + dlng) 
left-bottom : (lat – dlat, lng – dlng) 
right-bottom: (lat – dlat, lng + dlng)
로그인 후 복사

我把以上方法写成了一个函数,综合起来就是:

define(EARTH_RADIUS, 6371);//地球半径,平均半径为6371km 
 /** 
 *计算某个经纬度的周围某段距离的正方形的四个点 
 * 
 *@param lng float 经度 
 *@param lat float 纬度 
 *@param distance float 该点所在圆的半径,该圆与此正方形内切,默认值为0.5千米 
 *@return array 正方形的四个点的经纬度坐标 
 */ 
 function returnSquarePoint($lng, $lat,$distance = 0.5){ 
    $dlng =  2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat))); 
    $dlng = rad2deg($dlng); 
    $dlat = $distance/EARTH_RADIUS; 
    $dlat = rad2deg($dlat); 
    return array( 
'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng), 
'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng), 
'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng), 
'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng) 
);
 } 
//使用此函数计算得到结果后,带入sql查询。 
$squares = returnSquarePoint($lng, $lat); 
$info_sql = "select id,locateinfo,lat,lng from `lbs_info` where lat<>0 and lat>{$squares[&#39;right-bottom&#39;][&#39;lat&#39;]} and lat<{$squares[&#39;left-top&#39;][&#39;lat&#39;]} and lng>{$squares[&#39;left-top&#39;][&#39;lng&#39;]} and lng<{$squares[&#39;right-bottom&#39;][&#39;lng&#39;]} ";
로그인 후 복사

在lat和lng上建立一个联合索引后,使用此项查询,每条记录的查询消耗平均为0.8毫秒,相比以前的1700ms,真的是天壤之别啊,效率真真的是以前的2125倍~~

总结:这应该也不是效率最好的办法,但是效率比以前确实有明显的提升,请记住,总有办法更好的.


文章网址:

随意转载^^但请附上教程地址。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)