- NodeStore eviction was a min_by_key scan of the whole cache per miss;
with the Europe-sized cache that scan became the bottleneck (1.2k
ways/s). FIFO queue eviction is O(1) amortized
- way resolution now fans out over a resolver worker pool (each with
its own NodeStore handle and cache slice); geometry is localized on
the workers via prepare_lines/prepare_polygons and a single writer
thread owns the spool, so the on-disk format is untouched. The
id-ordered relation-way store stays on the ordered consumer thread
- Noord-Holland: pass 3 32.6s -> 5.6s, full conversion 25.7s; per-layer
feature counts identical (byte diff is record interleave order only)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two fixes to the detail converter that spent 10+ hours on Europe:
- visit_pbf: ordered parallel decode — blob reads stay serial, the
zlib+protobuf decode fans out over a worker pool, and the callback
runs in exact file order on the calling thread, so id-ordered store
builders need no changes
- NodeStore group cache: 256 groups (128MB) thrashed on Europe-scale
way resolution (~115us/way of cache-miss zlib re-decode, ~8.6k
ways/s); now MAKEPAD_NODE_CACHE_MIB (default 8GB), way resolution
~370k/s
Noord-Holland: 61s end-to-end, output byte-identical to the slow
converter (7547 tiles, same bytes).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Hella Haasseplein root cause: pedestrian squares in osm_lines arrive
as LineStrings, so `closed` was never set and the area admission
skipped them — detect implicit closure (first==last) and mark the
ring closed for the fill pass
- icon collision: doors and generic dots now yield to real symbols
(the recycling icon was losing to the building entrance beside it);
entrances gate at z18 like carto
- tools: tagprobe <pbf> <name> — dump every OSM element matching a
name, for answering "how is this actually tagged" without overpass
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
score_search_hit: settlements are near-immune to distance ("brussels"
from Amsterdam means Bruxelles, not the closest Brusselsestraat),
POIs/streets keep strong local bias, and a number token signals
address intent. nav-build --places-only scans a pbf for settlement
nodes into a compact index (Europe: 1.31M places, 67MB, 60s); the app
merges it with the regional full index, deduping same-name near hits.
Route overlay decimation now measures against the last drawn point,
bounding the error at ~1.5px — pairwise skipping compounded and
visibly reshaped the route when zoomed out.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Conversion tooling (tools/map_tiles): curated Shortbread base pyramid
from a VersaTiles planet archive (bbox extract, brotli->gzip transcode
parallelized per 256x256 block), all-tag native OSM pbf detail
converter, pbf audit, and nav-build/nav-probe producing the routing
graph + search index artifacts. download_map.sh orchestrates pinned
downloads and conversions. mbtile_reader writer now skips SQLite's
lock-byte page at byte offset 1 GiB — allocating through it corrupted
every database over 1 GiB ("2nd reference to page 16385"); the 31 GB
Europe conversion passes integrity checks.
Navigation (libs/map_nav, new): region.search place/POI/street/address
index (prefix autocomplete, NL/EN category synonyms, proximity
ranking) and region.graph routing graph (CSR directed edges,
car/bike/foot speeds, oneway, turn restrictions, snap grid, A*),
maneuver generation and the NavSession map-matching state machine;
26 unit tests.
MapView interaction layer: MapViewAction, camera API + animated
fly_to, overlay.rs (route polyline with traveled dimming, markers,
position puck), per-widget mbtiles_path override, archive
minzoom/maxzoom honored for tile requests, zoom-level cross-fade over
the previous level's imagery, floating panels win hit-testing.
examples/map is the navigator app: worker-thread search, Drive/Bike/
Walk routing, simulated turn-by-turn with banner, follow camera.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>