onthegomap / planetiler

Flexible tool to build planet-scale vector tilesets from OpenStreetMap data fast
Apache License 2.0
1.46k stars 116 forks source link

[BUG] Respect the order of conditions in a match expression array #1091

Closed zstadler closed 1 week ago

zstadler commented 2 weeks ago

Describe the bug When using the array form of a match expression, the order of elements in the array is sometimes ignored.

Consider a schema defining a color attribute taking different OSM tags in descending order of priority. An over-simplification of the expression could be:

    - key: color
      value:
      - if:
          natural: tree
        value: green
      - if:
          historic: memorial
        value: black
      - if:
          tourism: viewpoint
        value: green

An OSM element, that has both a historic=memorial and a tourism=viewpoint tag, is assigned a color=green attribute rather than color=black.

To Reproduce

  1. Use the following my_pois.yml definition

    schema_name: My POIs
    schema_description: My Points of Interest (not openmaptiles)
    attribution: <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy;
    OpenStreetMap contributors</a>
    args:
    area:
    description: Geofabrik area to download
    default: israel-and-palestine
    osm_url:
    description: OSM URL to download
    default: '${ args.area == "planet" ? "aws:latest" : ("geofabrik:" + args.area) }'
    sources:
    osm:
    type: osm
    url: '${ args.osm_url }'
    layers:
    - id: my_pois
    features:
    
    - source: osm
    geometry: point
    
    include_when:
      natural: tree
      historic: memorial
      tourism: viewpoint
    
    attributes:
    - key: historic
    - key: tourism
    
    - key: color
      value:
      - if:
          natural: tree
        value: green
      - if:
          historic: memorial
        value: black
      - if:
          tourism: viewpoint
        value: green
  2. Generate my_pois.pmtiles
    docker run --rm -v .:/data ghcr.io/onthegomap/planetiler generate-custom --download --force --output=/data/my_pois.pmtiles --schema=/data/my_pois.yml
  3. Serve the tiles
    docker run --rm --detach --name my-pois-tileserver -v .:/data -p 8080:8080 maptiler/tileserver-gl --verbose --file /data/my_pois.pmtiles
  4. Node 2156431602 has both a historic=memorial and a tourism=viewpoint tags. Examine its tile and see that it was assigned color: green rather than color: black

Expected behavior I expect the "if" conditions to be evaluated in the order they appear in the array.

I believe this is natural expectation after reading the documentation for the match expression

Regardless of my interpretation of the documentation, I believe this evaluation order would provide a valuable expressibility enhancements for priority-based value expressions.

Screenshots image

Environment:

Additional context It seems like the implementation is unifying all conditions with the same resulting value and thus converting the above into

    - key: color
      value:
      - if:
          natural: tree
          tourism: viewpoint
        value: green
      - if:
          historic: memorial
        value: black

As far as I could see, the order is preserved between different value expressions, i.e. green has higher priority that black.

msbarry commented 1 week ago

Good catch, I put out a fix in #1101, the description there explains what was going on.