How can I compare CLLocationCoordinate2D

Core LocationCllocationEquatable

Core Location Problem Overview


I need a way of comparing two CLLocationCoordinate2D's however when I tried using == it wouldn't work. Please can someone help me out with the best way of comparing them?

Core Location Solutions


Solution 1 - Core Location

Either the generic approach for comparing two instances of any given struct type:

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

or

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

should work, if you really want to be sure they're exactly equal. However, given that latitude and longitude are defined as doubles, you might really want to do a "close enough" comparison:

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

where epsilon is whatever level of error you want to accept.

Solution 2 - Core Location

As a small addition to all these answers, it's quite handy to have the comparison defined as a preprocessor define:

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

or with 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)

This allows you to do a comparison as follows:

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

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

Another alternative is to use an inline method, if you don't like the preprocessor.

Solution 3 - Core Location

A Swift extension:

import MapKit

extension CLLocationCoordinate2D: Equatable {}

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

[tested as of Xcode 7.3.1, Swift 2.2] [and, of course, still has the intrinsic danger of comparing floating point values, so you might want to consider using epsilon as mentioned in earlier answers]

Solution 4 - Core Location

You can use the CLLocation class' distanceFromLocation: method. The return value is a CLLocationDistance, which is really just a double.

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location

Solution 5 - Core Location

You could define a function which feels pretty like coming from CoreLocation:

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

Solution 6 - Core Location

In Swift 3, DBL_EPSILON is deprecated. Use Double.ulpOfOne.

extension CLLocationCoordinate2D {
    func isEqual(_ coord: CLLocationCoordinate2D) -> Bool {
        return (fabs(self.latitude - coord.latitude) < .ulpOfOne) && (fabs(self.longitude - coord.longitude) < .ulpOfOne)
    }
}

Solution 7 - Core Location

Updated for Swift 5 based on leann's answer.

import CoreLocation

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

Solution 8 - Core Location

CLLocationCoordinate2D c1, c2;
if (c1.latitude == c2.latitude && c1.longitude == c2.longitude)
{
    // ...
}

I'm not kidding. CLLocationCoordinate2D is a C struct, and there's no easy way to compare C structs, apart from comparing the individual members.

Solution 9 - Core Location

CLLocationCoordinate2D is a C struct, thus, you need to compare its fields:

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

Note, CLLocationCoordinate2D fields are double, thus, you may get the same issues like with any other floating point comparison. Thus, I suggest to round a little bit values, e.g.:

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
}

Yes, this, code is slower, but this may help you to avoid problems caused by not so perfect precision of floating point numbers.

Solution 10 - Core Location

You can wrap CLLocationCoordinate into an NSValue using this function + (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinate

And then use isEqualToValue to compare.

Quote from Apple doc of isEqualToValue function:

> The NSValue class compares the type and contents of each value object to determine equality.

Ref: Apple doc of NSValue

Solution 11 - Core Location

We can convert latitude and longitude to NSString and do a string compare.

+ (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;
}

}

Since %g will convert truncate decimal number to 4 digit.

Solution 12 - Core Location

Swift 5.3 way

I've created a gist

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
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser843337View Question on Stackoverflow
Solution 1 - Core LocationGlennView Answer on Stackoverflow
Solution 2 - Core LocationKlaasView Answer on Stackoverflow
Solution 3 - Core LocationleanneView Answer on Stackoverflow
Solution 4 - Core LocationGreg M. KrsakView Answer on Stackoverflow
Solution 5 - Core LocationAlbert SchulzView Answer on Stackoverflow
Solution 6 - Core LocationRyanView Answer on Stackoverflow
Solution 7 - Core LocationAdrianView Answer on Stackoverflow
Solution 8 - Core LocationjoerickView Answer on Stackoverflow
Solution 9 - Core LocationAleksejs MjaliksView Answer on Stackoverflow
Solution 10 - Core LocationRaymondView Answer on Stackoverflow
Solution 11 - Core LocationSaifView Answer on Stackoverflow
Solution 12 - Core LocationNike KovView Answer on Stackoverflow