iphone - 在缩放的 MKMapView 上合并注释

标签 iphone objective-c cocoa annotations mkmapview

我想做的事情有很多糟糕的方法,但这似乎是“必须有更好的方法”的情况之一。

我在 iPhone 应用程序中使用 MKMapView 来显示许多注释。假装进行概念性讨论,美国各州的每个城镇都有一个注释,因此屏幕上有一堆相当密集的注释。当用户缩小 map 时,这些注释开始相互挤压,直到它们重叠并且变得难以单独挑选出来。

我想做的是,在特定密度的注释下(比如当任何注释重叠时),将这些注释合并为一个注释,表明它包含许多子注释(一些视觉指示器说, “放大你会看到更多注释”)。

我可以在注释 View 上调用 CGRectIntersectsRect,但使用它似乎是一个 N^2 问题——我将不得不为每个注释迭代每个注释。考虑这个伪代码:

FOR firstAnnotationView IN allAnnotationViews
   FOR secondAnnotationView in allAnnotationViews
       IF CGRectIntersectsRect(firstAnnotationView.frame, secondAnnotationView.frame)
           // found two overlapping annotations, consolidate them
       ENDIF
   ENDFOR
ENDFOR

您可以看到为什么它会很慢,并且每次放大或缩小 map 时都必须运行它!

那么你们将如何检测 map 中的重叠注释,并以精通性能的方式智能地合并它们?

最佳答案

我会根据经度/纬度对您的注释进行分类,然后使用这些分类进行整合。基本想法看起来像这样:

#include <vector>

float minLongitude = 180.0f;
float maxLongitude = -180.0f;
float longitudeBinSize = 0.1; // Degrees
float minLatitude = -90.0f;
float maxLatitude = 90.0f;
float latitudeBinSize = 0.1; // Degrees
int numBinColumns = int((maxLongitude - minLongitude) / longitudeBinSize);
int numBinRows = int((maxLatitude - minLatitude) / latitudeBinSize);

void calcBinCoords(float longitude, float latitude, int &column, int &row) {
    column = int((latitude - minLatitude) / latitudeBinSize);
    row = int((longitude - minLongitude) / longitudeBinSize);
}

typedef std::vector<AnnotationView *> AnnotationViews;

void binAnnotations(NSArray *annotationViews, std::vector<AnnotationViews> &binnedAnnotations) {
    binnedAnnotations.clear();
    binnedAnnotations.resize(numBinColumns * numBinRows);
    for (AnnotationView *annotationView in annotationViews) {
        int column, row;
        calcBinCoords(annotationView.longitude, annotationView.latitude, column, row);
        binnedAnnotations[row * numBinColumns + column].push_back(annotationView);
    }
}

longitudeBinSize 和 latitudeBinSize 的值将是合并时您打算搜索的最大距离。一旦所有东西都在箱子里,那么您的搜索问题只涉及在相邻箱子中搜索候选值列表。此外,由于您将在合并期间扫描阵列,因此您实际上只需要为您处理的每个箱子检查三个相邻的箱子——箱子位于 (column+1,row),箱子位于 (column,row+1) ), 以及 (column+1,row+1) 的 bin。

您可以使用 NSMutableArrays 而不是 std::vector 作为容器,但听起来您有大量项目要处理,我怀疑 std::vector 会更快。不过,这只是我的偏好,甚至可能都不够关心。如果您使用 ObjC 而不是 ObjC++,那么您当然不能使用 std::vector。

关于iphone - 在缩放的 MKMapView 上合并注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1589891/

相关文章:

iphone - 创建类似于新的 iOS 6 按钮共享的自定义共享 View

ios - 无法使用 ARC 设置自定义协议(protocol)委托(delegate),并使用 UINavigationController 和两个 UITableViewController

ios - 在 viewDidLoad 方法中链接到另一个 ViewController

ios - 处理组合的 react 性 cocoa 信号

objective-c - 从 Cocoa 中的 URL 方案中捕获 URL

iphone - xcode sqlite3 libsqlite.dylib

iphone - 是否可以对 C++ 类执行任何 GUI 操作

iphone - 隐藏Tabbar还占空间?

iphone - 2 个开发者许可证 -1 个 iPhone

iphone - 用于跨选项卡保留 UI 状态的单例