3

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

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

我对 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

4

5 回答 5

4

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

给定这两个位置,您将创建一个球面三角形,角 A 在阿姆斯特丹,B 在迪拜,C 在北极,边 a = 90° - φ Ams,b = 90° - φ Dub,角 C = Δλ = λ配音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 φ配音。余弦Δλ

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


将此应用于您的数据:

Dubai:φ Dub = 25.248665°N , λ Dub = 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 公里。它说它使用的位置数据与您指定的值相当,维基百科确认您提供的半径。这是相当接近的——在计算中使用相同的坐标和更多的数字重做计算会产生更好的答案,但接近这个答案。


于 2010-01-13T02:01:18.703 回答
3

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

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

于 2010-01-13T00:33:09.400 回答
2

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

于 2010-01-13T01:50:21.167 回答
1

伙计们,我很抱歉 :( 脸红了。我对这些坐标进行了一些其他计算。我计算了他们的 (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 的帖子,突然觉得这很有意义。

我记录并测试了来自单独类的坐标和距离,因此在将错误数据传递给方法之前记录了所有内容。

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

再次抱歉,感谢你们每一个人。

于 2010-01-13T02:30:21.507 回答
0

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

问候,阿里

于 2010-01-13T00:50:17.870 回答