7

I am using TileStache to combine and server multiple vector layers in a single Mutli-Response GeoJSON tile, which is basically all my individual tiles/layers (GeoJSONs containing either roads, pois, buildings) merged into one.

When TileStache combines the layers, the original layer name (like "roads" or "pois") is added before the features of that layer are included in the GeoJSON, so when I parse the tile to render it in leaflet (using the TileLayer.GeoJSON plugin) it doesn't recognize the objects in the GeoJSON file. It just skips over them and doesn't render anything.

This is what the sample response looks like:

{
    "roads": {
        "type": "FeatureCollection",
        "features": [{
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [73.12500, 33.61371],
                    [73.12432, 33.61462]
                ]
            },
            "type": "Feature",
            "id": "ff7274b342",
            "clipped": true,
            "properties": {
                "priority": 5.00000,
                "name": "Islamabad Highway"
            }
        }]
    },
    "boundary": {
        "type": "FeatureCollection",
        "features": []
    },
    "pois": {
        "type": "FeatureCollection",
        "features": [{
            "geometry": {
                "type": "Point",
                "coordinates": [73.10332, 33.60876]
            },
            "type": "Feature",
            "id": "0d39282b10",
            "clipped": true,
            "properties": {
                "priority": 1,
                "name": "BENAZIR BHUTTO INTERNATIONAL AIRPORT ISLAMABAD"
            }
        }]
    },
    "cartographic": {
        "type": "FeatureCollection",
        "features": [{
            "geometry": {
                "type": "MultiPolygon",
                "coordinates": 
                    [

                        [
                            [73.10095, 33.61462],
                            [73.10065, 33.61438],
                            [73.09731, 33.61462],
                            [73.10095, 33.61462]
                        ]
                    ]
            },
            "type": "Feature",
            "id": "963cec5810",
            "clipped": true,
            "properties": {
                "category": 6,
                "priority": 5,
                "kind": "port places",
                "name": "BENAZIR BHUTTO INTERNATIONAL AIRPORT"
            }
        }
}

And this is the code I am using in Leaflet:

var geojsonURL1 = 'http://localhost:8080/composite/{z}/{x}/{y}.json'; 
var geojsonTileLayer1 = new L.TileLayer.GeoJSON(geojsonURL1, { maxZoom:22,
        //clipTiles: true,
        unique: function (feature) {
            return feature.id; 
        }
    }, {
        style: style,
        onEachFeature: function (feature, layer) {
            if (feature.properties) {
                var popupString = '<div class="popup">';
                for (var k in feature.properties) {
                    var v = feature.properties[k];
                    popupString += k + ': ' + v + '<br />';
                }
                popupString += '</div>';
                layer.bindPopup(popupString);
            }
            if (!(layer instanceof L.Point)) {
                layer.on('mouseover', function () {
                    layer.setStyle(hoverStyle);
                });
                layer.on('mouseout', function () {
                    layer.setStyle(style);
                });
            }
        }
    }
);

map.addLayer(geojsonTileLayer);

How can I render them in Leaflet? Are there any viable alternatives to render the GeoJSON tiles?

7

The so-called "multiresponse GeoJSON object" is not valid GeoJSON. Split the data before instantiating the Leaflet GeoJSON layers, e.g.:

// Assuming that you've already fetched the data off the network
var data = {
  roads: {
    type: "FeatureCollection",
    features: .....
  },
  pois: {
    type: "FeatureCollection",
    features: .....
  },
  .......
};

for (var featureLayer in data) {
    console.log(featureLayer); // e.g. "roads", "pois", etc
    var geoJson = data[featureLayer]; // This is now a valid geojson object

    // Now we can spawn Leaflet layers based on valid GeoJSON
    var layer = L.geoJson(geoJson, {...}).addTo(map);
}
  • How can I store the JSON response I get in the variable when I am accessing the data using http://localhost:8080/composite/{z}/{x}/{y}.json? – Hasan Mustafa Feb 12 '16 at 10:04
  • 1
    The problem is that you're not just fetching "multiresponse GeoJSON", you're fetching "multiresponse GeoJSON tiles". You might want to have a look at the code for TileLayer.GeoJSON, and see how the addTileData method receives the geojson and creates features - you should be able to extend the TileLayer.GeoJSON class and wrap the behaviour of that method, so it can handle the payload. I've written a gist for inspiration. – IvanSanchez Feb 12 '16 at 12:16
  • You're right I am dealing with Tiles, I've updated the question to reflect that now. I am looking into the code for TileLayer.GeoJSON while taking inspiration from your gist. – Hasan Mustafa Feb 12 '16 at 12:58
6

I am now using Tangram to display my tiles, Tangram allows me to parse the composite response with no issues at all, it can identify the layers with just the name I supply, and it has good documentation and support.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.