Comment comparer deux CLLocationCoordinate2D? (iPhone / iPad)

J’ai besoin d’un moyen de comparer deux CLLocationCoordinate2D mais quand j’ai essayé d’utiliser == cela ne fonctionnerait pas. S’il vous plaît quelqu’un peut-il m’aider avec la meilleure façon de les comparer?

Soit l’approche générique pour comparer deux instances d’un type de structure donné:

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

ou

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

devrait fonctionner, si vous voulez vraiment être sûr qu’ils sont exactement égaux. Cependant, étant donné que la latitude et la longitude sont définies comme doubles, vous pouvez vraiment vouloir faire une comparaison “suffisamment proche”:

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

epsilon correspond au niveau d'erreur que vous souhaitez accepter.

Comme un petit ajout à toutes ces réponses, il est très pratique de définir la comparaison en tant que préprocesseur pour définir:

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

ou avec 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) 

Cela vous permet de faire une comparaison comme suit:

 CLLocationCoordinate2D resultingCoordinate = ... a method call ...; CLLocationCoordinate2D expectedCoordinate = CLLocationCoordinate2DMake(48.11, 11.12); if(CLCOORDINATES_EQUAL( resultingCoordinate, expectedCoordinate)) { NSLog(@"equal"); } else { NSLog(@"not equal"); } 

Une autre alternative consiste à utiliser une méthode en ligne, si vous n'aimez pas le préprocesseur.

Une extension Swift:

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

[testé à partir de Xcode 7.3.1, Swift 2.2] [et, bien sûr, présente toujours le danger insortingnsèque de comparer des valeurs à virgule flottante, vous pouvez donc envisager d’utiliser epsilon comme mentionné dans les réponses précédentes]

Vous pouvez utiliser la classe CLLocation ‘distanceFromLocation: method. La valeur de retour est une CLLocationDistance , qui est vraiment un double.

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

Vous pouvez définir une fonction qui ressemble à celle de CoreLocation:

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

Dans Swift 3, DBL_EPSILON est obsolète. Utilisez Double.ulpOfOne .

 extension CLLocationCoordinate2D { func isEqual(_ coord: CLLocationCoordinate2D) -> Bool { return (fabs(self.latitude - coord.latitude) < .ulpOfOne) && (fabs(self.longitude - coord.longitude) < .ulpOfOne) } } 
 CLLocationCoordinate2D c1, c2; if (c1.latitude == c2.latitude && c1.longitude == c2.longitude) { // ... } 

Je ne plaisante pas. CLLocationCoordinate2D est une structure C, et il n’y a pas de moyen facile de comparer les structures C, en plus de comparer les membres individuels.

CLLocationCoordinate2D est une structure C, vous devez donc comparer ses champs:

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

Notez CLLocationCoordinate2D champs CLLocationCoordinate2D sont double . Vous pouvez donc rencontrer les mêmes problèmes que pour toute autre comparaison en virgule flottante. Ainsi, je suggère de arrondir un peu les valeurs, par exemple:

 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 } 

Oui, le code est plus lent, mais cela peut vous aider à éviter les problèmes causés par une précision moins parfaite des nombres à virgule flottante.

Vous pouvez CLLocationCoordinate dans une NSValue utilisant cette fonction + (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinate

Et puis utilisez isEqualToValue pour comparer.

Citation de doc Apple de la fonction isEqualToValue :

La classe NSValue compare le type et le contenu de chaque object de valeur pour déterminer l’égalité.

Ref: doc Apple de NSValue

Nous pouvons convertir la latitude et la longitude en NSSsortingng et faire une comparaison de chaîne.

 + (BOOL)isEqualWithCoordinate:(CLLocationCoordinate2D)location1 withAnotherCoordinate:(CLLocationCoordinate2D)location2{ NSSsortingng *locationSsortingng1 = [NSSsortingng ssortingngWithFormat:@"%g, %g", location1.latitude, location1.longitude]; NSSsortingng *locationSsortingng2 = [NSSsortingng ssortingngWithFormat:@"%g, %g", location2.latitude, location2.longitude]; if ([locationSsortingng1 isEqualToSsortingng:locationSsortingng2]) { return YES; }else{ return NO; } 

}

Puisque% g convertira le nombre décimal tronqué en 4 chiffres.