28

I'm trying to calculate if a specific annotation(like the blue circle of the user location) or a MKPinAnnotation is inside an MKPolygon layer on the mapview.

Any advice to achieve this?

Mat
  • 7,613
  • 4
  • 40
  • 56

2 Answers2

39

The following converts the coordinate to a CGPoint in the polygon view and uses CGPathContainsPoint to test if that point is in the path (which may be non-rectangular):

CLLocationCoordinate2D mapCoordinate = ...; //user location or annot coord

MKMapPoint mapPoint = MKMapPointForCoordinate(mapCoordinate);

MKPolygonView *polygonView = 
    (MKPolygonView *)[mapView viewForOverlay:polygonOverlay];

CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];

BOOL mapCoordinateIsInPolygon = 
    CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);

This should work with any overlay view that is a subclass of MKOverlayPathView. You can actually replace MKPolygonView with MKOverlayPathView in the example.

  • 1
    Would this work on MKPolygons with holes (internal polygons)? – Greg Combs Feb 09 '11 at 16:12
  • 7
    @Greg Combs: If the polygon (or overlay path) has holes, CGPathContainsPoint will return NO if the point queried is in a hole. –  Feb 09 '11 at 16:40
  • @AnnaKarenina - how to determine this same mapCoordinateIsInPolygon value for a scenario with MKPolygon but no map view? (because all I have is set of coordinates but no need for a view) – Nirav Bhatt Feb 01 '13 at 10:58
  • How could this be achieved for a MKPolygon in memory, but not on a map? – capikaw Jul 18 '13 at 18:20
  • @capikaw: By creating a CGMutablePathRef as described in comment to NiravBhatt above. An MKPolygon or map is not needed since the key part is CGPathContainsPoint. Create a CGMutablePathRef from the coordinates (use longitude for x value and latitude for the y value). –  Jul 18 '13 at 18:54
  • 2
    In the current release of iOS 7, the `path` property seems to incorrectly return NULL making the above approach fail. For a workaround, see http://stackoverflow.com/questions/19014926/detecting-a-point-in-a-mkpolygon-broke-with-ios7-cgpathcontainspoint. –  Sep 26 '13 at 03:25
  • Is there any solution in IOS7 for this issue? – Jagdev Sendhav Mar 26 '14 at 12:20
  • @UserDev, see the comment above starting with "In the current release of iOS 7...". It gives a link to a workaround. –  Mar 26 '14 at 12:28
  • `[MKPolygonView initWithPolygon]` is deprecated in iOS 7 but can be replaced with `MKPolygonRenderer`. – Trasplazio Garzuglio Jun 25 '14 at 14:46
9

Slightly modified above to do calculations for points/coordinates in polygons without the use of a MKMapView formatted as an extension to MKPolygon class:

//MKPolygon+PointInPolygon.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MKPolygon (PointInPolygon)

-(BOOL)coordInPolygon:(CLLocationCoordinate2D)coord;
-(BOOL)pointInPolygon:(MKMapPoint)point;

@end

//MKPolygon+PointInPolygon.m

#import "MKPolygon+PointInPolygon.h"

@implementation MKPolygon (PointInPolygon)

-(BOOL)coordInPolygon:(CLLocationCoordinate2D)coord {

    MKMapPoint mapPoint = MKMapPointForCoordinate(coord);
    return [self pointInPolygon:mapPoint];
}

-(BOOL)pointInPolygon:(MKMapPoint)mapPoint {

    MKPolygonRenderer *polygonRenderer = [[MKPolygonRenderer alloc] initWithPolygon:self];
    CGPoint polygonViewPoint = [polygonRenderer pointForMapPoint:mapPoint];
    return CGPathContainsPoint(polygonRenderer.path, NULL, polygonViewPoint, NO);
}

@end

Enjoy!

capikaw
  • 12,232
  • 2
  • 43
  • 46