Clusterflag

Fast marker clustering for Google Maps supporting hundreds of thousands of markers. A solution to 'too many markers'.

See an awesome demo

View the Project on GitHub bcaller/ClusterFlag

ClusterFlag

Clusters LatLng points to allow a map to display different numbers of markers at different zoom levels. Built with the fast retrieval of hundreds of thousands of Google Maps markers in mind.

Originally developed for a personal project TheyHaveYour.Info which required a clusterer for Google Maps capable of fast browsing and aggregation of 200,000+ map markers.

No production dependencies required.

Even if it takes a few seconds to actually cluster 200000 markers, once it's done you can zoom the map it doesn't need to recalculate (unlike MarkerClusterer in google-maps-utility-library-v3) - browsing the map with ClusterFlag is fast! This greedy clustering algorithm is heavily based on the wonderful Leaflet.markercluster (MIT License).

See an awesome demo

Using ClusterFlag

Include the javascript file which will set the global variable ClusterFlag. Including the script within an IIFE will make the variable non-global.

Include your mapping library and then import the LatLng and LatLngBounds classes into ClusterFlag, e.g.

ClusterFlag.setImports(google.maps.LatLng, google.maps.LatLngBounds);

The LatLng class must have lat() and lng() methods and constructor LatLng(lat, lng). The LatLngBounds class must have constructor LatLngBounds(NE, SW) and methods getSouthWest(), getNorthEast(), contains(latlng), intersects(bounds), extend(latlng) and union(bounds) If you aren't using Google Maps or a mapping library, you can use the MapLatLng and MapBounds classes included in the test folder.

Creating Clusterer

To create the clusterer use var cf = new ClusterFlag.Clusterer(maxZoom, clusterWidth) where:

Clustering

Each marker added to the clusterer can have any properties, but must always have:

To add a marker cf.add(marker) When everything has been added you can call cf.finish() to clean up temporary arrays which are only required if adding more items and to calculate aggregate properties such as child count and centre of mass.

Getting markers

On map events such as zooming or dragging, call cf.get(map.getBounds() : LatLngBounds, zoomLevel) to return an array containing marker objects (the same as you added to the clusterer) and Cluster objects. Actually displaying the results on the map is your problem although a basic example app is included!

Cluster objects

A cluster object has the following properties populated:

Accumulating Aggregate Properties

Calculate aggregate properties of clusters using accumulate(acc, marker, cluster, finish) as seen in Cluster.js. Used in Cluster.recalculateBounds to calculate and attach the bounds, count and centreOfMass properties of clusters. Example to calculate the number of blue and green markers and to attach the result to each cluster object:

    cf.accumulate(function() {
        return {
            blue: 0, green: 0
        }
    }, function(accum, marker) {
        //Our markers will of course need to have a color property
        if (marker.color === 'blue')
            accum.blue++
        else if(marker.color === 'green')
            accum.green++
    }, function(accum, childCluster) {
        accum.blue += childCluster.blueDescendants
        accum.green += childCluster.greenDescendants
    }, function(self, accum) {
        //Every cluster will now have the following properties
        self.blueDescendants = accum.blue
        self.greenDescendants = accum.green
        self.overallColor = accum.blue >= accum.green ? 'blue' : 'green';
    })

License

Copyright 2014 Benjamin Caller

ClusterFlag is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

ClusterFlag is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with ClusterFlag. If not, see http://www.gnu.org/licenses/.

For alternative licensing please contact me. Also it'd be nice to know if you make use of this library in a project.