Determining if Latitude/Longitude Point is in a MKPolygon within Mapview?
Asked Answered
D

3

11

At this moment, I am trying to figure out whether a coordinate on a MKMapView is within a MKPolygon drawn out ahead of time with latitudes/longitudes.

I am using CGPathContainsPoint to determine whether a coordinate is within the polygon on the map but it always returns false regardless of the coordinate I choose.

Can anyone please explain what exactly is going wrong? Below is my code in Swift.

class ViewController: UIViewController, MKMapViewDelegate

@IBOutlet weak var mapView: MKMapView!

    let initialLocation = CLLocation(latitude: 43.656734, longitude: -79.381576)
    let point = CGPointMake(43.656734, -79.381576)
    let regionRadius: CLLocationDistance = 500
    let point1 = CLLocationCoordinate2D(latitude: 43.656734, longitude: -79.381576)

    var points = [CLLocationCoordinate2DMake(43.655782, -79.382094),
        CLLocationCoordinate2DMake(43.657499, -79.382310),
        CLLocationCoordinate2DMake(43.656656, -79.380497),
        CLLocationCoordinate2DMake(43.655782, -79.382094)]

    override func viewDidLoad() {
        super.viewDidLoad()

        centerMapOnLocation(initialLocation)

        let polygon = MKPolygon(coordinates: &points, count: points.count)
        mapView.addOverlay(polygon)

        var annotation = MKPointAnnotation()
        annotation.coordinate = point1
        annotation.title = "Test"
        annotation.subtitle = "Test"

        mapView.addAnnotation(annotation)
        self.mapView.delegate = self

    }

    func centerMapOnLocation(location: CLLocation) {
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, regionRadius * 2.0, regionRadius * 2.0)

        mapView.setRegion(coordinateRegion, animated: true)
    }

    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        if overlay is MKPolygon {
            let polygonView = MKPolygonRenderer(overlay: overlay)
            polygonView.strokeColor = UIColor.redColor()

            if  CGPathContainsPoint(polygonView.path, nil, CGPointMake(43.656734, -79.381576), true) {
                print("True!!!!!")
            } else {
                println("False")
            }

            return polygonView
        }
        return nil
    }
Demetrius answered 21/8, 2015 at 20:50 Comment(2)
hey wouldn't you use "false" (to get the winding-style path) .. last argument to CGPathContainsPoint.Mayfield
I've tried both true and false but no avail. :(Demetrius
D
13

UPDATED FOR SWIFT 4

You are confusing CGPoints, which are x and y coordinate pairs that point to a location on your view, with CLLocationCoordinate2Ds, which are coordinates on Earth.

For CGPathContainsPoint, you want to pass in your polygonRenderer path (created from your polygon in viewDidLoad()) and current location like this:

let polygonRenderer = MKPolygonRenderer(polygon: polygon)
let mapPoint: MKMapPoint = MKMapPointForCoordinate(coordinate)
let polygonViewPoint: CGPoint = polygonRenderer.pointForMapPoint(mapPoint)

if polygonRenderer.path.contains(polygonViewPoint) {
    print("Your location was inside your polygon.")
}

So you want to think about where you should be putting this code, as where you currently have it is inside the function that gets called whenever an MKOverlay gets drawn on screen, and that is completely unrelated to this.

Dextran answered 13/4, 2016 at 20:13 Comment(0)
C
7

Updated for Swift 3

let polygonRenderer = MKPolygonRenderer(polygon: polygon)
let mapPoint: MKMapPoint = MKMapPointForCoordinate(coordinate)
let polygonViewPoint: CGPoint = polygonRenderer.point(for: mapPoint)

if polygonRenderer.path.contains(polygonViewPoint)
{
    print("Your location was inside your polygon.")
}
Chadd answered 13/3, 2017 at 12:8 Comment(1)
What your are passing over MKPolygonRenderer(polygon: polygon), since we have only mappoint getting after user pressed on polylineSidon
C
1

Solution for Swift 5:

Since renderer.path's contains method needs point as CGPoint we need convert it throught MKMapPoint from geo coordintates to rederer's point, otherwise the result will be unexpected.

@objc
func mapTapped(_ tap: UILongPressGestureRecognizer) {

    if tap.state == .recognized {
        let touchPoint = tap.location(in: mapView)
        let coord = mapView.convert(touchPoint, toCoordinateFrom: mapView)

        for overlay: MKOverlay in mapView.overlays {

            if let polygon = overlay as? MKPolygon {
                let renderer = MKPolygonRenderer(polygon: polygon)
                let mapPoint = MKMapPoint(coord)
                let rendererPoint = renderer.point(for: mapPoint)

                if renderer.path.contains(rendererPoint) {
                    // here comes your code
                }
            }
        }
    }
}

Convincing answered 2/11, 2020 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.