Skip to content

Add a standards mode that renders strictly by the chart standards - #49

Open
bkeepers wants to merge 3 commits into
mainfrom
standards-mode
Open

Add a standards mode that renders strictly by the chart standards#49
bkeepers wants to merge 3 commits into
mainfrom
standards-mode

Conversation

@bkeepers

Copy link
Copy Markdown
Member

A standards style option (viewer: ?standards) renders the strict S-52 portrayal instead of the chart's own: symbols at their fixed sizes with no zoom interpolation, visibility taken from the SCAMIN derivation rather than the chart's earlier floors and density budgets, and light sectors as the display-fixed 20 mm arcs. The deviations recorded in the design docs are all deliberate, and this makes the standard they depart from viewable next to them.

How it works

The tiles gain two things, both additive. Every light sector now emits a point (bearings, width, colour, visibility, extended) and a point per deduped limit alongside the existing ground-geometry lines, because a display-fixed arc is drawn as rotated sprites and line geometry cannot feed that. And every seamark and light feature carries std_minzoom, the floor from the Derived column in zoom.md, baked by SeamarkZoomRules.getStandardMinZoom (0 means SCAMIN NOT SET). Tile minzooms are unchanged: the chart floor sits at or below the strict one everywhere, so the style always has the feature to filter.

On the style side, visibility(standards) is the single switch. In standards mode the budgets, topOfCell, and decoration legibility gates become pass-throughs, every icon and text size ramp collapses to its full-size constant, and one filter clause per seamap layer thresholds on std_minzoom, coalesced to 0 so the style degrades gracefully against tiles built before the attribute existed. Sectors switch to the sprite portrayal: quantized arc sprites in three copies rotated to a sector's start, middle and end, cased for legibility, 25 mm for the smaller of an overlapping pair (obscured included), magenta for any colour the S-52 precedence cannot name, and icon-ignore-placement so a conventional figure never takes space from a real symbol.

Verification

  • Chart mode is byte-identical to main: checked by compiling both layer trees side by side over four option sets, and pinned by a snapshot test.
  • Built Malta tiles with the new schema and drove the viewer: arcs hold the same pixel radius from z13 to z15 while the world scales under them, rotation and colours are correct at Ċirkewwa's red/green pair, and a minor light's sectors and flare drop out below their std_minzoom of 11 while a major light's stay.
  • 84 Java tests and 47 style tests pass, including an invariant that no chart floor trails a non-zero standard floor, a tie between SPRITE_SPAN and the artwork's own angles, and coverage of the obscured three-copy case.

Accepted limits

  • The destructive tile cap still bounds what dense cells carry below z13, so standards mode shows at most what the tiles kept. Raising the cap wasn't worth a fatter planet for a comparison mode.
  • An all-scales class (std_minzoom 0) exists only from its tile floor: TSS linework from z2, conspicuous landmarks from z6.
  • Sector figures start at the light layer's z8 floor even for major lights whose standard floor is 5.
  • line-width ramps and text-variable-anchor-offset still interpolate over zoom.

Remaining

  • Planet build: production tiles carry sector_point and std_minzoom only after the next build, so until then standards mode fixes sizes but shows neither strict floors nor sector arcs. Previews serve published tiles and have the same gap.
  • docs/design/zoom.md and visibility.md gained short sections on the baked floor and the off-switch; there are uncommitted local edits to both files on another desk that may need reconciling.

Display-fixed sector arcs are sprites rotated to the sector's limits, which
line geometry cannot feed: the tiles now carry one point per sector
(bearings, width, colour, visibility, extended) and one per deduped limit,
at the light's position, alongside the ground-geometry lines.

The strict floor S-52 would read off SCAMIN — zoom.md's Derived column —
is baked per feature as std_minzoom (0 = NOT SET), sharing the chart
floor's dispatch and range promotion. Tile minzooms are unchanged: the
chart floor sits at or below the strict one everywhere, so a style
thresholding on std_minzoom always has the feature to filter.
A `standards` style option (viewer: ?standards) draws the strict S-52
portrayal instead of the chart's own, so the deviations recorded in the
design docs stay visible against the standard they depart from.

visibility(standards) is the single switch: budgets, topOfCell and the
decoration legibility gates become pass-throughs, and every icon and text
size ramp collapses to its fixed full size. Visibility comes from the
SCAMIN-derived std_minzoom the tiles carry, added as one filter clause to
every seamap layer and coalesced to 0 so older tiles still draw.

Sectors switch to S-52's display-fixed figure: 20 mm arcs (25 mm for the
smaller of an overlapping pair, obscured included) as quantized sprites,
three copies rotated to a sector's start, middle and end, cased for
legibility, with legs at each limit and magenta for any colour the S-52
precedence cannot name. The arcs ignore collision placement — a
conventional figure must never reserve space from a real symbol.

Chart mode is pinned byte-identical by a snapshot test; the sprite spans
are tied to the artwork's own angles so a redrawn arc fails loudly.
Copilot AI lite review requested due to automatic review settings August 16, 2026 18:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional standards mode that renders chart symbology strictly per S-52 alongside the existing “chart portrayal” mode. This spans the tile pipeline (baking per-feature standard floors and emitting additional light-sector point features) and the style package (a single standards switch that disables chart-specific thinning/sizing logic and renders display-fixed sector arcs via sprites), with a viewer query param to toggle it.

Changes:

  • Plumbs a standards option from the viewer (?standards) through style()/layers() into chartLayers({ standards }).
  • Implements standards portrayal behavior in the style: pass-through visibility helpers, per-feature std_minzoom gating, and sprite-based display-fixed light sector arcs/legs.
  • Updates the Planetiler profile to bake std_minzoom and emit sector/limit point features; adds/extends Java + style tests and design docs.

Reviewed changes

Copilot reviewed 23 out of 40 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
viewer/src/main.js Adds ?standards query param and passes it into style() options.
style/README.md Documents new standards option and exposes it on layers().
style/index.ts Adds standards to public options and forwards it into chartLayers.
style/index.test.ts Adds snapshot + standards-mode tests (std_minzoom gating, fixed sizes, sector sprites).
style/layers/index.ts Introduces standards toggle, builds Visibility, and applies std_minzoom filter across seamap layers.
style/layers/visibility.ts Refactors visibility helpers behind visibility(standards) and adds symbolSize helper.
style/layers/areas.ts Adapts to Visibility and uses symbolSize in standards mode.
style/layers/hazards.ts Adapts to Visibility; uses symbolSize for size expressions under standards.
style/layers/routes.ts Adapts to Visibility; uses symbolSize for line symbol scaling.
style/layers/structures.ts Adapts to Visibility; replaces zoom interpolations with symbolSize where needed.
style/layers/lights.ts Adapts to Visibility; uses symbolSize/sizeRamp behavior appropriate to standards mode.
style/layers/sectors.ts Splits sector rendering: ground-geometry (chart) vs sprite-based display-fixed arcs (standards).
style/layers/marks.ts Adapts to Visibility; standards mode makes decoration and budgets pass-through.
style/layers/labels.ts Adapts to Visibility; uses symbolSize for text/icon sizing behavior in standards mode.
style/layers/palette.ts Documents that sectorLeg color is duplicated in sprite artwork.
style/sprites/icons/sector-leg.svg Adds dedicated sprite for standards-mode sector limit legs.
style/sprites/icons/arc-4-obscured.svg Adds arc sprite artwork (obscured variant, span index 4).
style/sprites/icons/arc-4-M.svg Adds arc sprite artwork (fallback/magenta variant, span index 4).
style/sprites/icons/arc-4-casing.svg Adds arc sprite artwork (casing variant, span index 4).
style/sprites/icons/arc-3-obscured.svg Adds arc sprite artwork (obscured variant, span index 3).
style/sprites/icons/arc-3-M.svg Adds arc sprite artwork (fallback/magenta variant, span index 3).
style/sprites/icons/arc-3-casing.svg Adds arc sprite artwork (casing variant, span index 3).
style/sprites/icons/arc-2-obscured.svg Adds arc sprite artwork (obscured variant, span index 2).
style/sprites/icons/arc-2-M.svg Adds arc sprite artwork (fallback/magenta variant, span index 2).
style/sprites/icons/arc-2-casing.svg Adds arc sprite artwork (casing variant, span index 2).
style/sprites/icons/arc-1-obscured.svg Adds arc sprite artwork (obscured variant, span index 1).
style/sprites/icons/arc-1-M.svg Adds arc sprite artwork (fallback/magenta variant, span index 1).
style/sprites/icons/arc-1-casing.svg Adds arc sprite artwork (casing variant, span index 1).
style/sprites/icons/arc-0-obscured.svg Adds arc sprite artwork (obscured variant, span index 0).
style/sprites/icons/arc-0-M.svg Adds arc sprite artwork (fallback/magenta variant, span index 0).
style/sprites/icons/arc-0-casing.svg Adds arc sprite artwork (casing variant, span index 0).
src/main/java/SeamarkZoomRules.java Adds getStandardMinZoom derivation and refactors chart-floor + range promotion helpers.
src/main/java/Seamap.java Bakes std_minzoom onto seamark + light features so the style can filter strictly by SCAMIN-derived floor.
src/main/java/Lights.java Emits sector/limit point features (angles/bearings/width/extended) alongside existing ground geometry.
src/test/java/SeamarkZoomRulesTest.java Adds tests for standard floors, SCAMIN NOT SET behavior, and chart-floor ≤ standard-floor invariant.
src/test/java/SeamapTest.java Verifies sector lights emit both portrayals and inherit the host’s std_minzoom.
src/test/java/LightsTest.java Tests sector point/limit emission details (wrapping width, deduped limits, extended marking).
docs/design/zoom.md Documents baked std_minzoom and standards-mode gating behavior.
docs/design/visibility.md Documents standards mode as the “off switch” for chart-portrayal deviations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/design/zoom.md Outdated
Comment thread style/README.md Outdated
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