java 实现微信搜索附近人功能

最近给andorid做后台查询数据功能,有一个需求是模仿微信的查找附近人功能。 数据库中存储每个用户的经纬度信息及用户信息,通过当前用户传递过来的经纬度查询这个用户半径N公里以内的用户信息。   

数据库表结构

表信息
表名Mobile_User
mu_id自增,主键
mu_u_id用户表的ID 外键
mu_longitud精度
mu_latitude纬度
(还有其他的一些信息,这里就列举4个字段足矣)



首先需要一个方法,是把传递过来的经纬度按照半径N公里扩散,找出距离中心经纬度N公里的上下左右经纬度值。效果如图


尴尬 随手画的  勿喷


以中心生成经纬度时 正上方和正下方的精度是不变的,只有纬度变化。 生成左右时道理一样,只有精度变化,纬度是不变的。

所以只需要生成上下的纬度,左右的精度就可以了。

参考了网上的文章,http://digdeeply.info/archives/06152067.html 这篇文章是用PHP实现的经纬度查询。修改成java的 代码如下

[java]  view plain copy
  1. /**  
  2.      * 生成以中心点为中心的四方形经纬度  
  3.      *   
  4.      * @param lat 纬度  
  5.      * @param lon 精度  
  6.      * @param raidus 半径(以米为单位)  
  7.      * @return  
  8.      */    
  9.     public static double[] getAround(double lat, double lon, int raidus) {    
  10.     
  11.         Double latitude = lat;    
  12.         Double longitude = lon;    
  13.     
  14.         Double degree = (24901 * 1609) / 360.0;    
  15.         double raidusMile = raidus;    
  16.     
  17.         Double dpmLat = 1 / degree;    
  18.         Double radiusLat = dpmLat * raidusMile;    
  19.         Double minLat = latitude - radiusLat;    
  20.         Double maxLat = latitude + radiusLat;    
  21.     
  22.         Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));    
  23.         Double dpmLng = 1 / mpdLng;                 
  24.         Double radiusLng = dpmLng * raidusMile;     
  25.         Double minLng = longitude - radiusLng;      
  26.         Double maxLng = longitude + radiusLng;      
  27.         return new double[] { minLat, minLng, maxLat, maxLng };    
  28.     }  

这样四周的经纬度都已经生成了。    
下一步是查询数据库中和四周经纬度匹配的数据。 如果数据量很大的话会很耗时间,而且会很消耗流量。所以需要用到分页查询 

代码如下 


[sql]  view plain copy
  1. select * from mobile_user   
  2.             where mu_latitude <> 0  
  3.             and mu_longitud > #left_lat#  
  4.             and mu_longitud < #right_lat#  
  5.             and mu_latitude > #down_lon#  
  6.             and mu_latitude < #top_lon#  
  7.             and mu_u_id <> #uid#  
  8.             order by ACOS(SIN((#lat# * 3.1415) / 180 ) * SIN((mu_latitude * 3.1415) / 180 )   
  9.             +COS((#lat# * 3.1415) / 180 ) * COS((mu_latitude * 3.1415) / 180 )   
  10.             *COS((#lon# * 3.1415) / 180 - (mu_longitud * 3.1415) / 180 ) )   
  11.             * 6380 asc limit #start#,#end#  





我用的是ibatis框架,sql里以#开始并结束的 是我传递过来的参数。  sql语句计算了每条数据和中心经纬度的距离并且以最近进行排序。  sql语句是根据下面的方法演变而来
方法是计算两个经纬度之间的直线距离。

[java]  view plain copy
  1. /**  
  2.      * 计算中心经纬度与目标经纬度的距离(米)  
  3.      *   
  4.      * @param centerLon  
  5.      *            中心精度  
  6.      * @param centerLan  
  7.      *            中心纬度  
  8.      * @param targetLon  
  9.      *            需要计算的精度  
  10.      * @param targetLan  
  11.      *            需要计算的纬度  
  12.      * @return 米  
  13.      */    
  14.     private static double distance(double centerLon, double centerLat, double targetLon, double targetLat) {    
  15.     
  16.         double jl_jd = 102834.74258026089786013677476285;// 每经度单位米;    
  17.         double jl_wd = 111712.69150641055729984301412873;// 每纬度单位米;    
  18.         double b = Math.abs((centerLat - targetLat) * jl_jd);    
  19.         double a = Math.abs((centerLon - targetLon) * jl_wd);    
  20.         return Math.sqrt((a * a + b * b));    
  21.     }   


这样既实现了分页处理,又实现了每条数据的经纬度与中心经纬度的直线距离(以米为单位)。   
  
最后就是组成json数组返回给android使用了。  
做个笔记,欢迎补充。


鉴于一些网站采集本blog的文章,  本站原创。  http://blog.csdn.net/qq7342272   转载请注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值