Comment vérifier si MKCoordinateRegion contient CLLocationCoordinate2D sans utiliser MKMapView?

Je dois vérifier si l'location de l'user appartient à MKCoordinateRegion. J'ai été surpris de ne pas find de fonction simple pour cela, quelque chose comme: CGRectContainsCGPoint (rect, point) .

J'ai trouvé le morceau de code suivant:

CLLocationCoordinate2D topLeftCoordinate = CLLocationCoordinate2DMake(region.center.latitude + (region.span.latitudeDelta/2.0), region.center.longitude - (region.span.longitudeDelta/2.0)); CLLocationCoordinate2D bottomRightCoordinate = CLLocationCoordinate2DMake(region.center.latitude - (region.span.latitudeDelta/2.0), region.center.longitude + (region.span.longitudeDelta/2.0)); if (location.latitude < topLeftCoordinate.latitude || location.latitude > bottomRightCoordinate.latitude || location.longitude < bottomRightCoordinate.longitude || location.longitude > bottomRightCoordinate.longitude) { // Coordinate fits into the region } 

Mais, je ne suis pas sûr si c'est exact que la documentation ne spécifie pas exactement comment le rectangle de la région est calculé.

Il doit y avoir une façon plus simple de le faire. Ai-je négligé certaines fonctions dans la documentation du framework MapKit?

Vous pouvez convertir votre location en un point avec MKMapPointForCoordinate , puis utiliser MKMapRectContainsPoint dans la vue visibleMapRect de visibleMapRect . C'est complètement hors de ma tête. Laissez-moi savoir si cela fonctionne.

Dans le cas où il y a quelqu'un d'autre confus avec les latitudes et les longitues, voici testé, solution de travail:

 MKCoordinateRegion region = self.mapView.region; CLLocationCoordinate2D location = user.gpsposition.coordinate; CLLocationCoordinate2D center = region.center; CLLocationCoordinate2D northWestCorner, southEastCorner; northWestCorner.latitude = center.latitude - (region.span.latitudeDelta / 2.0); northWestCorner.longitude = center.longitude - (region.span.longitudeDelta / 2.0); southEastCorner.latitude = center.latitude + (region.span.latitudeDelta / 2.0); southEastCorner.longitude = center.longitude + (region.span.longitudeDelta / 2.0); if ( location.latitude >= northWestCorner.latitude && location.latitude <= southEastCorner.latitude && location.longitude >= northWestCorner.longitude && location.longitude <= southEastCorner.longitude ) { // User location (location) in the region - OK :-) NSLog(@"Center (%f, %f) span (%f, %f) user: (%f, %f)| IN!", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta, location.latitude, location.longitude); }else { // User location (location) out of the region - NOT ok :-( NSLog(@"Center (%f, %f) span (%f, %f) user: (%f, %f)| OUT!", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta, location.latitude, location.longitude); } 

Je post cette réponse car la solution acceptée n'est pas valide à mon avis. Cette réponse n'est pas non plus parfaite, mais elle gère le cas lorsque les coordonnées enveloppent des limites de 360 ​​degrés, ce qui est suffisant pour convenir à ma situation.

 + (BOOL)coordinate:(CLLocationCoordinate2D)coord inRegion:(MKCoordinateRegion)region { CLLocationCoordinate2D center = region.center; MKCoordinateSpan span = region.span; BOOL result = YES; result &= cos((center.latitude - coord.latitude)*M_PI/180.0) > cos(span.latitudeDelta/2.0*M_PI/180.0); result &= cos((center.longitude - coord.longitude)*M_PI/180.0) > cos(span.longitudeDelta/2.0*M_PI/180.0); return result; } 

Les autres réponses ont toutes des défauts. La réponse acceptée est un peu verbeuse, et échoue près de la ligne de time internationale. La réponse en cosinus est réalisable, mais échoue pour de très petites régions (parce que le cosinus delta est sinusoïdal qui tend vers zéro près de zéro, ce qui signifie que pour des différences angulars plus petites, nous attendons zéro changement).

Rapide:

 /* Standardises and angle to [-180 to 180] degrees */ class func standardAngle(var angle: CLLocationDegrees) -> CLLocationDegrees { angle %= 360 return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle } /* confirms that a region contains a location */ class func regionContains(region: MKCoordinateRegion, location: CLLocation) -> Bool { let deltaLat = abs(standardAngle(region.center.latitude - location.coordinate.latitude)) let deltalong = abs(standardAngle(region.center.longitude - location.coordinate.longitude)) return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong } 

Objectif c:

 /* Standardises and angle to [-180 to 180] degrees */ + (CLLocationDegrees)standardAngle:(CLLocationDegrees)angle { angle %= 360 return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle } /* confirms that a region contains a location */ + (BOOL)region:(MKCoordinateRegion*)region containsLocation:(CLLocation*)location { CLLocationDegrees deltaLat = fabs(standardAngle(region.center.latitude - location.coordinate.latitude)) CLLocationDegrees deltalong = fabs(standardAngle(region.center.longitude - location.coordinate.longitude)) return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong } 

Cette méthode échoue pour les régions qui incluent l'un ou l'autre pôle, mais le système de coordonnées lui-même échoue aux pôles. Pour la plupart des applications, cette solution devrait suffire. (Remarque, non testé sur l'objective C)

J'ai utilisé ce code pour déterminer si une coordonnée est dans une région circulaire (une coordonnée avec un rayon autour d'elle).

 - (BOOL)location:(CLLocation *)location isNearCoordinate:(CLLocationCoordinate2D)coordinate withRadius:(CLLocationDistance)radius { CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:radius identifier:@"radiusCheck"]; return [circularRegion containsCoordinate:coordinate]; } 

Owen Godfrey, le code objective-C ne fonctionne pas, c'est le bon code: échoue sur Objective-C, c'est le bon code:

 /* Standardises and angle to [-180 to 180] degrees */ - (CLLocationDegrees)standardAngle:(CLLocationDegrees)angle { angle=fmod(angle,360); return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle; } -(BOOL)thisRegion:(MKCoordinateRegion)region containsLocation:(CLLocation *)location{ CLLocationDegrees deltaLat =fabs([self standardAngle:(region.center.latitude-location.coordinate.latitude)]); CLLocationDegrees deltaLong =fabs([self standardAngle:(region.center.longitude-location.coordinate.longitude)]); return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >=deltaLong; } CLLocationDegrees deltalong = fabs(standardAngle(region.center.longitude - location.coordinate.longitude)); return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong; } 

Merci!

Basé sur la solution de Lukasz, mais dans Swift, au cas où quelqu'un pourrait utiliser Swift:

 func isInRegion (region : MKCoordinateRegion, coordinate : CLLocationCoordinate2D) -> Bool { let center = region.center; let northWestCorner = CLLocationCoordinate2D(latitude: center.latitude - (region.span.latitudeDelta / 2.0), longitude: center.longitude - (region.span.longitudeDelta / 2.0)) let southEastCorner = CLLocationCoordinate2D(latitude: center.latitude + (region.span.latitudeDelta / 2.0), longitude: center.longitude + (region.span.longitudeDelta / 2.0)) return ( coordinate.latitude >= northWestCorner.latitude && coordinate.latitude <= southEastCorner.latitude && coordinate.longitude >= northWestCorner.longitude && coordinate.longitude <= southEastCorner.longitude ) }