Thursday, April 5, 2012

iOS Photos App Map Pin Clustering

Screenshot of Sample App
While working on a new application for iOS, I wanted to replicate the way the Photos app does their map pin clustering when you look at where you've taken pictures.  I did a bunch of searching around and there is a nice solution at http://revolver.be/blog/mapkit-clustering-with-ios/  but it wasn't exactly what I wanted to do.  After putting together code from everything I've found, I was able to get it working well enough that I thought I'd share it.

I've created a project on GitHub - https://github.com/kazmiekr/MapPinClustering where you can download the code for the sample project.  The sample project shows a map of a handful of annotations in the Boston area, you can zoom in and out and watch the pins animate to their locations.  There are a bunch of pins in the downtown Boston area as well.

The core of the code is in the ClusteringMapView subclass of the MKMapView class that handles the logic of clustering the pins.  Basically it divides the map into squares using the 'distance' property and while looping over the annotations, it only shows one pin per square.  If there is already a pin displayed for that square, it sets that pin's cluster point to the shown pin.  Each annotation is a custom MKAnnotation class that contains it's actual location and it's clustered point so we can animate the property as we show and hide the pins.

There is a lot you could do to improve this.

  1. You could try to do fancy measurement logic using meters/miles instead of random boxes to determine what to show, but at a cost to performance.
  2. You could get really fancy with a k-means clustering algorithm
  3. You could come up with weighted points to ensure that cluster points with a higher amount of points ensure visibility over others.
All of that is cool, but this works for now.  Let me know what you think and I hope it's something you can use.




5 comments:

  1. This is great--thanks for posting this! I was looking at the way Rail Time was doing clustering but was overwhelmed with the k(d)-tree implementations. Thank you!

    ReplyDelete
  2. First all thank you very much for your post! I'm trying to integrate it into one project and I want to change the pin color for the pins with more than 1 point. Do you've got any suggestion to start with this development over your example project? thank you very much!

    ReplyDelete
    Replies
    1. Sorry for the late reply, but I just merged in a change from a contributor to the MapPinClustering project that tracks the number of annotations in a cluster. Then my thought would be that in your ViewController and in viewForAnnotation, you could check the count of childAnnotations and then set the pinColor accordingly. You can see the new changes here: https://github.com/kazmiekr/MapPinClustering/commit/9ab4e0be1243cbfd374eaa905e0b49677fa26fd5

      Delete
  3. Fuelmate comments, 1st sorry I could not find your contact info but wanted to see if this was of your interest
    I would love your tracker to have a field to place the retailer name.

    this would be filled out each fill up and after entering your fill up info the results / summary are displayed showing mpg of last fill up with name of retailer that automaticity takes name from last fill up to keep easy track of mpg with mpg per retailer.

    Also

    Then in your statistics tracker could include a field for mpg based on retailers would also be great

    ReplyDelete
  4. Hi Kevin, This is the only way I can find to contact you. I backed up my data to dropbox and now have a new replacement iphone How do I import saved data files?
    Regards,
    Mick

    ReplyDelete