3

I have some vector layers in a shapefile that I would like to display in the Google Maps Javascript API. I recently learned that you can generate GeoJSON from shapefiles in the correct CRS using QGIS: Convert Shapefiles to GeoJSON? that worked well for me, but the problem is that the file is large - the resulting JSON is 250MB in my case. So I'd like to have it as a collection of tiles instead. I discovered that the Google Maps API can load tiles from GeoJSON as described here

https://stackoverflow.com/questions/27284251/vector-tiles-with-google-maps-v3

But I can't find a way to actually generate tiled GeoJSON like that. I noticed that both QGIS and MapTiler have an option to write vector tiles in the XYZ structure, but the individual files come out as .pbf, which Google Maps can't handle. So I am looking to create them as GeoJSON. Is there a way to do that?

Edit: In searching around, I also discovered tippecanoe and was able to run it, but it looks like it also generates pbf files. I want the individual tiles in geoJSON.

Edit 2: I then discovered that I could run tippecanoe-decode on the very same pbf files that tippecanoe itself had created. While a little weird, it seemed to work and generated JSON that looked like below, which is throwing errors in Google, I'm assuming because of the nested FeatureCollection...

    {
  "type": "FeatureCollection",
  "properties": {
    "zoom": 18,
    "x": 42016,
    "y": 91728
  },
  "features": [
    {
      "type": "FeatureCollection",
      "properties": {
        "layer": "sea",
        "version": 2,
        "extent": 4096
      },
      "features": [
        {
          "type": "Feature",
          "properties": {
            "autocad_el": 0,
            "autocad_th": 0,
            "autocad_wi": 0,
            "autocad_co": 106,
            "autocad_la": "C_1CON_ROAD_CURB",
            "autocad_li": "ByLayer"
          },
          "geometry": {
            "type": "LineString",
            "coordinates": [
              [
                -122.299832,
                47.442148
              ],
              [
                -122.299805,
                47.44213
              ],
              [
                -122.299647,
                47.442021
              ],
              [
                -122.299621,
                47.442003
              ]
            ]
          }
        },
        {
          "type": "Feature",
          "properties": {
            "autocad_el": 0,
            "autocad_th": 0,
            "autocad_wi": 0,
            "autocad_co": 106,
            "autocad_la": "C_1CON_ROAD_CURB",
            "autocad_li": "ByLayer"
          },
          "geometry": {
            "type": "LineString",
            "coordinates": [
              [
                -122.299832,
                47.442153
              ],
              [
                -122.299805,
                47.442135
              ],
              [
                -122.29964,
                47.442021
              ],
              [
                -122.299613,
                47.442003
              ]
            ]
          }
        }
      ]
    }
  ]
}
2
  • My advice is to use Postgres with Post GIS extension where you can have more control over output based on your query structure.
    – Kumbra
    Commented Oct 23, 2020 at 22:02
  • 1
    You could use MapBox Tippecanoe: github.com/mapbox/tippecanoe for one time creation.
    – TomazicM
    Commented Oct 27, 2020 at 10:40

1 Answer 1

3
+100

I would recommend using GeoServer for this.
It can generate tiles as geoJSON natively and can installed very easily,
setting the GEOWEBCACHE_CACHE_DIR environment variable will let you choose where your cache of XYZ tiles will be genrated.
You would need to add a data source from a folder of shapefiles, and then publish the layer from the file you want to use.
Use this guide if you have any proplems: Publishing a shapefile
After publishing the layer (which can happen locally) you will need to enable caching geojson

enable publishing geojson

You will then need to seed the tiles in EPSG:900913 (which is Google Maps Global Mercator or more simply called web mercator) which is compatible with xyz tiles.

To get your tiles in XYZ file structure you will need GeoServer version 2.17 and up. You will need to create a file blob store with SLIPPY layout and set it as the blob store for your layer.

creating your blob store

setting the blob store

You can now seed your geojson cache and find your files inside the folder of the blob store.

You can find more explanations in the official guide

enter image description here

EDIT

Just so this is clear, what is described above, will give you a cache of static geojson tiles in an XYZ folder layout.
This means something like this {z}/{x}/{y}.geojson These tiles can be copied later to a S3 Bucket or whatever other way you want to serve them.
For the test layer I seeded yesterday the folder layout looks like this:

enter image description here

6
  • That's intriguing, but for my purposes I would strongly prefer to generate the tiles statically, as I would do for raster tiles. I already have a mechanism for serving them from S3, among other reasons.
    – Dan
    Commented Oct 26, 2020 at 16:08
  • 1
    This will work for both raster, geojson and pbf. You are just setting the folder structure to be the same as required for xyz tiles.
    – Dror Bogin
    Commented Oct 26, 2020 at 17:05
  • What I meant was, I don't want to have to have a server running all the time for this. i'd like to just generate the tiles and export them to a static structure.
    – Dan
    Commented Oct 26, 2020 at 22:39
  • 1
    Again, this method gives you what you want, look at the edit i added at the end of the answer. You can switch the server off the second the seeding is done, though i would check the results first.
    – Dror Bogin
    Commented Oct 27, 2020 at 6:11
  • Thanks. It doesn't seem that Google is actually able to read the geoJSON in EPSG:900913, it expects lat/lng, but I was able to cache the image tiles instead and that works well enough for me!
    – Dan
    Commented Oct 27, 2020 at 17:07

Your Answer

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

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