Detect If a Point Is Inside a Mkpolygon Overlay

detect if a point is inside a MKPolygon overlay

I created this MKPolygon category in case anyone wants to use it. Seems to work well. You have to account for the interior polygons (i.e. holes in the polygon):

@interface MKPolygon (PointInPolygon)
-(BOOL) pointInPolygon:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView;
@end

@implementation MKPolygon (PointInPolygon)

-(BOOL) pointInPolygon:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
MKMapPoint mapPoint = MKMapPointForCoordinate(point);
MKPolygonView * polygonView = (MKPolygonView*)[mapView viewForOverlay:self];
CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];
return CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO) &&
![self pointInInteriorPolygons:point mapView:mapView];
}

-(BOOL) pointInInteriorPolygons:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
return [self pointInInteriorPolygonIndex:0 point:point mapView:mapView];
}

-(BOOL) pointInInteriorPolygonIndex:(int) index point:(CLLocationCoordinate2D) point mapView: (MKMapView*) mapView {
if(index >= [self.interiorPolygons count])
return NO;
return [[self.interiorPolygons objectAtIndex:index] pointInPolygon:point mapView:mapView] || [self pointInInteriorPolygonIndex:(index+1) point:point mapView:mapView];
}

@end

SwiftUI - how to know if the user location is in a MKPolygon?

I don't see any code that is actually handling the location updates?

Assuming you have implemented that in your LocationManager along the lines of:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let loc = locations.first {
self.location = loc
}
}

Your problematic line would change from:

self.isInArea = MKPolygon(coordinates: model.zona40, count: model.zona40.count).isCoordinateInsidePolyon(coordinate: locationManager)

to:

guard let c2D = self.locationManager.location?.coordinate else {
return
}

self.isInArea = MKPolygon(coordinates: model.zona40, count: model.zona40.count).isCoordinateInsidePolyon(coordinate: c2D)

If you have not already implemented the didUpdateLocations delegate func, take a read through a Core Location tutorial or two.

How to determine if an annotation is inside of MKPolygonView (iOS)

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.

Validate if a latlong is inside a MKPolygon in iOS

The picture shown appears to demonstrate the even-odd fill rule. By specifying FALSE as the final parameter to CGPathContainsPoint you've asked it to apply the winding number rule. Try passing TRUE.

For information on the teo rules see Apple's Quartz documentation, particularly 'Filling a Path' (slightly less than halfway down).

Check if MKPolyline intersects MKPolygon

They both conform to the MKOverlay protocol. You can use the property defined on the protocol called boundingMapRect, and use it on a protocol-defined method called intersectsMapRect. More info here:

http://developer.apple.com/library/ios/#DOCUMENTATION/MapKit/Reference/MKOverlay_protocol/Reference/Reference.html

Check if a point on map lies within an overlay

Well, I figured it out finally. The code above should work as is, except that there is a missing break statement in the loop. The code as is returns only the last checked point of the poly. Inserting a test to mapCoordinateIsInPolygon and then a break statement in the inner loop leaves the loop as soon as the first test is positive, thus giving the correct result. ;-)

Detecting a point in a MKPolygon broke with iOS7 (CGPathContainsPoint)

For some reason (possibly a bug), the path property returns NULL in the current release of iOS 7.

A workaround is to construct your own CGPathRef from the points of the polygon.

With this method, you don't need a reference to the MKPolygonView or the MKPolygonRenderer.

For example:

CGMutablePathRef mpr = CGPathCreateMutable();

MKMapPoint *polygonPoints = myPolygon.points;
//myPolygon is the MKPolygon

for (int p=0; p < myPolygon.pointCount; p++)
{
MKMapPoint mp = polygonPoints[p];
if (p == 0)
CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
else
CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
}

CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
//mapPoint above is the MKMapPoint of the coordinate we are testing.
//Putting it in a CGPoint because that's what CGPathContainsPoint wants.

BOOL pointIsInPolygon = CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE);

CGPathRelease(mpr);

This should work on iOS 6 as well.

However, you may want to do this manual construction only if the overlay view's path property returns NULL.



Related Topics



Leave a reply



Submit