现在所有的电商类APP都会有根据我的位置获取我附近的商户、离我最近的商户的筛选排序功能,那么这个功能是怎么实现的呢?显然单纯的数据库查询很难做到,一般数据库中只会存储商户的经度和纬度的坐标,那么根据这两个坐标获,再根据用户手机端定位到的经纬度坐标获经过计算得出离我最近的商户,这种实现方式可以有两种:第一种根据坐标及需要的距离计算出半径获取;第二种是通过geoHash算法进行转换。
咱们并不讨论这两种方式的优缺点及具体的可行性问题,但从理论上说明一下两种方式的实现过程,这篇文章先说一下根据半径获取的方式:
假定我们数据库中每个商户都有一个自己的地理位置坐标(经度:longitude;纬度:latitude),这两个参数可以精确到一个点,然后以这个点为圆心再根据需要的距离计算出最大的半径,代码如下:
/**
* 地图坐标BEAN
*
* @author sk.tian
*
*/
public class LocationBean {
private Double longitude; // 经度
private Double latitude; // 纬度
private int raidus; // 半径
private Double minLat; // 最小纬度
private Double maxLat; // 最大纬度
private Double minLng; // 最小经度
private Double maxLng; // 最大经度
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public int getRaidus() {
return raidus;
}
public void setRaidus(int raidus) {
this.raidus = raidus;
}
public Double getMinLat() {
return minLat;
}
public void setMinLat(Double minLat) {
this.minLat = minLat;
}
public Double getMaxLat() {
return maxLat;
}
public void setMaxLat(Double maxLat) {
this.maxLat = maxLat;
}
public Double getMinLng() {
return minLng;
}
public void setMinLng(Double minLng) {
this.minLng = minLng;
}
public Double getMaxLng() {
return maxLng;
}
public void setMaxLng(Double maxLng) {
this.maxLng = maxLng;
}
}
/**
* 根据坐标计算半径多少米范围之内的最大、最小经度和纬度
*
* @param longitude
* 经度
* @param latitude
* 纬度
* @param raidus
* 半径(米)
* @return
*/
public static LocationBean loadCirle(Double longitude, Double latitude,
int raidus) {
LocationBean bean = new LocationBean();
bean.setLongitude(longitude);
bean.setLatitude(latitude);
bean.setRaidus(raidus);
Double degree = (24901 * 1609) / 360.0;
double raidusMile = raidus;
Double dpmLat = 1 / degree;
Double radiusLat = dpmLat * raidusMile;
Double minLat = latitude - radiusLat;
Double maxLat = latitude + radiusLat;
Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
Double dpmLng = 1 / mpdLng;
Double radiusLng = dpmLng * raidusMile;
Double minLng = longitude - radiusLng;
Double maxLng = longitude + radiusLng;
bean.setMaxLat(maxLat);
bean.setMaxLng(maxLng);
bean.setMinLat(minLat);
bean.setMinLng(minLng);
return bean;
}
这个loadCirle方法就是计算出最大和最小经纬度的,将结果封装近LocationBean中,获取到locationBean之后,数据库查询的时候最大和最小的经纬度查询即可:
select * from shops where latitude >=#{minLat} and latitude<=#{maxLat} and longitude>=#{minLng} and longitude<=#{maxLng}