Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone MKMapView: set map region to show all pins on map

I'm trying to set the map region (center and span) so that the map shows all pin-annotations at the same time.

I'm having trouble converting the long/lat coordinates from NSString to double, resp. make calculations with them. Here is the code I'm using:

- (void)updateMemberPins{

//calculate new region to show on map
double center_long = 0.0f;
double center_lat = 0.0f;
double max_long = 0.0f;
double min_long = 0.0f;
double max_lat = 0.0f;
double min_lat = 0.0f;

for (Member *member in members) {
    
    //find min and max values
    if ([member.locLat doubleValue] > max_lat) {max_lat = [member.locLat doubleValue];}
    if ([member.locLat doubleValue] < min_lat) {min_lat = [member.locLat doubleValue];}
    if ([member.locLong doubleValue] > max_long) {max_long = [member.locLong doubleValue];}
    if ([member.locLong doubleValue] < min_long) {min_long = [member.locLong doubleValue];}
    
    //sum up long and lang to get average later
    center_lat = center_lat + [member.locLat doubleValue];
    center_long = center_long + [member.locLong doubleValue];
}

//calculate average long / lat
center_lat = center_lat / [members count];
center_long = center_long / [members count];

NSLog(@"center long: %d, center lat: %d", center_long, center_lat);
NSLog(@"max_long: %d, min_long: %d, max_lat: %d, min_lat: %d", max_long, min_long, max_lat, min_lat);
    
//create new region and set map
CLLocationCoordinate2D coord = {latitude: center_lat, longitude: center_long};
MKCoordinateSpan span = MKCoordinateSpanMake(abs(max_lat) + abs(min_lat), abs(max_long) + abs(min_long));
MKCoordinateRegion region = {coord, span};
[resultMapView setRegion:region];

//remove all pins from map
[resultMapView removeAnnotations:resultMapView.annotations];

//show member pins
for (id member in members) {
    [resultMapView addAnnotation:(Member *) member];
}

}

The result of the log-output is:

center long: -1946827116, center lat: 1075651472

max_long: -6267216, min_long: 1076018553, max_lat: 0, min_lat: 0

I think the problem comes from (wrongly) converting values from NSString to double, however I cannot find a way to make it work... The format of the location-strings is like '43.5686473'.

Any hints? Cheerz

like image 904
pawi Avatar asked Feb 18 '11 10:02

pawi


2 Answers

The final, working code for those looking for something similiar:

    - (void)updateMemberPins{

    //remove all pins from map
    [resultMapView removeAnnotations:resultMapView.annotations];

    if ([members count] > 0) {

        @try {
            //calculate new region to show on map           
            Member *firstMember = [members objectAtIndex:0];
            double max_long = [firstMember.locLong doubleValue];
            double min_long = [firstMember.locLong doubleValue];
            double max_lat = [firstMember.locLat doubleValue];
            double min_lat = [firstMember.locLat doubleValue];

            //find min and max values
            for (Member *member in members) {
                if ([member.locLat doubleValue] > max_lat) {max_lat = [member.locLat doubleValue];}
                if ([member.locLat doubleValue] < min_lat) {min_lat = [member.locLat doubleValue];}
                if ([member.locLong doubleValue] > max_long) {max_long = [member.locLong doubleValue];}
                if ([member.locLong doubleValue] < min_long) {min_long = [member.locLong doubleValue];}
            }

            //calculate center of map
            double center_long = (max_long + min_long) / 2;
            double center_lat = (max_lat + min_lat) / 2;

            //calculate deltas
            double deltaLat = abs(max_lat - min_lat);
            double deltaLong = abs(max_long - min_long);

            //set minimal delta
            if (deltaLat < 5) {deltaLat = 5;}
            if (deltaLong < 5) {deltaLong = 5;}

            //debug
            //NSLog(@"center long: %f, center lat: %f", center_long, center_lat);
            //NSLog(@"max_long: %f, min_long: %f, max_lat: %f, min_lat: %f", max_long, min_long, max_lat, min_lat);

            //create new region and set map
            CLLocationCoordinate2D coord = {latitude: center_lat, longitude: center_long};
            MKCoordinateSpan span = MKCoordinateSpanMake(deltaLat, deltaLong);
            MKCoordinateRegion region = {coord, span};
            [resultMapView setRegion:region];


        }
        @catch (NSException * e) {
            NSLog(@"Error calculating new map region: %@", e);
        }
        @finally {
            //show member pins
            for (id member in members) {
                [resultMapView addAnnotation:(Member *) member];
            }
        }



    }

}
like image 178
pawi Avatar answered Nov 02 '22 22:11

pawi


To show double value in NSLog(), you should use %f, instead of %d Change NSLog() part like this:

NSLog(@"center long: %f, center lat: %f", center_long, center_lat);
NSLog(@"max_long: %f, min_long: %f, max_lat: %f, min_lat: %f", max_long, min_long, max_lat, min_lat);

Also, using region from MKMapView is much simpler than making your own. Once it's set with zoom ratio, all you need is to dynamically move around the map with different coordinates.

MKCoordinateRegion region = self.mapView.region;
region.center = centerCoordinate;
region.span.longitudeDelta /= ratioZoomMax; // Bigger the value, closer the map view
region.span.latitudeDelta /= ratioZoomMax;
[self.mapView setRegion:region animated:YES]; // Choose if you want animate or not
like image 23
petershine Avatar answered Nov 02 '22 22:11

petershine