How can I compare CLLocationCoordinate2D
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);
}
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on July 09, 2022Comments
-
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 about 12 yearsThe first might be considered sketchy, since you're making the assumption that the struct is packed without any bytes between the members.
-
Glenn about 12 yearsGood 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 almost 12 years@Glenn can you please fix abs to fabs and < to <=.
-
Glenn almost 12 yearsGood suggestions, @Flink. Done.
-
user4951 over 11 yearswhat 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 almost 11 yearsI'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 over 10 yearsNever compare floating point numbers with
==
. See answers where people useepsilon
. -
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 over 10 yearsYou 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 over 10 yearsI 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 over 10 yearsBut some one computed that coordinates. You mean that all that float coordinates were set manually by some person? Not a computer?
-
Klaas over 10 yearsIm 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 over 9 yearsupvoted as this is the most maintainable solution IMO
-
iLearner about 8 yearsGood 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 about 8 yearsNever 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 about 8 yearsThe 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 over 5 yearsJust 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, of38.627003
, there's no guarantee that the computer will store exactly38.627003
. A recent test printing a computer's interpretation to 15 decimal places returned a value of38.627002716064453
! Now, if you retrieve and store the user's response as aString
, then the result would be exact - but remember the default isDouble
. -
Frank Mancini over 4 yearsfyi, sizeof is now undefined