@chrtco/sdk 0.10.48 → 0.10.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/index.cjs +148 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +141 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to `@chrtco/sdk` will be documented in this file.
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
7
|
### Added
|
|
8
|
+
- **`generateStyle({ dangerDepthPlacers: true })`** — the danger depths (the depth beside a rock,
|
|
9
|
+
wreck or obstruction) as a pair: an invisible placer `s52-{UWTROC,OBSTRN,WRECKS}-placer-label`
|
|
10
|
+
in 0.10.3's collision form (`text-opacity: 0`) beneath each callout, which is then always drawn
|
|
11
|
+
and inserts no collision box, so no sounding is hidden and a tile draws the callouts once.
|
|
12
|
+
Default off: the style is unchanged unless asked. `addDangerDepthPlacers`,
|
|
13
|
+
`isDangerDepthPlacer` (skip the placers when hit-testing), `dangerDepthPlacerId`,
|
|
14
|
+
`DANGER_DEPTH_LABEL_ID`, `DANGER_DEPTH_PLACER_ID`, `DANGER_DEPTH_PLACER_LAYOUT`,
|
|
15
|
+
`DANGER_DEPTH_VISIBLE_LAYOUT`. The style routes take it as `?placers=1`.
|
|
8
16
|
- **`EINK_NIGHT`** — the e-ink night palette (`theme=eink_night`, offline `palette=EINK_NIGHT`,
|
|
9
17
|
`EINK_COLOR_TABLES.night`): `EINK_MONO`'s four greys on a black page, for any e-ink screen at
|
|
10
18
|
night with the front light on, in place of red night. Water black; lines and labels `#aaaaaa`;
|
package/dist/index.cjs
CHANGED
|
@@ -61,6 +61,10 @@ __export(index_exports, {
|
|
|
61
61
|
CHRT_STYLE_MODES: () => CHRT_STYLE_MODES,
|
|
62
62
|
Chrt: () => Chrt,
|
|
63
63
|
ChrtError: () => ChrtError,
|
|
64
|
+
DANGER_DEPTH_LABEL_ID: () => DANGER_DEPTH_LABEL_ID,
|
|
65
|
+
DANGER_DEPTH_PLACER_ID: () => DANGER_DEPTH_PLACER_ID,
|
|
66
|
+
DANGER_DEPTH_PLACER_LAYOUT: () => DANGER_DEPTH_PLACER_LAYOUT,
|
|
67
|
+
DANGER_DEPTH_VISIBLE_LAYOUT: () => DANGER_DEPTH_VISIBLE_LAYOUT,
|
|
64
68
|
DEFAULT_CLICK_TOLERANCE: () => DEFAULT_CLICK_TOLERANCE,
|
|
65
69
|
DEFAULT_CUSTOM_STYLE_CONFIG: () => DEFAULT_CUSTOM_STYLE_CONFIG,
|
|
66
70
|
DEFAULT_INSPECT_CLASS_RANK: () => DEFAULT_INSPECT_CLASS_RANK,
|
|
@@ -159,6 +163,7 @@ __export(index_exports, {
|
|
|
159
163
|
WATER_BODY_LAYER_GROUPS: () => WATER_BODY_LAYER_GROUPS,
|
|
160
164
|
WATER_TEXT_CLASSES: () => WATER_TEXT_CLASSES,
|
|
161
165
|
WeatherEndpoint: () => WeatherEndpoint,
|
|
166
|
+
addDangerDepthPlacers: () => addDangerDepthPlacers,
|
|
162
167
|
applyBaseBundle: () => applyBaseBundle,
|
|
163
168
|
applyChartSymbolScales: () => applyChartSymbolScales,
|
|
164
169
|
applyChartSymbolScalesToLayer: () => applyChartSymbolScalesToLayer,
|
|
@@ -201,6 +206,7 @@ __export(index_exports, {
|
|
|
201
206
|
combineWithBandFilter: () => combineWithBandFilter,
|
|
202
207
|
contourValueFactor: () => contourValueFactor,
|
|
203
208
|
contrastRatio: () => contrastRatio,
|
|
209
|
+
dangerDepthPlacerId: () => dangerDepthPlacerId,
|
|
204
210
|
daymarkColor: () => daymarkColor,
|
|
205
211
|
decimateFeatures: () => decimateFeatures,
|
|
206
212
|
decodeAreaFeatureProps: () => decodeAreaFeatureProps,
|
|
@@ -251,6 +257,7 @@ __export(index_exports, {
|
|
|
251
257
|
hazardFillExpression: () => hazardFillExpression,
|
|
252
258
|
iconExpressionForFamily: () => iconExpressionForFamily,
|
|
253
259
|
iconSliderFor: () => iconSliderFor,
|
|
260
|
+
isDangerDepthPlacer: () => isDangerDepthPlacer,
|
|
254
261
|
isDepthAreaClassLayerId: () => isDepthAreaClassLayerId,
|
|
255
262
|
isDrapeable: () => isDrapeable,
|
|
256
263
|
isEinkColorTable: () => isEinkColorTable,
|
|
@@ -24903,6 +24910,11 @@ function labelSortKey(rank, within) {
|
|
|
24903
24910
|
["min", 999, ["max", 0, within]]
|
|
24904
24911
|
];
|
|
24905
24912
|
}
|
|
24913
|
+
var DANGER_DEPTH_PLACEMENT_KEY = labelSortKey(100, [
|
|
24914
|
+
"*",
|
|
24915
|
+
10,
|
|
24916
|
+
["to-number", ["coalesce", ["get", "VALSOU"], ["get", "valsou"], 0], 0]
|
|
24917
|
+
]);
|
|
24906
24918
|
var NAV_DESIGNATION_STOPWORDS = [
|
|
24907
24919
|
"Buoy",
|
|
24908
24920
|
"Can",
|
|
@@ -25706,32 +25718,27 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
25706
25718
|
// UWTROC/OBSTRN/WRECKS are dominance-PARTICIPATING classes —
|
|
25707
25719
|
// exactly one band's copy renders at any zoom, so anchor-shifting
|
|
25708
25720
|
// can't split a cross-band duplicate pair into two visible labels.
|
|
25709
|
-
// Shallowest (most dangerous) hazard wins within-class contests;
|
|
25710
|
-
// VALSOU-less hazards (awash / unsounded) rank first of all.
|
|
25711
25721
|
layout: {
|
|
25712
25722
|
"text-variable-anchor": ["top-left", "bottom-left", "top-right", "bottom-right"],
|
|
25713
25723
|
"text-radial-offset": 0.9,
|
|
25714
25724
|
"text-justify": "auto",
|
|
25715
|
-
// ⚠ A DANGER DEPTH IS NEVER DROPPED (owner, 2026-10-06).
|
|
25716
|
-
//
|
|
25717
|
-
//
|
|
25718
|
-
//
|
|
25719
|
-
//
|
|
25720
|
-
//
|
|
25721
|
-
//
|
|
25722
|
-
//
|
|
25723
|
-
//
|
|
25724
|
-
//
|
|
25725
|
-
//
|
|
25726
|
-
//
|
|
25727
|
-
//
|
|
25728
|
-
// at z12.3 on the bench. This form: 0.
|
|
25729
|
-
// The census and its numbers: `scripts/chart-bench/
|
|
25730
|
-
// danger-depth-census.ts` and `.chrt/standards/s-52.md` §8a.
|
|
25725
|
+
// ⚠ A DANGER DEPTH IS NEVER DROPPED (owner, 2026-10-06). This is
|
|
25726
|
+
// 0.10.4's form, which the SERVED style keeps: always drawn
|
|
25727
|
+
// (`text-allow-overlap`), still in collision, fanned out by its four
|
|
25728
|
+
// variable anchors, placed shallowest first. Its cost, measured: a
|
|
25729
|
+
// newly drawn callout takes space a sounding held (7 soundings under
|
|
25730
|
+
// 3.048 m hidden at the 100 % default), and the depth key on an
|
|
25731
|
+
// overlapping layer draws one segment per depth (+14 % draw calls).
|
|
25732
|
+
// With `generateStyle({ dangerDepthPlacers: true })` — CHRTweb and
|
|
25733
|
+
// CHRTdesktop — `danger-depth-placer.ts` turns it into a PAIR: an
|
|
25734
|
+
// invisible placer in 0.10.3's form holds the space, and this label
|
|
25735
|
+
// is drawn over it, displacing nothing, with one key. The census:
|
|
25736
|
+
// `scripts/chart-bench/danger-depth-census.ts`; `.chrt/standards/
|
|
25737
|
+
// s-52.md` §8a.
|
|
25731
25738
|
"text-allow-overlap": true,
|
|
25732
25739
|
"text-optional": true,
|
|
25733
25740
|
"text-padding": 2,
|
|
25734
|
-
"symbol-sort-key":
|
|
25741
|
+
"symbol-sort-key": DANGER_DEPTH_PLACEMENT_KEY
|
|
25735
25742
|
}
|
|
25736
25743
|
};
|
|
25737
25744
|
}
|
|
@@ -26492,6 +26499,62 @@ function buildBridgeNoteLayers(sourceId, palette = "DAY", depthUnits = "meters")
|
|
|
26492
26499
|
];
|
|
26493
26500
|
}
|
|
26494
26501
|
|
|
26502
|
+
// src/atlas/danger-depth-placer.ts
|
|
26503
|
+
var DANGER_DEPTH_LABEL_ID = /^s52-(UWTROC|OBSTRN|WRECKS)-label(?=$|-)/;
|
|
26504
|
+
var DANGER_DEPTH_PLACER_ID = /^s52-(UWTROC|OBSTRN|WRECKS)-placer-label(?=$|-)/;
|
|
26505
|
+
function dangerDepthPlacerId(labelId) {
|
|
26506
|
+
return labelId.replace(/^s52-(UWTROC|OBSTRN|WRECKS)-label/, "s52-$1-placer-label");
|
|
26507
|
+
}
|
|
26508
|
+
function isDangerDepthPlacer(layerId) {
|
|
26509
|
+
return DANGER_DEPTH_PLACER_ID.test(layerId);
|
|
26510
|
+
}
|
|
26511
|
+
var DANGER_DEPTH_VISIBLE_LAYOUT = {
|
|
26512
|
+
"text-allow-overlap": true,
|
|
26513
|
+
"text-ignore-placement": true,
|
|
26514
|
+
"symbol-sort-key": labelSortKey(100),
|
|
26515
|
+
"symbol-z-order": "source"
|
|
26516
|
+
};
|
|
26517
|
+
var DANGER_DEPTH_PLACER_LAYOUT = {
|
|
26518
|
+
"text-allow-overlap": false,
|
|
26519
|
+
"text-ignore-placement": false,
|
|
26520
|
+
"symbol-sort-key": DANGER_DEPTH_PLACEMENT_KEY
|
|
26521
|
+
};
|
|
26522
|
+
function addDangerDepthPlacers(layers) {
|
|
26523
|
+
if (!layers.some((l) => isVisibleDangerDepthLabel(l))) return layers;
|
|
26524
|
+
const out = [];
|
|
26525
|
+
for (let i = 0; i < layers.length; ) {
|
|
26526
|
+
const cls = classOf(layers[i]);
|
|
26527
|
+
if (cls === null) {
|
|
26528
|
+
out.push(layers[i]);
|
|
26529
|
+
i++;
|
|
26530
|
+
continue;
|
|
26531
|
+
}
|
|
26532
|
+
let j = i;
|
|
26533
|
+
while (j < layers.length && classOf(layers[j]) === cls) j++;
|
|
26534
|
+
const run = layers.slice(i, j);
|
|
26535
|
+
for (const l of run) out.push(placerFor(l));
|
|
26536
|
+
for (const l of run) out.push({ ...l, layout: { ...l.layout ?? {}, ...DANGER_DEPTH_VISIBLE_LAYOUT } });
|
|
26537
|
+
i = j;
|
|
26538
|
+
}
|
|
26539
|
+
return out;
|
|
26540
|
+
}
|
|
26541
|
+
function placerFor(l) {
|
|
26542
|
+
const { "symbol-z-order": _zOrder, ...layout } = l.layout ?? {};
|
|
26543
|
+
return {
|
|
26544
|
+
...l,
|
|
26545
|
+
id: dangerDepthPlacerId(l.id),
|
|
26546
|
+
layout: { ...layout, ...DANGER_DEPTH_PLACER_LAYOUT },
|
|
26547
|
+
paint: { ...l.paint ?? {}, "text-opacity": 0 },
|
|
26548
|
+
metadata: { ...l.metadata ?? {}, "chrt:placerFor": l.id }
|
|
26549
|
+
};
|
|
26550
|
+
}
|
|
26551
|
+
function isVisibleDangerDepthLabel(l) {
|
|
26552
|
+
return l.type === "symbol" && DANGER_DEPTH_LABEL_ID.test(l.id) && l.layout?.["text-field"] !== void 0;
|
|
26553
|
+
}
|
|
26554
|
+
function classOf(l) {
|
|
26555
|
+
return isVisibleDangerDepthLabel(l) ? DANGER_DEPTH_LABEL_ID.exec(l.id)?.[1] ?? null : null;
|
|
26556
|
+
}
|
|
26557
|
+
|
|
26495
26558
|
// src/atlas/feature-decimation.ts
|
|
26496
26559
|
function getGridSizeForZoom(zoom) {
|
|
26497
26560
|
if (zoom < 7) return 50;
|
|
@@ -29648,7 +29711,6 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29648
29711
|
};
|
|
29649
29712
|
if (HAZARD_GROUPS.has(entry?.viewingGroup ?? 0)) {
|
|
29650
29713
|
const watlev = ["to-number", ["coalesce", ["get", "WATLEV"], ["get", "watlev"], 0], 0];
|
|
29651
|
-
const valsou = ["to-number", ["coalesce", ["get", "VALSOU"], ["get", "valsou"], 99], 99];
|
|
29652
29714
|
const hazardIconSize = [
|
|
29653
29715
|
"interpolate",
|
|
29654
29716
|
["linear"],
|
|
@@ -29692,9 +29754,9 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29692
29754
|
//
|
|
29693
29755
|
// Deconflicting hazards against each other stays; it just no longer
|
|
29694
29756
|
// runs through suppression:
|
|
29695
|
-
// - `symbol-sort-key` (below)
|
|
29696
|
-
//
|
|
29697
|
-
//
|
|
29757
|
+
// - `symbol-sort-key` (below) sets PAINT ORDER, so the worst
|
|
29758
|
+
// hazard is the one painted on top rather than the one that
|
|
29759
|
+
// survives.
|
|
29698
29760
|
// - the icon-size curve above is what keeps a dense ledge legible
|
|
29699
29761
|
// at the zoomed-out end of Harbor. That is now the only thing
|
|
29700
29762
|
// doing it, which is why its low end was lowered in the same
|
|
@@ -29711,18 +29773,59 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29711
29773
|
// hazards present to OTHER classes' placement, keeping labels off
|
|
29712
29774
|
// them.
|
|
29713
29775
|
"icon-padding": 2,
|
|
29776
|
+
// ── PAINT ORDER: THE WORST HAZARD ON TOP, IN FOUR KEYS ─────────────
|
|
29777
|
+
//
|
|
29778
|
+
// With overlap allowed MapLibre paints a layer in ascending key,
|
|
29779
|
+
// so a HIGHER key is painted OVER a lower one:
|
|
29780
|
+
// 3 covers and uncovers (WATLEV 4)
|
|
29781
|
+
// 2 awash (WATLEV 5)
|
|
29782
|
+
// 1 everything else: submerged, unknown, subject to inundation,
|
|
29783
|
+
// floating
|
|
29784
|
+
// 0 stands above the water (WATLEV 1 partly submerged at high
|
|
29785
|
+
// water, 2 always dry). Seen by eye, and it usually carries no
|
|
29786
|
+
// sounding, so the old key already ranked it last (a missing
|
|
29787
|
+
// VALSOU counted as 99 m).
|
|
29788
|
+
//
|
|
29789
|
+
// Until 2026-10-09 this was `case 4 → 1, 5 → 2, else 10 + VALSOU`,
|
|
29790
|
+
// meant as "worst first". With overlap that is "worst UNDERNEATH":
|
|
29791
|
+
// the deepest rock was painted over everything. Measured on the
|
|
29792
|
+
// chart bench, Boston z12.3 at 1280×800: of 758 overlapping pairs
|
|
29793
|
+
// with different icons, all 758 had the lesser hazard on top.
|
|
29794
|
+
//
|
|
29795
|
+
// Why four keys and not a depth ladder:
|
|
29796
|
+
// - An icon is picked by WATLEV alone (the `icon-image` match
|
|
29797
|
+
// above, every symbol family), never by depth. Each key holds
|
|
29798
|
+
// ONE icon per class (UWTROC 01 | 03 | 04 | 04, OBSTRN
|
|
29799
|
+
// 03 | 03 | 03 | 01, WRECKS 04 | 04 | 04 | 01), so two hazards
|
|
29800
|
+
// that share a key look the same, and which is on top cannot be
|
|
29801
|
+
// seen. With three keys the dry obstructions and wrecks shared
|
|
29802
|
+
// the lowest one and were painted over submerged ones up to 4
|
|
29803
|
+
// times a view; with four, never.
|
|
29804
|
+
// - MapLibre 5.24 draws a layer that can overlap and has a
|
|
29805
|
+
// feature-reading key ONE SEGMENT PER DISTINCT KEY PER TILE
|
|
29806
|
+
// (`SymbolBucket.addSymbols` → `prepareSegment`;
|
|
29807
|
+
// `drawLayerSymbols`, `hasSortKey && bucket.canOverlap`). The
|
|
29808
|
+
// old key had one value per sounded depth, so it cost a draw
|
|
29809
|
+
// call for every distinct VALSOU in every tile (up to 50 in one
|
|
29810
|
+
// bucket). Four keys cost at most four, and no bucket measured
|
|
29811
|
+
// held more than three.
|
|
29812
|
+
//
|
|
29813
|
+
// It should change paint order only. A hazard icon has one fixed
|
|
29814
|
+
// anchor and is always drawn, and every one of them puts its box in
|
|
29815
|
+
// the collision index whatever the order. The census measures that
|
|
29816
|
+
// rather than assuming it: every icon, label and sounding in view,
|
|
29817
|
+
// each form booted twice (`scripts/chart-bench/hazard-icon-census.ts`).
|
|
29818
|
+
// Its numbers are in `danger-depth-callouts.test.ts`, which pins
|
|
29819
|
+
// this order.
|
|
29714
29820
|
"symbol-sort-key": [
|
|
29715
29821
|
"case",
|
|
29716
29822
|
["==", watlev, 4],
|
|
29717
|
-
|
|
29823
|
+
3,
|
|
29718
29824
|
["==", watlev, 5],
|
|
29719
29825
|
2,
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29723
|
-
// hazard at the same point, but ranks dangerously-shallow
|
|
29724
|
-
// submerged rocks above deeper ones.
|
|
29725
|
-
["+", 10, valsou]
|
|
29826
|
+
["any", ["==", watlev, 1], ["==", watlev, 2]],
|
|
29827
|
+
0,
|
|
29828
|
+
1
|
|
29726
29829
|
]
|
|
29727
29830
|
};
|
|
29728
29831
|
}
|
|
@@ -32294,7 +32397,14 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
32294
32397
|
layers: finalLayers
|
|
32295
32398
|
};
|
|
32296
32399
|
const familyStyle = symbolSet === "s101" ? applyS101SymbolSet(style) : symbolSet === "chrt" ? applyChrtSymbolSet(style, palette) : symbolSet === "raster" ? applyRasterSymbolSet(style) : style;
|
|
32297
|
-
const
|
|
32400
|
+
const einked = applyEinkPortrayal(familyStyle, palette, { safetyContour: opts.safetyContour });
|
|
32401
|
+
const placed = opts.dangerDepthPlacers === true ? addDangerDepthPlacers(einked.layers) : einked.layers;
|
|
32402
|
+
const portrayed = placed === einked.layers ? einked : {
|
|
32403
|
+
...einked,
|
|
32404
|
+
layers: placed,
|
|
32405
|
+
// The placers are emitted layers: the count is of what the style carries.
|
|
32406
|
+
metadata: { ...einked.metadata, "chrt:layer-count": placed.length }
|
|
32407
|
+
};
|
|
32298
32408
|
const sized = applyChartSymbolScales(portrayed.layers, opts.symbolScales, opts.soundingsRule);
|
|
32299
32409
|
return sized === portrayed.layers ? portrayed : { ...portrayed, layers: sized };
|
|
32300
32410
|
}
|
|
@@ -33220,6 +33330,10 @@ var Chrt = class {
|
|
|
33220
33330
|
CHRT_STYLE_MODES,
|
|
33221
33331
|
Chrt,
|
|
33222
33332
|
ChrtError,
|
|
33333
|
+
DANGER_DEPTH_LABEL_ID,
|
|
33334
|
+
DANGER_DEPTH_PLACER_ID,
|
|
33335
|
+
DANGER_DEPTH_PLACER_LAYOUT,
|
|
33336
|
+
DANGER_DEPTH_VISIBLE_LAYOUT,
|
|
33223
33337
|
DEFAULT_CLICK_TOLERANCE,
|
|
33224
33338
|
DEFAULT_CUSTOM_STYLE_CONFIG,
|
|
33225
33339
|
DEFAULT_INSPECT_CLASS_RANK,
|
|
@@ -33318,6 +33432,7 @@ var Chrt = class {
|
|
|
33318
33432
|
WATER_BODY_LAYER_GROUPS,
|
|
33319
33433
|
WATER_TEXT_CLASSES,
|
|
33320
33434
|
WeatherEndpoint,
|
|
33435
|
+
addDangerDepthPlacers,
|
|
33321
33436
|
applyBaseBundle,
|
|
33322
33437
|
applyChartSymbolScales,
|
|
33323
33438
|
applyChartSymbolScalesToLayer,
|
|
@@ -33360,6 +33475,7 @@ var Chrt = class {
|
|
|
33360
33475
|
combineWithBandFilter,
|
|
33361
33476
|
contourValueFactor,
|
|
33362
33477
|
contrastRatio,
|
|
33478
|
+
dangerDepthPlacerId,
|
|
33363
33479
|
daymarkColor,
|
|
33364
33480
|
decimateFeatures,
|
|
33365
33481
|
decodeAreaFeatureProps,
|
|
@@ -33410,6 +33526,7 @@ var Chrt = class {
|
|
|
33410
33526
|
hazardFillExpression,
|
|
33411
33527
|
iconExpressionForFamily,
|
|
33412
33528
|
iconSliderFor,
|
|
33529
|
+
isDangerDepthPlacer,
|
|
33413
33530
|
isDepthAreaClassLayerId,
|
|
33414
33531
|
isDrapeable,
|
|
33415
33532
|
isEinkColorTable,
|