Adding polygon map overlays

For an introduction to MapKit, see Ray Wenderlich‘s tutorial post, Introduction to MapKit on iOS.

It’s been a while since I did a mapkit tutorial and I thought it was about time I got back to it. This is going to be a simple one, it’s about adding polygon overlays to a map. Say for instance you want to outline an area or a building. In my case I’m going to mark parking buildings on a map. This way visitors to the area can easily find which buildings have parking.

We’ll start by adding the MapKit and CoreLocation framework to our application. The way to do this changed a little bit in Xcode 4 and it took me a little searching to figure it out. Hopefully this will save you some time…
Xcode 4 Add Framework

The screen shot says it all. Highlight the project in the left pane of Xcode. Click on the project target and then click Build Phases. Look for the “Link Binary With Libraries” section and click the plus sign to add MapKit framework and CoreLocation.

Now add a map to your view in Interface Builder Xcode 4. And lets create the property and synthesize it and don’t forget to include MapKit.h and set this view controller as the MKMapViewDelegate:

PolygonOverlaySampleViewController.h

#import
#import

 

@interface PolygonOverlaySampleViewController : UIViewController {
MKMapView *_myMapView;
}
@property (nonatomic, retain) IBOutlet MKMapView *myMapView;
@end

As usual, the good stuff goes in the .m file. So synthesize the property:

#import "PolygonOverlaySampleViewController.h"

 

@implementation PolygonOverlaySampleViewController

 

 

@synthesize myMapView = _myMapView;

And in viewDidLoad we start some magic:

- (void)viewDidLoad
{
[super viewDidLoad];

 

//Define map view region
MKCoordinateSpan span;
span.latitudeDelta=.01;
span.longitudeDelta=.01;

MKCoordinateRegion region;
region.span=span;
region.center=CLLocationCoordinate2DMake(39.046259, -76.851195);

 

 

[_myMapView setRegion:region animated:YES];
[_myMapView regionThatFits:region];

This basically declares how much of our map to show and where to center it. I’m centering it on my alma mater, Capitol College.

Now we want to add some coordinates to create our polygons. There are two lots at Capitol, one for commuters and then an overflow lot/resident parking. Lets do the commuter parking first because it’s an easy rectangle:

[_myMapView setRegion:region animated:YES];
[_myMapView regionThatFits:region];

 

CLLocationCoordinate2D commuterLotCoords[5]={
CLLocationCoordinate2DMake(39.048019,-76.850535),
CLLocationCoordinate2DMake(39.048027,-76.850234),
CLLocationCoordinate2DMake(39.047407,-76.850181),
CLLocationCoordinate2DMake(39.047407,-76.8505),
CLLocationCoordinate2DMake(39.048019,-76.850535)
};

MKPolygon *commuterPoly1 = [MKPolygon polygonWithCoordinates:commuterLotCoords count:5];
[self.mapView addOverlay:commuterPoly1];
[commuterPoly1 release];

Why are there 5 coordinates for a rectangle? Because you need to close your polygon by connecting it to the opening point at the end.

Now the overflow lot right below the commuterLotCoordinates:

CLLocationCoordinate2D overflowLotCoords[16]={
CLLocationCoordinate2DMake(39.04864351611461,-76.8513227245313),
CLLocationCoordinate2DMake(39.04851710015167,-76.8517540587399),
CLLocationCoordinate2DMake(39.04868674731313,-76.85192728689483),
CLLocationCoordinate2DMake(39.04850095882104,-76.85230365946416),
CLLocationCoordinate2DMake(39.04819087100218,-76.85265260435219),
CLLocationCoordinate2DMake(39.0477370134458,-76.85286078490296),
CLLocationCoordinate2DMake(39.04692851484644,-76.85283202926037),
CLLocationCoordinate2DMake(39.04695987529381,-76.85235192135768),
CLLocationCoordinate2DMake(39.04734847050665,-76.85236298239703),
CLLocationCoordinate2DMake(39.04779491740192,-76.85232236959109),
CLLocationCoordinate2DMake(39.04814366462639,-76.85208905182692),
CLLocationCoordinate2DMake(39.04838024069194,-76.85164072166863),
CLLocationCoordinate2DMake(39.04843331131504,-76.85085998781742),
CLLocationCoordinate2DMake(39.04857547181026,-76.8507923535788),
CLLocationCoordinate2DMake(39.04864351611461,-76.8513227245313)
};

MKPolygon *overflowPoly1 = [MKPolygon polygonWithCoordinates:overflowLotCoords count:15];
[self.mapView addOverlay:overflowPoly1];
[overflowPoly1 release];

 

Where did I get all of those coordinates you ask? Google Earth. You can draw a polygon right on their map and then save the results as a .kml file. Open this file in your favorite text editor and you’ll see the coordinates in there.

Now one last thing, you need to tell the map view how to display those polygons. This is easily done with a delegate method:

-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay{
if([overlay isKindOfClass:[MKPolygon class]]){
MKPolygonView *view = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease];
view.lineWidth=1;
view.strokeColor=[UIColor blueColor];
view.fillColor=[[UIColor blueColor] colorWithAlphaComponent:0.5];
return view;
}
return nil;
}

and voila…
Mapkit Polygon Overlay for iPhone

Download the Polygon Map Overlay sample project here.

In the next MapKit tutorial, I will go over placing parking icons on those lots to clearly identify what they are.

10 Responses to “Adding polygon map overlays”

  1. Sasha Rambles
    May 16, 2011 at 9:33 pm #

    Thank you very much for this. I had been cursing and swearing trying to figure out how to link in the Locations framework in XCode 4 – you did indeed save me some time!

  2. Chris
    September 18, 2011 at 6:26 pm #

    Do you know if it’s possible to style the 2 polygons differently?

    • Shawn Grimes
      September 20, 2011 at 4:41 pm #

      The easiest way would be to set the title of the polygon and then check the title. You could also subclass the MKPolygonOverlay and check the class of each polygon and style them differently. Let me know if that doesn’t make sense and I can go into more detail.

  3. Zaggo
    February 8, 2012 at 6:52 am #

    MKPolygon polygonWithCoordinates already returns an autoreleased object. Releasing the returned object after adding it to the map overreleases it and potentially crashes the app.

    Xcode4′s static analyzer also throws an error on this.

    See Apple’s memory management rules (aka the ownership policy for more information on this.

  4. ChuckM
    July 13, 2012 at 4:14 am #

    The pictures on your website aren’t showing. Any chance you could fix it. I’m loving the mapkit tutorials… I think they’d be more helpful with the pictures, though. Thanks.

    • Leo T
      September 3, 2012 at 6:55 pm #

      The download link for the project doesn’t work. Also, I tried running the code; however, all i get is the map without the polygon shapes. No errors other than xCode not allowing me to release / autorelease. I just deleted those parts of the code. Other changes I made were
      [self.mapView addOverlay:overflowPoly1]; to
      [self.myMapView addOverlay:overflowPoly1];
      Any help would be appreciated

      • Leo T
        September 3, 2012 at 6:57 pm #

        Also, I did some NSLog tests throughout the code and found that xCode doesn’t even run through:
        -(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay{…}
        I’m sure this is the problem for the polygon not showing. Can you help me out? Thanks in advance

        • Leo T
          September 5, 2012 at 9:39 pm #

          Disregard. I fixed it. My delegate just wasn’t set to my map. Thanks

  5. Dylan
    December 21, 2012 at 6:49 am #

    Download link is broken :(

Leave a Reply