50

我需要一种比较两个的方法,CLLocationCoordinate2D但是当我尝试使用==它时它不起作用。请有人可以帮助我以最好的方式比较它们吗?

4

12 回答 12

59

用于比较任何给定结构类型的两个实例的通用方法:

memcmp(&cllc2d1, &second_cllc2d, sizeof(CLLocationCoordinate2D))

或者

cllc2d1.latitude == cllc2d2.latitude && cllc2d1.longitude == cllc2d2.longitude

如果您真的想确保它们完全相等,应该可以工作。但是,鉴于纬度和经度被定义为双精度,您可能真的想做一个“足够接近”的比较:

fabs(cllc2d1.latitude - cllc2d2.latitude) <= epsilon && fabs(cllc2d1.longitude - cllc2d2.longitude) <= epsilon

epsilon您想接受的任何级别的错误在哪里。

于 2012-04-17T21:10:56.203 回答
34

作为所有这些答案的一个小补充,将比较定义为预处理器定义非常方便:

#define CLCOORDINATES_EQUAL( coord1, coord2 ) (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude)

或使用 epsilon:

#define CLCOORDINATE_EPSILON 0.005f
#define CLCOORDINATES_EQUAL2( coord1, coord2 ) (fabs(coord1.latitude - coord2.latitude) < CLCOORDINATE_EPSILON && fabs(coord1.longitude - coord2.longitude) < CLCOORDINATE_EPSILON)

这使您可以进行如下比较:

CLLocationCoordinate2D resultingCoordinate = ... a method call ...;
CLLocationCoordinate2D expectedCoordinate = CLLocationCoordinate2DMake(48.11, 11.12);

if(CLCOORDINATES_EQUAL( resultingCoordinate, expectedCoordinate)) {
    NSLog(@"equal");
} else {
    NSLog(@"not equal");
}

如果您不喜欢预处理器,另一种选择是使用内联方法。

于 2012-08-16T22:02:31.887 回答
24

一个 Swift 扩展:

import MapKit

extension CLLocationCoordinate2D: Equatable {}

public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
    return (lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude)
}

[从 Xcode 7.3.1、Swift 2.2 开始测试] [当然,仍然存在比较浮点值的内在危险,因此您可能需要考虑使用epsilon前面答案中提到的方法]

于 2016-07-25T22:04:26.370 回答
14

您可以使用CLLocation类的 distanceFromLocation: 方法。返回值是一个CLLocationDistance,它实际上只是一个双精度值。

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
于 2013-10-26T19:10:24.030 回答
9

你可以定义一个感觉很像来自 CoreLocation 的函数:

BOOL CLLocationCoordinateEqual(CLLocationCoordinate2D coordinate1, CLLocationCoordinate2D coordinate2) { return (fabs(coordinate1.latitude - coordinate2.latitude) <= DBL_EPSILON && fabs(coordinate1.longitude - coordinate2.longitude) <= DBL_EPSILON); }

于 2015-02-23T14:30:31.417 回答
8

在 Swift 3 中,DBL_EPSILON已弃用。使用Double.ulpOfOne.

extension CLLocationCoordinate2D {
    func isEqual(_ coord: CLLocationCoordinate2D) -> Bool {
        return (fabs(self.latitude - coord.latitude) < .ulpOfOne) && (fabs(self.longitude - coord.longitude) < .ulpOfOne)
    }
}
于 2017-07-31T16:54:41.287 回答
4

根据leann 的 回答为 Swift 5 更新。

import CoreLocation

extension CLLocationCoordinate2D: Equatable {
    static public func ==(lhs: Self, rhs: Self) -> Bool {
        return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
    }
}
于 2019-10-20T02:29:59.033 回答
2
CLLocationCoordinate2D c1, c2;
if (c1.latitude == c2.latitude && c1.longitude == c2.longitude)
{
    // ...
}

我不是在开玩笑。CLLocationCoordinate2D 是一个 C 结构,除了比较各个成员之外,没有简单的方法来比较 C 结构。

于 2012-04-17T21:09:58.370 回答
1

CLLocationCoordinate2D是一个 C 结构,因此,您需要比较它的字段:

CLLocationCoordinate2D coord1, coord2;
if (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude) {
    // coordinates are equal
}

请注意,CLLocationCoordinate2D字段是double,因此,您可能会遇到与任何其他浮点比较相同的问题。因此,我建议对值进行四舍五入,例如:

CLLocationCoordinate2D coord1, coord2;
if (round(coord1.latitude * 1000.0) == round(coord2.latitude * 1000.0)
    && round(coord1.longitude * 1000.0) == round(coord2.longitude * 1000.0)) {
    // coordinates are equal
}

是的,这个,代码比较慢,但这可以帮助你避免因浮点数精度不那么完美而导致的问题。

于 2012-04-17T21:17:57.877 回答
1

您可以使用此功能包装CLLocationCoordinateNSValue+ (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinate

然后isEqualToValue用来比较。

引用Apple doc of isEqualToValuefunction:

NSValue 类比较每个值对象的类型和内容以确定相等性。

参考:苹果文档NSValue

于 2015-09-23T05:09:59.417 回答
0

我们可以将纬度和经度转换为 NSString 并进行字符串比较。

+ (BOOL)isEqualWithCoordinate:(CLLocationCoordinate2D)location1 withAnotherCoordinate:(CLLocationCoordinate2D)location2{
NSString *locationString1 = [NSString stringWithFormat:@"%g, %g", location1.latitude, location1.longitude];
NSString *locationString2 = [NSString stringWithFormat:@"%g, %g", location2.latitude, location2.longitude];

if ([locationString1 isEqualToString:locationString2]) {
    return YES;
}else{
    return NO;
}

}

由于 %g 会将截断的十进制数转换为 4 位数字。

于 2016-03-16T10:23:07.573 回答
0

斯威夫特 5.3 方式

我创建了一个要点

extension CLLocationCoordinate2D: Equatable {
    public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
        let numbersAfterCommaAccuracy: Double = 4
        let ratio = numbersAfterCommaAccuracy * 10
        let isLatitudeEqual = ((lhs.latitude - rhs.latitude) * ratio).rounded(.down) == 0
        let isLongitudeEqual = ((lhs.latitude - rhs.latitude) * ratio).rounded(.down) == 0
        return isLatitudeEqual && isLongitudeEqual
    }
}
于 2021-04-02T15:17:57.550 回答