• 高德地图计算两坐标之间距离


    最近在做与地图相关的应用,使用了高德地图,研究了下高德地图计算两坐标距离的方法,官网上提供的开发包中有相关的方法,但是我的产品中比较特殊,无法直接使用提供的方法,所以就自己封装了相关计算方法,供大家参考。

    Java实现

    首先定义一个用于存储经纬度的类,这里起个名字叫:LngLat

    package amap;
    
    import java.text.DecimalFormat;
    import java.text.DecimalFormatSymbols;
    import java.util.Locale;
    
    /**
     * 存储经纬度坐标值的类,单位角度
     * 
     * @author jianggujin
     *
     */
    public final class LngLat implements Cloneable
    {
       /**
        * 纬度 (垂直方向)
        */
       public final double latitude;
       /**
        * 经度 (水平方向)
        */
       public final double longitude;
       /**
        * 格式化
        */
       private static DecimalFormat format = new DecimalFormat("0.000000", new DecimalFormatSymbols(Locale.US));
    
       /**
        * 使用传入的经纬度构造LatLng 对象,一对经纬度值代表地球上一个地点。
        * 
        * @param longitude
        *           地点的经度,在-180 与180 之间的double 型数值。
        * @param latitude
        *           地点的纬度,在-90 与90 之间的double 型数值。
        */
       public LngLat(double longitude, double latitude)
       {
          this(longitude, latitude, true);
       }
    
       /**
        * 使用传入的经纬度构造LatLng 对象,一对经纬度值代表地球上一个地点
        * 
        * @param longitude
        *           地点的经度,在-180 与180 之间的double 型数值。
        * 
        * @param latitude
        *           地点的纬度,在-90 与90 之间的double 型数值。
        * @param isCheck
        *           是否需要检查经纬度的合理性,建议填写true
        */
       public LngLat(double longitude, double latitude, boolean isCheck)
       {
          if (isCheck)
          {
             if ((-180.0D <= longitude) && (longitude < 180.0D))
                this.longitude = parse(longitude);
             else
             {
                throw new IllegalArgumentException("the longitude range [-180, 180].");
                // this.longitude = parse(((longitude - 180.0D) % 360.0D + 360.0D) %
                // 360.0D - 180.0D);
             }
    
             if ((latitude < -90.0D) || (latitude > 90.0D))
             {
                throw new IllegalArgumentException("the latitude range [-90, 90].");
             }
             this.latitude = latitude;
             // this.latitude = parse(Math.max(-90.0D, Math.min(90.0D, latitude)));
          }
          else
          {
             this.latitude = latitude;
             this.longitude = longitude;
          }
       }
    
       /**
        * 解析
        * 
        * @param d
        * @return
        */
       private static double parse(double d)
       {
          return Double.parseDouble(format.format(d));
       }
    
       public LngLat clone()
       {
          return new LngLat(this.latitude, this.longitude);
       }
    
       @Override
       public int hashCode()
       {
          final int prime = 31;
          int result = 1;
          long temp;
          temp = Double.doubleToLongBits(latitude);
          result = prime * result + (int) (temp ^ (temp >>> 32));
          temp = Double.doubleToLongBits(longitude);
          result = prime * result + (int) (temp ^ (temp >>> 32));
          return result;
       }
    
       @Override
       public boolean equals(Object obj)
       {
          if (this == obj)
             return true;
          if (obj == null)
             return false;
          if (getClass() != obj.getClass())
             return false;
          LngLat other = (LngLat) obj;
          if (Double.doubleToLongBits(latitude) != Double.doubleToLongBits(other.latitude))
             return false;
          if (Double.doubleToLongBits(longitude) != Double.doubleToLongBits(other.longitude))
             return false;
          return true;
       }
    
       public String toString()
       {
          return "lat/lng: (" + this.latitude + "," + this.longitude + ")";
       }
    }

    计算工具类如下:

    package amap;
    
    /**
     * 高德地图工具
     * 
     * @author jianggujin
     *
     */
    public class AMapUtils
    {
       /**
        * 根据用户的起点和终点经纬度计算两点间距离,此距离为相对较短的距离,单位米。
        * 
        * @param start
        *           起点的坐标
        * @param end
        *           终点的坐标
        * @return
        */
       public static double calculateLineDistance(LngLat start, LngLat end)
       {
          if ((start == null) || (end == null))
          {
             throw new IllegalArgumentException("非法坐标值,不能为null");
          }
          double d1 = 0.01745329251994329D;
          double d2 = start.longitude;
          double d3 = start.latitude;
          double d4 = end.longitude;
          double d5 = end.latitude;
          d2 *= d1;
          d3 *= d1;
          d4 *= d1;
          d5 *= d1;
          double d6 = Math.sin(d2);
          double d7 = Math.sin(d3);
          double d8 = Math.cos(d2);
          double d9 = Math.cos(d3);
          double d10 = Math.sin(d4);
          double d11 = Math.sin(d5);
          double d12 = Math.cos(d4);
          double d13 = Math.cos(d5);
          double[] arrayOfDouble1 = new double[3];
          double[] arrayOfDouble2 = new double[3];
          arrayOfDouble1[0] = (d9 * d8);
          arrayOfDouble1[1] = (d9 * d6);
          arrayOfDouble1[2] = d7;
          arrayOfDouble2[0] = (d13 * d12);
          arrayOfDouble2[1] = (d13 * d10);
          arrayOfDouble2[2] = d11;
          double d14 = Math.sqrt((arrayOfDouble1[0] - arrayOfDouble2[0]) * (arrayOfDouble1[0] - arrayOfDouble2[0])
                + (arrayOfDouble1[1] - arrayOfDouble2[1]) * (arrayOfDouble1[1] - arrayOfDouble2[1])
                + (arrayOfDouble1[2] - arrayOfDouble2[2]) * (arrayOfDouble1[2] - arrayOfDouble2[2]));
    
          return (Math.asin(d14 / 2.0D) * 12742001.579854401D);
       }
    }

    最后边写一段测试代码测试一下:

    package test;
    
    import org.junit.Test;
    
    import amap.AMapUtils;
    import amap.LngLat;
    
    public class AMapTest
    {
       @Test
       public void Test()
       {
          LngLat start = new LngLat(116.368904, 39.923423);
          LngLat end = new LngLat(116.387271, 39.922501);
          System.err.println(AMapUtils.calculateLineDistance(start, end));
       }
    }

    运行结果为:1569.6213922679392,官网的javascript API示例结果如图:

    这里写图片描述

    结果虽然有一点误差,但是这hi在可接受范围内的。

    Javascript实现

    同样的算法,将其转换成JS的写法,完整的代码如下:

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="utf-8" />
            <title></title>
            <script type="text/javascript" src="js/ajax.js"></script>
            <script>
                /**
                 * 存储经纬度
                 * @param {Object} longitude
                 * @param {Object} latitude
                 */
                function LngLat(longitude, latitude) {
                    this.longitude = longitude;
                    this.latitude = latitude;
                }
    
                function calculateLineDistance(start, end) {
                    var d1 = 0.01745329251994329;
                    var d2 = start.longitude;
                    var d3 = start.latitude;
                    var d4 = end.longitude;
                    var d5 = end.latitude;
                    d2 *= d1;
                    d3 *= d1;
                    d4 *= d1;
                    d5 *= d1;
                    var d6 = Math.sin(d2);
                    var d7 = Math.sin(d3);
                    var d8 = Math.cos(d2);
                    var d9 = Math.cos(d3);
                    var d10 = Math.sin(d4);
                    var d11 = Math.sin(d5);
                    var d12 = Math.cos(d4);
                    var d13 = Math.cos(d5);
                    var arrayOfDouble1 = [];
                    var arrayOfDouble2 = [];
                    arrayOfDouble1.push(d9 * d8);
                    arrayOfDouble1.push(d9 * d6);
                    arrayOfDouble1.push(d7);
                    arrayOfDouble2.push(d13 * d12);
                    arrayOfDouble2.push(d13 * d10);
                    arrayOfDouble2.push(d11);
                    var d14 = Math.sqrt((arrayOfDouble1[0] - arrayOfDouble2[0]) * (arrayOfDouble1[0] - arrayOfDouble2[0]) +
                        (arrayOfDouble1[1] - arrayOfDouble2[1]) * (arrayOfDouble1[1] - arrayOfDouble2[1]) +
                        (arrayOfDouble1[2] - arrayOfDouble2[2]) * (arrayOfDouble1[2] - arrayOfDouble2[2]));
    
                    return(Math.asin(d14 / 2.0) * 12742001.579854401);
                }
                var start = new LngLat(116.368904, 39.923423);
                var end = new LngLat(116.387271, 39.922501);
            </script>
        </head>
    
        <body>
            <script>
                document.write(calculateLineDistance(start, end));
            </script>
        </body>
    </html>

    MySQL实现

    DELIMITER $$
    CREATE FUNCTION `calculateLineDistance`(startLng double, startLat double, endLng double, endLat double) RETURNS double
    BEGIN
    declare d2 DOUBLE;
    declare d3 DOUBLE;
    declare d4 DOUBLE;
    declare d5 DOUBLE;
    declare d6 DOUBLE;
    declare d7 DOUBLE;
    declare d8 DOUBLE;
    declare d9 DOUBLE;
    declare d10 DOUBLE;
    declare d11 DOUBLE;
    declare d12 DOUBLE;
    declare d13 DOUBLE;
    declare d14 DOUBLE;
    declare arrayOfDouble10 DOUBLE;
    declare arrayOfDouble11 DOUBLE;
    declare arrayOfDouble12 DOUBLe;
    declare arrayOfDouble20 DOUBLE;
    declare arrayOfDouble21 DOUBLE;
    declare arrayOfDouble22 DOUBLE;
    set d2 = startLng * 0.01745329251994329;
    set d3 = startLat * 0.01745329251994329;
    set d4 = endLng * 0.01745329251994329;
    set d5 = endLat * 0.01745329251994329;
    set d6 = sin(d2);
    set d7 = sin(d3);
    set d8 = cos(d2);
    set d9 = cos(d3);
    set d10 = sin(d4);
    set d11 = sin(d5);
    set d12 = cos(d4);
    set d13 = cos(d5);
    set arrayOfDouble10 = (d9 * d8);
    set arrayOfDouble11 = (d9 * d6);
    set arrayOfDouble12 = d7;
    set arrayOfDouble20 = (d13 * d12);
    set arrayOfDouble21 = (d13 * d10);
    set arrayOfDouble22 = d11;
    set d14 = sqrt((arrayOfDouble10 - arrayOfDouble20) * (arrayOfDouble10 - arrayOfDouble20)
                + (arrayOfDouble11 - arrayOfDouble21) * (arrayOfDouble11 - arrayOfDouble21)
                + (arrayOfDouble12 - arrayOfDouble22) * (arrayOfDouble12 - arrayOfDouble22));
    return (asin(d14 / 2.0) * 12742001.579854401); 
    END $$  
    DELIMITER ;  
  • 相关阅读:
    jdbc连接数据库 url
    解决IntelliJ IDEA 使用 TOMCAT 中文乱码问题
    web.xml 4.0 头部信息
    jar包冲突解决方案
    idea 快捷键
    基于单片机的车辆防碰撞及自动刹车系统(STC89C52RC芯片+超声波传感器HC-SR04+液晶屏1602+继电器+蜂鸣器)
    电子时钟万年历+51单片机+1602液晶屏+DS1302+DS18B20+按键
    1008 数组元素循环右移问题(PAT)
    1007 素数对猜想(PAT)
    1006 换个格式输出整数(PAT)
  • 原文地址:https://www.cnblogs.com/jiangxiaobo/p/7760122.html
Copyright © 2020-2023  润新知