【问题标题】:How can I compare CLLocationCoordinate2D如何比较 CLLocationCoordinate2D
【发布时间】:2012-04-29 06:13:06
【问题描述】:

我需要一种比较两个CLLocationCoordinate2D 的方法,但是当我尝试使用== 时它不起作用。请问有人能帮我找出比较它们的最佳方法吗?

【问题讨论】:

    标签: core-location cllocation equatable


    【解决方案1】:

    Swift 5.3 方式

    我创建了一个gist

    extension CLLocationCoordinate2D: Equatable {
        public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
            let numbersAfterCommaAccuracy: Double = 4
            let ratio = numbersAfterCommaAccuracy * 10
            let isLatitudeEqual = ((lhs.latitude - rhs.latitude) * ratio).rounded(.down) == 0
            let isLongitudeEqual = ((lhs.latitude - rhs.latitude) * ratio).rounded(.down) == 0
            return isLatitudeEqual && isLongitudeEqual
        }
    }
    

    【讨论】:

      【解决方案2】:

      基于 leann's answer 为 Swift 5 更新。

      import CoreLocation
      
      extension CLLocationCoordinate2D: Equatable {
          static public func ==(lhs: Self, rhs: Self) -> Bool {
              return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
          }
      }
      

      【讨论】:

        【解决方案3】:

        您可以使用CLLocation 类的distanceFromLocation: 方法。返回值为CLLocationDistance,实际上只是一个double。

        - (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
        

        【讨论】:

          【解决方案4】:

          在 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)
              }
          }
          

          【讨论】:

            【解决方案5】:

            一个 Swift 扩展:

            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,如前面的答案中所述]

            【讨论】:

              【解决方案6】:

              您可以定义一个感觉很像来自 CoreLocation 的函数:

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

              【讨论】:

              • 赞成,因为这是 IMO 最可维护的解决方案
              • 很好的解决方案。这是新蜜蜂的完整方法。 -(BOOL)compairLastSavedCoordinates:(CLLocationCoordinate2D)coordinate1 withNewCoordinates:(CLLocationCoordinate2D)coordinate2 { return (coordinate1.latitude == coordinate2.latitude) && (coordinate1.longitude == coordinate2.longitude); }
              • 永远不要比较浮点数!如果你这样做,那是不可靠的。在实践中,来自不同来源生成的真实位置的大多数比较将返回false - 即使它们彼此非常接近并且可以被视为“相等”。
              【解决方案7】:

              我们可以将纬度和经度转换为 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 位数字。

              【讨论】:

                【解决方案8】:

                您可以使用此函数+ (NSValue *)valueWithMKCoordinate:(CLLocationCoordinate2D)coordinateCLLocationCoordinate 包装成NSValue

                然后使用isEqualToValue进行比较。

                引用苹果文档isEqualToValue函数:

                NSValue 类比较每个值对象的类型和内容以确定相等性。

                参考:NSValue 的 Apple 文档

                【讨论】:

                  【解决方案9】:

                  比较任何给定结构类型的两个实例的通用方法:

                  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 是您想要接受的任何级别的错误。

                  【讨论】:

                  • 第一个可能被认为是粗略的,因为您假设结构是打包的,成员之间没有任何字节。
                  • 好点。如果在创建/分配时将整个结构归零,则 memcmp 方法即使对于非打包结构也是安全的,否则请谨慎使用。
                  • @Glenn 你能把 abs 修复到 fabs 和
                  • 好建议,@Flink。完成。
                  • 整个结构为零是什么意思?你是什​​么意思结构被打包,成员之间没有任何字节?你的意思是它甚至可能不是这种情况>?
                  【解决方案10】:

                  作为所有这些答案的一个小补充,将比较定义为预处理器定义非常方便:

                  #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");
                  }
                  

                  如果您不喜欢预处理器,另一种选择是使用内联方法。

                  【讨论】:

                  • 永远不要将浮点数与== 进行比较。查看人们使用 epsilon 的答案。
                  • @DanSkeel 查看我编辑的答案。有时你有一个用例,你想比较精确的坐标。例如。如果坐标源是地点数据库,而您只想比较它们。那么就不需要一个范围来进行相等比较。所以你可能会再次考虑你的反对票。
                  • 你没有明白我的意思。想象一下1 != 0.99999999999 的情况......这是任何浮点比较的一般规则。 Read about它。这条规则就像计算机一样古老。
                  • 我还是不明白你的意思。如果您的坐标来源是例如一个数据库,并且您不需要对坐标进行任何计算,使用常规 == 比较就可以了。
                  • 这里只是对较早的 cmets 的后期澄清:问题是 如何 存储坐标。默认情况下,纬度和经度是 Double 值。 Double 值在计算机中很少准确。如果用户输入一个纬度,例如38.627003,则不能保证计算机将准确存储38.627003。最近一次将计算机的解释打印到小数点后 15 位的测试返回值38.627002716064453!现在,如果您将用户的响应检索并存储为 String那么 结果将是准确的 - 但请记住 默认Double
                  【解决方案11】:

                  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
                  }
                  

                  是的,这个,代码比较慢,但这可以帮助您避免因浮点数精度不那么完美而导致的问题。

                  【讨论】:

                    【解决方案12】:
                    CLLocationCoordinate2D c1, c2;
                    if (c1.latitude == c2.latitude && c1.longitude == c2.longitude)
                    {
                        // ...
                    }
                    

                    我不是在开玩笑。 CLLocationCoordinate2D 是一个 C 结构,除了比较各个成员之外,没有简单的方法来比较 C 结构。

                    【讨论】:

                      猜你喜欢
                      • 2013-08-14
                      • 2012-12-28
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-05-23
                      • 2012-11-10
                      • 2012-09-04
                      • 2011-03-27
                      相关资源
                      最近更新 更多