基于经纬度的简单附近地理位置搜索

1 篇文章 0 订阅
1 篇文章 0 订阅

1,获取经纬度

    注意有3中经纬度的表示方法

经纬度以度数表示 ,一般可直接以小数点表示,但亦可把度数的小数点分为角分(1角分等于六十分之一度),和秒(一秒等于六十分之一分)。表示经纬度有多样模式,以下是其中一些例子。
  1. 度分秒表示(度:分:秒)-49°30'00"-123d30m00s
  2. 度分表示(度:分)-49°30.0'-123d30.0m
  3. 度数表示-49.5000°-123.5000d(一般会有四位小数)。

这里的经纬度是用度数表示的,在有些公式的计算中,是需要把角度转换为弧度的,注意他们的转换


经纬度转换的函数:
deg2rad  —  将角度转换为弧度
rad2deg() - 将弧度数转换为相应的角度数


2,数据库中存储经纬度

    保存类型float(10,6)

创建 MySQL 表时,您应当特别注意 lat 和 lng 属性。鉴于 Google Maps 目前的缩放能力,您只需要精确到小数点后六位数。为了让表占用的存储空间降至最低,您可以将 lat 和 lng 属性指定为大小是 (10,6) 的浮点数。这样,这些字段将会存储小数点后 6 位数以及小数点前最多 4 位数,如 -123.456789 度。




3,实现算法(基于一定范围内)

在庞大的地理数据库中搜索地点,索引是很重要的。但是,我们的需求是搜索附近地点, 例如,坐标(39.91, 116.37)附近500米内有什么地点?搜索条件是地点坐标与当前坐标之间的距离, 显然是无法应用索引的。

那么换个思路:首先算出“给定坐标附近500米”这个范围的坐标范围。 虽然它是个圆,但我们可以先求出该圆的外接正方形,然后拿正方形的经纬度范围去搜索数据库。

先算出该点周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录。



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

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

假设已知点的经纬度分别为$lng, $lat
先实现经度范围的查询,
在haversin公式中令φ1 = φ2,可得:



用PHP进行计算,就是:

Example
1
2
3
//$lat 已知点的纬度
$dlng =  2 * asin(sin( $distance / (2 * EARTH_RADIUS)) / cos ( deg2rad ( $lat )));
$dlng = rad2deg( $dlng ); //转换弧度

然后是纬度范围的查询,
在haversin公式中令 Δλ = 0,可得



在PHP中进行计算,就是:

Example
1
2
$dlat = $distance /EARTH_RADIUS; //EARTH_RADIUS地球半径
$dlat = rad2deg( $dlat ); //转换弧度
 

latlng列上建立索引,能从一定程度上提高范围查询的效率。

不过,这样查询到的地点是正方形范围内的地点,一些结果与当前点的距离可能会超出给定的距离。 如果要求严格,可以遍历结果并计算与当前点之间的距离,并过滤掉不符合要求的结果。


4,由近到远进行排序显示

基于第3步的范围内进行计算距离





5,详细代码实现过程

根据用户的经纬度获取搜索范围的经纬度:
    public function googleTest()
    {
        $distance = 0.2;//单位是10KM
        $radius = 6371.393;//代为是KM
        
        //用户当前的地理位置(经纬度的第三种表示方法)
        $lng '121.606546';
        $lat '29.918017';
        
        //计算偏移的角度并转化为弧度
        $dlng rad2deg(2*asin(sin($distance/(2*$radius))/cos($lat)));
        $dlat rad2deg($distance*10/$radius);
        
        //计算实际搜索的四边形的四个边界范围
        $lng_left round($lng-$dlng,6);
        $lng_right round($lng+$dlng,6);
        $lat_top round($lat+$dlat,6);
        $lat_bottomround($lat $dlat,6);
    }
将上述获取的边界范围带入到sql语句中用于查询:
SELECT   *  
FROM   `t_store`  
WHERE   m_lat   >   29.900032
AND   m_lat   <   2 9.936002
AND   m_lng   >   121.581848
AND   m_lng   <   121.631244
LIMIT   0   ,   30




6,参考资料

附近地点搜索初探: http://blog.charlee.li/location-search/
GPS经纬度的表示方法与转换: http://blog.sina.com.cn/s/blog_3d955ce60100ymz9.html
PHP,Mysql-根据一个给定的经纬度的店,进行附近地点查询-合理利用算法,效率提高2125倍: http://digdeeply.org/archives/06152067.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要将经纬度转化为地理位置,你可以使用百度地图的地理编码功能。具体步骤如下: 1. 实例化一个地理编码查询对象。 2. 设置反地理编码位置坐标。 3. 发起反地理编码请求(经纬度->地址信息)。 4. 获取反地理编码结果中的地址信息。 下面是一个示例代码: ``` //实例化一个地理编码查询对象 GeoCoder geoCoder = GeoCoder.newInstance(); //设置反地理编码位置坐标 ReverseGeoCodeOption op = new ReverseGeoCodeOption(); op.location(latLng); op.newVersion(1);//百度4.5.2版本之后需要加新版本标准。 //发起反地理编码请求(经纬度->地址信息) geoCoder.reverseGeoCode(op); geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() { @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult arg0) { //获取点击的坐标地址 String address = arg0.getAddress(); Log.e("LatLngToAddress","address=" + address); } @Override public void onGetGeoCodeResult(GeoCodeResult arg0) { } }); ``` 这样,你就可以通过经纬度获取对应的地理位置信息了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [经纬度转换地址](https://blog.csdn.net/smile6868/article/details/126739063)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [经纬度与位置信息的转换](https://blog.csdn.net/dong_xg/article/details/53102478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值