Java实现

public final class DistanceUtils {/*** 地球半径,单位 km*/private static final double EARTH_RADIUS = 6378.137;/*** 根据经纬度,计算两点间的距离** @param longitude1 第一个点的经度* @param latitude1  第一个点的纬度* @param longitude2 第二个点的经度* @param latitude2  第二个点的纬度* @return 返回距离 单位千米*/public static double getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {// 纬度double lat1 = Math.toRadians(latitude1);double lat2 = Math.toRadians(latitude2);// 经度double lng1 = Math.toRadians(longitude1);double lng2 = Math.toRadians(longitude2);// 纬度之差double a = lat1 - lat2;// 经度之差double b = lng1 - lng2;// 计算两点距离的公式double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));// 弧长乘地球半径, 返回单位: 千米s =  s * EARTH_RADIUS;return s;}public static void main(String[] args) {double d = getDistance(116.308479, 39.983171, 116.353454, 39.996059);System.out.println(d);}
}

用到的几个函数:

Math.pow(x,y)      //这个函数是求x的y次方
Math.toRadians     //将一个角度测量的角度转换成以弧度表示的近似角度
Math.sin           //正弦函数
Math.cos           //余弦函数
Math.sqrt          //求平方根函数
Math.asin          //反正弦函数

由于三角函数中特定的关联关系,Haversine公式的最终实现方式可以有多种,比如借助转角度的函数atan2:

public static double getDistance2(double longitude1, double latitude1,double longitude2, double latitude2) {double latDistance = Math.toRadians(longitude1 - longitude2);double lngDistance = Math.toRadians(latitude1 - latitude2);double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)+ Math.cos(Math.toRadians(longitude1)) * Math.cos(Math.toRadians(longitude2))* Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));return c * EARTH_RADIUS;
}

返回的单位是千米,如果想返回米,可以修改地球半径的单位从千米到米,并且由于该结果是double类型的,所以还可以借助Math.round方法进行四舍五入为long类型,然后精确到米:

// ......
// 弧长乘地球半径(6378137)
s =  s * EARTH_RADIUS;
// 返回类型: long,单位: 米
return Math.round(s * 10000) / 10000;

接下来说几点概念:

3.1 地球半径

由于地球不是一个完美的球体,所以并不能用一个特别准确的值来表示地球的实际半径,不过由于地球的形状很接近球体,用[6357km] 到 [6378km]的范围值可以涵盖需要的所有半径。并且通常情况下,地球半径有几个常用值:

极半径,从地球中心至南极或北极的距离, 相当于6356.7523km;
赤道半径,从地球中心到赤道的距离,大约6378.137km;
平均半径,6371.393km,表示地球中心到地球表面所有各点距离的平均值;
RE,地球半径,有时被使用作为距离单位, 特别是在天文学和地质学中常用,大概距离是6370.856km;

所以我们通过地球半径进行计算的时候,通常情况下,我们可以使用上面的每一个值都可以进行计算,不过或多或少都会有误差的,但这样的误差是也是允许存在的。这里参考自维基百科:维基百科-地球半径

MySQL实现
同样,在MySQL中实现该功能,计算公式还是通过Haversine公式。不过在Google Map中,已经提供了相应的实现方式,我们先来看一下。

4.1 Google Map实现

首先,我们需要先创建表结构:

CREATE TABLE `markers` (`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,`name` VARCHAR( 60 ) NOT NULL ,`address` VARCHAR( 80 ) NOT NULL ,`lat` FLOAT( 10, 6 ) NOT NULL ,`lng` FLOAT( 10, 6 ) NOT NULL
) ENGINE = MYISAM ;

当然存储引擎可以是InnoDB。然后,进行初始化数据:

INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('1','Heir Apparel','Crowea Pl, Frenchs Forest NSW 2086','-33.737885','151.235260');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('2','BeeYourself Clothing','Thalia St, Hassall Grove NSW 2761','-33.729752','150.836090');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('3','Dress Code','Glenview Avenue, Revesby, NSW 2212','-33.949448','151.008591');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('4','The Legacy','Charlotte Ln, Chatswood NSW 2067','-33.796669','151.183609');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('5','Fashiontasia','Braidwood Dr, Prestons NSW 2170','-33.944489','150.854706');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('6','Trish & Tash','Lincoln St, Lane Cove West NSW 2066','-33.812222','151.143707');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('7','Perfect Fit','Darley Rd, Randwick NSW 2031','-33.903557','151.237732');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('8','Buena Ropa!','Brodie St, Rydalmere NSW 2116','-33.815521','151.026642');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('9','Coxcomb and Lily Boutique','Ferrers Rd, Horsley Park NSW 2175','-33.829525','150.873764');
INSERT INTO `markers` (`id`, `name`, `address`, `lat`, `lng`) VALUES ('10','Moda Couture','Northcote Rd, Glebe NSW 2037','-33.873882','151.177460');

然后就可以根据经纬度值,然后基于Haversine公式来查询数据,假设我们要查询latitude=37.38714,longitude=-122.083235,范围在25英里内的前20条数据:

SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM markers
HAVING distance < 25
ORDER BY distance
LIMIT 0 , 20;

而如果我们要查询公里,将3959英里也就是地球半径,修改为6371即可。

Geohash算法
Geohash是目前比较主流的范围搜索的算法,比如说搜索附近500米内的地点这种问题。Geohash算法将二维的经纬度编码为一个字符串,每个字符串代表了某一矩形区域,也就是说,这个矩形区域内所有的点(经纬度坐标)都共享相同的GeoHash字符串,这样在查询的时候就可以对该字符串做索引,然后根据该字符串进行过滤。

Geohash算法的最大用途其实就是附近地址搜索了,不过,从geohash的编码算法中可以看出它的一个缺点,也就是边界问题:虽然两个地点距离很近,但恰好位于分界点的两侧,这样geohash字符串就会不相同,然后匹配的时候就会有问题。不过要解决这个问题也很简单,就是计算的时候,计算出8个分别分布在周围8个区域的地点。

在实际应用中,可以先根据Geohash筛选出附近的地点,然后再算出距离附近地点的距离。而如果要计算Geohash,可以通过 spatial4j 工具包来实现,GeohashUtils.encodeLatLon(lat, lon),默认精度是12位,其中lucene就使用了spatial4j工具包来计算距离。

<dependency><groupId>org.locationtech.spatial4j</groupId><artifactId>spatial4j</artifactId><version>0.7</version>
</dependency>

有管GeoHash算法,可参考:

GeoHash介绍-核心原理解析
Github-Java实现Geohash算法- github.com/GongDexing/Geohash

Java 根据经纬度计算两点间的距离相关推荐

  1. 经纬度互换、换算成米、两点的经纬度计算两点间的距离

    经纬度互换 度(DDD):E 108.90593度    N 34.21630度 如何将度(DDD):: 108.90593度换算成度分秒(DMS)东经E 108度54分22.2秒?转换方法是将108 ...

  2. ArcGIS操作系列14- 经纬度互换、换算成米、两点的经纬度计算两点间的距离

    1. 经纬度互换 度(DDD):E 108.90593度    N 34.21630度 1.1  如何将度(DDD):: 108.90593度换算成度分秒(DMS)东经E 108度54分22.2秒? ...

  3. Java根据经纬度计算两点之间的距离

    1. 前言   在我们平时使用美团,饿了么等app进行订餐,或者使用猫眼进行订电影票的时候,都有一个距离的排序,表明该家店距离我们当前的位置,这种基于地理位置的服务,统一被称为LBS(Location ...

  4. 根据地图经纬度计算两点间的距离

    经纬度丢失计算距离 1.纬度相同,经度不同 在纬度相同的情况下: 经度每隔0.00001度,距离相差约1米: 每隔0.0001度,距离相差约10米: 每隔0.001度,距离相差约100米: 每隔0.0 ...

  5. 根据地球上任意两点的经纬度计算两点间的距离

    http://blog.chinaunix.net/u/6776/showart_694778.html 地球是一个近乎标准的椭球体,它的赤道半径为6378.140千米,极半径为6356.755千米, ...

  6. 百度地图 地理位置 转 经纬度 计算两点间的距离

    调用百度地图转成经纬度 百度地图web-api地址 tp 位置转经纬度 function getMap($address){$ak = config('common.map.ak');$url = c ...

  7. 地理大圆距离 C语言,通过经纬度计算两点之间的距离

    2019独角兽企业重金招聘Python工程师标准>>> 项目里有一个需求是计算两台机器之间的距离,有了这两台机器的经纬度,距离就很好计算了. 有一个 球面余弦定律 可以用来可以计算球 ...

  8. 通过经纬度计算两点间的直线距离

    /*** @description 通过经纬度计算两点间的直线距离* @param lat1* @param lng1* @param lat2* @param lng2* @returns {num ...

  9. matlab利用经纬度计算距离_【Matlab】根据经纬度计算两点间的球面距离

    做建模或者研究空间数据,可能会遇到"根据经纬度计算两点间的球面距离"的问题,网上的资料很多,都是各种公式推导,但是一旦按公式编程计算,很可能得不到正确的距离.根本原因是在" ...

最新文章

  1. gi克隆github文件_如何构建GitHub文件搜索功能的克隆
  2. 静态库与动态库详细剖析
  3. 算法:螺旋矩阵 ||
  4. React个Vue的对比
  5. C++ stringstream介绍,使用方法与例子
  6. python3  循环输出当前时间。
  7. 小米9正在争取首月供货超百万台 雷军:请大家帮我一起催货
  8. C语言函数的递归调用
  9. 《算法竞赛入门经典2th》 习题 2-4 子序列的和
  10. 产品经理面试——简历填写
  11. Matlab在线运行网址
  12. python 实现combination和permutation
  13. Linux dd烧写系统
  14. 作为应届大学生的我和准职业人的差距
  15. 个人完成案例之乐学成语(显示所有动物类成语的列表和每条成语的详细信息)
  16. Dya3:Python的开发工具
  17. Mansory 基本用法
  18. TED的字幕到哪里下载?介绍一个很好的网站
  19. 两个多月学习安卓的心得,给新手一点建议
  20. 【CodeCombat-Python】边远地区的森林 1~10

热门文章

  1. 数据结构实验公交车系统
  2. Linux服务器安装matlab
  3. RxJava 2.x入门教程
  4. ffmpeg编译选项汇总
  5. ffmpeg——简单播放器代码
  6. html和css制作上三角和下三角
  7. ArcGIS基础实验操作100例--实验61数据框投影变换
  8. DNS和IP的WHOIS查询
  9. 再见了微服务!K8S 云原生架构已成气候!
  10. 使用USB-串口工具仿真STC8G1K08