MKMapView - Zoom to fit nearest annotations around userlocation

I want to zoom my mapview to show atleast one annotation of the nearest annotations, with highest possible zoom, and the user location. I have tried the following:

-(void)zoomToFitNearestAnnotationsAroundUserLocation {


    MKMapPoint userLocationPoint = MKMapPointForCoordinate(self.restaurantsMap.userLocation.coordinate);
    MKCoordinateRegion region;
    if ([self.restaurantsMap.annotations count] > 1) {

        for (id<MKAnnotation> annotation in self.restaurantsMap.annotations) {

          MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
          CLLocationDistance distanceBetweenAnnotationsAndUserLocation = MKMetersBetweenMapPoints(annotationPoint, userLocationPoint);


             region =  MKCoordinateRegionMakeWithDistance(self.restaurantsMap.userLocation.coordinate, distanceBetweenAnnotationsAndUserLocation, distanceBetweenAnnotationsAndUserLocation);


        }

        [self.restaurantsMap setRegion:region animated:YES];

    }



}

How would I manage to save 2-3 of the nearest distances and make a region based on that info?

Upvotes: 1

Views: 5348

Answers (2)

Julio Montoya
Julio Montoya

Reputation: 1614

Store your annotations in an Array

Add this function and change the distance as you need

- (MKCoordinateRegion)regionForAnnotations:(NSArray *)annotations
{
MKCoordinateRegion region;

if ([annotations count] == 0)
{
    region = MKCoordinateRegionMakeWithDistance(_mapView.userLocation.coordinate, 1000, 1000);
}

else if ([annotations count] == 1)
{
    id <MKAnnotation> annotation = [annotations lastObject];
    region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 1000, 1000);
} else {
    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;

    for (id <MKAnnotation> annotation in annotations)
    {
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
    }

    const double extraSpace = 1.12;
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) / 2.0;
    region.center.longitude = topLeftCoord.longitude - (topLeftCoord.longitude - bottomRightCoord.longitude) / 2.0;
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * extraSpace;
    region.span.longitudeDelta = fabs(topLeftCoord.longitude - bottomRightCoord.longitude) * extraSpace;
}

return [self.mapView regionThatFits:region];
}

and call it like this

 MKCoordinateRegion region = [self regionForAnnotations:_locations];
[self.mapView setRegion:region animated:YES];

Now the zoom should fit all annotations in the array

Good Luck!!

Upvotes: 2

Gad
Gad

Reputation: 2877

If you're developing for iOS 7 and above you could just save an array of annotations sorted by the distance between the user's location and the annotation, then take the first 3 annotations. Once you have those you can use showAnnotations:animated: which will position the map so that all of the annotations are visible.

Here's another way (taken from here):

MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations)
{
    MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
    MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
    zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
[mapView setVisibleMapRect:zoomRect animated:YES];

//You could also update this to include the userLocation pin by replacing the first line with
MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);

Of course you'll have to update the second solution to use only the closest annotation points but you already know how to find those so that shouldn't be a problem.

Upvotes: 3

Related Questions