当前位置:   article > 正文

Java根据坐标经纬度计算两点距离(5种方法)、校验经纬度是否在圆 多边形区域内的算法推荐_java计算两个经纬度之间的距离_java区域内经纬度随机算法

java区域内经纬度随机算法
    double lon1 = Math.toRadians(longitude1);
    double lon2 = Math.toRadians(longitude2);
    // 纬度之差
    double a = lat1 - lat2;
    // 经度之差
    double b = lon1 - lon2;
    // 计算两点距离的公式
    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 * EQUATOR_RADIUS;
    return s;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

}


### 2.方法二



  • 1
  • 2
  • 3
  • 4
  • 5

package com.test.java.util;

/**

  • 坐标位置相关util
    */
    public class PositionUtil {

    /**

    • 地球平均半径(单位:米)
      */
      private static final double EARTH_AVG_RADIUS = 6371000;

    /**

    • 方法二:(反余弦计算方式)

    • @param longitude1 第一点的经度

    • @param latitude1 第一点的纬度

    • @param longitude2 第二点的经度

    • @param latitude2 第二点的纬度

    • @return 返回的距离,单位m
      */
      public static double getDistance3(double longitude1, double latitude1, double longitude2, double latitude2) {
      // 经纬度(角度)转弧度。弧度作为作参数,用以调用Math.cos和Math.sin
      // A经弧度
      double radiansAX = Math.toRadians(longitude1);
      // A纬弧度
      double radiansAY = Math.toRadians(latitude1);
      // B经弧度
      double radiansBX = Math.toRadians(longitude2);
      // B纬弧度
      double radiansBY = Math.toRadians(latitude2);

      // 公式中“cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2”的部分,得到∠AOB的cos值
      double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX) + Math.sin(radiansAY) * Math.sin(radiansBY);
      // System.out.println("cos = " + cos); // 值域[-1,1]

      // 反余弦值
      double acos = Math.acos(cos);
      // System.out.println("acos = " + acos); // 值域[0,π]
      // System.out.println("∠AOB = " + Math.toDegrees(acos)); // 球心角 值域[0,180]

      // 最终结果
      return EARTH_AVG_RADIUS * acos;
      }

}


### 3.方法三


基于谷歌地图的计算公式计算距离



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

package com.test.java.util;

/**

  • 坐标位置相关util
    */
    public class PositionUtil {

    /**

    • 地球平均半径(单位:米)
      */
      private static final double EARTH_AVG_RADIUS = 6371000;

    /**

    • 经纬度转化为弧度(rad)
    • @param d 经度/纬度
      */
      private static double rad(double d) {
      return d * Math.PI / 180.0;
      }

    /**

    • 方法三:(基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多。)
    • @param longitude1 第一点的经度
    • @param latitude1 第一点的纬度
    • @param longitude2 第二点的经度
    • @param latitude2 第二点的纬度
    • @return 返回的距离,单位m
      */
      public static double getDistance2(double longitude1, double latitude1, double longitude2, double latitude2) {
      double radLat1 = rad(latitude1);
      double radLat2 = rad(latitude2);
      double a = radLat1 - radLat2;
      double b = rad(longitude1) - rad(longitude2);
      double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
      s = s * EARTH_AVG_RADIUS;
      s = Math.round(s * 10000d) / 10000d;
      return s;
      }

}


### 4.方法四


基于高德地图



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

package com.test.java.util;

/**

  • 计算距离
    */
    public class PositionUtil {

    /**

    • 方法四:(高德地图计算方法)

    • @param longitude1 第一点的经度

    • @param latitude1 第一点的纬度

    • @param longitude2 第二点的经度

    • @param latitude2 第二点的纬度

    • @return 返回的距离,单位m
      */
      public static Double getDistance4(double longitude1, double latitude1, double longitude2, double latitude2) {
      if (longitude1 == 0 || latitude1 == 0 || latitude2 == 0 || longitude2 == 0) {
      return -1.0;
      }
      longitude1 *= 0.01745329251994329;
      latitude1 *= 0.01745329251994329;
      longitude2 *= 0.01745329251994329;
      latitude2 *= 0.01745329251994329;
      double var1 = Math.sin(longitude1);
      double var2 = Math.sin(latitude1);
      double var3 = Math.cos(longitude1);
      double var4 = Math.cos(latitude1);
      double var5 = Math.sin(longitude2);
      double var6 = Math.sin(latitude2);
      double var7 = Math.cos(longitude2);
      double var8 = Math.cos(latitude2);
      double[] var10 = new double[3];
      double[] var20 = new double[3];
      var10[0] = var4 * var3;
      var10[1] = var4 * var1;
      var10[2] = var2;
      var20[0] = var8 * var7;
      var20[1] = var8 * var5;
      var20[2] = var6;

      return Math.asin(Math.sqrt((var10[0] - var20[0]) * (var10[0] - var20[0]) + (var10[1] - var20[1]) * (var10[1] - var20[1]) + (var10[2] - var20[2]) * (var10[2] - var20[2])) / 2.0) * 1.27420015798544E7;
      // 结果四舍五入 保留2位小数
      //return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP).doubleValue();
      }

}


### 5.方法五


**该方法是利用第三方jar包计算**


#### 5.1 POM引入第三方依赖



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
<!--用于计算两点之间的距离-->
<dependency>
    <groupId>org.gavaghan</groupId>
    <artifactId>geodesy</artifactId>
    <version>1.1.3</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

#### 5.2 代码



  • 1
  • 2
  • 3
  • 4
  • 5

package com.test.java.util;

import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

/**

  • 坐标位置相关util
    */
    public class PositionUtil {

    /**

    • 方法四:(利用第三方jar包计算)
    • 计算两个经纬度之间的距离
    • @param longitude1 第一点的经度
    • @param latitude1 第一点的纬度
    • @param longitude2 第二点的经度
    • @param latitude2 第二点的纬度
    • @param ellipsoid 计算方式
    • @return 返回的距离,单位m
      */
      public static double getDistance4(double longitude1, double latitude1, double longitude2, double latitude2, Ellipsoid ellipsoid) {
      // 创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
      GlobalCoordinates firstPoint = new GlobalCoordinates(latitude1, longitude1);
      GlobalCoordinates secondPoint = new GlobalCoordinates(latitude2, longitude2);
      GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, firstPoint, secondPoint);
      return geoCurve.getEllipsoidalDistance();
      }

}


### 6.测试结果对比


这里我直接一起调用者4种方法,这样看结果也更加直观些。



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
public static void main(String[] args) {

    double longitude1 = 117.344733;
    double latitude1 = 31.912334;
    double longitude2 = 117.272186;
    double latitude2 = 31.79422;

    double distance1 = PositionUtil.getDistance1(longitude1, latitude1, longitude2, latitude2);
    double distance2 = PositionUtil.getDistance2(longitude1, latitude1, longitude2, latitude2);
    double distance3 = PositionUtil.getDistance3(longitude1, latitude1, longitude2, latitude2);
    double distance4 = PositionUtil.getDistance4(longitude1, latitude1, longitude2, latitude2);
    double distance5 = PositionUtil.getDistance4(longitude1, latitude1, longitude2, latitude2, Ellipsoid.Sphere);
    double distance6 = PositionUtil.getDistance4(longitude1, latitude1, longitude2, latitude2, Ellipsoid.WGS84);


    System.out.println("方法1算出的距离:" + distance1);
    System.out.println("方法2算出的距离:" + distance2);
    System.out.println("方法3算出的距离:" + distance3);
    System.out.println("方法4算出的距离:" + distance4);
    System.out.println("方法4-Sphere算出的距离:" + distance5);
    System.out.println("方法4-WGS84算出的距离:" + distance6);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

![](https://img-blog.csdnimg.cn/5880b81ebe0643869071af70cc490d7b.jpeg)


可以看出,这几个方法算出的距离误差相对较小。而且main方法中提供的测试数据也是我自身的真实数据,结合百度地图的测距工具进行的测试。有需要的小伙伴,可以自行选择合适的方法。



## 二、校验经纬度是否在制定区域内


怎么样判断一个坐标点在指定的区域内?其中区域又会分为:圆,多边形和不规则的多边形。


### 1.判断一个坐标是否在圆形区域内


计算这个坐标点和圆心之间的距离,然后跟圆的半径进行比较,如果比半径大,就不在圆形区域内,如果小于等于圆的半径,则该坐标点在圆形区域内。



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

package com.test.java.util;

import org.apache.commons.lang3.StringUtils;

/**

  • 计算距离
    */
    public class PositionUtil {

    /**

    • 赤道半径(单位:米)
      */
      private static final double EQUATOR_RADIUS = 6378137;

    /**

    • 方法一:(反余弦计算方式)
    • @param longitude1 第一个点的经度
    • @param latitude1 第一个点的纬度
    • @param longitude2 第二个点的经度
    • @param latitude2 第二个点的纬度
    • @return 返回距离,单位m
      */
      public static double getDistance1(double longitude1, double latitude1, double longitude2, double latitude2) {
      // 纬度
      double lat1 = Math.toRadians(latitude1);
      double lat2 = Math.toRadians(latitude2);
      // 经度
      double lon1 = Math.toRadians(longitude1);
      double lon2 = Math.toRadians(longitude2);
      // 纬度之差
      double a = lat1 - lat2;
      // 经度之差
      double b = lon1 - lon2;
      // 计算两点距离的公式
      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 * EQUATOR_RADIUS;
      return s;
      }

    /**

    • 判断坐标点是否在圆形区域内
    • 计算这个坐标点和圆心点之间的距离,然后跟圆的半径进行比较,如果比半径大,就不在圆形区域内,如果小于等于圆的半径,则该坐标点在圆形区域内
    • @param longitude1 第一点的经度
    • @param latitude1 第一点的纬度
    • @param longitude2 第二点的经度
    • @param latitude2 第二点的纬度
    • @param radius 圆形范围半径(单位:米)
    • @return true:不在区域内; false:在区域内
      */
      public static boolean isInCircle(double longitude1, double latitude1, double longitude2, double latitude2, String radius) {
      if (StringUtils.isBlank(radius)) {
      throw new RuntimeException(“请输入范围半径”);
      }
      return getDistance1(longitude1, latitude1, longitude2, latitude2) > Double.parseDouble(radius);
      }

}


### 2.判断一个坐标是否在一个多边形区域内


这里用到JAVA的一个类**GeneralPath**(由直线和二次和三次(B?zier)曲线构成的几何路径。 它可以包含多个子路径)使用这个类,结合传入的各顶点参数,画一个几何图形,并通过它自身的**contains**方法,判断该点是否在这个几何图形内。



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

package com.test.java.util;

import org.apache.commons.lang3.StringUtils;

import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

/**

  • 计算距离
    */
    public class PositionUtil {

    /**

    • 判断坐标点是否在多边形区域内
    • @param pointLon 要判断的点的经度
    • @param pointLat 要判断的点的纬度
    • @param lon 区域各顶点的经度数组
      自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

onvert/252731a671c1fb70aad5355a2c5eeff0.png)

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)

img
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/569703
推荐阅读
相关标签
  

闽ICP备14008679号