Skip to content

Releases: gmpassos/geo_tile_builder

v0.4.0 — traffic controls

Choose a tag to compare

@gmpassos gmpassos released this 15 Sep 20:05
a8e7538

Traffic controls

DeliverySchema gains a signal point layer carrying the things a vehicle has to stop at: traffic lights, stop and give-way signs, and level crossings. A navigation map that cannot show a junction's lights is missing the one feature at that junction a driver plans around.

Four classes, not the dozen OSM offers, and the line is drawn at things that stop a vehicle. highway=crossing is the notable exclusion — an unsignalised pedestrian crossing appears several times a block, would outnumber every other control by an order of magnitude, and means nothing to a driver at speed. A signalised crossing (crossing=traffic_signals, or crossing:signals=yes) is a set of lights and is kept, which is why the exclusion is a specific test rather than a blanket one.

Emitted from z14 rather than from the schema's minZoom: a set of lights is meaningless on a map of a whole city, and carrying a few thousand points through eight zoom levels that never display one is pure archive weight.

readsNodes is now a decision rather than a constant

DeliverySchema reads the node stream only when it is carrying signals, and includeSignals: false restores the old behaviour exactly — no signal layer, no node decoding.

That flag is the real cost of this change and it is worth stating plainly: node tags live in a packed stream a reader can otherwise skip whole, so wanting any node means decoding tens of millions of entries that are almost all untagged shape points. The cost is per build, not per pack byte — the tiles themselves grow by points with one short attribute, a few thousand in a city against a road network of hundreds of thousands of segments.

geoTileBuilderVersion / geoTileBuilderId

So a tool that bakes an artefact can record which release baked it. Dart cannot read pubspec.yaml at runtime and a compiled executable has none beside it, so the version has to be repeated in code; test/version_test.dart reads the pubspec and compares.

The motivation is a real defect rather than tidiness: map packs in production carry an empty builder string, because the only way to set one was a hand-typed flag that defaulted to nothing. A build recorded as 0.3.0 while 0.4.0 ran would be worse than one recorded as nothing, because it looks like an answer.

Full changelog: https://github.com/gmpassos/geo_tile_builder/blob/master/CHANGELOG.md

v0.3.0

Choose a tag to compare

@gmpassos gmpassos released this 07 Sep 07:46
  • Areas. Polygons are now produced, from both closed ways and multipolygon
    relations. Verified end to end and on screen: Monaco's harbour basins render
    as basins, not as an inverted fill flooding the tile — which is what a
    winding mistake looks like.
  • RingBuilder (new):
    • assemble joins a relation's member ways into closed rings. Members arrive
      in no order and no consistent direction, so fragments are indexed by both
      endpoints, reversed where needed, and chained until a ring closes.
      Fragments that never close are dropped: an unclosed boundary is not an
      area, and regional extracts contain them routinely.
    • orient imposes winding — exterior positive, holes negative in tile
      coordinates — rather than trusting source data, which respects no
      convention.
    • nest attaches each hole to the smallest exterior ring containing it,
      because rings nest (an island in a lake on an island) and choosing the
      largest container punches the hole through the wrong shape. Holes inside
      nothing are dropped rather than guessed at.
    • containsPoint, even–odd ray test.
  • TileBuilder:
    • Added a relations pass, run first — a multipolygon's member ways
      usually carry no tags, so which geometry to retain is only knowable once
      the relations are known.
    • Polygons are clipped as rings and re-nested per tile, since clipping can
      remove a hole or cut an area away entirely.
    • Features now carry multiple parts, so one feature can be several disjoint
      areas with their own holes.
  • PmTilesWriter: centerZoom is clamped into the zoom range actually
    written.
    • Why: a caller passes the centre of the range it asked for, which need
      not be the range it got. The mismatch produced a header that strict
      readers reject outright — found by the pmtiles oracle, not by inspection.
  • TileBuildReport.tiles documents that zero means an empty archive, whose
    empty directory strict readers reject: a failed build, not a small one.
  • OpenMapTilesSchema (new): a subset of the OpenMapTiles schema using its own
    layer and field names, so an existing style — Dark Matter, Positron, OSM
    Liberty — renders the output unmodified and degrades over the layers this
    subset omits.
    • Implements transportation, transportation_name, water, waterway,
      building and place.
    • On Monaco it costs 2x the delivery schema (310 kB vs 158 kB), of which
      buildings alone are 112 kB. That is the price of compatibility, now
      measured rather than guessed.
  • Point features. TileSchema.node was declared but never called; tagged
    nodes now become point features, which is what place labels are.
    • TileSchema.readsNodes (new) declares whether a schema wants them. Node
      tags live in a packed stream a reader can skip entirely, so a schema
      without labels — DeliverySchema — never pays to decode tens of millions
      of untagged shape points.