Мне нужен способ сравнения двух CLLocationCoordinate2D
, однако, когда я пытался использовать ==
, это не сработало. Пожалуйста, кто-нибудь может помочь мне с наилучшим способом их сравнения?
Как я могу сравнить CLLocationCoordinate2D
Ответ 1
Либо общий подход для сравнения двух экземпляров любого типа структуры:
memcmp(&cllc2d1, &second_cllc2d, sizeof(CLLocationCoordinate2D))
или
cllc2d1.latitude == cllc2d2.latitude && cllc2d1.longitude == cllc2d2.longitude
должен работать, если вы действительно хотите быть уверенным, что они ровно равны. Однако, учитывая, что широта и долгота определяются как двойные, вы действительно можете сделать "достаточно близкое" сравнение:
fabs(cllc2d1.latitude - cllc2d2.latitude) <= epsilon && fabs(cllc2d1.longitude - cllc2d2.longitude) <= epsilon
где epsilon
- любой уровень ошибки, который вы хотите принять.
Ответ 2
В качестве небольшого дополнения ко всем этим ответам довольно удобно определить сравнение, определенное как препроцессор:
#define CLCOORDINATES_EQUAL( coord1, coord2 ) (coord1.latitude == coord2.latitude && coord1.longitude == coord2.longitude)
или с epsilon:
#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");
}
Другой альтернативой является использование встроенного метода, если вам не нравится препроцессор.
Ответ 3
Быстрое расширение:
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
, как указано в более ранних ответах)
Ответ 4
Вы можете использовать CLLocation class 'distanceFromLocation: метод. Возвращаемое значение - CLLocationDistance, которое на самом деле просто удваивается.
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
Ответ 5
Вы можете определить функцию, которая очень похожа на CoreLocation:
BOOL CLLocationCoordinateEqual(CLLocationCoordinate2D coordinate1, CLLocationCoordinate2D coordinate2)
{
return (fabs(coordinate1.latitude - coordinate2.latitude) <= DBL_EPSILON &&
fabs(coordinate1.longitude - coordinate2.longitude) <= DBL_EPSILON);
}
Ответ 6
В 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)
}
}
Ответ 7
CLLocationCoordinate2D c1, c2;
if (c1.latitude == c2.latitude && c1.longitude == c2.longitude)
{
// ...
}
Я не шучу. CLLocationCoordinate2D - это C-структура, и нет простого способа сравнить C-структуры, кроме сравнения отдельных членов.
Ответ 8
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
}
Да, это код медленнее, но это может помочь вам избежать проблем, вызванных не столь совершенной точностью чисел с плавающей запятой.
Ответ 9
Вы можете обернуть CLLocationCoordinate
в NSValue
, используя эту функцию + (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinate
И затем используйте isEqualToValue
для сравнения.
Цитата из документа Apple isEqualToValue
:
Класс NSValue сравнивает тип и содержимое каждого объекта значения для определения равенства.
Ссылка: Apple doc NSValue
Ответ 10
Мы можем преобразовать широту и долготу в 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 преобразует усеченное десятичное число в 4 цифры.
Ответ 11
Обновлено для Swift 5 на основе постного ответа.
import CoreLocation
extension CLLocationCoordinate2D: Equatable {
static public func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
}