【问题标题】:CLLocation distanceFromLocation result is differ when I calculate计算时 CLLocation distanceFromLocation 结果不同
【发布时间】:2023-12-10 12:46:02
【问题描述】:

我使用了 CLLocation 的 distanceFromLocation: 方法来计算与某个位置的距离。

但是当我使用“Haversine公式”计算时,结果略有不同。

- (CLLocationDistance)distanceFromCoordinate:(CLLocationCoordinate2D)fromCoord {
  double earthRadius = 6371.0; // Earth's radius in Kilometers

  // Get the difference between our two points then convert the difference into radians
  double nDLat = RADIANS((fromCoord.latitude - self.coordinate.latitude));
  double nDLon = RADIANS((fromCoord.longitude - self.coordinate.longitude));

  double fromLat = RADIANS(self.coordinate.latitude);
  double toLat =  RADIANS(fromCoord.latitude);

  double nA = pow ( sin(nDLat/2.0), 2 ) + cos(fromLat) * cos(toLat) * pow ( sin(nDLon/2.0), 2 );

  double nC = 2.0 * atan2( sqrt(nA), sqrt( 1 - nA ));
  double nD = earthRadius * nC;

  return nD * 1000.0;
}


CLLocation * loc = [[CLLocation alloc] initWithLatitude:[location.latitude doubleValue]
                                                           longitude:[location.longitude doubleValue]];

CLLocationDistance dist = [userLocation distanceFromLocation:loc];
CLLocationDistance dist2 = [userLocation distanceFromCoordinate:loc.coordinate];

为什么两个值不同?

我应该用horizo​​ntalAccuracy和verticalAccuracy初始化位置对象吗?

【问题讨论】:

  • 您有没有找到使distanceFromLocation 匹配Haversine 公式的方法?我遇到了同样的问题。

标签: ios objective-c distance core-location cllocation


【解决方案1】:

使用官方 WGS84 地球半径: 6 378 137 米

我记得 ios 提供的结果完全相同。

我应该用 Horizo​​ntalAccuracy 和 垂直精度?

不,当然不是。这些属性暗示了该位置的准确性。
距离仅按纬度和经度计算。

公式不多:
- 半正弦公式(比余弦定律慢一点,否则很好)
- 余弦定律(如果不使用 64 位精度,小距离上会出现问题)
- 我更准确的 vicenties,它使用椭球地球模型。

【讨论】:

  • 我用 distanceFromLocation: 方法和以上公式的距离计算了地球半径。结果似乎很奇怪,因为我得到了两个结果。 6367.150394 6381.907010 我认为苹果不使用“Haversine 公式”,他们有自己的算法。所以我必须找到另一个公式或直接使用它。
  • 那是 6367.15 米还是公里?只需使用它就可以了,尝试更接近现实的距离。那么差异就是千分之一毫米。然而,公式并不多:Greater Circle、Haversine 和 Vicenties。
【解决方案2】:

我也遇到了同样的问题...所以我使用谷歌网络服务来计算距离。使用这种方法,你会得到准确的距离

-(void)calculateDistance()
{
//http://maps.googleapis.com/maps/api/directions/json?origin=41.742964,-87.995971&   destination=41.811511,-87.967923&mode=driving&sensor=false
NSString *LocationUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@,%@&destination=%@,%@&mode=driving&sensor=false",origin.latitude,origin.longitude,destination.latitude,destination.latitude];
NSLog(@"Location URL:%@",LocationUrl);

NSURL *finalurl = [NSURL URLWithString: LocationUrl];

NSLog(@"Final URL = %@",finalurl);

NSData *data = [NSData dataWithContentsOfURL:finalurl];
NSLog(@"Data:-%@",data);
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data       
options:kNilOptions error:&error];

// NSLog(@"josn data of location:%@",[json description]);
NSMutableDictionary *routes = [json objectForKey:@"routes"];
NSMutableArray *legs = [routes valueForKey:@"legs"];
NSMutableDictionary *newDistance =[legs valueForKey:@"distance"];
NSMutableArray distanceList =[[newDistance valueForKey:@"text"]objectAtIndex:0];
distance = [[distanceList objectAtIndex:0]floatValue];
NSLog(@"%.1f",distance);
}

希望对你有帮助

【讨论】:

  • 我同意@AlexWien
  • 另外,我相信这个答案是在谈论 driving 距离,而问题是在谈论 straight line 距离。
【解决方案3】:

略有不同,因为地球半径不准确6371公里。使用正确的地球半径,可能会得到更好的结果。

【讨论】:

    【解决方案4】:

    您的结果不同,因为您使用了不同的代码。

    你没有说有多么不同。 完全不同?您的代码中有一个错误。 靠近的地方差异很大?也许您的公式存在舍入错误的问题。 随着地方的距离越来越远,差异会越来越大?也许你对距离的定义不同。应该是沿地球表面的路径上的最近距离。

    一般来说,地球不是一个球体,而是一个球体。考虑到这一点更困难,但会给出更精确的结果。

    【讨论】: