[GIS] Leaflet marker cluster not working on GeoJSON with MultiPoint geometry

geojsonjavascriptleaflet

I have a GeoJSON file of fly tipping incidents that I have managed to display on a basic Leaflet map.

I am now trying to incorporate the marker cluster plugin, but I am having problems as it does not seem to be clustering the markers when zooming out.

My code is below, is there an obvious reason why it is not working? I am receiving no error messages.

(I followed the tutorial from http://maptimeboston.github.io/leaflet-intro/)

// initialize the map
  var map = L.map('map').setView([51.394845, -0.538516], 12);

  // load a tile layer
  L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    {
      maxZoom: 17,
      minZoom: 9
    }).addTo(map);

  // load GeoJSON from an external file
  $.getJSON("data/incidents.geojson",function(data){
    // add GeoJSON layer to the map once the file is loaded
    var incidents = L.geoJson(data,{
      pointToLayer: function(feature,latlng){
        var marker = L.marker(latlng);
        marker.bindPopup('Fly tip reported on ' + feature.properties.date_rec + '<br/>' + 'Reported waste type: ' + feature.properties.waste_type + '<br/>' + 'Located on land type: ' + feature.properties.land_type);
        return marker;
      }
    });
    var clusters = L.markerClusterGroup();
    clusters.addLayer(incidents);
    map.addLayer(clusters);
  });

Best Answer

This is because in your GeoJSON data, you use MultiPoint geometry type.

{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "properties": {
      "date_rec": "2016\/01\/13",
      "land_type": "…",
      "waste_type": "…"
    },
    "geometry": {
      "type": "MultiPoint",
      "coordinates": [
        [2.35, 48.86]
      ]
    }
  }]
}

So Leaflet creates a GeoJSON layer group with nested groups: incidents is a group of groups, each containing a single point (marker).

Now this does not make any difference with the use of Point geometry type, except in the context of Leaflet.markercluster plugin: when you instruct clusters.addLayer(incidents), Marker Cluster sees that incidents is a group and extracts the first level children. So in your case it is an array of Layer Groups again. Then it tries to add those layers into itself, but it no longer checks if they are Groups: it now just sees that the layers are non "point" layers (since they are groups), so it thinks they cannot be clustered. That is why you see your markers without clustering functionality.

To avoid this behaviour, instead of adding all your markers in bulk, you can add each "group with 1 marker" to clusters group, e.g. through the onEachFeature function of the GeoJSON factory:

$.getJSON("incidents.geojson", function(data) {
  var clusters = L.markerClusterGroup();
  var incidents = L.geoJson(data, {
    pointToLayer: function(feature, latlng) {
      var marker = L.marker(latlng);
      marker.bindPopup('Fly tip reported on ' + feature.properties.date_rec + '<br/>' + 'Reported waste type: ' + feature.properties.waste_type + '<br/>' + 'Located on land type: ' + feature.properties.land_type);
      return marker;
    },
    onEachFeature: function (feature, layer) {
      layer.addTo(clusters);
    }
  });
  map.addLayer(clusters);
});

Demo: http://plnkr.co/edit/9sOXgqlkwmxx0XcKWdos?p=preview

Of course the proper solution would be to re-factor your GeoJSON data to use Point geometry type instead of MultiPoint, since each of your features has only 1 point.

Note: your server sends a force-download header with your GeoJSON file, so jQuery has troubles (at least within JSFiddle) to load it through AJAX.


EDIT: submitted issue #622 on Leaflet.markercluster repository.

Related Question