web-dev-qa-db-ja.com

CLLocationCoordinate2Dを比較する方法

2つのCLLocationCoordinate2Dを比較する方法が必要ですが、==を使用しようとしてもうまくいきませんでした。誰かがそれらを比較する最良の方法で私を助けてくれますか?

48
The Crazy Chimp

特定の構造体タイプの2つのインスタンスを比較するための一般的なアプローチ:

memcmp(&cllc2d1, &second_cllc2d, sizeof(CLLocationCoordinate2D))

または

cllc2d1.latitude == cllc2d2.latitude && cllc2d1.longitude == cllc2d2.longitude

exactlyが等しいことを本当に確認したい場合は、動作するはずです。ただし、緯度と経度が倍精度として定義されている場合、「十分に近い」比較を実行することができます。

fabs(cllc2d1.latitude - cllc2d2.latitude) <= epsilon && fabs(cllc2d1.longitude - cllc2d2.longitude) <= epsilon

ここで、epsilonは、受け入れたいエラーのレベルです。

56
Glenn

これらすべての答えへの小さな追加として、比較をプリプロセッサとして定義することは非常に便利です:

#define CLCOORDINATES_EQUAL( coord1, coord2 ) (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude)

またはイプシロン付き:

#define CLCOORDINATE_EPSILON 0.005f
#define CLCOORDINATES_EQUAL2( coord1, coord2 ) (fabs(coord1.latitude - coord2.latitude) < CLCOORDINATE_EPSILON && fabs(coord1.longitude - coord2.longitude) < CLCOORDINATE_EPSILON)

これにより、次のように比較できます。

CLLocationCoordinate2D resultingCoordinate = ... a method call ...;
CLLocationCoordinate2D expectedCoordinate = CLLocationCoordinate2DMake(48.11, 11.12);

if(CLCOORDINATES_EQUAL( resultingCoordinate, expectedCoordinate)) {
    NSLog(@"equal");
} else {
    NSLog(@"not equal");
}

別の方法としては、プリプロセッサが気に入らない場合は、インラインメソッドを使用します。

33
Klaas

A Swift extension:

import MapKit

extension CLLocationCoordinate2D: Equatable {}

public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
    return (lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude)
}

[Xcode 7.3.1でテスト済み、Swift 2.2] [そして、もちろん、浮動小数点値を比較する本質的な危険性があるため、前述のようにepsilonの使用を検討することをお勧めします回答]

19
leanne

CLLocation クラスのdistanceFromLocation:メソッドを使用できます。戻り値は CLLocationDistance であり、実際には単なる2倍です。

- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
12
Greg M. Krsak

CoreLocationから来るように感じる関数を定義できます。

BOOL CLLocationCoordinateEqual(CLLocationCoordinate2D coordinate1, CLLocationCoordinate2D coordinate2) { return (fabs(coordinate1.latitude - coordinate2.latitude) <= DBL_EPSILON && fabs(coordinate1.longitude - coordinate2.longitude) <= DBL_EPSILON); }

8
Albert Schulz

In Swift 3、DBL_EPSILONは非推奨です。使用する Double.ulpOfOne

extension CLLocationCoordinate2D {
    func isEqual(_ coord: CLLocationCoordinate2D) -> Bool {
        return (fabs(self.latitude - coord.latitude) < .ulpOfOne) && (fabs(self.longitude - coord.longitude) < .ulpOfOne)
    }
}
6
Ryan
CLLocationCoordinate2D c1, c2;
if (c1.latitude == c2.latitude && c1.longitude == c2.longitude)
{
    // ...
}

冗談じゃないよ。 CLLocationCoordinate2DはC構造体であり、個々のメンバーを比較する以外に、C構造体を比較する簡単な方法はありません。

2
joerick

CLLocationCoordinate2DはC構造体です。したがって、フィールドを比較する必要があります。

CLLocationCoordinate2D coord1, coord2;
if (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude) {
    // coordinates are equal
}

注意、 CLLocationCoordinate2Dフィールドはdoubleであるため、他の浮動小数点比較と同じ問題が発生する可能性があります。したがって、少し値を丸めることをお勧めします、例えば:

CLLocationCoordinate2D coord1, coord2;
if (round(coord1.latitude * 1000.0) == round(coord2.latitude * 1000.0)
    && round(coord1.longitude * 1000.0) == round(coord2.longitude * 1000.0)) {
    // coordinates are equal
}

はい、これはコードの方が遅くなりますが、浮動小数点数の完全な精度ではないことに起因する問題を回避するのに役立ちます。

1

この関数+ (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinateを使用して、CLLocationCoordinateNSValueにラップできます。

そして、isEqualToValueを使用して比較します。

Apple isEqualToValue関数のドキュメント:

NSValueクラスは、各値オブジェクトのタイプと内容を比較して、等しいかどうかを判断します。

参照:Apple doc of NSValue

1
Raymond

緯度と経度をNSStringに変換し、文字列を比較できます。

+ (BOOL)isEqualWithCoordinate:(CLLocationCoordinate2D)location1 withAnotherCoordinate:(CLLocationCoordinate2D)location2{
NSString *locationString1 = [NSString stringWithFormat:@"%g, %g", location1.latitude, location1.longitude];
NSString *locationString2 = [NSString stringWithFormat:@"%g, %g", location2.latitude, location2.longitude];

if ([locationString1 isEqualToString:locationString2]) {
    return YES;
}else{
    return NO;
}

}

%gは切り捨てられた10進数を4桁に変換するためです。

0
Saif