java已知两点经纬度,已知距离,计算两点间线上某一点的经纬度。

java已知两点经纬度,已知距离,计算两点间线上某一点的经纬度。

背景:项目中已知两点的经纬度,并且知道距离其中某一点的距离。计算这个点的经纬度。84坐标系。要求这个点要在线上。

引入依赖:

		<dependency>
            <groupId>org.gavaghan</groupId>
            <artifactId>geodesy</artifactId>
            <version>1.1.3</version>
        </dependency>

第一种方式,精度不是很高。用的比例的方式,距离比暂定的都是赤道比例:

@Data
public class GpsDTO {


    private Double lon;
    private Double lat;


    @Override
    public String toString() {
        return "GpsDTO{" +
                "lon=" + lon +
                ", lat=" + lat +
                '}';
    }
}
public class CalLonLat {
	public static void main(String[] args) {
		//得到对象
	  GpsDTO dto = disposeGps(120.0867552200001, 31.579709308000076, 120.08736669600012, 31.57955501200007, 17.23);
	    
	
	}

//处理
 public static GpsDTO disposeGps(double firstLon, double firstLat, double secondLon, double secondLat, double meter) {
        //赤道比例  1m大概多少度
        double lonRate = 0.00000932;
        double latRate = 0.00000898;
        Double lon = null;
        Double lat = null;
        //第一和第二个点精度相同
        if (firstLon == secondLon) {
            lon = firstLon;
            if (firstLat == secondLat) {
                //如果纬度也相同
                lat = secondLat;
            } else {
                //如果不同
                if (firstLat > secondLat) {
                    //如果第一个纬度大于第二个纬度
                    lat = firstLat - latRate * meter;
                } else {
                    lat = firstLat + latRate * meter;
                }
            }
        }
        //第一个点和第二个点纬度相同
        if (firstLat == secondLat) {
            lat = firstLat;
            if (firstLon == secondLon) {
                //如果精度也相同
                lon = firstLon;
            } else {
                //如果不同
                if (firstLon > secondLon) {
                    //如果第一个精度大于第二个精度
                    lon = firstLon - lonRate * meter;
                } else {
                    lon = firstLon + lonRate * meter;
                }
            }
        }
        //如果都不相同
        if (firstLon != secondLon && firstLat != secondLat) {
            GlobalCoordinates one = new GlobalCoordinates(firstLon, firstLat);
            GlobalCoordinates two = new GlobalCoordinates(secondLon, secondLat);
            GlobalCoordinates three = new GlobalCoordinates(firstLon, secondLat);
            double oneThree = getDistanceMeter(one, three, Ellipsoid.WGS84);
            double twoThree = getDistanceMeter(two, three, Ellipsoid.WGS84);
            double oneTwo = getDistanceMeter(one, two, Ellipsoid.WGS84);
            if (firstLon > secondLon) {
                //如果第一个精度大于第二个精度
                //纵向距离
                double sinA = oneThree / oneTwo;
                double latDis = meter * sinA;
                //横向距离
                double cosA = twoThree / oneTwo;
                double lonDis = meter * cosA;

                lon = firstLon - lonDis * lonRate;
                if (firstLat > secondLat) {
                    //如果第一个纬度大于第二个纬度
                    lat = firstLat - latDis * latRate;
                } else {
                    //如果第一个纬度小于第二个纬度
                    lat = firstLat + latDis * latRate;
                }
            } else {
                //如果第一个精度小于于第二个精度
                //纵向距离
                double sinA = twoThree / oneTwo;
                double latDis = meter * sinA;
                //横向距离
                double cosA = oneThree / oneTwo;
                double lonDis = meter * cosA;

                lon = firstLon + lonDis * lonRate;
                if (firstLat > secondLat) {
                    //如果第一个纬度大于第二个纬度
                    lat = firstLat - latDis * latRate;
                } else {
                    //如果第一个纬度小于第二个纬度
                    lat = firstLat + latDis * latRate;
                }
            }
        }
        GpsDTO dto = new GpsDTO();
        dto.setLon(lon);
        dto.setLat(lat);
        return dto;
    }

}

第二种,已知两点经纬度和距离,先计算第一个点到第二个点的角度,按照360度,由正北方向顺时针旋转得到。
这种精度比较高,大概在一米以下。

public class MyLatLng {

    public static double Rc = 6378137;
    public static double Rj = 6356725;
    public double m_LoDeg, m_LoMin, m_LoSec;
    public double m_LaDeg, m_LaMin, m_LaSec;
    public double m_Longitude, m_Latitude;
    public double m_RadLo, m_RadLa;
    public double Ec;
    public double Ed;

    public MyLatLng(double longitude, double latitude) {
        m_LoDeg = (int) longitude;
        m_LoMin = (int) ((longitude - m_LoDeg) * 60);
        m_LoSec = (longitude - m_LoDeg - m_LoMin / 60) * 3600;

        m_LaDeg = (int) latitude;
        m_LaMin = (int) ((latitude - m_LaDeg) * 60);
        m_LaSec = (latitude - m_LaDeg - m_LaMin / 60) * 3600;

        m_Longitude = longitude;
        m_Latitude = latitude;
        m_RadLo = longitude * Math.PI / 180;
        m_RadLa = latitude * Math.PI / 180;
        Ec = Rj + (Rc - Rj) * (90 - m_Latitude) / 90;
        Ed = Ec * Math.cos(m_RadLa);

    }


}
public class CalLonLat {
	public static void main(String[] args) {
	 		//角度
	 		//第一个点
	        MyLatLng A=new MyLatLng(120.0867552200001,31.579709308000076);
	        //第二个点
	        MyLatLng B=new MyLatLng(120.08736669600012,31.57955501200007);
	        //得到角度
	        double brang=getAngle(A,B);
	        System.out.println(brang);
	
	        LonLatTest3 test=new LonLatTest3();
	        double lon=120.0867552200001;
	        double lat=31.579709308000076;
	        double brng=brang;
	        //已知到第一个点的距离
	        double dist=17.23;
			//处理
	        test.computerThatLonLat(lon, lat, brng, dist);
	
	}
}

public class LonLatTest3 {

    /*
     * 大地坐标系资料WGS-84 长半径a=6378137 短半径b=6356752.3142 扁率f=1/298.2572236
     */
    /** 长半径a=6378137 */
    private double a = 6378137;
    /** 短半径b=6356752.3142 */
    private double b = 6356752.3142;
    /** 扁率f=1/298.2572236 */
    private double f = 1 / 298.2572236;

    /**
     * 计算另一点经纬度
     *
     * @param lon
     *            经度
     * @param lat
     *            维度
     * @param lonlat
     *            已知点经纬度
     * @param brng
     *            方位角
     * @param dist
     *            距离(米)
     */
    public void computerThatLonLat(double lon, double lat, double brng, double dist) {

        double alpha1 = rad(brng);
        double sinAlpha1 = Math.sin(alpha1);
        double cosAlpha1 = Math.cos(alpha1);

        double tanU1 = (1 - f) * Math.tan(rad(lat));
        double cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1));
        double sinU1 = tanU1 * cosU1;
        double sigma1 = Math.atan2(tanU1, cosAlpha1);
        double sinAlpha = cosU1 * sinAlpha1;
        double cosSqAlpha = 1 - sinAlpha * sinAlpha;
        double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
        double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
        double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));

        double cos2SigmaM=0;
        double sinSigma=0;
        double cosSigma=0;
        double sigma = dist / (b * A), sigmaP = 2 * Math.PI;
        while (Math.abs(sigma - sigmaP) > 1e-12) {
            cos2SigmaM = Math.cos(2 * sigma1 + sigma);
            sinSigma = Math.sin(sigma);
            cosSigma = Math.cos(sigma);
            double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)
                    - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
            sigmaP = sigma;
            sigma = dist / (b * A) + deltaSigma;
        }

        double tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
        double lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
                (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
        double lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
        double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
        double L = lambda - (1 - C) * f * sinAlpha
                * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

        double revAz = Math.atan2(sinAlpha, -tmp); // final bearing

        System.out.println(revAz);
        System.out.println(lon+deg(L)+","+deg(lat2));
    }

    /**
     * 度换成弧度
     *
     * @param d
     *            度
     * @return 弧度
     */
    private double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 弧度换成度
     *
     * @param x
     *            弧度
     * @return 度
     */
    private double deg(double x) {
        return x * 180 / Math.PI;
    }

}





  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值