Search code examples
iphoneiosmkmapviewmkannotationmkoverlay

Creating a MKPolygon from user-placed annotations in map


I want the user to be able to create polygons after placing some (unknown number) MKpointAnnotations in the map.I have put a gesture recognizer that gets activated once the user taps a button, and so annotations are placed.But how to use these as corners for a MKPolygon? Below the code for saving the corners of the polygon.This after some mods I did to it.Now the app crashes and the crash reporter says index out of range.The corners are MKPointAnnotation-s created via a GestureRecognizer.

-(IBAction)addCorner:(id)sender
{
NSMutableArray *addCorners = [[NSMutableArray alloc] init];
[addCorners addObject:pointAnnotation];
ptsArray = addCorners;
}

-(IBAction)addPolygonOverlay:(id)sender
{
int cornersNumber = sizeof(ptsArray);
MKMapPoint points[cornersNumber];

for (int i=0; i<cornersNumber; i++) {
    points[i] = MKMapPointForCoordinate([[ptsArray objectAtIndex:i] coordinate]);
}

MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:cornersNumber];
[mapview addOverlay:polygon];

}

Solution

  • First problem is the addCorner method. Instead of adding each corner to the ptsArray variable, it creates a new array with just the last corner and sets theptsArray equal to that so it only has the one, last corner.

    Change the addCorner method like this:

    -(IBAction)addCorner:(id)sender
    {
        if (ptsArray == nil)
        {
            self.ptsArray = [NSMutableArray array];
        }
    
        [ptsArray addObject:pointAnnotation];
    }
    

    Also make sure ptsArray is declared and synthesized properly:

    //in the .h file...
    @property (nonatomic, retain) NSMutableArray *ptsArray;
    //in the .m file...
    @synthesize ptsArray;
    

    (By the way, why not add the corner to ptsArray right where the pointAnnotation is created instead of in a separate user action?)


    Second problem is in the addPolygonOverlay method. You have to use the NSArray count property to get the number of items in the array. The sizeof function returns the number of bytes of physical memory the passed variable uses. For ptsArray which is a pointer, it will return 4. If the ptsArray has less than 4 items, you will get the "index out of range" exception.

    So change

    int cornersNumber = sizeof(ptsArray);
    

    to

    int cornersNumber = ptsArray.count;
    


    Another important thing to note is that the polygon sides will be drawn in the order the points are in the array. If the user does not add corners in a clockwise or counter-clockwise order, the polygon will look strange. You could re-create the polygon overlay immediately after a user adds/removes an annotation so they get immediate feedback on how it will look.