Check if user location is inside a shape

2019-04-02 14:38发布

I made this method to check if an user location is inside a polygon on a map view (mapkit). I pass to the method the current user location (CLLocationCoordinate2D) and return a boolean just to know if the user is in a polygon or not.

func userInsidePolygon(userlocation: CLLocationCoordinate2D ) -> Bool{
    // get every overlay on the map  
    let o = self.mapView.overlays
    // loop every overlay on map
    for overlay in o {
        // handle only polygon
        if overlay is MKPolygon{
            let polygon:MKPolygon =  overlay as! MKPolygon
            let polygonPath:CGMutablePathRef  = CGPathCreateMutable()
            // get points of polygon
            let arrPoints = polygon.points()
            // create cgpath
            for (var i:Int=0; i < polygon.pointCount; i++){
                let mp:MKMapPoint = arrPoints[i]
                if (i == 0){
                    CGPathMoveToPoint(polygonPath, nil, CGFloat(mp.x), CGFloat(mp.y))
                }
                else{
                    CGPathAddLineToPoint(polygonPath, nil, CGFloat(mp.x), CGFloat(mp.y))
                }
            }
            let mapPointAsCGP:CGPoint = self.mapView.convertCoordinate(userlocation, toPointToView: self.mapView)
            return CGPathContainsPoint(polygonPath , nil, mapPointAsCGP, false)
        }
    }
    return false
}

I don't really understand why, but the user is never inside a polygon after this test. (and i'm pretty sure he is)

I think it's possible that i have a logic problem with lat/long against x,y.

Does anybody already have work with like this ?

Thanks in advance for all suggestions.

Cheers

2条回答
姐就是有狂的资本
2楼-- · 2019-04-02 14:54

Swift 3, Xcode 8 answer:

func userInsidePolygon(userlocation: CLLocationCoordinate2D ) -> Bool {
    var containsPoint: Bool = false
    // get every overlay on the map
    let o = self.mapView.overlays
    // loop every overlay on map
    for overlay in o {
        // handle only polygon
        if overlay is MKPolygon{
            let polygon:MKPolygon =  overlay as! MKPolygon
            let polygonPath:CGMutablePath  = CGMutablePath()
            // get points of polygon
            let arrPoints = polygon.points()
            // create cgpath
            for i in 0..<polygon.pointCount {

                let polygonMapPoint: MKMapPoint = arrPoints[i]
                let polygonCoordinate = MKCoordinateForMapPoint(polygonMapPoint)
                let polygonPoint = self.mapView.convert(polygonCoordinate, toPointTo: self.mapView)

                if (i == 0){
                    polygonPath.move(to: CGPoint(x: polygonPoint.x, y: polygonPoint.y))
                }
                else{
                    polygonPath.addLine(to: CGPoint(x: polygonPoint.x, y: polygonPoint.y))
                }
            }
            let mapPointAsCGP:CGPoint = self.mapView.convert(userlocation, toPointTo: self.mapView)
            containsPoint =  polygonPath.contains(mapPointAsCGP)
            if containsPoint {
                return true
            }
        }
    }
    return containsPoint
}
查看更多
仙女界的扛把子
3楼-- · 2019-04-02 15:00

The problem is that you are converting the userLocation from the map coordinates to the view coordinates but when you build the path, you don't convert the points to the views coordinates.

You'll need to convert the MKMapPoint to a CLLocationCoordinate2D then to a CGPoint.

let polygonMapPoint: MKMapPoint = arrPoints[i]
let polygonCoordinate = MKCoordinateForMapPoint(polygonPoint)
let polygonPoint self.mapView.convertCoordinate(polygonPointAsCoordinate, toPointToView: self.mapView)

Then use polygonPoint when building the path

CGPathMoveToPoint(polygonPath, nil, polygonPoint.x, polygonPoint.y)
查看更多
登录 后发表回答