5

I add a MKCircle overlay to my mapview and I want to know if a point (tap in screen) is inside the circle. This is my code :

- (BOOL)pointInsideOverlay:(CLLocationCoordinate2D )tapPoint overlay:(id<MKOverlay>)overlay  {

   BOOL isInside = FALSE;
   MKPolygonView *polygonView = (MKPolygonView *)[self.mapView viewForOverlay:overlay];
   MKMapPoint mapPoint = MKMapPointForCoordinate(tapPoint);
   CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];
   BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);

   if (mapCoordinateIsInPolygon) {
       isInside = TRUE;
   }
   return isInside;
}

viewForOverlay, pointForMapPoint & path are deprecated. Is this the problem?

Thank you.

Hari
  • 1,509
  • 15
  • 34
aminovic09
  • 81
  • 1
  • 6
  • For a circle, you don't need to use CGPathContainsPoint (but for polygons in iOS 7, see http://stackoverflow.com/questions/19014926/detecting-a-point-in-a-mkpolygon-broke-with-ios7-cgpathcontainspoint). As the answer says, you can just check if distance from center is less than or equal to the radius. However, instead of using the Pythagorean (flat) distance, you may want to use CLLocation's distanceFromLocation method or MapKit's MKMetersBetweenMapPoints function which account for the Earth's curved surface. –  Mar 30 '14 at 12:45
  • Thank you. I use distanceFromLocation to do it. Thank s a lot :) – aminovic09 Mar 30 '14 at 13:57

3 Answers3

11

This apporach should work too, using MKCircleRenderer :

    MKCircleRenderer *circleRenderer = (MKCircleRenderer *)[mapview rendererForOverlay:circleOverlay];
    [circleRenderer invalidatePath];

    MKMapPoint mapPoint = MKMapPointForCoordinate(tapPoint);
    CGPoint circlePoint = [circleRenderer pointForMapPoint:mapPoint];
    BOOL mapCoordinateIsInCircle = CGPathContainsPoint(circleRenderer.path, NULL, circlePoint, NO);

    if ( mapCoordinateIsInCircle )

    {
        //do something
    }
Hari
  • 1,509
  • 15
  • 34
0

If you know the centre of the circle and the radius then you could do something like...

-(BOOL)isPoint:(CGPoint)point insideCircleCentre:(CGPoint)centre radius:(CGFloat)radius
{
    CGFloat dx = point.x - centre.x;
    CGFloat dy = point.y - centre.y;

    CGFloat distance = sqrtf(dx * dx + dy * dy);

    return distance <= radius;
}
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • 2
    Thank you. I use distanceFromLocation to do it -(BOOL)isPoint:(CLLocationCoordinate2D)point insideCircleCentre:(CLLocationCoordinate2D)centre radius:(CGFloat)radius { CLLocation *pointALocation = [[CLLocation alloc] initWithLatitude:point.latitude longitude:point.longitude]; CLLocation *pointBLocation = [[CLLocation alloc] initWithLatitude:centre.latitude longitude:centre.longitude]; double distanceMeters = [pointALocation distanceFromLocation:pointBLocation]; if (distanceMeters > radius) { return NO; } else { return YES; } } – aminovic09 Mar 30 '14 at 13:56
0

Fogmeisters answer is incorrect because the unit system for expressing the point and radius are different. The point is expressed as degrees and a radius is typically expressed in meters. Aminovic09's answer is correct and is the advisable answer because it levers iOS' own method of distance calculation.

Chris Hatton
  • 787
  • 9
  • 17