20

ユーザーの場所が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

    }

ただし、ドキュメントでは領域の長方形の計算方法が正確に指定されていないため、正確かどうかはわかりません。

それを行うためのより簡単な方法がなければなりません。MapKitフレームワークのドキュメントの一部の機能を見落としていませんか?

4

9 に答える 9

20

私の意見では、受け入れられた解決策は有効ではないため、この回答を投稿しています。この答えも完璧ではありませんが、座標が 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;
}
于 2014-05-08T15:35:54.920 に答える
16

で現在地をポイントに変換してから、マップビューでMKMapPointForCoordinate使用できます。これは完全に頭から離れています。動作するかどうか教えてください。MKMapRectContainsPointvisibleMapRect

于 2012-05-11T14:48:21.187 に答える
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);
}
于 2012-05-13T18:51:32.493 に答える
7

他の答えにはすべて欠点があります。受け入れられた答えは少し冗長で、国際日付変更線の近くで失敗します。コサインの答えは実行可能ですが、非常に小さな領域では失敗します (デルタ コサインはゼロ近くでゼロに向かうサインであるため、角度差が小さい場合は変化がゼロであると予想されるため)。この答えはすべての状況で正しく機能し、より単純です。

迅速:

/* 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
}

目標 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
}

ただし、この方法はいずれかの極を含む領域では失敗しますが、座標系自体は極で失敗します。ほとんどのアプリケーションでは、このソリューションで十分です。(注意、Objective C ではテストされていません)

于 2014-10-22T09:18:47.610 に答える
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];
}
于 2014-10-06T12:32:06.993 に答える
1

Owen Godfrey さん、Objective-C のコードが機能しません。これは良いコードです: Objective-C で失敗します。これは良いコードです:

/* Standardises and angle to [-180 to 180] degrees */
- (CLLocationDegrees)standardAngle:(CLLocationDegrees)angle {
    angle=fmod(angle,360);
    return angle < -180 ? -360 - angle : angle > 180 ? 360 - 180 : angle;
}

-(BOOL)thisRegion:(MKCoordinateRegion)region containsLocation:(CLLocation *)location{
    CLLocationDegrees deltaLat =fabs([self standardAngle:(region.center.latitude-location.coordinate.latitude)]);
    CLLocationDegrees deltaLong =fabs([self standardAngle:(region.center.longitude-location.coordinate.longitude)]);
    return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >=deltaLong;
}
    CLLocationDegrees deltalong = fabs(standardAngle(region.center.longitude - location.coordinate.longitude));
    return region.span.latitudeDelta >= deltaLat && region.span.longitudeDelta >= deltalong;
}

ありがとう!

于 2015-02-19T10:47:58.637 に答える
0

Lukasz ソリューションに基づいていますが、Swift では、誰でも 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
    )
}
于 2016-03-23T21:20:23.057 に答える