Skip to content

osm basemap: split the green bucket, texture the ground cover, region as config - #121

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/q2-osm-map-reencoding-56p5e2
Aug 12, 2026
Merged

osm basemap: split the green bucket, texture the ground cover, region as config#121
AdaWorldAPI merged 1 commit into
mainfrom
claude/q2-osm-map-reencoding-56p5e2

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Three findings off the live deploy. None of these is the bake-format work (see the note at the bottom) — this is the render side plus the config that a second region needs.

1. The flat green wash was my class table

class_for_tags collapsed landuse|leisure|natural into one Green bucket, so landuse=residential — which covers most of a suburb — rendered as vegetation. That is why a whole z16 Zehlendorf viewport read as meadow.

Split into Meadow (grass/farmland/heath), Park (leisure/cemetery), Built (residential/industrial/commercial — grey, not green), with Green kept as the fallback so widening the specific set can never demote something to Other.

Wire codes are appended (7/8/9), never inserted: 0-6 stay a contract with the client's CLASS_ORDER, so an older client renders a new class as unknown rather than as the wrong one.

One pre-existing assertion moved: leisure=park asserted Green because that was the collapsed behaviour. Re-pinned to Park with a comment saying the behaviour changed deliberately — flagging it rather than quietly editing a test that got in the way.

2. Meadows had no texture

A flat fill cannot tell a meadow from a park from a lawn, and at z16 those are most of the viewport. Canvas gives this cheaply where the old SVG layer would not have: one 8×8 offscreen tile per texture, built once, handed to createPattern and reused for every polygon of that class — one pattern object per session, not per shape. Stipple for meadow, canopy strokes for wood.

The pattern is deliberately not transform-corrected: it is created in canvas space and we translate() per tile, so the texture rides with the map instead of crawling underneath it while panning.

3. A region is now config, not code

ARTIFACTS was hardcoded to berlin.* and the prefix to q2/bakes/berlin-v1, so a second bake required a code change. OSM_BAKE_REGION now drives artifact names, S3 prefix and volume path.

The name is validated to [a-z0-9-] — it is interpolated into an S3 key and joined onto a filesystem path, so .. or / would traverse; an invalid value warns and falls back rather than building that path. Because the cache dir is region-keyed, two regions coexist on one volume and flipping between them costs no re-download.

Also: a discarded cross-bake pin

open_books did Ok((_header, books)) — the header's slab digest, the same cross-bake pin .chains already enforces, was thrown away. A codebook from a different bake was accepted silently, resolving every ordinal to some other bake's string. Now verified. And a magic mismatch is reported as an outdated bake format naming expected vs found, instead of a generic "unreadable" after which every shape silently falls to ShapeClass::Other.

Verified

Headless Chromium against the shipped page, bake endpoints stubbed with the new classes:

distinct painted colours 2,698 (was a flat wash)
SVG nodes 0
external requests 0
pan repaints yes
binary vs JSON wire 4.7× smaller on the same shapes

103 tests pass, 0 failed.

Docs: claude-notes/instructions/osm-bake-new-region.md — the Baden-Württemberg runbook with measured sizing (645 MB PBF against Berlin's 99 MB; ~9.1 GB output; budget 32 GB RAM, which is why BW cannot be baked in the dev container).

What this does NOT do

It does not produce a bake in the new format. EdgeBlock is still written zeroed by the baker (build_row: "edges — zeroed. Reserved, never shrunk."), there are no junction/street-node rows, and BOOKS = 3 is pinned so a label codebook is a fourth book and an OSMCBK\0\x02\0\x03 version bump. That work is the actual re-bake and is tracked separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Added richer map styling for meadows, parks, built-up areas, wooded areas, and vegetation textures.
    • Added support for selecting regional map data during OSM data preparation, including region-specific artifacts and storage paths.
    • Improved handling of unknown map classifications with safe fallback styling.
  • Bug Fixes
    • Added integrity checks to detect mismatched or outdated map metadata and data formats.
  • Documentation
    • Added an operational guide for preparing, publishing, deploying, and verifying Baden-Württemberg map data.

…ke a region a config value

Three things, all found from the live deploy.

1. THE FLAT GREEN WASH. `class_for_tags` collapsed landuse|leisure|natural
   into one `Green` bucket, so `landuse=residential` — which covers most of a
   suburb — rendered as vegetation. A whole z16 viewport read as meadow.
   Split into `Meadow` (grass/farmland/heath), `Park` (leisure/cemetery) and
   `Built` (residential/industrial/commercial, grey and NOT green), with
   `Green` kept as the fallback so widening the specific set can never demote
   something to `Other`. Wire codes are APPENDED (7/8/9), never inserted: 0-6
   stay a contract with the client's CLASS_ORDER, so an older client renders a
   new class as unknown rather than as the wrong one.

   One pre-existing assertion moved: `leisure=park` asserted `Green` because
   that WAS the collapsed behaviour. It is re-pinned to `Park` with a comment
   saying the behaviour changed deliberately — not a test edited for
   convenience.

2. MEADOWS HAD NO TEXTURE (operator). A flat fill cannot tell a meadow from a
   park from a lawn, and at z16 those are most of the viewport. Canvas gives
   this cheaply where SVG would not have: one 8x8 offscreen tile per texture,
   built once, handed to createPattern and reused for every polygon of that
   class — one pattern object per session, not per shape. Stipple for meadow,
   canopy strokes for wood. The pattern is deliberately NOT transform-
   corrected: it is created in canvas space and we translate() per tile, so
   the texture rides with the map instead of crawling under it while panning.

3. A REGION IS NOW CONFIG, NOT CODE. `ARTIFACTS` was hardcoded to berlin.*
   and the prefix to q2/bakes/berlin-v1, so a second bake needed a code
   change. `OSM_BAKE_REGION` now drives artifact names, S3 prefix and the
   volume path. The name is validated to [a-z0-9-]: it is interpolated into
   an S3 key AND joined onto a filesystem path, so `..` or `/` would traverse
   — an invalid value warns and falls back rather than building that path.
   Because the cache dir is region-keyed, two regions coexist on one volume
   and flipping between them costs no re-download.

Also: the books header's `slab` digest — the same cross-bake pin `.chains`
already enforces — was being DISCARDED (`Ok((_header, books))`). A codebook
from a different bake was accepted silently, resolving every ordinal to some
other bake's string. Now verified, and a magic mismatch is reported as an
OUTDATED bake format naming expected vs found, instead of a generic
"unreadable" after which every shape silently falls to `ShapeClass::Other`.

Verified in headless Chromium against the shipped page, bake endpoints
stubbed with the new classes: 2,698 distinct painted colours (was a flat
wash), textures visible, 0 SVG nodes, 0 external requests, pan repaints, and
the binary wire still 4.7x smaller than JSON on the same shapes.

Docs: claude-notes/instructions/osm-bake-new-region.md — the BW runbook with
measured sizing (645 MB PBF vs Berlin's 99 MB; ~9.1 GB output; budget 32 GB
RAM, which is why BW cannot be baked in the dev container).

103 passed, 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMeiLmtDKhomJNSo2ecbJw
@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_f1070966-f1c6-45f6-8678-fac60959a3c1)

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe1ec5cf-b90f-43ae-be11-7ae08c1f95bb

📥 Commits

Reviewing files that changed from the base of the PR and between 40c4d05 and c0e8a07.

📒 Files selected for processing (4)
  • claude-notes/instructions/osm-bake-new-region.md
  • crates/cockpit-server/src/osm.rs
  • crates/cockpit-server/src/osm_features.rs
  • crates/cockpit-server/src/osm_slab_hydrate.rs

📝 Walkthrough

Walkthrough

The PR adds operational instructions for baking Baden-Württemberg OSM data, supports region-specific slab hydration, introduces Meadow, Park, and Built feature classes, strengthens sidecar validation, and renders new classes with textured basemap styles.

Changes

OSM region and basemap updates

Layer / File(s) Summary
Region-aware hydration and bake workflow
claude-notes/instructions/osm-bake-new-region.md, crates/cockpit-server/src/osm_slab_hydrate.rs
Hydration validates OSM_BAKE_REGION, derives artifact names and S3 prefixes, supports explicit prefix overrides, and processes region-specific artifacts. The guide documents the Baden-Württemberg bake, publish, deploy, and verification workflow.
Feature classes and sidecar compatibility
crates/cockpit-server/src/osm_features.rs
ShapeClass adds stable Meadow, Park, and Built wire codes. Tag classification maps related land uses to these classes. Codebook loading checks slab digests and reports outdated formats. Chains loading reports outdated formats. Tests cover mappings and validation.
Textured basemap rendering
crates/cockpit-server/src/osm.rs
Rendering adds styles for the new classes, cached meadow and wood textures, updated draw ordering, texture-aware fills, and fallback styling for unknown class bytes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: claude

Poem

I hop through fields of green and gold,
New meadow codes are neatly told.
The slabs find regions, paths align,
Textured parks now softly shine.
Safe checks guard each sidecar byte—
OSM bakes are set just right.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 12, 2026 09:51
@AdaWorldAPI
AdaWorldAPI merged commit bd79275 into main Aug 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants