3

I want to get geo data as geojson for geojson tile layer requests in leaflet. I set up a geojson layer like this:

https://github.com/glenrobertson/leaflet-tilelayer-geojson/

A php script answers requests and reads polygon geometries as geojson with ST_AsGeoJSON from postgreSQL.

Each request is mapped to those php file by an htaccess to geo.php.

I can see all requests in Google Chrome in developer tools on network tab. It looks like:

.../geo.php/12/2165/1356.json

with following response:

{"type":"MultiPolygon","coordinates":[[[[10.42523568,51.79692078],[10.4301414,51.80612562],[10.43525988,51.82238007],[10.4370354,51.82429887],[10.44274896,51.82353972],[10.43982036,51.81211476],[10.45402992,51.8089752],[10.45623312,51.80868153],[10.46150892,51.81088257],[10.46547216,51.81090543],[10.466424,51.8089905],[10.46608272,51.80111316],[10.45419408,51.79484178],[10.45109448,51.79397202],[10.4386608,51.79716873],[10.42523568,51.79692078]]],[[[10.4174298,51.83180235],[10.42399224,51.83617779],[10.42398648,51.83724978],[10.42081272,51.83961867],[10.4292108,51.84436419],[10.43632332,51.84550854],[10.4398488,51.84357831],[10.44083196,51.83844759],[10.425852,51.83020782],[10.42100424,51.83043291],[10.4174298,51.83180235]]]]}

Output is calculated by x,y and z as zoom. Those parameters are calculated and transformed by the following function:

function tileCoord2BBox($url)
{
    $parsed = explode("/",$url);

    $z = $parsed[3];
    $x = $parsed[4];
    $y = $parsed[5];

    $n = pow(2, $z);

    $lon1 = $x / $n * 360.0 - 180.0;
    $lat1 = rad2deg(atan(sinh(pi() * (1 - 2 * $y / $n))));

    $lon2 = ($x + 1) / $n * 360.0 - 180.0;
    $lat2 = rad2deg(atan(sinh(pi() * (1 - 2 * ($y + 1) / $n))));

    $bbox =  array();
    $bbox['lon1'] = $lon1;
    $bbox['lat1'] = $lat1;
    $bbox['lon2'] = $lon2;
    $bbox['lat2'] = $lat2;

    return $bbox;
}

Reference: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

Those return values are used in sql statement defininig a bounding box which selects those polygons which are in that tile. Postgres returns geojson for resulting geometry.

I tested the responses with http://geojsonlint.com/ They all looks great.

But on leaflet map, I only see a partial polygon on only one tile. When I zoom or pan over leaflet map then another tile shows up with partial polygon.

In tilelayer.geojson.js on line 187 Chrome reports many errors with following output:

Uncaught TypeError: Cannot read property 'type' of undefined TileLayer.GeoJSON.js:187 L.TileLayer.GeoJSON.L.TileLayer.Ajax.extend.addTileData TileLayer.GeoJSON.js:187 L.TileLayer.GeoJSON.L.TileLayer.Ajax.extend._tileLoaded TileLayer.GeoJSON.js:246 (anonymous function)

It is reported on this line: https://github.com/glenrobertson/leaflet-tilelayer-geojson/blob/master/TileLayer.GeoJSON.js#L187

I think my output from server is ok. I will see a result on one tile and http://geojsonlint.com/ shows correctly that those data is valid for all the other requests. Also all requests have valid output.

Why is it still showing an error even though all responses seem to be valid?

I seek a complete example with client and server side code using a geojson layer and with postgres or similar.

I do not know how I can solve my problem.

1 Answer 1

1

I've done very similar thing only that i use geoserver vectortiles plugin. Your BBOX transformation function looks fine. The generated errors denote something at the response. Just make sure that you pass the correct BBOX order to your sql statement, i.e $lon1.",".$lat2.",".$lon2.",".$lat1

And in my case, i slightly modified the _xhrHandler function at TileLayer.GeoJSON.js just to deal with the output, start from line 17

if ((s >= 200 && s < 300 && s != 204) || s === 304) {
   tile.datum = JSON.parse(req.responseText);
   layer._tileLoaded(tile, tilePoint);
} else {
   layer._tileLoaded(tile, tilePoint);
}

into something like this

if ((s >= 200 && s < 300 && s != 204) || s === 304) {

    if(req.responseText = "") return;
    if(req.responseText == null && req.responseText == undefined) return;

    try {
        tile.datum = JSON.parse(req.responseText);
        layer._tileLoaded(tile, tilePoint);
    }catch (err) {
        //console.log(err);
    }

 } else {
       layer._tileLoaded(tile, tilePoint);
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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