mapbox / tippecanoe

Build vector tilesets from large collections of GeoJSON features.
BSD 2-Clause "Simplified" License
2.71k stars 429 forks source link

Feature filter error with valid Mapbox Style Expression #836

Open kylebarron opened 4 years ago

kylebarron commented 4 years ago

It appears that -j doesn't work with an expression, but only the deprecated filter syntax, is that true? (Given that the link in the README points to https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter, which says that it's deprecated syntax).

I'm making vector tiles from contour lines in a newline-delimited GeoJSON file. I'm trying to include only contours that have an elevation that is a multiple of 20, but I'm getting errors of key is not a string. Here's a simplified example, with data at the bottom:

> tippecanoe -Z11 -z13 -P -y ele_m -l contour_10m -j '{"*": ["==", ["%", ["get", "ele_m"], 20], 0]}' -f -o out.mbtiles contours.geojson
"!has" key is not a string: ["==",["%",["get","ele_m"],20],0]
"!has" key is not a string: ["==",["%",["get","ele_m"],20],0]

I believe that this is a valid expression because a simplified style that uses it as a filter passes gl-style-validate: tempstyle.json

{
  "version": 8,
  "name": "teststyle",
  "sources": {
    "contours": {
      "type": "vector",
      "url": ""
    }
  },
  "sprite": "https://example.com",
  "glyphs": "https://example.com/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "contour_label2",
      "type": "symbol",
      "source": "contours",
      "source-layer": "contour_10m",
      "filter": ["==", ["%", ["get", "ele_m"], 20], 0],
      "layout": {},
      "paint": {}
    }
  ],
  "id": "teststyle"
}

Example data: contours.geojson

{ "type": "Feature", "properties": { "ID": 0, "ele_m": 200.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.0076389, 33.0005556 ], [ -116.0076389, 33.0005093 ], [ -116.0075463, 33.0004784 ], [ -116.0074537, 33.0004861 ], [ -116.0073611, 33.0005093 ], [ -116.0073611, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 1, "ele_m": 210.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.0328858, 33.0005556 ], [ -116.0328858, 33.0005093 ], [ -116.0328241, 33.0004167 ], [ -116.0327315, 33.0004167 ], [ -116.0326389, 33.0005093 ], [ -116.0326389, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 2, "ele_m": 220.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1497685, 33.0005556 ], [ -116.1497685, 33.0005093 ], [ -116.1497685, 33.0005093 ], [ -116.1497685, 33.0005093 ], [ -116.1497685, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 3, "ele_m": 220.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1461883, 33.0005556 ], [ -116.1461883, 33.0005093 ], [ -116.14625, 33.000463 ], [ -116.1463426, 33.0004784 ], [ -116.1464352, 33.0004784 ], [ -116.1465278, 33.000463 ], [ -116.1465741, 33.0005093 ], [ -116.1465741, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 4, "ele_m": 220.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1409722, 33.0005556 ], [ -116.1409722, 33.0005093 ], [ -116.1409722, 33.0005093 ], [ -116.1410648, 33.0005093 ], [ -116.1411574, 33.0005093 ], [ -116.1411574, 33.0005093 ], [ -116.1411574, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 5, "ele_m": 230.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1105093, 33.0005556 ], [ -116.1105093, 33.0005093 ], [ -116.1104167, 33.0004907 ], [ -116.1103241, 33.0005093 ], [ -116.1103241, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 6, "ele_m": 230.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.0056944, 33.0005556 ], [ -116.0056944, 33.0005093 ], [ -116.0056944, 33.0005093 ], [ -116.0056944, 33.0005093 ], [ -116.0056944, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 7, "ele_m": 240.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.0543056, 33.0005556 ], [ -116.0543056, 33.0005093 ], [ -116.0543056, 33.0005093 ], [ -116.0543981, 33.000463 ], [ -116.0544907, 33.0004475 ], [ -116.0545833, 33.000463 ], [ -116.0546759, 33.0005093 ], [ -116.0546759, 33.0005093 ], [ -116.0546759, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 8, "ele_m": 270.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1717747, 33.0005556 ], [ -116.1717747, 33.0005093 ], [ -116.171713, 33.0004167 ], [ -116.1716204, 33.000463 ], [ -116.1715895, 33.0005093 ], [ -116.1715895, 33.0005556 ] ] } }
{ "type": "Feature", "properties": { "ID": 9, "ele_m": 280.0 }, "geometry": { "type": "LineString", "coordinates": [ [ -116.1694907, 33.0005556 ], [ -116.1694907, 33.0005093 ], [ -116.1694907, 33.0005093 ], [ -116.1694907, 33.0005093 ], [ -116.1694907, 33.0005556 ] ] } }
> tippecanoe --version
tippecanoe v1.34.3
kylebarron commented 4 years ago

For what it's worth, I found a workaround by using jq as a filter, i.e. to select only contours at a 50-meter interval at zoom 11 and 20-meter interval at zoom 12:

tippecanoe \
    `# Set min zoom to 11` \
    -Z11 \
    `# Set max zoom to 13` \
    -z13 \
    `# Read features in parallel; only works with GeoJSONSeq input` \
    -P \
    `# Keep only the ele_m attribute` \
    -y ele_m \
    `# Put contours into layer named 'contour_10m'` \
    -l contour_10m \
    `# Filter contours at different zoom levels` \
    -C 'if [[ $1 -le 11 ]]; then jq "if .properties.ele_m % 50 == 0 then . else {} end"; elif [[ $1 -eq 12 ]]; then jq "if .properties.ele_m % 20 == 0 then . else {} end"; else jq "."; fi' \
    `# Export to contour_10m.mbtiles` \
    -o data/contour_10m.mbtiles \
    data/contour_10m/*.geojson
e-n-f commented 4 years ago

Thanks. Unfortunately what you are running into is that Tippecanoe currently only supports the old expression syntax, not the new full GL style spec expression language. I would like to rectify this someday but unfortunately can't prioritize it at the moment.

pm0u commented 3 months ago

Unfamiliar with this older syntax myself I found this somewhat helpful: https://docs.mapbox.com/style-spec/reference/other/#other-filters

to fix my usage essentially replace ["get", "featureProperty"] with "featureProperty"