【问题标题】:Finding closest match of Latitude & Longitude in a list of Lat/Longs在纬度/经度列表中查找纬度和经度的最接近匹配
【发布时间】:2013-02-06 11:17:07
【问题描述】:

我正在为特定位置创建一个带有天气查找功能的 iPhone 应用程序,但我遇到了以下问题,我不确定最好的解决方法。

我有一个位置的纬度和经度,并想从 5000 多个位置的列表中找到最接近的经纬度匹配

5000 多个位置来自 Met Office Datapoint API 的 JSON 提要,并采用 NSDictionaries 的 NSArray 形式,NSDictionary 包括 id、lat、long 和 name。

我想将我的位置与气象局列表中最近的位置相匹配,并获取 id 键值。

提前致谢

【问题讨论】:

    标签: iphone ios objective-c location


    【解决方案1】:

    我假设您在此使用 CLLocation 对象...

    - (CLLocation*)closestLocationToLocation:(CLLocation*)currLocation
    {
        CLLocationDistance minDistance;
    
        CLLocation *closestLocation = nil;
    
        for (CLLocation *location in arrayOfLocations) {
            CLLocationDistance distance = [location distanceFromLocation:currLocation];
    
            if (distance <= minDistance
                || closestLocation == nil) {
                minDistance = distance;
                closestLocation = location;
            }
        }
    
        //closestLocation is now the location from your array which is closest to the current location or nil if there are no locations in your array.
    
        return closestLocation;
    
    }
    

    可能有更快的方法来做这件事,但这会完成。

    编辑使用 CLLocation 函数

    【讨论】:

    • 只是好奇:为什么不使用 CLLocation 的内置 distanceFromLocation: 方法来解释曲率而不是 2D 距离公式?
    • 我没有使用它,因为我不知道它存在 :D 将相应地编辑代码,谢谢 :D
    • 刚刚得到旧版本并进行了一些快速测试,现在将实施这个新版本。感谢@AnnaKarenina 和 Fogmeister 的更新。
    • 有没有更好的方法来做 CLLocationDistance minDistance = 9999999999;好像有点坑
    • 已编辑...这看起来好多了。
    【解决方案2】:

    我曾经做过类似的事情(找到一个最大半径的点周围的所有纬度/经度对象)并使用此处给出的公式: http://www.movable-type.co.uk/scripts/latlong.html 但是,这非常耗时。所以我有点“装箱”了对象的拳头。基于上面的计算(当然恢复),我计算了那些坐标的纬度和经度,这些坐标的北、西、南和东正好具有最大距离。使用软管最大值和最小值(对于纬度和经度),我查询了所有有问题的对象。并且仅针对那些我计算了确切距离并将它们包含在结果列表中或排除它们的人。

    但是,到目前为止,这并不完全符合您的问题。但我试图进一步加快计算。为此,我对自己说,我不需要从搜索对象到我的确切距离,但知道它是否比其中一个框坐标更近就足够了。这部分与您的问题非常吻合:

    您的情况可能会容易得多。假设有问题的位置(最短的一次)靠近您尝试分配的一个位置,那么所有这些复杂的数学运算可能都不起作用。您不需要确切的距离。你需要的是最昂贵的。为此,我假设地球是平的,并且经度(或纬度)之间的距离是线性的。这当然不是真的,但应该足以弄清楚其中哪一个是最接近的。 从那里你可以使用毕达哥拉斯。

    Distance = sqrt(sqr(difference-in-lat) + sqr(difference-in-lon));
    

    仅出于比较距离和找到最短距离的目的,您甚至可以用更快的平方运算代替耗时的平方路线。

    Square-Of-Distance = sqr(difference-in-lat) + sqr(difference-in-lon).
    

    然后比较各种Square-Of-Distance而不是Distance。结果将是相同的,但要快得多。

    顺便说一句,那是一个 PHP 项目。这就是为什么我不能提供示例代码而只是解释算法的原因。

    【讨论】:

    • 感谢您抽出宝贵时间回复。
    • 这不是一个好主意,并且会给出错误的结果。 lat 和 long 的比例不同,在纬度 48 度,你有 cos(48) 的失真,在纬度上大约是 0,66
    • 是的,它们在全球范围内的比例不同。这个想法是,在要比较的对象靠近的那些区域中,比例足够相似,以提供距离的准确比较(没有绝对值,只是比较)。由于规模的差异可以说从一个度到下一个度数相当小(除了靠近极点区域),“两度外”的点总是会比“一度”更远。即使它下降到几分钟也很好。日期线上还有另一个问题,但很容易用“如果”来解决。
    【解决方案3】:

    我建议这样:

    NSMutableArray *tempArray = [NSMutableArray new];
    for (NSMutableDictionary *location in yourArrayOfLocations){
        CLLocation coord;
        coord.latitude = [location objectForKey:@"latitude"];
        coord.longitude = [location objectForKey:@"longitude"];
    
        [location setValue:[usersLocation distanceFromLocation:coord] forKey:@"distance"];
        [tempArray addObject:location];
    }
    // Now sort the array 
    NSArray *sortedArray = [tempArray sortedArrayUsingComparator:^(id o1, id o2) {
                NSDictionary *location1 = (NSDictionary *)o1;
                NSDictionary *location2 = (NSDictionary *)o2;
    
                return [[location1 objectForKey:@"distance"] compare:[location2 objectForKey:@"distance"]];
            }];
    [tempArray release];
    

    现在你有一个按距离排序的数组。您可以使用索引 0 处的对象,因为它最接近用户的位置。

    祝你好运!

    【讨论】:

    • 感谢您抽出宝贵时间回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多