Tiling GeoJSON data?

I've written my own geojson map tiler driver in ruby. it's a quick and dirty ruby script to create geojson tiles from a postgis database using gdal/ogr. I could not find out how to cut the geojson directly, so I imported the json into a postgis database and exported them using ogr.

ogr is supposed to read geojson but I could not get the driver to work directly. maybe someone else can figure out how. here is how it worked for me using postgis:

requires

  • ruby > 1.9.3, but ruby > 2.0.0 recommended
  • gdal/ogr > 2.0.0, the script utilizes the system command ogr2ogr
  • postgresql > 9.0.0, with postgis > 2.0.0 extension installed

usage

setup environment

#!/usr/bin/env ruby

require 'mkmf'
require 'fileutils'
require './tiler/geojson.rb'

geojson_tiler = Tiler::GeoJson.new

set up working directory

geojson_tiler.set_basedir "/path/to/my/tiles"

enable verbose verbose output if desired

geojson_tiler.debug true

setup postgis database connection and sql query to retrieve geodataset

connection = "'PG:host=localhost dbname=distance user=qwertyu password=asdfghj'"
sql_query = "'SELECT id,flags,kmh,geom_way_web_mercator,time FROM streets WHERE time <= 600 ORDER BY time ASC'"
geojson_tiler.setup_db connection, sql_query

write full tile stack for zoom levels 0, 1, 2 and 3

(0..3).each do |zoom|
  geojson_tiler.write_tiles zoom
end

or write partial tile stack for zoom level 8 in range x: 136..138 and y: 82..84

geojson_tiler.write_tiles 8, 136, 138, 82, 84

syntax is zoom, xmin, xmax, ymin, ymax

result

is a full or partial stack of geojson tiles:

/path/to/my/tiles/0/0/0.json
/path/to/my/tiles/1/0/0.json
/path/to/my/tiles/1/0/1.json
/path/to/my/tiles/1/1/0.json
/path/to/my/tiles/1/1/1.json
/path/to/my/tiles/2/0/0.json
/path/to/my/tiles/2/0/1.json
/path/to/my/tiles/2/0/2.json
/path/to/my/tiles/2/0/3.json
/path/to/my/tiles/2/1/0.json
/path/to/my/tiles/2/1/1.json
/path/to/my/tiles/2/1/2.json
/path/to/my/tiles/2/1/3.json
/path/to/my/tiles/2/2/0.json
/path/to/my/tiles/2/2/1.json
/path/to/my/tiles/2/2/2.json
/path/to/my/tiles/2/2/3.json
/path/to/my/tiles/2/3/0.json
/path/to/my/tiles/2/3/1.json
/path/to/my/tiles/2/3/2.json
/path/to/my/tiles/2/3/3.json
/path/to/my/tiles/3/0/0.json
/path/to/my/tiles/3/0/1.json
/path/to/my/tiles/3/0/2.json
/path/to/my/tiles/3/0/3.json
/path/to/my/tiles/3/0/4.json
/path/to/my/tiles/3/0/5.json
/path/to/my/tiles/3/0/6.json
/path/to/my/tiles/3/0/7.json
/path/to/my/tiles/3/1/0.json
/path/to/my/tiles/3/1/1.json
/path/to/my/tiles/3/1/2.json
/path/to/my/tiles/3/1/3.json
/path/to/my/tiles/3/1/4.json
/path/to/my/tiles/3/1/5.json
/path/to/my/tiles/3/1/6.json
/path/to/my/tiles/3/1/7.json
/path/to/my/tiles/3/2/0.json
/path/to/my/tiles/3/2/1.json
/path/to/my/tiles/3/2/2.json
/path/to/my/tiles/3/2/3.json
/path/to/my/tiles/3/2/4.json
/path/to/my/tiles/3/2/5.json
/path/to/my/tiles/3/2/6.json
/path/to/my/tiles/3/2/7.json
/path/to/my/tiles/3/3/0.json
/path/to/my/tiles/3/3/1.json
/path/to/my/tiles/3/3/2.json
/path/to/my/tiles/3/3/3.json
/path/to/my/tiles/3/3/4.json
/path/to/my/tiles/3/3/5.json
/path/to/my/tiles/3/3/6.json
/path/to/my/tiles/3/3/7.json
/path/to/my/tiles/3/4/0.json
/path/to/my/tiles/3/4/1.json
/path/to/my/tiles/3/4/2.json
/path/to/my/tiles/3/4/3.json
/path/to/my/tiles/3/4/4.json
/path/to/my/tiles/3/4/5.json
/path/to/my/tiles/3/4/6.json
/path/to/my/tiles/3/4/7.json
/path/to/my/tiles/3/5/0.json
/path/to/my/tiles/3/5/1.json
/path/to/my/tiles/3/5/2.json
/path/to/my/tiles/3/5/3.json
/path/to/my/tiles/3/5/4.json
/path/to/my/tiles/3/5/5.json
/path/to/my/tiles/3/5/6.json
/path/to/my/tiles/3/5/7.json
/path/to/my/tiles/3/6/0.json
/path/to/my/tiles/3/6/1.json
/path/to/my/tiles/3/6/2.json
/path/to/my/tiles/3/6/3.json
/path/to/my/tiles/3/6/4.json
/path/to/my/tiles/3/6/5.json
/path/to/my/tiles/3/6/6.json
/path/to/my/tiles/3/6/7.json
/path/to/my/tiles/3/7/0.json
/path/to/my/tiles/3/7/1.json
/path/to/my/tiles/3/7/2.json
/path/to/my/tiles/3/7/3.json
/path/to/my/tiles/3/7/4.json
/path/to/my/tiles/3/7/5.json
/path/to/my/tiles/3/7/6.json
/path/to/my/tiles/3/7/7.json
/path/to/my/tiles/8/136/82.json
/path/to/my/tiles/8/136/83.json
/path/to/my/tiles/8/136/84.json
/path/to/my/tiles/8/137/82.json
/path/to/my/tiles/8/137/83.json
/path/to/my/tiles/8/137/84.json
/path/to/my/tiles/8/138/82.json
/path/to/my/tiles/8/138/83.json
/path/to/my/tiles/8/138/84.json

A little late to the game but if you want vector tiles in mbtiles format then I suggest the following:

(1) tippecanoe: Go to https://github.com/mapbox/tippecanoe and install it, if you are on a mac then brew install tippecanoe; Next you can tile the geojson directly using the following command: tippecanoe -e tiles -l layer_name file.geojson

Next, because they are gzipped using this method, you need to use the following commands(same if you use mbutil to unpack a .mbtiles file and get them that way):

cd /{the tiles folder}
gzip -d -r -S .pbf *;
find . -type f -exec mv '{}' '{}'.pbf \;

Then, in your style.json sources use the tile package in the following way(if you are serving them on a server then use http, if on a device use file:///, etc):

  "sources": {
        "customtiles": {
            "type": "vector",
            "tiles": [
                "{0}/assets/tiles/{z}/{x}/{y}.pbf"
            ],
            "minzoom": 0,
            "maxzoom": 18
        },...

And in your layers section: layers:[{ "id": "rds", "type": "line", "source": "customtiles", "source-layer": "layer_name", "paint": { "line-opacity": 0.8, "line-width": 2, "line-color": "#FF0000" } },...]

(2) Use the nodejs geojson-vt and vt-pbf method. I am personally using this as I am running it on Heroku and do not want to make a module using C++ or make a Heroku add on/use a child process. One great example for this is found at https://github.com/NYCPlanning/geojson2mvt. Essentially you can just change this script to output pbfs instead of mvts and it works.

One big difference is that geojson-vt simplifies a lot and tippecanoe does not. Thus geojson-vt tiles are much smaller and I have not found the quality degrade too much. For an on-the fly version check out this example: http://fuzzytolerance.info/blog/2016/07/31/Adding-GeoJSON-and-MVT-to-PostGIS-HTTP-API/