1

I have been trying to work out if a tap gesture is in an overlay polygon, to no avail.

I am trying to make a map of country overlays - on clicking on an overlay I want to be able to tell what country the overlay is of.

First I found this: Detecting touches on MKOverlay in iOS7 (MKOverlayRenderer) and this: detect if a point is inside a MKPolygon overlay which suggest either:

  1. make a tiny rectangle around your touch point and see if it intersects any overlays.

```

           //point clicked
           let point = MKMapPointForCoordinate(newCoordinates)

           //make a rectangle around this click
           let mapRect = MKMapRectMake(point.x, point.y, 0,0);

           //loop through the polygons on the map and 
           for polygon in worldMap.overlays as! [MKPolygon] {
              if polygon.intersectsMapRect(mapRect) {
                 print("found intersection")
              }
           }

```

  1. Using viewForOverlay with a promising sounding function CGPathContainsPoint, however viewForOverlay is now deprecated.

This led me to find Detecting a point in a MKPolygon broke with iOS7 (CGPathContainsPoint) which suggests the following method:

  1. Make a mutable polygon from the points of each overlay(instead of using the deprecated viewForOverlay) and then use CGPathContainsPoint to return if the clicked point is in the overlay. However I am unable to make this code work.

```

func overlaySelected (gestureRecognizer: UIGestureRecognizer) {
    let pointTapped = gestureRecognizer.locationInView(worldMap)
    let newCoordinates = worldMap.convertPoint(pointTapped, toCoordinateFromView: worldMap)
    let mapPointAsCGP = CGPointMake(CGFloat(newCoordinates.latitude), CGFloat(newCoordinates.longitude));

    print(mapPointAsCGP.x, mapPointAsCGP.y)    

    for overlay: MKOverlay in worldMap.overlays {
        if (overlay is MKPolygon) {
            let polygon: MKPolygon = (overlay as! MKPolygon)
            let mpr: CGMutablePathRef = CGPathCreateMutable()

            for p in 0..<polygon.pointCount {
                let mp = polygon.points()[p]
                print(polygon.coordinate)
                if p == 0 {
                    CGPathMoveToPoint(mpr, nil, CGFloat(mp.x), CGFloat(mp.y))
                }
                else {
                    CGPathAddLineToPoint(mpr, nil, CGFloat(mp.x), CGFloat(mp.y))
                }
            }

            if CGPathContainsPoint(mpr, nil, mapPointAsCGP, false) {
                print("------ is inside! ------")
            }

        }
    }
}

```

The first method works but no matter how small I try and make the height and width of the rectangle around the click point let mapRect = MKMapRectMake(point.x, point.y, 0.00000000001,0.00000000001); the accuracy of the tap is not reliable and so you can end up clicking on several polygons at once.

Currently I am working on deciding on which county is nearer to the tap by using the 'MKPolygon' property coordinate - which gives the central point of the polygon. With this one can then measure the distance from this polygon to the tapped point to find the closest one. But this is not ideal as the user may never be able to tap on the country that they intend.

So, to sum up my questions:

  1. Is there something that I am not implementing correctly in the second method above (one using CGPathContainsPoint)?
  2. Is there a more accurate way to register an on click event with the rectangle method?
  3. Any other suggestions or pointers on how to achieve my goal of clicking the map and seeing if the click is on an overlay.
Community
  • 1
  • 1
Anna
  • 121
  • 1
  • 7
  • I finally uncovered an answer: http://stackoverflow.com/questions/29344791/check-whether-a-point-is-inside-of-a-simple-polygon – Anna Aug 14 '16 at 19:53
  • I'm working on this too, thanks for the ideas. Just FYI, the docs for intersectsMapRect() says it only does bounding box intersections. That's why your accuracy was so off. Cheers! – rjcarr Aug 04 '17 at 05:45

0 Answers0