I need to fit a certain bounds within a map. I get the bounds from calling the google geocoder and reading the viewport property which looks like:
{
northeas
If your bounds can span the 180th meridian, you have to account for that in the conversion:
- (MKMapRect) mapRectThatFitsBoundsSW:(CLLocationCoordinate2D)sw
NE:(CLLocationCoordinate2D)ne
{
MKMapPoint pSW = MKMapPointForCoordinate(sw);
MKMapPoint pNE = MKMapPointForCoordinate(ne);
double antimeridianOveflow =
(ne.longitude > sw.longitude) ? 0 : MKMapSizeWorld.width;
return MKMapRectMake(pSW.x, pNE.y,
(pNE.x - pSW.x) + antimeridianOveflow,
(pSW.y - pNE.y));
}
But beware those MKMapRect
s that span the anitmeridian, because they come from the land where the dragons live. If you want to learn about some of the dangers that lie there, have a look at
MKMapRect and displaying map overlays that span 180th meridian. You have been warned!
I found something that works. I ended up going with this:
- (MKMapRect) mapRectThatFitsBoundsSW:(CLLocationCoordinate2D)sw
NE:(CLLocationCoordinate2D)ne {
MKMapPoint nePoint = MKMapPointForCoordinate(ne);
MKMapPoint swPoint = MKMapPointForCoordinate(sw);
CGFloat width = ABS(nePoint.x - swPoint.x);
CGFloat height = ABS(nePoint.y - swPoint.y);
MKMapRect newMapRect = MKMapRectMake(
MIN(swPoint.x, nePoint.x),
MIN(swPoint.y, nePoint.y),
width,
height
);
// if (!MKMapRectSpans180thMeridian(newMapRect)) {
return newMapRect;
// } else {
// ????
// }
}
There are several ways to do this.
You could create an MKCoordinateRegion
by figuring out the center
point and then the span
is the absolute difference in degrees between the corners.
Or you could create an MKMapRect
by using the MapKit function MKMapPointForCoordinate
. To get the origin
, figure out the northwest coordinate and convert it to an MKMapPoint
. To get the width
and height
, get the absolute difference in mappoints between the corners (convert the corners from coordinates to MKMapPoint
s using the function first).
Another quick way is a slight trick using the MKMapRectUnion
function. Create a zero-size MKMapRect
from each coordinate and then merge the two rects into one big rect using the function:
MKMapPoint swPoint = MKMapPointForCoordinate(SWCoordinate);
MKMapRect swRect = MKMapRectMake(swPoint.x, swPoint.y, 0, 0);
MKMapPoint nePoint = MKMapPointForCoordinate(NECoordinate);
MKMapRect neRect = MKMapRectMake(nePoint.x, nePoint.y, 0, 0);
MKMapRect rect = MKMapRectUnion(swRect, neRect);
Remember that the map view will still make its own adjustments to the rect you request based on the proportions of the map view and the required zoom. (If you want to know what that adjusted rect will be, call the map view's mapRectThatFits:
method.)