【问题标题】:Calculate latitude and longitude having meters distance from another latitude/longitude point计算与另一个纬度/经度点有米距离的纬度和经度
【发布时间】:2011-08-16 23:36:15
【问题描述】:

我需要计算给定点的纬度和经度。

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

我搜索了类似的问题,但看起来大多数问题都是关于查找两个纬度/经度点之间的距离。我需要反其道而行之。

我该怎么办? 我使用Java

【问题讨论】:

  • 欢迎来到 StackOverflow! 问候。

标签: java geocoding latitude-longitude


【解决方案1】:

这是此类问题的最佳起点: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】:

这不是一个真正的答案,但是 cmets 框对于我想要发布的内容来说太短了,当我在谷歌上搜索答案时,这个结果非常高。上面的 BertNase 代码很好,我正在使用它。但是,边缘情况有一些奇怪之处。我不是 100% 确定代码是错误的,因为我仍在学习地理知识,但我正在添加我围绕它编写的 junit 测试用例中的参数。例如,当我向南移动 100m 时,经度从 180 变为 -90(案例 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) },

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-16
    • 2013-02-21
    • 2012-10-13
    • 2012-01-26
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多