【问题标题】:Using the Cosine law to calculate distance between 2 points in Objective C?使用余弦定律计算Objective C中2点之间的距离?
【发布时间】:2023-03-07 01:36:01
【问题描述】:

我从 Google 地图获得了一些 GPS 坐标,我需要找到它们之间的距离 使用 Objective C。我已经实现了公式,但我得到的结果非常大。

我已经通过将 Google 地图中的值传回 Google 地球和互联网上的地理编码服务来测试这些值,并且一切都检查出来了。我现在开始怀疑余弦定律要求我在传递坐标之前对坐标进行某种转换。

我对 Haversine 公式进行了类似的实现,但这也给了我很大的结果。然后我切换到余弦,因为它更容易调试并且我不需要非常高的精度。

希望有人能对此有所了解,或使用代码:)

- (CGFloat) calculateDistanceBetweenPoints:(CGPoint) origin andDestination:(CGPoint) destination {

//To convert kilometers to miles, divide by 1.609
// x = latitude 
// y = longitude

/* example:
 Dubai      : 25.248665, 55.352917 
 Amsterdam  : 52.309071, 4.763385
 Approx dist: 5,182.62 KM
 Calc. dist : 8,253.33
 */

CGFloat toRad           =   (M_PI / 180);
CGFloat R               =   6371.0f; //earth's mean radius in Km

CGFloat sinePart        =   sinf( origin.x * toRad ) * sinf( destination.x * toRad );
CGFloat cosinePart      =   cosf( origin.x * toRad ) * cosf( destination.x * toRad );
CGFloat deltaCosinePart =   cosf( ( destination.y - origin.y ) * toRad );

CGFloat delta           =   acosf( sinePart + cosinePart * deltaCosinePart) * R;

return delta;
}

以上是根据此处引用的链接计算得出的:stackoverflow question

【问题讨论】:

    标签: objective-c coordinate-systems trigonometry


    【解决方案1】:

    有许多问题可能会有所帮助,包括:

    给定这两个位置,您可以创建一个球面三角形,角 A 在阿姆斯特丹,B 在迪拜,C 在北极,边 a = 90° - ϕAms, b = 90° - φDub,角度 C = Δλ = λDub - λAms。要求的答案是边c。

    使用我对 SO 389211 的回答中的一些材料。

    (这是一个彻底修改过的答案——我之前的尝试使用了错误的球形三角形,因此得到了错误的答案。)


    最糟糕的 ASCII 艺术:

                       + C (North Pole)
                      /|
                    b/ |
                    /  |
    (Amsterdam) A  +   | a
                    \  |
                    c\ |
                      \|
                       + B (Dubai)
    

    球三角形的基本余弦定律是:

    cos c = cos a . cos b + sin a . sin b . cos C
    

    注意到 cos (90º - x) = sin x 和 sin (90º - x) = cos x,我们可以写成:

    cos c = sin φAms 。 sin φDub + cos φAms 。 cos φ配音。 cos Δλ

    然后以弧度为单位的角度 c 通过乘以地球的半径转换为距离。


    将此应用于您的数据:

    Dubai: φ配音= 25.248665°N, λ配音= 55.352917°E
    Amsterdam: φAms= 52.309071°N, λAms= 4.763385°E

    Δλ = 50.589532°

    三角函数精确到小数点后 6 位:

    cos c = 0.426548 × 0.791320 + 0.904465 × 0.611402 × 0.634872
          = 0.337536            + 0.351079
          = 0.688615
    

    出处:

    c = 46.479426°
      =  0.811219 radians
    

    将其乘以 6371 公里作为地球的标称半径

    c = 5168 km
    

    因此,对于 R = 6371 公里,距离为 0.811219 × 6371 = 5168 公里(至 4 平方英尺)。

    TrueKnowledge 说应该是 5155 公里。它说它使用的位置数据与您指定的值相当,维基百科确认您提供的半径。这相当接近 - 在计算中使用相同的坐标和更多数字重做计算会产生更好的答案,但接近这个答案。


    【讨论】:

    • ASCII 数学艺术,有什么不值得喜欢的:) 我得到了这个值,使用正确的坐标:5168.279785,这完全在我的误差范围内。
    • @High-Performance Mark:我已经使用不同的(正确的)球形三角形完全修改了答案,并且给出的答案足够接近以纠正可信。
    • 嗨乔纳森,感谢你做这个教科书例子:) 我相信这篇文章现在已经完成了代码和理论。我希望你从 1 月份以来没有为此失眠过多:)
    • @RickiG:失眠了——不。但它确实让我感到厌烦,我可以看到我做错了什么,但没有弄清楚是什么……然后,最终,我意识到我哪里出错了。谢谢。
    【解决方案2】:

    您是否考虑过使用CLLocation中提供的方法:

    - (CLLocationDistance)getDistanceFrom:(const CLLocation *)location?

    【讨论】:

    • 感谢 Johan 在阅读了听起来很诱人的文档之后:) 我用三行代码实现了它: CLLocation *originPos = [[CLLocation alloc] initWithLatitude:origin.x longitude:origin.y]; CLLocation *destinationPos = [[CLLocation alloc] initWithLatitude:(double)destination.x longitude:(double)destination.y]; CGFloat dist = [originPos getDistanceFrom:destinationPos];奇怪的是,这给了我完全相同的值??它仍然坚持阿姆斯特丹和迪拜相距约 8,200 公里?好吧,我确实发现我的错误更普遍:/
    【解决方案3】:

    代码可能没问题,当我在您的示例数据上运行它时(减去几个小数位),它返回 5168.3584

    【讨论】:

    • 感谢 hic3456 为我进行了测试。我传递了更改的坐标,您的回答让我回去再次检查……请在下面查看我的回答。
    • 非常欢迎 RickiG - 帮助我获得了一个帐户 :) +尊重 Johan 和 Mark 的更多信息回复'
    【解决方案4】:

    伙计们,我很抱歉 :( 还有一张红脸。 我对这些坐标做了一些其他的计算。我计算了他们的 (x, y) 位置 所以他们在我绘制的自定义地图上正确定位了城市。这些坐标是这样计算的:

    - (CGPoint) translateToPixelsFromLatitude:(CGFloat) latitude andLongitude:(CGFloat) longitude {
    
    CGPoint position    = CGPointMake(0, 0);
    CGFloat mapWidth    = 300.0f;
    CGFloat mapHeight   = 200.0f;
    
    CGFloat offsetX     = 5.0f;
    CGFloat offsetY     = 35.0f;
    
    position.x = (((180 + longitude) / 360) * mapWidth) + offsetX;
    position.y = (mapHeight - (((90 + latitude) / 180) * mapHeight)) + offsetY;
    
    return position;
    
    }
    

    有些人不应该在半夜编码,然后去 SO 寻求忙碌的人的帮助,意外的是我将转换后的坐标传递给了方法。

    当我注意到在对不同城市进行地理编码时,我得到了非常相似的结果时,我发现了这一点,然后我阅读了 hic3456 的帖子,突然觉得这很有意义。

    我从一个单独的类记录并测试坐标和距离,以便在将错误数据传递给方法之前记录所有内容。

    现在我真的希望我以外的其他人也能从中受益。

    再次抱歉,谢谢大家。

    【讨论】:

      【解决方案5】:

      好吧,如果我正确理解了这个问题,那么您并没有考虑地球的曲率。余弦定律适用于平面,而不适用于球体。例如:如果你飞行,北极和南极相距约 20,000 公里,但如果你挖隧道,则只有约 6000 公里;)

      问候,阿里

      【讨论】:

      • 我相信他的结果太大了,而不是太小了。
      • 感谢 Ari 出于我的目的和对精度的有限需求,我在公式末尾乘以地球的半径 R 来解释曲率。
      猜你喜欢
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 2014-08-21
      • 2017-09-15
      • 1970-01-01
      相关资源
      最近更新 更多