2011-05-02 205 views
7

我需要计算给定点的纬度和经度。计算距离另一纬度/经度点米的纬度和经度

我知道参考点的经度和纬度,以及从参考点指示x轴和y轴上的米的值。 从这些数据开始,我必须找到经纬度。

我搜索了类似的问题,但它看起来像大多数问题都是关于找到两个纬度/长点之间的距离。我需要做相反的事情。

我该怎么办? 我使用Java

+0

**欢迎计算器-90!**问候。 – 2011-05-02 14:22:23

回答

9

以下是此类问题的最佳出发点:Aviation Formulary。他们拥有做这类事情的所有公式。

从这些公式中,我创建了自己的Java util类。它使用了很多内部的东西,所以我不能在这里发布实际的类,但给你一些关于如何将公式中的知识转换为Java代码的例子。

我这里还有一些基本的方法:

/** 
* the length of one degree of latitude (and one degree of longitude at equator) in meters. 
*/ 
private static final int DEGREE_DISTANCE_AT_EQUATOR = 111329; 
/** 
* the radius of the earth in meters. 
*/ 
private static final double EARTH_RADIUS = 6378137; //meters 
/** 
* the length of one minute of latitude in meters, i.e. one nautical mile in meters. 
*/ 
private static final double MINUTES_TO_METERS = 1852d; 
/** 
* the amount of minutes in one degree. 
*/ 
private static final double DEGREE_TO_MINUTES = 60d; 


/** 
* This method extrapolates the endpoint of a movement with a given length from a given starting point using a given 
* course. 
* 
* @param startPointLat the latitude of the starting point in degrees, must not be {@link Double#NaN}. 
* @param startPointLon the longitude of the starting point in degrees, must not be {@link Double#NaN}. 
* @param course  the course to be used for extrapolation in degrees, must not be {@link Double#NaN}. 
* @param distance  the distance to be extrapolated in meters, must not be {@link Double#NaN}. 
* 
* @return the extrapolated point. 
*/ 
public static Point extrapolate(final double startPointLat, final double startPointLon, final double course, 
           final double distance) { 
    // 
    //lat =asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc)) 
    //dlon=atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat)) 
    //lon=mod(lon1+dlon +pi,2*pi)-pi 
    // 
    // where: 
    // lat1,lon1 -start pointi n radians 
    // d   - distance in radians Deg2Rad(nm/60) 
    // tc   - course in radians 

    final double crs = Math.toRadians(course); 
    final double d12 = Math.toRadians(distance/MINUTES_TO_METERS/DEGREE_TO_MINUTES); 

    final double lat1 = Math.toRadians(startPointLat); 
    final double lon1 = Math.toRadians(startPointLon); 

    final double lat = Math.asin(Math.sin(lat1) * Math.cos(d12) 
     + Math.cos(lat1) * Math.sin(d12) * Math.cos(crs)); 
    final double dlon = Math.atan2(Math.sin(crs) * Math.sin(d12) * Math.cos(lat1), 
     Math.cos(d12) - Math.sin(lat1) * Math.sin(lat)); 
    final double lon = (lon1 + dlon + Math.PI) % (2 * Math.PI) - Math.PI; 

    return new Point(Math.toDegrees(lat), Math.toDegrees(lon)); 
} 

/** 
* calculates the length of one degree of longitude at the given latitude. 
* 
* @param latitude the latitude to calculate the longitude distance for, must not be {@link Double#NaN}. 
* 
* @return the length of one degree of longitude at the given latitude in meters. 
*/ 
public static double longitudeDistanceAtLatitude(final double latitude) { 

    final double longitudeDistanceScaleForCurrentLatitude = Math.cos(Math.toRadians(latitude)); 
    return DEGREE_DISTANCE_AT_EQUATOR * longitudeDistanceScaleForCurrentLatitude; 
} 
+2

这是否回答你的问题? - 那么请接受答案。 – BertNase 2011-05-26 04:27:50

0

这是不是一个真正的答案,但在评论栏中太短,我要发布,而这一结果提出了相当高的,当我用Google搜索一个答案。上面的BertNase代码很好,我正在使用它。然而,围绕边缘案例有些奇怪。我并不是100%确定代码是错误的,因为我仍在学习地理信息,但是我从我写的junit测试用例中添加了参数。例如经度从180变为当我南下100M的(情况10)

/*0*/ { inputOf(0.0, 0.0), NORTH, shouldGiveAnswerOf(0.0009, 0.0) }, 
/*1*/ { inputOf(0.0, 0.0), SOUTH, shouldGiveAnswerOf(-0.0009, 0.0) }, 
/*2*/ { inputOf(0.0, 0.0), WEST, shouldGiveAnswerOf(0.0, -0.0009) }, 
/*3*/ { inputOf(0.0, 0.0), EAST, shouldGiveAnswerOf(0.0, 0.0009) }, 

/*4*/ { inputOf(90.0, 180.0), NORTH, shouldGiveAnswerOf(89.9991, -180.0) }, 
/*5*/ { inputOf(0.0, 180.0), NORTH, shouldGiveAnswerOf(0.0009, -180.0) }, 
/*6*/ { inputOf(-90.0, 180.0), NORTH, shouldGiveAnswerOf(-89.9991, -180.0) }, 
/*7*/ { inputOf(90.0, -180.0), NORTH, shouldGiveAnswerOf(89.9991, -180.0) }, 
/*8*/ { inputOf(0.0, -180.0), NORTH, shouldGiveAnswerOf(0.0009, -180.0) }, 
/*9*/ { inputOf(-90.0, -180.0), NORTH, shouldGiveAnswerOf(-89.9991, -180) }, 

/*10*/ { inputOf(90.0, 180.0), SOUTH, shouldGiveAnswerOf(89.9991, -90.0) }, 
/*11*/ { inputOf(0.0, 180.0), SOUTH, shouldGiveAnswerOf(-0.0009, -180.0) }, 
/*12*/ { inputOf(-90.0, 180.0), SOUTH, shouldGiveAnswerOf(-89.9991, -90.0) }, 
/*13*/ { inputOf(90.0, -180.0), SOUTH, shouldGiveAnswerOf(89.9991, -90.0) }, 
/*14*/ { inputOf(0.0, -180.0), SOUTH, shouldGiveAnswerOf(-0.0009, -180.0) }, 
/*15*/ { inputOf(-90.0, -180.0), SOUTH, shouldGiveAnswerOf(-89.9991, -90) }, 

/*16*/ { inputOf(90.0, 180.0), EAST, shouldGiveAnswerOf(89.9991, -90.0) }, 
/*17*/ { inputOf(0.0, 180.0), EAST, shouldGiveAnswerOf(0.0, -179.9991) }, 
/*18*/ { inputOf(-90.0, 180.0), EAST, shouldGiveAnswerOf(-89.9991, -90.0) }, 
/*19*/ { inputOf(90.0, -180.0), EAST, shouldGiveAnswerOf(89.9991, -90.0) }, 
/*20*/ { inputOf(0.0, -180.0), EAST, shouldGiveAnswerOf(0.0, -179.9991) }, 
/*21*/ { inputOf(-90.0, -180.0), EAST, shouldGiveAnswerOf(-89.9991, -90) }, 

/*22*/ { inputOf(10.0, 5.0), NORTH, shouldGiveAnswerOf(10.0009, 5.0) }, 
/*23*/ { inputOf(10.0, 5.0), SOUTH, shouldGiveAnswerOf(9.9991, 5.0) }, 
/*24*/ { inputOf(10.0, 5.0), WEST, shouldGiveAnswerOf(10.0, 4.999086) }, 
/*25*/ { inputOf(10.0, 5.0), EAST, shouldGiveAnswerOf(10.0, 5.000914) }, 

/*26*/ { inputOf(10.0, 5.0), NORTH_EAST, shouldGiveAnswerOf(10.000636, 5.000646) },