How to check if MKCoordinateRegion contains CLLocationCoordinate2D without using MKMapView?

后端 未结 9 802
天涯浪人
天涯浪人 2020-12-13 05:08

I need to check if user location belongs to the MKCoordinateRegion. I was surprised not to find simple function for this, something like: CGRectContainsCGPoint(rect,

相关标签:
9条回答
  • 2020-12-13 05:28

    Based on Lukasz solution, but in Swift, in case anybody can make use of Swift:

    func isInRegion (region : MKCoordinateRegion, coordinate : CLLocationCoordinate2D) -> Bool {
    
        let center   = region.center;
        let northWestCorner = CLLocationCoordinate2D(latitude: center.latitude  - (region.span.latitudeDelta  / 2.0), longitude: center.longitude - (region.span.longitudeDelta / 2.0))
        let southEastCorner = CLLocationCoordinate2D(latitude: center.latitude  + (region.span.latitudeDelta  / 2.0), longitude: center.longitude + (region.span.longitudeDelta / 2.0))
    
        return (
            coordinate.latitude  >= northWestCorner.latitude &&
            coordinate.latitude  <= southEastCorner.latitude &&
    
            coordinate.longitude >= northWestCorner.longitude &&
            coordinate.longitude <= southEastCorner.longitude
        )
    }
    
    0 讨论(0)
  • 2020-12-13 05:29

    The other answers all have faults. The accepted answer is a little verbose, and fails near the international dateline. The cosine answer is workable, but fails for very small regions (because delta cosine is sine which tends towards zero near zero, meaning for smaller angular differences we expect zero change) This answer should work correctly for all situations, and is simpler.

    Swift:

    /* Standardises and angle to [-180 to 180] degrees */
    class func standardAngle(var angle: CLLocationDegrees) -> CLLocationDegrees {
        angle %= 360
        return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle
    }
    
    /* confirms that a region contains a location */
    class func regionContains(region: MKCoordinateRegion, location: CLLocation) -> Bool {
        let deltaLat = abs(standardAngle(region.center.latitude - location.coordinate.latitude))
        let deltalong = abs(standardAngle(region.center.longitude - location.coordinate.longitude))
        return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong
    }
    

    Objective C:

    /* Standardises and angle to [-180 to 180] degrees */
    + (CLLocationDegrees)standardAngle:(CLLocationDegrees)angle {
        angle %= 360
        return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle
    }
    
    /* confirms that a region contains a location */
    + (BOOL)region:(MKCoordinateRegion*)region containsLocation:(CLLocation*)location {
        CLLocationDegrees deltaLat = fabs(standardAngle(region.center.latitude - location.coordinate.latitude))
        CLLocationDegrees deltalong = fabs(standardAngle(region.center.longitude - location.coordinate.longitude))
        return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong
    }
    

    This method fails for regions that include either pole though, but then the coordinate system itself fails at the poles. For most applications, this solution should suffice. (Note, not tested on Objective C)

    0 讨论(0)
  • 2020-12-13 05:37

    I'm posting this answer as the accepted solution is not valid in my opinion. This answer is also not perfect but it handles the case when coordinates wrap around 360 degrees boundaries, which is enough to be suitable in my situation.

    + (BOOL)coordinate:(CLLocationCoordinate2D)coord inRegion:(MKCoordinateRegion)region
    {
        CLLocationCoordinate2D center = region.center;
        MKCoordinateSpan span = region.span;
    
        BOOL result = YES;
        result &= cos((center.latitude - coord.latitude)*M_PI/180.0) > cos(span.latitudeDelta/2.0*M_PI/180.0);
        result &= cos((center.longitude - coord.longitude)*M_PI/180.0) > cos(span.longitudeDelta/2.0*M_PI/180.0);
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题