如何在不使用MKMapView的情况下检查MKCoordinateRegion是否包含CLLocationCoordinate2D?

Luk*_*asz 19 iphone mkcoordinateregion cllocationmanager cllocation ios

我需要检查用户位置是否属于MKCoordinateRegion.我很惊讶没有为此找到简单的功能,例如:CGRectContainsCGPoint(rect,point).

我找到了以下代码:

CLLocationCoordinate2D topLeftCoordinate = 
    CLLocationCoordinate2DMake(region.center.latitude 
                               + (region.span.latitudeDelta/2.0), 
                               region.center.longitude 
                               - (region.span.longitudeDelta/2.0));


    CLLocationCoordinate2D bottomRightCoordinate = 
    CLLocationCoordinate2DMake(region.center.latitude 
                               - (region.span.latitudeDelta/2.0), 
                               region.center.longitude 
                               + (region.span.longitudeDelta/2.0));

        if (location.latitude < topLeftCoordinate.latitude || location.latitude > bottomRightCoordinate.latitude || location.longitude < bottomRightCoordinate.longitude || location.longitude > bottomRightCoordinate.longitude) {

    // Coordinate fits into the region

    }
Run Code Online (Sandbox Code Playgroud)

但是,我不确定它是否准确,因为文档没有准确指定区域矩形的计算方式.

必须有更简单的方法来做到这一点.我是否忽略了MapKit框架文档中的某些功能?

Mar*_*ekR 16

我发布了这个答案,因为我认为接受的解决方案无效.这个答案也不完美,但它处理的情况是坐标环绕360度边界,这足以适合我的情况.

+ (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;
}
Run Code Online (Sandbox Code Playgroud)


nev*_*ing 15

您可以将您的位置转换为某个点MKMapPointForCoordinate,然后MKMapRectContainsPoint在mapview上使用visibleMapRect.这完全脱离了我的头脑.如果有效,请告诉我.


Luk*_*asz 15

如果有人与纬度和长度相混淆,这里进行了测试,工作解决方案:

MKCoordinateRegion region = self.mapView.region;

CLLocationCoordinate2D location = user.gpsposition.coordinate;
CLLocationCoordinate2D center   = region.center;
CLLocationCoordinate2D northWestCorner, southEastCorner;

northWestCorner.latitude  = center.latitude  - (region.span.latitudeDelta  / 2.0);
northWestCorner.longitude = center.longitude - (region.span.longitudeDelta / 2.0);
southEastCorner.latitude  = center.latitude  + (region.span.latitudeDelta  / 2.0);
southEastCorner.longitude = center.longitude + (region.span.longitudeDelta / 2.0);

if (
    location.latitude  >= northWestCorner.latitude && 
    location.latitude  <= southEastCorner.latitude &&

    location.longitude >= northWestCorner.longitude && 
    location.longitude <= southEastCorner.longitude
    )
{
    // User location (location) in the region - OK :-)
    NSLog(@"Center (%f, %f) span (%f, %f) user: (%f, %f)| IN!", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta, location.latitude, location.longitude);

}else {

    // User location (location) out of the region - NOT ok :-(
    NSLog(@"Center (%f, %f) span (%f, %f) user: (%f, %f)| OUT!", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta, location.latitude, location.longitude);
}
Run Code Online (Sandbox Code Playgroud)

  • 我怀疑这是否可行:1.为什么location.latitude&gt; = northWestCorner.latitude?不应该是sounthEastCorner.latitude吗?2.如果计算出的最小经度是-2.0,最大经度是2.0,而您的location.longitude是359.0怎么办? (2认同)
  • @ lichen19853是正确的,它会在360度左右测试时失败.请参阅下面的答案,以获得更准确的解决方案. (2认同)

Owe*_*rey 7

其他答案都有缺点.接受的答案有点冗长,并且在国际日期附近失败了.余弦的答案是可行的,但对于非常小的区域则是失败的(因为delta余弦是正弦趋向零接近零,意味着较小的角度差异,我们期望零变化)这个答案应该适用于所有情况,并且更简单.

迅速:

/* 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
}
Run Code Online (Sandbox Code Playgroud)

目标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
}
Run Code Online (Sandbox Code Playgroud)

对于包含任一极点的区域,此方法失败,但随后坐标系本身在极点处失败.对于大多数应用,此解决方案应该足够了.(注意,未在目标C上测试)


jws*_*art 6

我已经使用此代码来确定坐标是否在圆形区域(围绕它的半径的坐标)内.

- (BOOL)location:(CLLocation *)location isNearCoordinate:(CLLocationCoordinate2D)coordinate withRadius:(CLLocationDistance)radius
{
    CLCircularRegion *circularRegion = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:radius identifier:@"radiusCheck"];

    return [circularRegion containsCoordinate:coordinate];
}
Run Code Online (Sandbox Code Playgroud)