【问题标题】:Calculate new rectangle's corner (two geopoints) by doubling up diagonal通过加倍对角线计算新矩形的角(两个地理点)
【发布时间】:2018-09-22 17:12:20
【问题描述】:

我有两个地理点定义的矩形:

1 -> 54.2749558,18.4287748 (lat, lng)
2 -> 54.4472187,18.9512795 (lat, lng)

这两点之间的距离(对角线)为 39 公里(使用this 算法计算)。 现在我需要将我的对角线加倍:39km * 2 = 78km 并找到新扩展矩形的坐标(与第一个矩形的中间位置相同)。

有人可以帮我在 Java 中创建该算法吗?

编辑: 我的代码使用 Mbo 的 答案:

public static void main(String[] args) {
    //example data
    double lat1d = 54.2749558;
    double lng1d = 18.4287748;
    double lat2d = 54.4472187;
    double lng2d = 18.9512795;
    Coordinate lat1 = Coordinate.fromDegrees(lat1d);
    Coordinate lng1 = Coordinate.fromDegrees(lng1d);
    Point point1 = Point.at(lat1, lng1);

    Coordinate lat2 = Coordinate.fromDegrees(lat2d);
    Coordinate lng2 = Coordinate.fromDegrees(lng2d);
    Point point2 = Point.at(lat2, lng2);
    System.out.println("Point1: " + point1);
    System.out.println("Point2: " + point2);

    double distance = EarthCalc.gcdDistance(point1, point2); //in meters
    System.out.println("Current distance between points 1 and 2: " + distance);
    double newDistance = distance * 2;
    System.out.println("Needed distance between points 3 and 4: " + newDistance);


    double y = Math.sin(lng2d - lng1d) * Math.cos(lat2d);
    double x = Math.cos(lat1d) * Math.sin(lat2d) - Math.sin(lat1d) * Math.cos(lat2d) * Math.cos(lng2d - lng1d);
    double brng4 = Math.toDegrees(Math.atan2(y, x)); // bearing for calculating point 4

    double earthRadiusInMeters = EarthCalc.EARTH_DIAMETER / 2;
    double distanceByRadius4 = distance * 1.5 / (earthRadiusInMeters / 2);

    double lat4d = Math.asin(Math.sin(lat1d) * Math.cos(distanceByRadius4) +
            Math.cos(lat1d) * Math.sin(distanceByRadius4) * Math.cos(brng4));
    double lng4d = lng1d + Math.atan2(Math.sin(brng4) * Math.sin(distanceByRadius4) * Math.cos(lat1d), Math.cos(distanceByRadius4) - Math.sin(lat1d) * Math.sin(lat2d));
    Point point4 = Point.at(Coordinate.fromDegrees(lat4d), Coordinate.fromDegrees(lng4d));


    double brng3 = brng4 + Math.PI; // bearing for calculating point 3
    double distanceByRadius3 = distance * 0.5 / (earthRadiusInMeters / 2);

    double lat3d = Math.asin(Math.sin(lat1d) * Math.cos(distanceByRadius3) +
            Math.cos(lat1d) * Math.sin(distanceByRadius3) * Math.cos(brng3));
    double lng3d = lng1d + Math.atan2(Math.sin(brng3) * Math.sin(distanceByRadius3) * Math.cos(lat1d),
            Math.cos(distanceByRadius3) - Math.sin(lat1d) * Math.sin(lat2d));

    Point point3 = Point.at(Coordinate.fromDegrees(lat3d), Coordinate.fromDegrees(lng3d));

    System.out.println("Point3: " + point3);
    System.out.println("Point4: " + point4);

    double actualDistance = EarthCalc.gcdDistance(point3, point4); //in meters
    System.out.println("Actual distance:" + actualDistance);
}

和控制台输出:

Point1: Point{latitude=54.2749558, longitude=18.4287748}
Point2: Point{latitude=54.4472187, longitude=18.9512795}
Current distance between points 1 and 2: 38896.62579783285
Needed distance between points 3 and 4: 77793.2515956657
Point3: Point{latitude=-0.8693568850955943, longitude=18.451667950625396}
Point4: Point{latitude=-0.8624187436224934, longitude=18.360085243458784}
Actual distance:10211.570252961072

【问题讨论】:

  • 请注意,两点不定义矩形 iirc。但这并不重要,因为您基本上想延长两个点之间的距离,每个点都停留在连接原始点的线上,并且与另一个点的距离相同,对吧?您是否尝试过自己进行距离计算以了解几何的工作原理?
  • 也许这个库有你需要的一切(在 EarthCalc 类中,使用“bearing”和“pointAt”github.com/grumlimited/geocalc
  • 我没有考虑地球的曲率(面积太小,不重要),所以对我来说 2 个对角定义了一个矩形 :) 我试过了,但得到了一些奇怪的结果,所以决定请求帮忙。 @ThomasSallaberger 谢谢你,去试试那个库

标签: java math geometry geo


【解决方案1】:

对于小区域,您可以使用“平面”近似:

   lat3 = lat1 - 0.5*(lat2 - lat1)
   lat4 = lat1 + 1.5*(lat2 - lat1)
   and similar for longitude

快速检查:

  1 -> 54.2749558,18.4287748 (lat, lng)  
  2 -> 54.4472187,18.9512795 (lat, lng)    
  dlat = 54.4472187 - 54.2749558 = 0.172
  dlon = 18.9512795 - 18.4287748  = 0.553
  lat3 = 54.2749558 - 0.086 = 54.189
  lon3 = 18.9512795 - 0.276 = 18.675
  lat4 = 54.2749558 + 3 * 0.086 = 54.533
  lon4 = 18.9512795 + 3 * 0.276 = 19.779

由于我的粗略舍入和切角变形,距离计算得出 81.11 公里

为了说明球面几何,使用latlong page 中的公式:

我假设“中间”是大圆弧中心(拐角之间的中间) - 它不同于坐标平均值

不要忘记以弧度转换坐标值

从第一点开始:

 y = Math.sin(λ2-λ1) * Math.cos(φ2);
 x = Math.cos(φ1)*Math.sin(φ2) - Math.sin(φ1)*Math.cos(φ2)*Math.cos(λ2-λ1);
 brng = Math.atan2(y, x).toDegrees();

其中 φ1,λ1 是起点,φ2,λ2 是终点

对于一个新的拐角 - 给定距离起点的目的地点和方位角:

φ4 = Math.asin( Math.sin(φ1)*Math.cos(d/R) +
                Math.cos(φ1)*Math.sin(d/R)*Math.cos(brng) );
λ4 = λ1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(φ1),
                     Math.cos(d/R)-Math.sin(φ1)*Math.sin(φ2));

其中 R 是地球半径,d 是需要的距离 - 这里是1.5 * 39 = 58.5

对于第二个拐角-使用d = 0.5*39 = 19.5 和反向轴承brng+Pi 的相同目标点公式

【讨论】:

  • 说实话我不想考虑地球的曲率(小区域,不需要那种精度)所以我想我可以通过坐标平均来简化它以获得中间点,对吧?
  • 当然。在这种情况下lat3 = lat1 - 0.5*(lat2 - lat1), lat4 = lat1 + 1.5*(lat2 - lat1) 和类似的经度
  • 我尝试同时使用(平面近似和考虑地球曲率),但不幸的是无法得到正确的结果。我已将我的代码添加到 EDIT 部分 - 与您提出的计算和控制台输出完全相同 - 您能检查我是否没有犯任何错误吗?试图把它做好却做不到。
  • 您在角度和弧度方面犯了一些错误。仅将度数用于最终结果。
猜你喜欢
  • 2011-04-13
  • 2015-06-16
  • 1970-01-01
  • 2023-02-01
  • 2015-07-29
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 2014-11-07
相关资源
最近更新 更多