How can I compare CLLocationCoordinate2D

25,366

Solution 1

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

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

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

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

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

Share:
25,366
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    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?

  • joerick
    joerick about 12 years
    The first might be considered sketchy, since you're making the assumption that the struct is packed without any bytes between the members.
  • Glenn
    Glenn about 12 years
    Good point. If you zero the entire struct when it's created/allocated then the memcmp approach is safe even for non-packed structs, but otherwise, use with caution.
  • Shmidt
    Shmidt almost 12 years
    @Glenn can you please fix abs to fabs and < to <=.
  • Glenn
    Glenn almost 12 years
    Good suggestions, @Flink. Done.
  • user4951
    user4951 over 11 years
    what do you mean by zero the entire struct? And what do you mean that struct is packed without any bytes between the members? you mean it may not even be the case>?
  • devios1
    devios1 almost 11 years
    I'm having trouble getting this to work for exactly equal locations and can't figure out what I'm doing wrong. See my question at stackoverflow.com/questions/18200609/…
  • DanSkeel
    DanSkeel over 10 years
    Never compare floating point numbers with ==. See answers where people use epsilon.
  • Klaas
    Klaas over 10 years
    @DanSkeel See my edited answer. Sometimes you have a use case where you want to compare exact coordinates. E.g. if the source for the coordinates is a place database and you only want to compare those. Then there is no need for a range for the equal comparison. So you might think about your down vote again.
  • DanSkeel
    DanSkeel over 10 years
    You didn't get my point. Imagine the case when 1 != 0.99999999999 ... It's general rule for any floating point comparison. Read about it. This rule is old as a computer.
  • Klaas
    Klaas over 10 years
    I still don't get your point. If the source of your coordinates is e.g. a database and you don't do any computations with the coordinates it is just fine to use a regular == comparison.
  • DanSkeel
    DanSkeel over 10 years
    But some one computed that coordinates. You mean that all that float coordinates were set manually by some person? Not a computer?
  • Klaas
    Klaas over 10 years
    Im my case I let the user choose a location and save the coordinates into my database. From that point on the coordinates are fixed and will never change. To to syncing between multiple devices I need the exact coordinates, because the user could create two locations that are very close to each other.
  • mvanallen
    mvanallen over 9 years
    upvoted as this is the most maintainable solution IMO
  • iLearner
    iLearner about 8 years
    Good solution. Here is the complete method just for new bee. -(BOOL)compairLastSavedCoordinates:(CLLocationCoordinate2D )coordinate1 withNewCoordinates:(CLLocationCoordinate2D)coordinate2 { return (coordinate1.latitude == coordinate2.latitude) && (coordinate1.longitude == coordinate2.longitude); }
  • CouchDeveloper
    CouchDeveloper about 8 years
    Never compare floating point numbers! If you do, it's unreliable. In practice, most comparisons from real locations generated by different sources will return false - even if they are pretty close to each other and can be considered "equal".
  • CouchDeveloper
    CouchDeveloper about 8 years
    The first approach is a completely unreliable approach. The second is difficult to use correctly. Why not just calculate the distance and compare the result with a minimum value where two locations are considered "equal"?
  • leanne
    leanne over 5 years
    Just a late clarification on the earlier comments here: the issue is how the coordinates are stored. Latitude and longitude are Double values by default. Double values are rarely exact in a computer. If the user enters a latitude, say, of 38.627003, there's no guarantee that the computer will store exactly 38.627003. A recent test printing a computer's interpretation to 15 decimal places returned a value of 38.627002716064453! Now, if you retrieve and store the user's response as a String, then the result would be exact - but remember the default is Double.
  • Frank Mancini
    Frank Mancini over 4 years
    fyi, sizeof is now undefined