@chrtco/sdk 0.10.32 → 0.10.34
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/dist/index.cjs +236 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +236 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24350,6 +24350,197 @@ function buildPlaceNameLayers(sourceId) {
|
|
|
24350
24350
|
make("land", PLACENAME_LAND_CLASSES, ["Open Sans Regular"], COLOR.LAND_REGION, 0.02, PLACENAME_LAND_SIZE_STOPS)
|
|
24351
24351
|
];
|
|
24352
24352
|
}
|
|
24353
|
+
var DRGNOTE_SOURCE_LAYER = "DRGNOTE";
|
|
24354
|
+
var DRGNOTE_LABEL_PRIORITY = 300;
|
|
24355
|
+
var DRGNOTE_MINZOOM = 13;
|
|
24356
|
+
var DRGNOTE_FULL_ZOOM = 16;
|
|
24357
|
+
var DRGNOTE_MIN_TEXT_PX = 1;
|
|
24358
|
+
var DRGNOTE_MAX_TEXT_PX = 64;
|
|
24359
|
+
function legacyNoteSizePx(zoom) {
|
|
24360
|
+
const z = Math.min(16, Math.max(13, zoom));
|
|
24361
|
+
return 10.5 + (13 - 10.5) * (z - 13) / 3;
|
|
24362
|
+
}
|
|
24363
|
+
var DRGNOTE_FIT_ZOOM = 15;
|
|
24364
|
+
function dredgeNoteSize() {
|
|
24365
|
+
const stops = [];
|
|
24366
|
+
for (let z = 12; z <= 20; z++) {
|
|
24367
|
+
const prop = z < DRGNOTE_FULL_ZOOM ? "size_s" : "size_f";
|
|
24368
|
+
const fitted = ["to-number", ["get", prop], 0];
|
|
24369
|
+
stops.push(z, [
|
|
24370
|
+
"case",
|
|
24371
|
+
[">", fitted, 0],
|
|
24372
|
+
[
|
|
24373
|
+
"min",
|
|
24374
|
+
DRGNOTE_MAX_TEXT_PX,
|
|
24375
|
+
["max", DRGNOTE_MIN_TEXT_PX, ["*", fitted, 2 ** (z - DRGNOTE_FIT_ZOOM)]]
|
|
24376
|
+
],
|
|
24377
|
+
legacyNoteSizePx(z)
|
|
24378
|
+
]);
|
|
24379
|
+
}
|
|
24380
|
+
return ["interpolate", ["exponential", 2], ["zoom"], ...stops];
|
|
24381
|
+
}
|
|
24382
|
+
function noteDepthText(prop, depthUnits) {
|
|
24383
|
+
return depthUnits === "feet" ? ["concat", ["to-string", ["round", ["*", ["to-number", ["get", prop]], 3.28084]]], " FT"] : ["concat", ["to-string", ["get", prop]], " M"];
|
|
24384
|
+
}
|
|
24385
|
+
function buildDredgeNoteLayers(sourceId, palette = "DAY", depthUnits = "meters") {
|
|
24386
|
+
const widthProp = depthUnits === "feet" ? "width_ft" : "width_m";
|
|
24387
|
+
const widthUnit = depthUnits === "feet" ? " FT" : " M";
|
|
24388
|
+
const titleText = [
|
|
24389
|
+
"to-string",
|
|
24390
|
+
["coalesce", ["get", "designation"], ["get", "name"], ""]
|
|
24391
|
+
];
|
|
24392
|
+
const placeText = ["to-string", ["coalesce", ["get", "place"], ""]];
|
|
24393
|
+
const sep = (prop) => [
|
|
24394
|
+
"to-string",
|
|
24395
|
+
["coalesce", ["get", prop], "\n"]
|
|
24396
|
+
];
|
|
24397
|
+
const legendText = [
|
|
24398
|
+
"concat",
|
|
24399
|
+
noteDepthText("depth_m", depthUnits),
|
|
24400
|
+
[
|
|
24401
|
+
"case",
|
|
24402
|
+
[">", ["to-number", ["get", "qual_m"], -1], 0],
|
|
24403
|
+
[
|
|
24404
|
+
"concat",
|
|
24405
|
+
" ",
|
|
24406
|
+
noteDepthText("qual_m", depthUnits),
|
|
24407
|
+
" ",
|
|
24408
|
+
["to-string", ["get", "qual_part"]]
|
|
24409
|
+
],
|
|
24410
|
+
""
|
|
24411
|
+
],
|
|
24412
|
+
[
|
|
24413
|
+
"case",
|
|
24414
|
+
[">", ["to-number", ["get", widthProp], -1], 0],
|
|
24415
|
+
["concat", " FOR A WIDTH OF ", ["to-string", ["get", widthProp]], widthUnit],
|
|
24416
|
+
""
|
|
24417
|
+
],
|
|
24418
|
+
[
|
|
24419
|
+
"case",
|
|
24420
|
+
["!=", ["to-string", ["get", "date"]], ""],
|
|
24421
|
+
["concat", " ", ["to-string", ["get", "date"]]],
|
|
24422
|
+
""
|
|
24423
|
+
],
|
|
24424
|
+
["case", ["==", ["get", "unmaintained"], true], " NOT MAINTAINED", ""]
|
|
24425
|
+
];
|
|
24426
|
+
const shortField = [
|
|
24427
|
+
"case",
|
|
24428
|
+
["!=", titleText, ""],
|
|
24429
|
+
["concat", titleText, sep("sep_s"), legendText],
|
|
24430
|
+
legendText
|
|
24431
|
+
];
|
|
24432
|
+
const fullField = [
|
|
24433
|
+
"case",
|
|
24434
|
+
["!=", placeText, ""],
|
|
24435
|
+
["concat", placeText, sep("sep_fp"), titleText, sep("sep_ft"), legendText],
|
|
24436
|
+
["case", ["!=", titleText, ""], ["concat", titleText, sep("sep_ft"), legendText], legendText]
|
|
24437
|
+
];
|
|
24438
|
+
const noteField = [
|
|
24439
|
+
"step",
|
|
24440
|
+
["zoom"],
|
|
24441
|
+
shortField,
|
|
24442
|
+
DRGNOTE_FULL_ZOOM,
|
|
24443
|
+
fullField
|
|
24444
|
+
];
|
|
24445
|
+
const sortKey = [
|
|
24446
|
+
"case",
|
|
24447
|
+
[">=", ["to-number", ["get", "rank"], -1], 0],
|
|
24448
|
+
["to-number", ["get", "rank"]],
|
|
24449
|
+
["*", 1e3, ["to-number", ["get", "depth_m"], 99]]
|
|
24450
|
+
];
|
|
24451
|
+
return [
|
|
24452
|
+
{
|
|
24453
|
+
// The `-label` suffix is how this repo marks a label layer, and
|
|
24454
|
+
// z-order guards partition on it (sector-light-zorder.test.ts).
|
|
24455
|
+
id: "chrt-dredge-note-label",
|
|
24456
|
+
type: "symbol",
|
|
24457
|
+
source: sourceId,
|
|
24458
|
+
"source-layer": DRGNOTE_SOURCE_LAYER,
|
|
24459
|
+
minzoom: DRGNOTE_MINZOOM,
|
|
24460
|
+
layout: {
|
|
24461
|
+
"text-field": noteField,
|
|
24462
|
+
"text-font": ["Open Sans Regular"],
|
|
24463
|
+
// Ink on the chart, not type on the screen.
|
|
24464
|
+
//
|
|
24465
|
+
// The size is fitted to THIS polygon at build time (px at z15) and
|
|
24466
|
+
// doubled per zoom here, so the note holds a fixed GEOGRAPHIC size
|
|
24467
|
+
// the way a raster chart's note is fixed to its paper. Set at one
|
|
24468
|
+
// screen size instead, a note fits its channel at one zoom and
|
|
24469
|
+
// spills at every other — measured at Gloucester z15, only 37% of
|
|
24470
|
+
// North Channel's note lay inside North Channel.
|
|
24471
|
+
//
|
|
24472
|
+
// `interpolate` with base 2 and stops ONE zoom apart is exactly
|
|
24473
|
+
// geometric: t = (2^(z-z1)-1)/(2^1-1) and v2 = 2*v1 collapse to
|
|
24474
|
+
// v1*2^(z-z1). Writing it the obvious way instead —
|
|
24475
|
+
// ["*", size, ["^", 2, ["-", ["zoom"], 15]]] — is INVALID, because
|
|
24476
|
+
// ["zoom"] may only be the direct input of an outer interpolate or
|
|
24477
|
+
// step. MapLibre rejects it silently, keeps the previous value and
|
|
24478
|
+
// renders on as if nothing happened.
|
|
24479
|
+
//
|
|
24480
|
+
// It is NOT clamped to a legible band. That was tried and it
|
|
24481
|
+
// defeated the point: measured across z13-z18 a clamp bound at
|
|
24482
|
+
// five of six zooms for every Gloucester note, pinning the note to
|
|
24483
|
+
// a fixed screen size while its channel grew. A note that keeps
|
|
24484
|
+
// its proportion is illegibly small when its channel is small,
|
|
24485
|
+
// and that is correct — it is how the eye tells which channel a
|
|
24486
|
+
// note belongs to, and how a raster chart behaves. Zoom in and it
|
|
24487
|
+
// grows with the water. A tile built before the fit carries no
|
|
24488
|
+
// size and keeps the fixed size it was designed for.
|
|
24489
|
+
"text-size": dredgeNoteSize(),
|
|
24490
|
+
"text-transform": "uppercase",
|
|
24491
|
+
"text-letter-spacing": 0.08,
|
|
24492
|
+
// ONE line, and wide enough never to wrap into a second.
|
|
24493
|
+
//
|
|
24494
|
+
// Must equal noteFit.ts#LINE_HEIGHT_EM — the build side measures
|
|
24495
|
+
// the note's height with it before deciding how large it can set.
|
|
24496
|
+
"text-line-height": 1.2,
|
|
24497
|
+
// Wide enough that MapLibre NEVER wraps. Every break in this note
|
|
24498
|
+
// is an explicit "\n" the build side chose by fitting the result
|
|
24499
|
+
// against the polygon; an automatic wrap on top of that would
|
|
24500
|
+
// re-flow the label into lines nothing measured, and MapLibre's
|
|
24501
|
+
// line breaker balances lines rather than filling greedily, so the
|
|
24502
|
+
// build side cannot predict where it would land.
|
|
24503
|
+
"text-max-width": 512,
|
|
24504
|
+
"text-rotate": ["get", "rotate"],
|
|
24505
|
+
"text-rotation-alignment": "map",
|
|
24506
|
+
"text-padding": 3,
|
|
24507
|
+
"text-allow-overlap": false,
|
|
24508
|
+
"text-ignore-placement": false,
|
|
24509
|
+
"text-optional": true,
|
|
24510
|
+
// Placement rank from the build side (dredgeNote.ts#stationRank):
|
|
24511
|
+
// shoaler water always survives a collision, bigger channel first
|
|
24512
|
+
// among equal depths.
|
|
24513
|
+
//
|
|
24514
|
+
// Deliberately NOT labelSortKey. That helper clamps its second
|
|
24515
|
+
// argument to [0, 999] — fine for a VALDCO contour value, fatal
|
|
24516
|
+
// here: every rank in the millions collapsed to 999 and both notes
|
|
24517
|
+
// evaluated to the identical key 300999, making the whole ranking
|
|
24518
|
+
// inert. The priority prefix it adds is redundant anyway, because
|
|
24519
|
+
// symbol-sort-key only orders WITHIN a layer; cross-layer order is
|
|
24520
|
+
// the layer stack's job (spliceByLabelPriority). PLACENAME reads
|
|
24521
|
+
// its own `rank` bare for exactly this reason.
|
|
24522
|
+
//
|
|
24523
|
+
// Tiles built before `rank` existed fall back to depth ordering,
|
|
24524
|
+
// so they degrade to shoal-first rather than to one flat value.
|
|
24525
|
+
"symbol-sort-key": sortKey
|
|
24526
|
+
},
|
|
24527
|
+
paint: {
|
|
24528
|
+
"text-color": resolveColor("CHBLK", palette),
|
|
24529
|
+
// Halo in the dredged-area fill itself, so the note reads as set
|
|
24530
|
+
// INTO the channel rather than floating over it. Kept thin: the
|
|
24531
|
+
// note crosses its own dashed limit and whatever soundings sit in
|
|
24532
|
+
// the channel, so it needs SOME separation — but a wide halo on
|
|
24533
|
+
// ~11px type erodes the glyph strokes and turns black type grey.
|
|
24534
|
+
"text-halo-color": resolveColor("DEPMD", palette),
|
|
24535
|
+
"text-halo-width": 1
|
|
24536
|
+
},
|
|
24537
|
+
metadata: {
|
|
24538
|
+
"chrt:dredgeNote": true,
|
|
24539
|
+
"chrt:labelPriority": DRGNOTE_LABEL_PRIORITY
|
|
24540
|
+
}
|
|
24541
|
+
}
|
|
24542
|
+
];
|
|
24543
|
+
}
|
|
24353
24544
|
|
|
24354
24545
|
// src/atlas/feature-decimation.ts
|
|
24355
24546
|
function getGridSizeForZoom(zoom) {
|
|
@@ -27620,6 +27811,22 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
27620
27811
|
metadata: { "s52:objectClass": "ACHARE", "s52:role": "boundary" }
|
|
27621
27812
|
});
|
|
27622
27813
|
}
|
|
27814
|
+
if (objectClass === "DRGARE" && resolved.type === "fill") {
|
|
27815
|
+
layers.push({
|
|
27816
|
+
id: "s52-DRGARE-boundary",
|
|
27817
|
+
type: "line",
|
|
27818
|
+
source: sourceId,
|
|
27819
|
+
"source-layer": "DRGARE",
|
|
27820
|
+
filter: GEOM_FILTERS.fill,
|
|
27821
|
+
paint: {
|
|
27822
|
+
"line-color": resolveColor("CHGRD", ct),
|
|
27823
|
+
"line-width": 0.9,
|
|
27824
|
+
"line-dasharray": [4, 3],
|
|
27825
|
+
"line-opacity": 0.75
|
|
27826
|
+
},
|
|
27827
|
+
metadata: { "s52:objectClass": "DRGARE", "s52:role": "boundary" }
|
|
27828
|
+
});
|
|
27829
|
+
}
|
|
27623
27830
|
if (objectClass === "ACHARE" && resolved.type === "fill") {
|
|
27624
27831
|
layers.push({
|
|
27625
27832
|
id: "s52-ACHARE-anchor-icon",
|
|
@@ -29695,6 +29902,17 @@ function byLabelPriorityBottomUp(bundles) {
|
|
|
29695
29902
|
(a, b) => getLabelPriority(b.objectClass) - getLabelPriority(a.objectClass)
|
|
29696
29903
|
);
|
|
29697
29904
|
}
|
|
29905
|
+
function spliceByLabelPriority(labelLayers, incoming, priority) {
|
|
29906
|
+
if (incoming.length === 0) return;
|
|
29907
|
+
const rankOf = (l) => {
|
|
29908
|
+
const meta = l.metadata;
|
|
29909
|
+
const p = meta?.["chrt:labelPriority"];
|
|
29910
|
+
return typeof p === "number" ? p : DEFAULT_LABEL_PRIORITY;
|
|
29911
|
+
};
|
|
29912
|
+
const at = labelLayers.findIndex((l) => rankOf(l) < priority);
|
|
29913
|
+
if (at === -1) labelLayers.push(...incoming);
|
|
29914
|
+
else labelLayers.splice(at, 0, ...incoming);
|
|
29915
|
+
}
|
|
29698
29916
|
function chartModeBandClauses(layer, B, higherCascadeBands, lockedBounds, isRequestedBand) {
|
|
29699
29917
|
const parts = [bandFilterExpression(B)];
|
|
29700
29918
|
if (!isDominanceExempt(layer)) {
|
|
@@ -29881,6 +30099,15 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
29881
30099
|
labelLayers.push(variant);
|
|
29882
30100
|
}
|
|
29883
30101
|
}
|
|
30102
|
+
spliceByLabelPriority(
|
|
30103
|
+
labelLayers,
|
|
30104
|
+
buildDredgeNoteLayers(
|
|
30105
|
+
sourceId,
|
|
30106
|
+
palette,
|
|
30107
|
+
opts.depthUnits ?? "meters"
|
|
30108
|
+
),
|
|
30109
|
+
DRGNOTE_LABEL_PRIORITY
|
|
30110
|
+
);
|
|
29884
30111
|
layers.push(...labelLayers);
|
|
29885
30112
|
} else {
|
|
29886
30113
|
const emitBand = (base, code) => bandFan === "legacy" ? makeBandVariants(base, code) : makeCollapsedBandVariant(base, code, isDominanceExempt(base));
|
|
@@ -29968,6 +30195,15 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
29968
30195
|
}
|
|
29969
30196
|
}
|
|
29970
30197
|
if (!majorsEmitted) labelLayers.push(...majorWaterLayers);
|
|
30198
|
+
spliceByLabelPriority(
|
|
30199
|
+
labelLayers,
|
|
30200
|
+
buildDredgeNoteLayers(
|
|
30201
|
+
sourceId,
|
|
30202
|
+
palette,
|
|
30203
|
+
opts.depthUnits ?? "meters"
|
|
30204
|
+
),
|
|
30205
|
+
DRGNOTE_LABEL_PRIORITY
|
|
30206
|
+
);
|
|
29971
30207
|
layers.push(...labelLayers);
|
|
29972
30208
|
}
|
|
29973
30209
|
const symbolSet = opts.symbolSet ?? "s52";
|