diff --git a/internal/engine/bake/bake.go b/internal/engine/bake/bake.go index ef3de11..48bd341 100644 --- a/internal/engine/bake/bake.go +++ b/internal/engine/bake/bake.go @@ -688,6 +688,15 @@ func (b *Baker) AddCell(chart *s57.Chart) { continue } } + // DRGARE dredged depth is emitted by the rule as a fixed-metres text + // label ("%gm", DredgedArea.lua). Drop it; the client labels the + // dredged area from the baked `drval1` (carried on the area below), + // converting to the chosen depth unit — same pattern as DEPCNT/valdco. + if class == "DRGARE" { + if _, ok := p.(portrayal.DrawText); ok { + continue + } + } b.route(p, class, fb.DisplayPriority, fb.DisplayCategory, zr, zMin, dr.Max, bnd, pts, drval1, drval2, valdco) } } diff --git a/web/src/chart-canvas/chart-canvas.mjs b/web/src/chart-canvas/chart-canvas.mjs index 7b92ef0..64a5e84 100644 --- a/web/src/chart-canvas/chart-canvas.mjs +++ b/web/src/chart-canvas/chart-canvas.mjs @@ -498,6 +498,10 @@ export class ChartCanvas extends HTMLElement { // the mariner picks imperial units), shown only when "contour labels" is on. contourLabelField() { return S52.contourLabelField(this._mariner); } + // Dredged-area depth label (S-52 row 47): DRVAL1 at the DRGARE centroid in the + // chosen depth unit — see s52-style.drgareLabelField. + drgareLabelField() { return S52.drgareLabelField(this._mariner); } + // SNDFRM04 (S-52 §13.2.16): a sounding ≤ the live safety depth uses the bold // SOUNDS glyphs, else the faint SOUNDG glyphs — picked client-side from the // baked depth + both name variants. Falls back to the baked names if a tile @@ -612,6 +616,8 @@ export class ChartCanvas extends HTMLElement { setIf("danger-boundary", "line-color", this.token("CHBLK", "#000000")); setIf("contour-labels", "text-color", this.contourLabelColor()); setIf("contour-labels", "text-halo-color", this.textHaloColor()); + setIf("drgare-labels", "text-color", this.textColor()); + setIf("drgare-labels", "text-halo-color", this.textHaloColor()); setIf("complex-lines", "line-color", this.colorExpr("color_token")); for (const v of TEXT_VARIANTS) { setIf(v.id, "text-color", this.textColor()); @@ -877,6 +883,7 @@ export class ChartCanvas extends HTMLElement { if (keys.includes("depthUnit")) { this._eachLayer("soundings", (id) => map.setLayoutProperty(id, "icon-image", this.soundingsIconImage())); this._eachLayer("contour-labels", (id) => map.setLayoutProperty(id, "text-field", this.contourLabelField())); + this._eachLayer("drgare-labels", (id) => map.setLayoutProperty(id, "text-field", this.drgareLabelField())); } // Distance unit: the S-52 scalebar reads in NM / km / mi — redraw it. if (keys.includes("distanceUnit")) this._renderScalebar(); diff --git a/web/src/chart-canvas/chart-style.mjs b/web/src/chart-canvas/chart-style.mjs index 12bcb4b..93d4ab4 100644 --- a/web/src/chart-canvas/chart-style.mjs +++ b/web/src/chart-canvas/chart-style.mjs @@ -127,6 +127,14 @@ function buildLayers(mariner, palette, atlasPpu, osm) { filter: ["all", ["==", ["get", "class"], "DEPCNT"], ["has", "valdco"]], layout: { "symbol-placement": "line", "text-field": S52.contourLabelField(mariner), "text-font": FONT, "text-size": 10, "text-max-angle": 30, "symbol-spacing": 300, "text-allow-overlap": false, "text-optional": true, visibility: mariner.showContourLabels ? "visible" : "none" }, paint: { "text-color": S52.contourLabelColor(active, palette), "text-halo-color": S52.textHaloColor(active), "text-halo-width": 1.2 } }, + // Dredged-area depth label (S-52 row 47, client-side): DRVAL1 placed at the + // DRGARE centroid, in the chosen depth unit. The baker drops the rule's + // fixed-metres "%gm" text so this tracks depthUnit (same pattern as + // contour-labels). Reads the `areas` source-layer → SCAMIN-cloned below. + { id: "drgare-labels", type: "symbol", source: "chart", "source-layer": "areas", + filter: ["all", ["==", ["get", "class"], "DRGARE"], ["has", "drval1"]], + layout: { "text-field": S52.drgareLabelField(mariner), "text-font": FONT, "text-size": 10, "text-allow-overlap": false, "text-optional": true }, + paint: { "text-color": S52.textColor(active, palette), "text-halo-color": S52.textHaloColor(active), "text-halo-width": 1.2 } }, // Light characteristics (LIGHTS06 TX, e.g. "Fl(1)R 3s 4.2m") — their own // layer. It precedes the feature-name layers in the style order, so MapLibre // places light text FIRST: it wins collisions against plain name labels (a name diff --git a/web/src/chart-canvas/s52-style.mjs b/web/src/chart-canvas/s52-style.mjs index cf9a96f..d5f02db 100644 --- a/web/src/chart-canvas/s52-style.mjs +++ b/web/src/chart-canvas/s52-style.mjs @@ -131,6 +131,18 @@ export function contourLabelField(mariner) { return ["case", ["has", "valdco"], ["to-string", v], ""]; } +// DredgedArea depth label (S-52 row 47 / S-101 DredgedArea.lua): the dredged +// depth (DRVAL1) with a unit suffix, e.g. "1.8m" / "6ft". Drawn client-side from +// the baked `drval1` so it tracks the mariner's depth unit — the baker no longer +// bakes the rule's fixed-metres "%gm" text. Feet round to whole (chart +// convention); metres keep one decimal (DRVAL1 is often fractional, e.g. 1.8). +export function drgareLabelField(mariner) { + const ft = mariner.depthUnit === "ft"; + const val = ft ? ["*", ["get", "drval1"], M_TO_FT] : ["get", "drval1"]; + const num = ["number-format", val, { "max-fraction-digits": ft ? 0 : 1 }]; + return ["case", ["has", "drval1"], ["concat", num, ft ? "ft" : "m"], ""]; +} + // SNDFRM04 (S-52 §13.2.16): a sounding ≤ the live safety depth uses the bold // SOUNDS glyphs, else the faint SOUNDG glyphs — picked client-side from the // baked depth + both name variants. Falls back to the baked names if a tile