A Blazingly Fast Open Source Algorithm for POI Clustering on iOS

a-blazingly-fast-open-source-algorithm-for-poi-clustering-on-ios-0

Most mobile apps nowadays include some kind of a map that’s dotted with markers – ATMs, gas stations or any other place relevant to the app’s purpose. The problem is, when you put many POIs on the map, the view gets cluttered and the performance suffers.

This problem can be solved by reducing the number of annotations. The simplest solution is to display a reduced number of objects when the map is zoomed out and add more of them as the user zooms in. The problem with this approach is that the user is not aware of all the available Places Of Interest. A better solution is something called POI clustering.

Clustering is a method of grouping multiple POIs which are close to each other into one location called a cluster. At lower zoom levels, the map should show clusters of locations represented by a special view. As the user zooms in on the map, clusters can be split into smaller clusters or even single object views, depending on the zoom level.

FBAnnotationClustering

title

This problem can be solved by using FBAnnotationClustering.

You’re probably wondering what’s FBAnnotationClustering and what Facebook has to do with it. Well, FBAC is an open source clustering library/algorithm I wrote for use in our projects. And FB – those are my initials – my name is Filip Beć.

Now let’s take a look at the library.

Clustering by using QuadTree

Clustering can be carried out efficiently with algorithms for space-partitioning. A tree data structure is usually used to store data for space-partitioning.

For storage, FBAnnotationClustering uses QuadTree. QuadTree is a data structure that can efficiently find all locations contained in a specific region. It’s built by recursively subdividing a two-dimensional space into smaller regions. Imagine that every node in the tree has a bucket of defined capacity. When that bucket is full of data, the node is subdivided into four new child nodes. Child nodes are smaller quadrants of a parent node.

You can find more details on how the QuadTree works on Wikipedia.

How to use it?

The main advantage of FBAnnotation clustering is that it can be installed into an existing project via CocoaPods. The library has four classes:

  • FBAnnotationCluster
  • FBClusteringManager
  • FBQuadTree
  • FBQuadTreeNode

You will never have to use FBQuadTree and FBQuadTreeNode. They are utilized only as internal structures. Almost all interaction with the library is achieved by using FBClusteringManager. It creates a data structure and it has some handy methods to deal with the map view. To use the library, you should first initialize an instance of FBClusteringManager. For example:

	self.clusteringManager = [[FBClusteringManager alloc] initWithAnnotations:arrayOfAnnotations];

Update the currently visible region of the map on every move with annotations obtained from clusteringManager.

	- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [[NSOperationQueue new] addOperationWithBlock:^{
        double scale = self.mapView.bounds.size.width / self.mapView.visibleMapRect.size.width;

        NSArray *annotations = [self.clusteringManager clusteredAnnotationsWithinMapRect:mapView.visibleMapRect withZoomScale:scale];
            [self.clusteringManager displayAnnotations:annotations onMapView:mapView];
    }];
}

Depending on the visible map region and the level of zoom, the method clusteredAnnotationsWithinMapRect:withZoomScale: will return an array of annotations of your own class and objects of FBAnnotationCluster class. Now it’s up to you to handle objects appropriately in the methods of MKMapViewDelegate.

	- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[FBAnnotationCluster class]]) {
        // handle cluster
    } else {
        // handle single annotation
    }
    ...
}

And that’s all you have to do to transform your mess of POIs into a beautiful, organized and informative map.

Blazing fast performance

I said that QuadTree is blazingly fast and I wasn’t kidding.

Critical to performance is the moment of creating the QuadTree structure and inserting new locations. Let’s take a look at the hard numbers. This example covers the creation of a QuadTree structure using a random data set.

At Infinum, we’ve used this library in production grade applications developed for our clients. The apps are free and publicly available on iTunes Store – Truck Parking Europe, Lístkomat České spořitelny.

Last but not least, FBAnnotationClustering is an open source library. The source code, including an example project, is available on Github. It’s a continuation of some work done by Thoughtbot, with improvements in some areas and architected to be used as a Cocoapods library.

If you come across any problems with it, I’d appreciate it if you would create an issue. Also, if you are interested in contributing to the project, you can open a pull request to add a bug fix or perhaps even a new functionality.