4

MySQL以及Java根据经纬度计算距离

 2 years ago
source link: http://www.lzhpo.com/article/171
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

MySQL以及Java根据经纬度计算距离

球面距离公式

球面距离公式是计算球面上两点间距离的公式。

举个例子:已知,设R为球体半径,点A ,纬度角β1 ,经度角α1 ;点B ,纬度角β2 ,经度角α2。求点A和点B两点间的距离?

公式:S=R·arccos[cosβ1·cosβ·2cos(α1-α2)+sinβ1·sinβ2]

公式参考:球面距离公式

地球半径:6371.393千米。

计算坐标点

广州塔,经纬度:113.324553,23.106414

东方明珠电视塔,经纬度:121.499718,31.239703

关于在线经纬度获取的话,可以看看高德地图的:https://lbs.amap.com/tools/picker

Java版本

/** * 根据球面距离公式计算两个地点之间的距离 * * <p>公式:S=R·arccos[cosβ1·cosβ·2cos(α1-α2)+sinβ1·sinβ2] */@UtilityClasspublic class DistanceUtil {  /** 地球半径(单位:米) */  private static final double EARTH_RADIUS = 6371393;  /** 以度为单位的角度值乘以该常数以获得以弧度为单位的角度值。 */  private static final double DEGREES_TO_RADIANS = 0.017453292519943295;  /**   * 根据公式进行计算   *   * @param longitude1 位置1经度   * @param latitude1 位置1纬度   * @param longitude2 位置2经度   * @param latitude2 位置2纬度   * @return 返回计算的距离,单位:米   */  public static double getDistance(      Double longitude1, Double latitude1, Double longitude2, Double latitude2) {    double radiansLongitude1 = toRadians(longitude1);    double radiansLatitude1 = toRadians(latitude1);    double radiansLongitude2 = toRadians(longitude2);    double radiansLatitude2 = Math.toRadians(latitude2);    final double cos =        BigDecimal.valueOf(Math.cos(radiansLatitude1))            .multiply(BigDecimal.valueOf(Math.cos(radiansLatitude2)))            .multiply(                BigDecimal.valueOf(                    Math.cos(                        BigDecimal.valueOf(radiansLongitude1)                            .subtract(BigDecimal.valueOf(radiansLongitude2))                            .doubleValue())))            .add(                BigDecimal.valueOf(Math.sin(radiansLatitude1))                    .multiply(BigDecimal.valueOf(Math.sin(radiansLatitude2))))            .doubleValue();    double acos = Math.acos(cos);    return BigDecimal.valueOf(EARTH_RADIUS).multiply(BigDecimal.valueOf(acos)).doubleValue();  }  /**   * 参考:{@link Math#toRadians(double)}   *   * @param value value   * @return {double}   */  private static double toRadians(double value) {    return BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(DEGREES_TO_RADIANS)).doubleValue();  }  /**   * 测试   *   * <pre>   * 广州塔,经纬度:113.324553,23.106414   * 东方明珠电视塔,经纬度:121.499718,31.239703   * </pre>   *   * @param args args   */  public static void main(String[] args) {    double distance = getDistance(113.324553, 23.106414, 121.499718, 31.239703);    System.out.println(distance);  }}

计算结果(单位:米):

1212391.2574948743

MySQL版本

开始写计算函数

有了前面球面距离计算公式基础之后,我们就可以一葫芦画瓢写出mysql版的函数了。

创建calculate_distance函数

这里我将计算距离结果单位设置为米。

CREATE FUNCTION calculate_distance ( longitude1 DOUBLE, latitude1 DOUBLE, longitude2 DOUBLE, latitude2 DOUBLE ) RETURNS DOUBLE BEGIN    RETURN 6371393 * ACOS(         COS( RADIANS( latitude1 ))          * COS( RADIANS( latitude2 ))         * COS( RADIANS( longitude2 - longitude1 ))         + SIN( RADIANS( latitude1 ))         * SIN( RADIANS( latitude2 ))     );END;

说明: MySQL中的RADIANS函数

将度数值转换为弧度值。

mysql> SELECT RADIANS(180);+-------------------+| RADIANS(180)      |+-------------------+| 3.141592653589793 |+-------------------+1 row in set (0.03 sec)

MySQL计算示例

示例sql查询两点的距离,实际情况你可以根据自己数据库中的字段去调整sql,在此我仅仅是演示:

mysql> SELECT calculate_distance(113.324553, 23.106414, 121.499718, 31.239703);+------------------------------------------------------------------+| calculate_distance(113.324553, 23.106414, 121.499718, 31.239703) |+------------------------------------------------------------------+|                                               1212391.2574948743 |+------------------------------------------------------------------+1 row in set (0.06 sec)

计算结果跟前面Java版本的一样。

结果大概都是1212391米。

对比验证计算结果

高德地图验证结果

高德地图经纬度计算在线地址

广州塔到东方明珠电视塔的距离:1213675 米。跟我们公式计算(Java版本&MySQL版本)的误差大概是:1284 米。

百度地图验证计算结果

百度地图经纬度计算在线地址

广州塔到东方明珠电视塔的距离:1212315.87 米。跟我们公式计算(Java版本&MySQL版本)的误差大概是:75.13 米。

毕竟这是计算的直线距离,不同的计算方法、坐标系(Sphere坐标系、WGS84坐标系)、精度等等因素都会影响计算的结果。

如果要计算驾车、步行这种分类计算距离的,建议可以去看看使用高德地图、百度地图、腾讯地图的API。

正文到此结束
所属分类:Java开发

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK