Convert Mkcoordinateregion to Mkmaprect

Convert MKCoordinateRegion to MKMapRect

To add another implementation to the pile:

- (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region
{
MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude + region.span.latitudeDelta / 2,
region.center.longitude - region.span.longitudeDelta / 2));
MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude - region.span.latitudeDelta / 2,
region.center.longitude + region.span.longitudeDelta / 2));
return MKMapRectMake(MIN(a.x,b.x), MIN(a.y,b.y), ABS(a.x-b.x), ABS(a.y-b.y));
}

NB: There are many ways to convert between MKMapRect and MKCoordinateRegion. This one certainly is not the exact inverse of MKCoordinateRegionMakeWithDistance(), but approximates it fairly well. So, be careful converting back and forth, because information can be lost.

Converting MKMapRect.origin to longitude and latitude

let rect = mapView.visibleMapRect
let mapPoint = MKMapPointMake(rect.origin.x, rect.origin.y)
let coordinate = MKCoordinateForMapPoint(mapPoint)
print(coordinate.latitude)
print(coordinate.longitude)

Converting a view from MKMapKit to a region

According to the Apple documentation, convert:toRegionFrom: method:

Converts a rectangle in the specified view’s coordinate system to a
map region.

Parameters

rect
The rectangle you want to convert.

view The view that serves as the reference coordinate system for the
rect parameter.

So you really need to specify the view for which you provide the coordinates as the second parameter, not the map view :)

So, I believe if you pass in the frame for the radar as the first parameter, you should pass the radar view's parent as the second parameter and that should (theoretically) work.

Basically, if view is the parent view of which map (the MKMapView instance) and radar (the radar view) are children, I tried the following code:

let frame = radar.frame
let radarRegion = map.convert(frame, toRegionFrom:view)
map.setRegion(radarRegion, animated:true)

Before the above code was executed, this is what the screen looked like:

Sample Image

And after the above code runs:

Sample Image

The basic region is correct though there is a little bit of shifting up.

If this is not what you were expecting with regards to the region selected by the radar view, could you please explain what I might be missing?

What's the difference between MKMapRect and MKCoordinateRegion

A MKCoordinateRegion is defined using degrees coordinate of type CLLocationCoordinate2D which represents the latitude and longitude of a point on the surface of the globe.

MKMapRect represents an actual flat rectangle defined with view coordinate (x, y) on your map view.

You can use functions to do conversions for you like MKCoordinateRegionForMapRect

See http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MapKitFunctionsReference/Reference/reference.html

And to answer your final question, you would use MKCoordinateRegion which will define what region of the globe's surface you want to see and by definition it will set your zoom level.

Convert MKMapRect to CGRect

The map view has the convertRegion:toRectToView: method which takes an MKCoordinateRegion and converts it to a CGRect relative to the specified view.

If you have an MKMapRect, first convert it to an MKCoordinateRegion using the MKCoordinateRegionForMapRect function and then call convertRegion:toRectToView:.

Example:

MKCoordinateRegion mkcr = MKCoordinateRegionForMapRect(someMKMapRect);

CGRect cgr = [mapView convertRegion:mkcr toRectToView:self.view];


Remember that although the MKMapRect for some fixed area will not change as the map is zoomed or panned, the corresponding CGRect will vary in its origin and size.

How to create an MKMapRect given two points, each specified with a latitude and longitude value?

This should do it:

// these are your two lat/long coordinates
CLLocationCoordinate2D coordinate1 = CLLocationCoordinate2DMake(lat1,long1);
CLLocationCoordinate2D coordinate2 = CLLocationCoordinate2DMake(lat2,long2);

// convert them to MKMapPoint
MKMapPoint p1 = MKMapPointForCoordinate (coordinate1);
MKMapPoint p2 = MKMapPointForCoordinate (coordinate2);

// and make a MKMapRect using mins and spans
MKMapRect mapRect = MKMapRectMake(fmin(p1.x,p2.x), fmin(p1.y,p2.y), fabs(p1.x-p2.x), fabs(p1.y-p2.y));

this uses the lesser of the two x and y coordinates for your start point, and calculates the x/y spans between the two points for the width and height.

How can I expand a MKMapRect by a fixed percentage?

In iOS7, rectForMapRect: and mapRectForRect: has been deprecated and now are part of the MKOverlayRenderer class. I'd rather recommend to use the MapView mapRectThatFits: edgePadding: methods. Here is a sample code :

MKMapRect visibleRect = self.mapView.visibleMapRect;
UIEdgeInsets insets = UIEdgeInsetsMake(50, 50, 50, 50);
MKMapRect biggerRect = [self.mapView mapRectThatFits:visibleRect edgePadding:insets];

latest Swift for 2017...

func updateMap() {

mkMap.removeAnnotations(mkMap.annotations)
mkMap.addAnnotations(yourAnnotationsArray)

var union = MKMapRectNull

for p in yourAnnotationsArray {
// make a small, say, 50meter square for each
let pReg = MKCoordinateRegionMakeWithDistance( pa.coordinate, 50, 50 )
// convert it to a MKMapRect
let r = mkMapRect(forMKCoordinateRegion: pReg)

// union all of those
union = MKMapRectUnion(union, r)

// probably want to turn on the "sign" for each
mkMap.selectAnnotation(pa, animated: false)
}

// expand the union, using the new #edgePadding call. T,L,B,R
let f = mkMap.mapRectThatFits(union, edgePadding: UIEdgeInsetsMake(70, 0, 10, 35))

// NOTE you want the TOP padding much bigger than the BOTTOM padding
// because the pins/signs are actually very tall

mkMap.setVisibleMapRect(f, animated: false)

}


Related Topics



Leave a reply



Submit