mapbox / tilesets-cli

CLI for interacting with the Mapbox Tilesets API and Mapbox Tiling Service
https://docs.mapbox.com/mapbox-tiling-service
BSD 2-Clause "Simplified" License
125 stars 27 forks source link

Abstract line delimiting of inputs #21

Closed mapsam closed 5 years ago

mapsam commented 5 years ago

Right now many Tilesets API docs suggest using the tippecanoe-json-tool for converting geojson to ld-geojson. We should avoid requiring folks to install two libraries, and create a tilesets convert command (name TBD) that uses shapely and the other python libraries set up to do this.

cc @mapbox/mts @dnomadb

dnomadb commented 5 years ago

We can use https://github.com/mapbox/cligj for the command line tool, which will make any geojson either (a) read from stdin or (b) passed as a filepath into a geojson feature iterable.

For example, with this:

import click

import cligj

@click.command()
@cligj.features_in_arg
def dothis(features):
    click.echo(list(features))

if __name__ == "__main__":
    dothis()

We'll get the same input for any of:

$ cat {GeoJSON Feature Collection}.geojson | python ./gj.py
$ cat {L-D GeoJSON }.geojson.ld | python ./gj.py
$ python ./gj.py {Path to GeoJSON Feature Collection}.geojson

EG:

$ echo '{"features": [{"geometry": {"coordinates": [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], "type": "Polygon"}, "id": "(0, 0, 0)", "properties": {"title": "XYZ tile (0, 0, 0)"}, "type": "Feature"}], "type": "FeatureCollection"}' | python ./gj.py
[{'geometry': {'coordinates': [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], 'type': 'Polygon'}, 'id': '(0, 0, 0)', 'properties': {'title': 'XYZ tile (0, 0, 0)'}, 'type': 'Feature'}]

$ echo '{"geometry": {"coordinates": [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], "type": "Polygon"}, "id": "(0, 0, 0)", "properties": {"title": "XYZ tile (0, 0, 0)"}, "type": "Feature"}' | python ./gj.py
[{'geometry': {'coordinates': [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], 'type': 'Polygon'}, 'id': '(0, 0, 0)', 'properties': {'title': 'XYZ tile (0, 0, 0)'}, 'type': 'Feature'}]

$ echo '{"features": [{"geometry": {"coordinates": [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], "type": "Polygon"}, "id": "(0, 0, 0)", "properties": {"title": "XYZ tile (0, 0, 0)"}, "type": "Feature"}], "type": "FeatureCollection"}' > /tmp/some-geojson.geojson && python ./gj.py /tmp/some-geojson.geojson
[{'geometry': {'coordinates': [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], 'type': 'Polygon'}, 'id': '(0, 0, 0)', 'properties': {'title': 'XYZ tile (0, 0, 0)'}, 'type': 'Feature'}]

For multiple files it will even work:

$ python ./gj.py {Path to GeoJSON Feature Collection 1}.geojson {Path to GeoJSON Feature Collection 2}.geojson

$ python ./gj.py /tmp/some-dir/*geojson

EG

echo "[0, 0, 0]" | mercantile children | parallel 'fp=$(xt -d - <<< {}); mercantile shapes <<< {} > /tmp/some-geojson-prefix-$fp.geojson' && python ./gj.py /tmp/some-geojson*geojson
[{'bbox': [-180.0, 0.0, 0.0, 85.0511287798066], 'geometry': {'coordinates': [[[-180.0, 0.0], [-180.0, 85.0511287798066], [0.0, 85.0511287798066], [0.0, 0.0], [-180.0, 0.0]]], 'type': 'Polygon'}, 'id': '(0, 0, 1)', 'properties': {'title': 'XYZ tile (0, 0, 1)'}, 'type': 'Feature'}, {'bbox': [-180.0, -85.0511287798066, 0.0, 0.0], 'geometry': {'coordinates': [[[-180.0, -85.0511287798066], [-180.0, 0.0], [0.0, 0.0], [0.0, -85.0511287798066], [-180.0, -85.0511287798066]]], 'type': 'Polygon'}, 'id': '(0, 1, 1)', 'properties': {'title': 'XYZ tile (0, 1, 1)'}, 'type': 'Feature'}, {'bbox': [0.0, 0.0, 180.0, 85.0511287798066], 'geometry': {'coordinates': [[[0.0, 0.0], [0.0, 85.0511287798066], [180.0, 85.0511287798066], [180.0, 0.0], [0.0, 0.0]]], 'type': 'Polygon'}, 'id': '(1, 0, 1)', 'properties': {'title': 'XYZ tile (1, 0, 1)'}, 'type': 'Feature'}, {'bbox': [0.0, -85.0511287798066, 180.0, 0.0], 'geometry': {'coordinates': [[[0.0, -85.0511287798066], [0.0, 0.0], [180.0, 0.0], [180.0, -85.0511287798066], [0.0, -85.0511287798066]]], 'type': 'Polygon'}, 'id': '(1, 1, 1)', 'properties': {'title': 'XYZ tile (1, 1, 1)'}, 'type': 'Feature'}, {'geometry': {'coordinates': [[[-180, -85.051], [-180, 85.051], [180, 85.051], [180, -85.051], [-180, -85.051]]], 'type': 'Polygon'}, 'id': '(0, 0, 0)', 'properties': {'title': 'XYZ tile (0, 0, 0)'}, 'type': 'Feature'}]

This is a change to the current pattern of passing in paths / folders, but I think avoiding side-effects and implicit relationships (pass the geojsons themselves not the filepath) is preferable anyways.

dnomadb commented 5 years ago

@mapsam also note that coupled with the fiona cli (which cligj depends on), it becomes arbitrary to do:

fio cat <some shapefile>.shp | ./gj.py
dnomadb commented 5 years ago

Added this in 0.3.0 #22