From a37f17eef64e75b50514dad4fd42990925696500 Mon Sep 17 00:00:00 2001 From: duandazhi Date: Mon, 5 Apr 2021 00:01:24 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=9C=B0=E7=90=83=E4=B8=A4?= =?UTF-8?q?=E7=82=B9=E4=B9=8B=E9=97=B4=E7=9A=84=E8=B7=9D=E7=A6=BB-Distance?= =?UTF-8?q?Util?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/lang/PatternPool.java | 1 + .../cn/hutool/core/util/DistanceUtil.java | 92 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java index a47f65340..053cd81a3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/PatternPool.java @@ -49,6 +49,7 @@ public class PatternPool { public final static Pattern MONEY = Pattern.compile("^(\\d+(?:\\.\\d+)?)$"); /** * 邮件,符合RFC 5322规范,正则来自:http://emailregex.com/ + * What is the maximum length of a valid email address? https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address/44317754 * 注意email 要宽松一点。比如 jetz.chong@hotmail.com、jetz-chong@ hotmail.com、jetz_chong@hotmail.com、dazhi.duan@com.cn 宽松一点把,都算是正常的邮箱 */ public final static Pattern EMAIL = Pattern.compile("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)])", Pattern.CASE_INSENSITIVE); diff --git a/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java new file mode 100644 index 000000000..683056ab9 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java @@ -0,0 +1,92 @@ +package cn.hutool.core.util; + +import java.awt.geom.Point2D; + +/** + * 通过经纬度获取地球上两点之间的距离 + * @author dazer & neusoft + * @date 2021/4/4 23:42 + * @since 5.6.3 + * thank you:JAVA通过经纬度获取两点之间的距离 https://www.cnblogs.com/pxblog/p/13359801.html + * thank you:JAVA根据经纬度获取两点之间的距离 https://blog.csdn.net/weixin_35815479/article/details/106972772 + * 百度地图拾取系统:http://api.map.baidu.com/lbsapi/getpoint/index.html + * 高德地图拾取:https://lbs.amap.com/tools/picker + */ +public class DistanceUtil { + /**地球半径,单位KM*/ + private static final double EARTH_RADIUS = 6378.137; + + private static double rad(double d) { + return d * Math.PI / 180.0; + } + + /** + * 根据两个位置的经纬度,来计算两地的距离(单位为KM) + * “经度”【longitude】、“纬度”【 Latitude】。 + * 参数为String类型 + * @param lat1Str 第一个位置经度 + * @param lng1Str 第一个位置纬度 + * @param lat2Str 第二个位置经度 + * @param lng2Str 第二个位置纬度 + * @return 地球上两点之间的距离,单位KM + */ + public static String getDistance(String lat1Str, String lng1Str, String lat2Str, String lng2Str) { + double lat1 = 0; + double lng1 = 0; + double lat2 = 0; + double lng2 = 0; + try { + lat1 = Double.parseDouble(lat1Str); + lng1 = Double.parseDouble(lng1Str); + lat2 = Double.parseDouble(lat2Str); + lng2 = Double.parseDouble(lng2Str); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("经纬度入参不合法,请检查!", e); + } + + double radLat1 = rad(lat1); + double radLat2 = rad(lat2); + double difference = radLat1 - radLat2; + double mdifference = rad(lng1) - rad(lng2); + double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(difference / 2), 2) + + Math.cos(radLat1) * Math.cos(radLat2) + * Math.pow(Math.sin(mdifference / 2), 2))); + distance = distance * EARTH_RADIUS; + distance = Math.round(distance * 10000) / 10000.0; + String distanceStr = distance+""; + distanceStr = distanceStr. + substring(0, distanceStr.indexOf(".")); + return distanceStr; + } + + /** + * 通过AB点经纬度获取距离 整数 + * @param pointA A点(经,纬) + * @param pointB B点(经,纬) + * @return 距离(单位:米) + */ + public static long getDistance(Point2D pointA, Point2D pointB) { + // 经纬度(角度)转弧度。弧度用作参数,以调用Math.cos和Math.sin + // A经弧度 + double radiansAx = Math.toRadians(pointA.getX()); + // A纬弧度 + double radiansAy = Math.toRadians(pointA.getY()); + // B经弧度 + double radiansBx = Math.toRadians(pointB.getX()); + // B纬弧度 + double radiansBy = Math.toRadians(pointB.getY()); + // 公式中“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); + // 反余弦值 + double acos = Math.acos(cos); + // 最终结果 + double h = EARTH_RADIUS * acos; + + //四舍五入 + //保留小数后两位 + /** BigDecimal b = new BigDecimal(h); + double f1 = b.setScale(2, RoundingMode.HALF_UP).doubleValue();*/ + return Math.round(h); + } +}