经纬度距离、范围、方位角计算、坐标转换

计算经纬度距离

	<!--测量距离-->
	<dependency>
	    <groupId>org.gavaghan</groupId>
	    <artifactId>geodesy</artifactId>
	    <version>1.1.3</version>
	</dependency>
public static double getDistance(String xy1, String xy2) throws Exception {
        String[] split1 = xy1.split(",");
        String[] split2 = xy2.split(",");
        if (split1.length == 2 && split2.length == 2) {
            double lon1 = Double.parseDouble(split1[0]);
            double lat1 = Double.parseDouble(split1[1]);
            double lon2 = Double.parseDouble(split2[0]);
            double lat2 = Double.parseDouble(split2[1]);
            double distanceMeter = getDistanceMeter(lat1, lon1, lat2, lon2, Ellipsoid.Sphere);
            return distanceMeter;
        } else {
            throw new Exception("计算距离经纬度错误");
        }
    }

 public static double getDistanceMeter(double lat1, double lon1, double lat2, double lon2, Ellipsoid ellipsoid) {
        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GlobalCoordinates source = new GlobalCoordinates(lat1, lon1);
        GlobalCoordinates target = new GlobalCoordinates(lat2, lon2);
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, source, target);
        return geoCurve.getEllipsoidalDistance();
    }

坐标转换(注意参数经纬度顺序,纬度lat在前,经度lon在后)

package com.hiwei.carclient.utils;

public class LngLonUtil {
    public static double pi = 3.1415926535897932384626;
    public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    public static double a = 6378245.0;
    public static double ee = 0.00669342162296594323;

    public static double transformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    public static double transformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
        return ret;
    }

    public static double[] transform(double lat, double lon) {
        if (outOfChina(lat, lon)) {
            return new double[]{lat, lon};
        }
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new double[]{mgLat, mgLon};
    }

    /**
     * 判断是否在中国
     *
     * @param lat
     * @param lon
     * @return
     */
    public static boolean outOfChina(double lat, double lon) {
        if (lon < 72.004 || lon > 137.8347)
            return true;
        if (lat < 0.8293 || lat > 55.8271)
            return true;
        return false;
    }

    /**
     * 84 ==》 高德
     *
     * @param lat
     * @param lon
     * @return
     */
    public static double[] gps84_To_Gcj02(double lat, double lon) {
        if (outOfChina(lat, lon)) {
            return new double[]{lat, lon};
        }
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new double[]{mgLat, mgLon};
    }

    /**
     * 84 ==》 高德
     *
     * @param vehxy gps地址
     * @return
     */
    public static String gpsToGcj02(String vehxy) {
        String[] split = vehxy.split(",");
        double lon = Double.parseDouble(split[0]);
        double lat = Double.parseDouble(split[1]);
        if (outOfChina(lat, lon)) {
            return lon + "," + lat;
        }
        double dLat = transformLat(lon - 105.0, lat - 35.0);
        double dLon = transformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return mgLon + "," + mgLat;
    }

    /**
     * 高德 ==》 84
     *
     * @param lon * @param lat * @return
     */
    public static double[] gcj02_To_Gps84(double lat, double lon) {
        double[] gps = transform(lat, lon);
        double lontitude = lon * 2 - gps[1];
        double latitude = lat * 2 - gps[0];
        return new double[]{latitude, lontitude};
    }

    /**
     * 高德 == 》 百度
     *
     * @param lat
     * @param lon
     */
    public static double[] gcj02_To_Bd09(double lat, double lon) {
        double x = lon, y = lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta) + 0.0065;
        double tempLat = z * Math.sin(theta) + 0.006;
        double[] gps = {tempLat, tempLon};
        return gps;
    }

    /**
     * 百度 == 》 高德
     *
     * @param lat
     * @param lon
     */
    public static double[] bd09_To_Gcj02(double lat, double lon) {
        double x = lon - 0.0065, y = lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta);
        double tempLat = z * Math.sin(theta);
        double[] gps = {tempLat, tempLon};
        return gps;
    }

    /**
     * 84 == 》 百度
     *
     * @param lat
     * @param lon
     * @return
     */
    public static double[] gps84_To_bd09(double lat, double lon) {
        double[] gcj02 = gps84_To_Gcj02(lat, lon);
        double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);
        return bd09;
    }

    /**
     * 百度 == 》 84
     *
     * @param lat
     * @param lon
     * @return
     */
    public static double[] bd09_To_gps84(double lat, double lon) {
        double[] gcj02 = bd09_To_Gcj02(lat, lon);
        double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
        //保留小数点后六位
        gps84[0] = retain6(gps84[0]);
        gps84[1] = retain6(gps84[1]);
        return gps84;
    }

    /*
     * 保留小数点后六位
     * @param num
     * @return
     */
    private static double retain6(double num) {
        String result = String.format("%.6f", num);
        return Double.valueOf(result);
    }
}

计算方位角

/**
     * 功能描述: 获取其他车辆相对自己的位置  左前  左后  右前  右后
     * <p>
     * azimuth 通过经纬度计算出的方位角
     * 方向角取值范围:-90~180
     * 方位角取值范围:0~360
     *
     * @param vehdirection 获取的车头方向
     * @return
     * @author zhouwenjie
     * @date 2021/1/21 10:08
     */
    public static double getRelativePosition(String xy1, String xy2, double vehdirection) {
        String[] split1 = xy1.split(",");
        String[] split2 = xy2.split(",");
        double lon1 = Double.parseDouble(split1[0]);
        double lat1 = Double.parseDouble(split1[1]);
        double lon2 = Double.parseDouble(split2[0]);
        double lat2 = Double.parseDouble(split2[1]);
        double azimuth = getAzimuth(lon1, lat1, lon2, lat2);
        //为了统一取值范围,方向角加90
        return azimuth - vehdirection - 90;
    }
/**
 * 转化为弧度(rad)
  */
 public static double rad(double d) {
     return d * Math.PI / 180.0;
 }
 
/**
     * 功能描述: 计算方位角 计算结果0-360度
     *
     * @return
     * @author zhouwenjie
     * @date 2021/1/21 10:08
     */
    public static double getAzimuth(double lon1, double lat1, double lon2, double lat2) {
        lat1 = rad(lat1);
        lat2 = rad(lat2);
        lon1 = rad(lon1);
        lon2 = rad(lon2);
        double y = Math.sin(lon2 - lon1) * Math.cos(lat2);
        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
        return (Math.toDegrees(Math.atan2(y, x)) + 360) % 360;
    }
		//2相对于1的位置
        double relativePosition1 = getRelativePosition(xy1, xy2, vehdirection1);
        relativePosition1 = relativePosition1 < 0 ? relativePosition1 + 360 : relativePosition1;
        //1相对于2的位置
        double relativePosition2 = getRelativePosition(xy2, xy1, vehdirection2);
        relativePosition2 = relativePosition2 < 0 ? relativePosition2 + 360 : relativePosition2;
        //右前,如果对方车方向在我车加减90度范围内则需要预警
        if (relativePosition1 >= 0.0 && relativePosition1 < 90.0) {
            //右前必然对应对方的右前 不会是左前
            if ((relativePosition2 >= 0.0 && relativePosition2 < 90.0)) {
               
            }
            //90度拐角会是右前也提示左前
            if ((relativePosition2 >= 270.0 && relativePosition2 < 360.0)) {
                
            }
        }
        //右后
        if (relativePosition1 >= 90.0 && relativePosition1 < 180.0) {
            //后方有车
            if (("02".equals(vehclass) && relativePosition2 >= 270.0 && relativePosition2 < 360.0)) {
            }
        }
        //左后
        if (relativePosition1 >= 180.0 && relativePosition1 < 270.0) {
            //后方有车
            if ("02".equals(vehclass) && relativePosition2 >= 0.0 && relativePosition2 < 90.0) {
                
            }
        }
        //左前
        if (relativePosition1 > 270.0 && relativePosition1 <= 360.0) {
            if ((relativePosition2 > 270.0 && relativePosition2 <= 360.0)) {
                
            }
            //90度拐角会是右前也提示
            if ((relativePosition2 >= 0.0 && relativePosition2 < 90.0)) {
              
            }
        }

图解
在这里插入图片描述
根据具体需求来决定方位角的作用,可以多找些坐标点试验一下

断一个点是否在区域内

圆形

/**
     * @param lat1   纬度
     * @param lat2   纬度
     * @param lng1   经度
     * @param lng2   经度
     * @param radius 判断一个点是否在圆形区域内,比较坐标点与圆心的距离是否小于半径
     */
    public static boolean isInCircle(double lng1, double lat1, double lng2, double lat2, double radius) {
        double distance = getDistance(lat1, lng1, lat2, lng2);
        if (distance > radius) {
            return false;
        } else {
            //System.err.println("经度:"+lng1+"维度:"+lat1+"经度:"+lng2+"维度:"+lat2+"距离:"+distance);
            return true;
        }
    }

多边形

 public static Double[] lon;
 public static Double[] lat;
 
 public static ArrayList<Point2D.Double> pointList =new ArrayList<Point2D.Double>();
 
	static{
		lon = new Double[]{lonERight, lonNLeft, lonNRight, lonWLeft, lonWRight, lonSLeft, lonSRight};
		lat = new Double[]{latERight, latNLeft, latNRight, latWLeft, latWRight, latSLeft, latSRight};
	}

	public static void getList() {
	   // 将区域各顶点的横纵坐标放到一个点集合里面
	    double polygonPoint_x = 0.0, polygonPoint_y = 0.0;
	    for (int i = 0; i < lon.length; i++) {
	        polygonPoint_x = lon[i];
	        polygonPoint_y = lat[i];
	        Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x, polygonPoint_y);
	        pointList.add(polygonPoint);
	    }
	}
/**
     * 判断是否在多边形区域内
     *
     * @param pointLon 要判断的点的横坐标 经度
     * @param pointLat 要判断的点的纵坐标 纬度
     * @return
     */
    public static boolean isInPolygon(double pointLon, double pointLat, List<Point2D.Double> pointList) {
        // 将要判断的横纵坐标组成一个点
        Point2D.Double point = new Point2D.Double(pointLon, pointLat);
        return check(point, pointList);
    }

    /**
     * @param point   要判断的点的横纵坐标
     * @param polygon 组成的顶点坐标集合
     * @return
     */
    private static boolean check(Point2D.Double point, List<Point2D.Double> polygon) {
        java.awt.geom.GeneralPath peneralPath = new java.awt.geom.GeneralPath();

        Point2D.Double first = polygon.get(0);
        // 通过移动到指定坐标(以双精度指定),将一个点添加到路径中
        peneralPath.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            // 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。
            peneralPath.lineTo(d.x, d.y);
        }
        // 将几何多边形封闭
        peneralPath.lineTo(first.x, first.y);
        peneralPath.closePath();
        // 测试指定的 Point2D 是否在 Shape 的边界内。
        return peneralPath.contains(point);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值