JAVA经纬度互转、计算工具类

1、经纬度转换工具类


import com.wh.whcloud.core.base.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 经纬度工具类
 */
@Slf4j
public class LonlatUtils {

/*    public static void main(String[] args) {
        System.out.println(DmTurnD("120°39.516'"));
        System.out.println(DmTurnD("30°46.237'"));
    }*/

    /**
     * 表示角度的度、分、秒分别使用°、′、″符号进行表示。
     * 1°=60′,1′=60″ ,1°=3600″。
     * 由上述可知度分秒转换度的计算公式为:(dd°mm′ss″) dd+mm/60+ss/3600
     * 经纬度转换 ,度分秒转度
     * @param jwd
     * @return
     */
    public static String DmsTurnD(String jwd){
        try{
            if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°"))){//如果不为空并且存在度单位
                //计算前进行数据处理
                jwd = jwd.replace("E", "").replace("N", "").replace(":", "").replace(":", "");
                double d=0,m=0,s=0;
                d = Double.parseDouble(jwd.split("°")[0]);
                //不同单位的分,可扩展
                if(jwd.contains("′")){//正常的′
                    m = Double.parseDouble(jwd.split("°")[1].split("′")[0]);
                }else if(jwd.contains("'")){//特殊的'
                    m = Double.parseDouble(jwd.split("°")[1].split("'")[0]);
                }
                //不同单位的秒,可扩展
                if(jwd.contains("″")){//正常的″
                    //有时候没有分 如:112°10.25″
                    s = jwd.contains("′")?Double.parseDouble(jwd.split("′")[1].split("″")[0]):Double.parseDouble(jwd.split("°")[1].split("″")[0]);
                }else if(jwd.contains("''")){//特殊的''
                    //有时候没有分 如:112°10.25''
                    s = jwd.contains("'")?Double.parseDouble(jwd.split("'")[1].split("''")[0]):Double.parseDouble(jwd.split("°")[1].split("''")[0]);
                }
                jwd = String.valueOf(d+m/60+s/60/60);//计算并转换为string
                //使用BigDecimal进行加减乘除
            /*BigDecimal bd = new BigDecimal("60");
            BigDecimal d = new BigDecimal(jwd.contains("°")?jwd.split("°")[0]:"0");
            BigDecimal m = new BigDecimal(jwd.contains("′")?jwd.split("°")[1].split("′")[0]:"0");
            BigDecimal s = new BigDecimal(jwd.contains("″")?jwd.split("′")[1].split("″")[0]:"0");
            //divide相除可能会报错(无限循环小数),要设置保留小数点
            jwd = String.valueOf(d.add(m.divide(bd,6,BigDecimal.ROUND_HALF_UP)
                    .add(s.divide(bd.multiply(bd),6,BigDecimal.ROUND_HALF_UP))));*/
            }
        }catch (Exception e){
            log.info("度分秒转换错误");
            return jwd;
        }
        return jwd;
    }


    /**
     * 度分 转度
     * 十进制经纬度转换 ddd°mm.mmmm' 转 ddd.ddddd°
     * 如:112°30.4128' = 112.50688
     * @param jwd
     * @return
     */
    public static String DmTurnD(String jwd){
        try {
            if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°")&&jwd.contains("'"))){//如果不为空并且存在度、分单位
                double d=0,m=0;
                d = Double.parseDouble(jwd.split("°")[0]);
                m = Double.parseDouble(jwd.split("°")[1].split("'")[0])/60;
                jwd = String.valueOf(d+m);
            }else if(StringUtil.isNotEmpty(jwd)&&(jwd.contains("°"))){//如果不为空并且存在度单位
                double d=0,m=0;
                d = Double.parseDouble(jwd.split("°")[0]);
                m = Double.parseDouble(jwd.split("°")[1])/60;
                jwd = String.valueOf(d+m);
            }
        }catch (Exception e){
            log.info("度分转换错误");
            return jwd;
        }
        return jwd;
    }

}

 2、DistanceUtil工具类

public class DistanceUtil {
    public static final double earthRadius = 6371.393D;
    public static final double nmi = 5.4E-4D;

    public DistanceUtil() {
    }

    public static double meterToNmi(double len) {
        return len * 5.4E-4D;
    }

    public static double meterToDegree(double len) {
        return km2Degree(len / 1000.0D);
    }

    private static double rad(double d) {
        return d * 3.141592653589793D / 180.0D;
    }

    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2.0D * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2.0D), 2.0D) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2.0D), 2.0D)));
        s *= 6371.393D;
        s = (double)Math.round(s * 10000.0D) / 10000.0D;
        s *= 1000.0D;
        return s;
    }

    public static Double km2Degree(Double l) {
        Double degree = 0.008992661340005603D * l;
        return degree;
    }

    public static Double degree2Km(Double degree) {
        Double l = 111.20178578851908D * degree;
        return l;
    }
}

3、经纬度角度计算工具类

import com.util.DistanceUtil;

public class AngleUtil {

  /**
   * 根据俯仰角计算水平距离 俯仰角小于45度时适用
   *
   * @param h     单位米
   * @param angle 单位度
   * @return
   */
  public static double HorizontalAngleCal(double h, double angle) {
    return h * Math.tan(angle);
  }

  /**
   * 获取云台和目标的直线距离(斜边长)
   * @param lon1
   * @param lat1
   * @param lon2
   * @param lat2
   * @param h
   * @return
   */
  public static double getDistance(double lon1,double lat1,double lon2,double lat2,double h){
    double l = DistanceUtil.getDistance(lat1,lon1,lat2,lon2);
    return Math.sqrt(Math.pow(h,2)+ Math.pow(l,2));
  }

  /**
   * 获取俯仰角度
   * @param lon1
   * @param lat1
   * @param lon2
   * @param lat2
   * @param h
   * @return
   */
  public static double getTilAngle(double lon1,double lat1,double lon2,double lat2,double h){
    double l = DistanceUtil.getDistance(lat1,lon1,lat2,lon2);
    return Math.toDegrees(Math.atan (l/h));
  }

  /**
   * 求两点连线与正北方向的角度(水平角度)
   * @param A
   * @param B
   * @return
   */
  public static double getPanAngle(LatLon A, LatLon B) {
    double dx = (B.m_RadLo - A.m_RadLo) * A.Ed;
    double dy = (B.m_RadLa - A.m_RadLa) * A.Ec;
    double angle = 0.0;
    angle = Math.atan(Math.abs(dx / dy)) * 180 / Math.PI;
    double dLo = B.m_Longitude - A.m_Longitude;
    double dLa = B.m_Latitude - A.m_Latitude;
    if (dLo > 0 && dLa <= 0) {
      angle = (90 - angle) + 90;
    } else if (dLo <= 0 && dLa < 0) {
      angle = angle + 180;
    } else if (dLo < 0 && dLa >= 0) {
      angle = (90 - angle) + 270;
    }
    return angle;
  }

  /**
   * 获取方位角
   * @param lat_a 纬度1
   * @param lng_a 经度1
   * @param lat_b 纬度2
   * @param lng_b 经度2
   * @return
   */
  public static double getBearingAngle(double lat_a, double lng_a, double lat_b, double lng_b) {
    try {
      double y = Math.sin(lng_b-lng_a) * Math.cos(lat_b);
      double x = Math.cos(lat_a)*Math.sin(lat_b) - Math.sin(lat_a)*Math.cos(lat_b)*Math.cos(lng_b-lng_a);
      double brng = Math.atan2(y, x);
      brng = Math.toDegrees(brng);
      if(brng < 0){
        brng = brng +360;
      }
      return brng;
    }catch (Exception e){
      e.printStackTrace();
      return 0d;
    }

  }
}

 4、判断经纬度坐标点是否在区域内工具类

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class PolygonUtil {

    /**
     * 求一个坐标点距离区域最近距离
     *
     * @param lon
     * @param lat
     * @param plotPointModelList
     * @return
     */
  /*public static double getDistanceFromPointToPolygon(BigDecimal lon, BigDecimal lat,
          List<PlotPointModel> plotPointModelList) {
    if (plotPointModelList.size() > 2) {
      //求出距离最短的两个点
      PlotPointModel minPoint1 = plotPointModelList.get(0);
      PlotPointModel minPoint2 = plotPointModelList.get(1);
      double d1 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
              minPoint1.getLat().doubleValue(), minPoint1.getLon().doubleValue());
      double d2 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
              minPoint2.getLat().doubleValue(), minPoint2.getLon().doubleValue());
      if (d1 > d2) {
        PlotPointModel temp = minPoint1;
        minPoint1 = minPoint2;
        minPoint2 = temp;
      }
      for (int i = 2; i < plotPointModelList.size(); i++) {
        PlotPointModel plotPoint = plotPointModelList.get(i);
        double d = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
                plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue());
        if (d < d1) {
          d2 = d1;
          d1 = d;
          minPoint2 = minPoint1;
          minPoint1 = plotPoint;
        } else if (d < d2) {
          d2 = d;
          minPoint2 = plotPoint;
        }
      }
      //根据最短两点,求最短距离
      double c = DistanceUtil
              .getDistance(minPoint1.getLat().doubleValue(), minPoint1.getLon().doubleValue(),
                      minPoint2.getLat().doubleValue(), minPoint2.getLon().doubleValue());
      if (Math.pow(d2, 2) >= Math.pow(d1, 2) + Math.pow(c, 2)) {
        //钝角三角形
        return d1;
      }
      //锐角三角形,计算垂足,海伦公式
      //计算周长
      double p = (d1 + d2 + c) / 2;
      //计算面积
      double a = p * (p - d1) * (p - d2) * (p - c);
      double s = Math.sqrt(a);
      //返回高
      return s / c;
    }
    return -1;
  }*/

    /**
     * <p>
     * 计算点到折线的最短距离
     * 计算点到每条线段的最短距离,排序之后,拿最短的一条
     * </p>
     *
     * @param lon
     * @param lat
     * @param plotPointModelList
     * @return {@link double}
     * @author hahalouti
     * @date 2021/10/26
     */
    public static double getDistanceFromPointToPolygon(BigDecimal lon, BigDecimal lat,
                                                       List<PlotPointModel> plotPointModelList) {
        List<Double> distance = new ArrayList<>();
        for (int i = 0; i < plotPointModelList.size() - 1; i++) {
            PlotPointModel plotPoint = plotPointModelList.get(i);
            PlotPointModel plotPoint2 = plotPointModelList.get(i + 1);
            double d1 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
                    plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue());
            double d2 = DistanceUtil.getDistance(lat.doubleValue(), lon.doubleValue(),
                    plotPoint2.getLat().doubleValue(), plotPoint2.getLon().doubleValue());
            double c = DistanceUtil
                    .getDistance(plotPoint.getLat().doubleValue(), plotPoint.getLon().doubleValue(),
                            plotPoint2.getLat().doubleValue(), plotPoint2.getLon().doubleValue());
            // 判断是否是钝角三角形
            if (Math.pow(d1, 2) >= Math.pow(d2, 2) + Math.pow(c, 2)) {
                //钝角三角形
                distance.add(d2);
            } else if (Math.pow(d2, 2) >= Math.pow(d1, 2) + Math.pow(c, 2)) {
                //钝角三角形
                distance.add(d1);
            } else {
                double p = (d1 + d2 + c) / 2;
                //计算面积
                double a = p * (p - d1) * (p - d2) * (p - c);
                double s = Math.sqrt(a);
                //返回高
                distance.add(s / c);
            }
        }
        Collections.sort(distance);
        return distance.get(0);
    }

    /**
     * 判断坐标点是否在一个区域内
     *
     * @param lon
     * @param lat
     * @param plotPointModelList
     * @return
     */
    public static boolean checkInPolygon(BigDecimal lon, BigDecimal lat,
                                         List<PlotPointModel> plotPointModelList) {
        double pointLon = lon.doubleValue();
        double pointLat = lat.doubleValue();
        int size = plotPointModelList.size();
        if (size < 3) {
            return false;
        } else {
            PlotPointModel first = plotPointModelList.get(0);
            PlotPointModel end = plotPointModelList.get(size - 1);
            if (first.getLon().doubleValue() == end.getLon().doubleValue()
                    && first.getLat().doubleValue() == end.getLat().doubleValue()) {
                plotPointModelList.remove(size - 1);
            }

            int pointCount = plotPointModelList.size();
            int intersectPointCount = 0;

            float intersectPointWeights = 0.0F;
            double precision = 2.0E-10D;
            for (int i = 1; i <= pointCount; ++i) {
                PlotPointModel next = plotPointModelList.get(i % pointCount);
                double firstLon = first.getLon().doubleValue();
                double firstLat = first.getLat().doubleValue();
                double nextLon = next.getLon().doubleValue();
                double nextLat = next.getLat().doubleValue();
                if (pointLat >= Math.min(firstLat, nextLat) && pointLat <= Math.max(firstLat, nextLat)) {
                    if (pointLat > Math.min(firstLat, nextLat) && pointLat < Math.max(firstLat, nextLat)) {
                        if (firstLon == nextLon) {
                            if (pointLon == firstLon) {
                                return true;
                            }

                            if (pointLon < firstLon) {
                                ++intersectPointCount;
                            }
                        } else if (pointLon <= Math.min(firstLon, nextLon)) {
                            ++intersectPointCount;
                        } else if (pointLon > Math.min(firstLon, nextLon) && pointLon < Math
                                .max(firstLon, nextLon)) {
                            double slopeDiff = 0.0D;
                            if (firstLat > nextLat) {
                                slopeDiff = (pointLat - nextLat) / (pointLon - nextLon) - (firstLat - nextLat) / (
                                        firstLon - nextLon);
                            } else {
                                slopeDiff = (pointLat - firstLat) / (pointLon - firstLon) - (nextLat - firstLat) / (
                                        nextLon - firstLon);
                            }

                            if (slopeDiff > 0.0D) {
                                if (slopeDiff < precision) {
                                    return true;
                                }

                                ++intersectPointCount;
                            }
                        }
                    } else {
                        if (firstLat == nextLat && pointLon <= Math.max(firstLon, nextLon) && pointLon >= Math
                                .min(firstLon, nextLon)) {
                            return true;
                        }

                        if (pointLat == firstLat && pointLon < firstLon
                                || pointLat == nextLat && pointLon < nextLon) {
                            if (nextLat < firstLat) {
                                intersectPointWeights = (float) ((double) intersectPointWeights + -0.5D);
                            } else if (nextLat > firstLat) {
                                intersectPointWeights = (float) ((double) intersectPointWeights + 0.5D);
                            }
                        }
                    }

                    first = next;
                } else {
                    first = next;
                }
            }

            if (((float) intersectPointCount + Math.abs(intersectPointWeights)) % 2.0F == 0.0F) {
                return false;
            } else {
                return true;
            }
        }
    }
//
//
//  public static void main(String[] args) {
//    BigDecimal lon = new BigDecimal(122.63987);
//    BigDecimal lat = new BigDecimal(39.25399);
//    List<PlotPointModel> plotPointModelList = new ArrayList<>();
//    PlotPointModel  plotPointModel = new PlotPointModel();
//    plotPointModel.setLon(new BigDecimal(122.6244164));
//    plotPointModel.setLat(new BigDecimal(39.2591590));
//    plotPointModelList.add(plotPointModel);
//
//    PlotPointModel  plotPointModel2 = new PlotPointModel();
//    plotPointModel2.setLon(new BigDecimal(122.6244164));
//    plotPointModel2.setLat(new BigDecimal(39.2463846));
//    plotPointModelList.add(plotPointModel2);
//
//    PlotPointModel  plotPointModel3 = new PlotPointModel();
//    plotPointModel3.setLon(new BigDecimal(122.6494789));
//    plotPointModel3.setLat(new BigDecimal(39.2466508));
//    plotPointModelList.add(plotPointModel3);
//
//    PlotPointModel  plotPointModel4 = new PlotPointModel();
//    plotPointModel4.setLon(new BigDecimal(122.6499939));
//    plotPointModel4.setLat(new BigDecimal(39.2588929));
//    plotPointModelList.add(plotPointModel4);
//
//    System.out.println(checkInPolygon(lon,lat,plotPointModelList));
//  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值