@chrtco/sdk 0.10.29 → 0.10.31
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 +382 -354
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +382 -354
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -28842,328 +28842,12 @@ function worldMinusBboxPolygon(bbox) {
|
|
|
28842
28842
|
};
|
|
28843
28843
|
}
|
|
28844
28844
|
|
|
28845
|
-
// src/atlas/land-layers.ts
|
|
28846
|
-
var LAND_SURFACE_MINZOOM = BAND_PRIORITY_RANGES["5"].minzoom;
|
|
28847
|
-
var LAND_SURFACE_LAYERS = (id) => id === "chrtland-base" || id === "chrtland-cover" || id === "chrtland-contour" || id === "chrtland-hillshade" || id.startsWith("chrtland-fade-");
|
|
28848
|
-
var FADE_PX = 80;
|
|
28849
|
-
var FADE_BANDS = 16;
|
|
28850
|
-
function fadeAlpha(r) {
|
|
28851
|
-
return Math.max(0, Math.min(1, (FADE_PX / 2 - Math.abs(r)) / FADE_PX));
|
|
28852
|
-
}
|
|
28853
|
-
function landBaseColor(palette) {
|
|
28854
|
-
return (LAND_THEMES[palette] ?? LAND_THEMES.DAY).base;
|
|
28855
|
-
}
|
|
28856
|
-
var LAND_THEMES = {
|
|
28857
|
-
DAY: {
|
|
28858
|
-
base: "#e8d9b0",
|
|
28859
|
-
cover: { wood: "#cfd8b4", wetland: "#c9d3c4", urban: "#dedad2", sand: "#efe4c2" },
|
|
28860
|
-
contour: "#a89878",
|
|
28861
|
-
contourIndex: "#8a7a5c",
|
|
28862
|
-
road: "#d9c9a4",
|
|
28863
|
-
roadMajor: "#d2bd8e",
|
|
28864
|
-
label: "#5b4f3a",
|
|
28865
|
-
halo: "#f2ead6",
|
|
28866
|
-
shadow: "#6b5a3e",
|
|
28867
|
-
highlight: "#fffaf0",
|
|
28868
|
-
fade: "#e8f2f8",
|
|
28869
|
-
// Raised from 0.45 on 2026-08-23. ⚠ Above the ~0.5 that
|
|
28870
|
-
// hillshade-style.mjs warns "starts competing with depth areas" — a
|
|
28871
|
-
// deliberate, sighted choice made against rendered evidence, not a
|
|
28872
|
-
// default. If soundings or DEPARE ever read as fighting the terrain,
|
|
28873
|
-
// this number is the first thing to walk back.
|
|
28874
|
-
exaggeration: 0.8
|
|
28875
|
-
},
|
|
28876
|
-
DUSK: {
|
|
28877
|
-
base: "#4a4433",
|
|
28878
|
-
cover: { wood: "#414a38", wetland: "#3f4740", urban: "#4e4a42", sand: "#544c39" },
|
|
28879
|
-
contour: "#6b6250",
|
|
28880
|
-
contourIndex: "#837961",
|
|
28881
|
-
road: "#565040",
|
|
28882
|
-
roadMajor: "#63594440",
|
|
28883
|
-
label: "#c3b898",
|
|
28884
|
-
halo: "#2b2820",
|
|
28885
|
-
shadow: "#2e2a20",
|
|
28886
|
-
highlight: "#8a8068",
|
|
28887
|
-
fade: "#16202a",
|
|
28888
|
-
// Unchanged. DUSK was not the palette the 0.8 decision was made against.
|
|
28889
|
-
exaggeration: 0.45
|
|
28890
|
-
},
|
|
28891
|
-
NIGHT: {
|
|
28892
|
-
base: "#2a2620",
|
|
28893
|
-
cover: { wood: "#242a20", wetland: "#232823", urban: "#2c2925", sand: "#302b22" },
|
|
28894
|
-
contour: "#413b30",
|
|
28895
|
-
contourIndex: "#524a3b",
|
|
28896
|
-
road: "#332f27",
|
|
28897
|
-
roadMajor: "#3d382d",
|
|
28898
|
-
label: "#7d745e",
|
|
28899
|
-
halo: "#15130f",
|
|
28900
|
-
shadow: "#1a1712",
|
|
28901
|
-
highlight: "#4a4436",
|
|
28902
|
-
fade: "#07090b",
|
|
28903
|
-
// ⚠ DELIBERATELY NOT RAISED. See the type's note: a strong hillshade
|
|
28904
|
-
// under red night vision is a grey haze over exactly the contrast a
|
|
28905
|
-
// skipper is navigating by. Left at the shipped value rather than
|
|
28906
|
-
// lowered, because lowering it is a separate decision from this one.
|
|
28907
|
-
exaggeration: 0.45
|
|
28908
|
-
}
|
|
28909
|
-
};
|
|
28910
|
-
var FITS = ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]];
|
|
28911
|
-
var ANCHOR = ["coalesce", ["get", "anchor"], "top"];
|
|
28912
|
-
var anchorOffset = (em) => [
|
|
28913
|
-
"match",
|
|
28914
|
-
["get", "anchor"],
|
|
28915
|
-
"left",
|
|
28916
|
-
["literal", [0.6, 0]],
|
|
28917
|
-
"right",
|
|
28918
|
-
["literal", [-0.6, 0]],
|
|
28919
|
-
"bottom",
|
|
28920
|
-
["literal", [0, -em]],
|
|
28921
|
-
["literal", [0, em]]
|
|
28922
|
-
];
|
|
28923
|
-
var FONT = ["Open Sans Regular"];
|
|
28924
|
-
var FONT_ITALIC = ["Open Sans Italic"];
|
|
28925
|
-
function landLayers(opts = {}) {
|
|
28926
|
-
const palette = opts.palette ?? "DAY";
|
|
28927
|
-
const T = LAND_THEMES[palette] ?? LAND_THEMES.DAY;
|
|
28928
|
-
const src = opts.sourceId ?? LAND_REGION;
|
|
28929
|
-
const demSrc = opts.reliefSourceId ?? RELIEF_REGION;
|
|
28930
|
-
const L = (o) => o;
|
|
28931
|
-
const layers = [
|
|
28932
|
-
// 1. The land itself — LNDARE ∩ coverage, so it can never outrun the chart.
|
|
28933
|
-
L({
|
|
28934
|
-
id: "chrtland-base",
|
|
28935
|
-
type: "fill",
|
|
28936
|
-
source: src,
|
|
28937
|
-
"source-layer": "land_base",
|
|
28938
|
-
paint: { "fill-color": T.base }
|
|
28939
|
-
})
|
|
28940
|
-
];
|
|
28941
|
-
layers.push(L({
|
|
28942
|
-
id: "chrtland-cover",
|
|
28943
|
-
type: "fill",
|
|
28944
|
-
source: src,
|
|
28945
|
-
"source-layer": "land_cover",
|
|
28946
|
-
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
28947
|
-
paint: {
|
|
28948
|
-
"fill-color": [
|
|
28949
|
-
"match",
|
|
28950
|
-
["get", "class"],
|
|
28951
|
-
"wood",
|
|
28952
|
-
T.cover.wood,
|
|
28953
|
-
"wetland",
|
|
28954
|
-
T.cover.wetland,
|
|
28955
|
-
"urban",
|
|
28956
|
-
T.cover.urban,
|
|
28957
|
-
"sand",
|
|
28958
|
-
T.cover.sand,
|
|
28959
|
-
T.base
|
|
28960
|
-
],
|
|
28961
|
-
"fill-opacity": 0.85
|
|
28962
|
-
}
|
|
28963
|
-
}));
|
|
28964
|
-
if (opts.relief) {
|
|
28965
|
-
layers.push(L({
|
|
28966
|
-
// No minzoom here: LAND_SURFACE_LAYERS floors it with the rest of the
|
|
28967
|
-
// surface, so the two can never drift apart again.
|
|
28968
|
-
id: "chrtland-hillshade",
|
|
28969
|
-
type: "hillshade",
|
|
28970
|
-
source: demSrc,
|
|
28971
|
-
paint: {
|
|
28972
|
-
"hillshade-exaggeration": T.exaggeration,
|
|
28973
|
-
"hillshade-shadow-color": T.shadow,
|
|
28974
|
-
"hillshade-highlight-color": T.highlight,
|
|
28975
|
-
"hillshade-accent-color": T.shadow
|
|
28976
|
-
}
|
|
28977
|
-
}));
|
|
28978
|
-
}
|
|
28979
|
-
const isIndexContour = [
|
|
28980
|
-
"any",
|
|
28981
|
-
["<=", ["coalesce", ["get", "index_z"], 99], ["zoom"]],
|
|
28982
|
-
["==", ["get", "is_index"], 1]
|
|
28983
|
-
];
|
|
28984
|
-
layers.push(L({
|
|
28985
|
-
id: "chrtland-contour",
|
|
28986
|
-
type: "line",
|
|
28987
|
-
source: src,
|
|
28988
|
-
"source-layer": "land_contour",
|
|
28989
|
-
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
28990
|
-
paint: {
|
|
28991
|
-
"line-color": ["case", isIndexContour, T.contourIndex, T.contour],
|
|
28992
|
-
"line-width": ["case", isIndexContour, 0.8, 0.4],
|
|
28993
|
-
"line-opacity": 0.7
|
|
28994
|
-
}
|
|
28995
|
-
}));
|
|
28996
|
-
const d = FADE_PX / 2 / FADE_BANDS;
|
|
28997
|
-
for (let k = 0; k < FADE_BANDS; k++) {
|
|
28998
|
-
const width = k === 0 ? { "line-width": 2 * d } : { "line-width": d, "line-gap-width": 2 * k * d };
|
|
28999
|
-
layers.push(L({
|
|
29000
|
-
id: `chrtland-fade-${k}`,
|
|
29001
|
-
type: "line",
|
|
29002
|
-
source: src,
|
|
29003
|
-
"source-layer": "land_edge",
|
|
29004
|
-
layout: { "line-join": "bevel" },
|
|
29005
|
-
paint: { "line-color": T.fade, "line-blur": 0, "line-opacity": fadeAlpha(k * d + d / 2), ...width }
|
|
29006
|
-
}));
|
|
29007
|
-
}
|
|
29008
|
-
layers.push(L({
|
|
29009
|
-
id: "chrtland-road",
|
|
29010
|
-
type: "line",
|
|
29011
|
-
source: src,
|
|
29012
|
-
"source-layer": "land_road",
|
|
29013
|
-
minzoom: 10,
|
|
29014
|
-
paint: {
|
|
29015
|
-
"line-color": ["match", ["get", "kind"], "highway", T.roadMajor, T.road],
|
|
29016
|
-
"line-width": [
|
|
29017
|
-
"interpolate",
|
|
29018
|
-
["linear"],
|
|
29019
|
-
["zoom"],
|
|
29020
|
-
10,
|
|
29021
|
-
["match", ["get", "kind"], "highway", 0.8, 0.4],
|
|
29022
|
-
14,
|
|
29023
|
-
["match", ["get", "kind"], "highway", 2.4, 1.2]
|
|
29024
|
-
],
|
|
29025
|
-
"line-opacity": 0.8
|
|
29026
|
-
}
|
|
29027
|
-
}));
|
|
29028
|
-
layers.push(L({
|
|
29029
|
-
id: "chrtland-city-major",
|
|
29030
|
-
type: "symbol",
|
|
29031
|
-
source: src,
|
|
29032
|
-
"source-layer": "land_town",
|
|
29033
|
-
minzoom: 6.5,
|
|
29034
|
-
filter: [">=", ["coalesce", ["get", "prank"], 0], 10],
|
|
29035
|
-
layout: {
|
|
29036
|
-
"text-field": [
|
|
29037
|
-
"case",
|
|
29038
|
-
["==", ["get", "upcase"], true],
|
|
29039
|
-
["upcase", ["get", "name"]],
|
|
29040
|
-
["get", "name"]
|
|
29041
|
-
],
|
|
29042
|
-
"text-font": FONT,
|
|
29043
|
-
"text-size": [
|
|
29044
|
-
"interpolate",
|
|
29045
|
-
["linear"],
|
|
29046
|
-
["zoom"],
|
|
29047
|
-
6.5,
|
|
29048
|
-
11.5,
|
|
29049
|
-
9,
|
|
29050
|
-
["+", 10, ["*", 0.4, ["coalesce", ["get", "prank"], 10]]],
|
|
29051
|
-
13,
|
|
29052
|
-
["+", 13, ["*", 0.5, ["coalesce", ["get", "prank"], 10]]]
|
|
29053
|
-
],
|
|
29054
|
-
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0.02],
|
|
29055
|
-
"text-offset": anchorOffset(0.75),
|
|
29056
|
-
"text-anchor": ANCHOR,
|
|
29057
|
-
"text-padding": 10,
|
|
29058
|
-
"text-allow-overlap": false,
|
|
29059
|
-
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29060
|
-
},
|
|
29061
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.6 }
|
|
29062
|
-
}));
|
|
29063
|
-
layers.push(L({
|
|
29064
|
-
id: "chrtland-town-port",
|
|
29065
|
-
type: "symbol",
|
|
29066
|
-
source: src,
|
|
29067
|
-
"source-layer": "land_town",
|
|
29068
|
-
minzoom: 8.5,
|
|
29069
|
-
filter: [
|
|
29070
|
-
"all",
|
|
29071
|
-
["==", ["get", "enc_dup"], true],
|
|
29072
|
-
["<", ["coalesce", ["get", "prank"], 0], 10]
|
|
29073
|
-
],
|
|
29074
|
-
layout: {
|
|
29075
|
-
"text-field": ["get", "name"],
|
|
29076
|
-
"text-font": FONT,
|
|
29077
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 8.5, 11, 12, 13.5],
|
|
29078
|
-
"text-offset": anchorOffset(0.75),
|
|
29079
|
-
"text-anchor": ANCHOR,
|
|
29080
|
-
"text-padding": 8,
|
|
29081
|
-
"text-allow-overlap": false,
|
|
29082
|
-
// Within the tier, the bigger place wins the space: without this the
|
|
29083
|
-
// tie broke on data order and "West Gloucester" beat Gloucester.
|
|
29084
|
-
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29085
|
-
},
|
|
29086
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.4 }
|
|
29087
|
-
}));
|
|
29088
|
-
layers.push(L({
|
|
29089
|
-
id: "chrtland-town",
|
|
29090
|
-
type: "symbol",
|
|
29091
|
-
source: src,
|
|
29092
|
-
"source-layer": "land_town",
|
|
29093
|
-
minzoom: 9,
|
|
29094
|
-
filter: [
|
|
29095
|
-
"all",
|
|
29096
|
-
FITS,
|
|
29097
|
-
["<", ["coalesce", ["get", "prank"], 0], 10],
|
|
29098
|
-
["!=", ["get", "enc_dup"], true]
|
|
29099
|
-
],
|
|
29100
|
-
layout: {
|
|
29101
|
-
"text-field": [
|
|
29102
|
-
"case",
|
|
29103
|
-
["==", ["get", "upcase"], true],
|
|
29104
|
-
["upcase", ["get", "name"]],
|
|
29105
|
-
["get", "name"]
|
|
29106
|
-
],
|
|
29107
|
-
"text-font": FONT,
|
|
29108
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 9, 10, 14, 13.5],
|
|
29109
|
-
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0],
|
|
29110
|
-
"text-offset": anchorOffset(0.75),
|
|
29111
|
-
"text-anchor": ANCHOR,
|
|
29112
|
-
"text-padding": 6,
|
|
29113
|
-
"text-allow-overlap": false,
|
|
29114
|
-
"symbol-sort-key": 2
|
|
29115
|
-
},
|
|
29116
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29117
|
-
}));
|
|
29118
|
-
layers.push(L({
|
|
29119
|
-
id: "chrtland-summit",
|
|
29120
|
-
type: "symbol",
|
|
29121
|
-
source: src,
|
|
29122
|
-
"source-layer": "land_summit",
|
|
29123
|
-
minzoom: 11.5,
|
|
29124
|
-
filter: ["all", FITS, [">=", ["get", "peak_m"], 40]],
|
|
29125
|
-
layout: {
|
|
29126
|
-
"text-field": ["concat", ["get", "name"], "\n", ["to-string", ["get", "peak_m"]], " m"],
|
|
29127
|
-
"text-font": FONT,
|
|
29128
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 11.5, 8.5, 14, 11],
|
|
29129
|
-
"text-offset": anchorOffset(0.8),
|
|
29130
|
-
"text-anchor": ANCHOR,
|
|
29131
|
-
"text-padding": 5,
|
|
29132
|
-
"text-allow-overlap": false,
|
|
29133
|
-
"symbol-sort-key": 3
|
|
29134
|
-
},
|
|
29135
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29136
|
-
}));
|
|
29137
|
-
layers.push(L({
|
|
29138
|
-
id: "chrtland-poi",
|
|
29139
|
-
type: "symbol",
|
|
29140
|
-
source: src,
|
|
29141
|
-
"source-layer": "land_poi",
|
|
29142
|
-
minzoom: 13,
|
|
29143
|
-
filter: FITS,
|
|
29144
|
-
layout: {
|
|
29145
|
-
"text-field": ["get", "name"],
|
|
29146
|
-
"text-font": FONT_ITALIC,
|
|
29147
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 13, 8, 14, 9.5],
|
|
29148
|
-
"text-offset": anchorOffset(0.7),
|
|
29149
|
-
"text-anchor": ANCHOR,
|
|
29150
|
-
"text-padding": 5,
|
|
29151
|
-
"text-allow-overlap": false,
|
|
29152
|
-
"symbol-sort-key": 5
|
|
29153
|
-
},
|
|
29154
|
-
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29155
|
-
}));
|
|
29156
|
-
for (const layer of layers) {
|
|
29157
|
-
const l = layer;
|
|
29158
|
-
if (!LAND_SURFACE_LAYERS(l.id)) continue;
|
|
29159
|
-
l.minzoom = Math.max(l.minzoom ?? 0, LAND_SURFACE_MINZOOM);
|
|
29160
|
-
}
|
|
29161
|
-
return layers;
|
|
29162
|
-
}
|
|
29163
|
-
|
|
29164
28845
|
// src/atlas/base-layers.ts
|
|
29165
28846
|
var NOCOVERAGE_PATTERN = "chrt:hatch-nocoverage";
|
|
29166
28847
|
var UNCHARTED_PATTERN = "chrt:hatch-uncharted";
|
|
28848
|
+
function inlandWaterColor(palette) {
|
|
28849
|
+
return (BASE_THEMES[palette] ?? BASE_THEMES.DAY).inlandWater;
|
|
28850
|
+
}
|
|
29167
28851
|
var BASE_THEMES = {
|
|
29168
28852
|
DAY: {
|
|
29169
28853
|
// ── `earth` is the jurisdiction tan DIMMED (~0.55), not a blue-grey ──
|
|
@@ -29182,7 +28866,7 @@ var BASE_THEMES = {
|
|
|
29182
28866
|
water: "#1B2328",
|
|
29183
28867
|
river: "#24313A",
|
|
29184
28868
|
boundary: "#4A575E",
|
|
29185
|
-
jurisdiction: "#
|
|
28869
|
+
jurisdiction: "#D4C69D",
|
|
29186
28870
|
// CHRTland's own tan — one land colour
|
|
29187
28871
|
inlandWater: "#B9CFDD",
|
|
29188
28872
|
// muted, unmistakably not a charted blue
|
|
@@ -29190,9 +28874,9 @@ var BASE_THEMES = {
|
|
|
29190
28874
|
// from this table (and its type — the long-standing TS2339 trio), so the
|
|
29191
28875
|
// lines shipped on MapLibre's DEFAULT black. Now deliberate: a hairline
|
|
29192
28876
|
// a shade deeper than the tan, quiet caps, tan halo.
|
|
29193
|
-
stateLine: "#
|
|
28877
|
+
stateLine: "#B1A077",
|
|
29194
28878
|
stateLabel: "#8E8468",
|
|
29195
|
-
stateHalo: "#
|
|
28879
|
+
stateHalo: "#D4C69D",
|
|
29196
28880
|
// Rough-lake furniture (owner ask 2026-08-28: "the lakes need labels,
|
|
29197
28881
|
// and shorelines drawn"): a shoreline a shade deeper than the rough
|
|
29198
28882
|
// water, and a name in the water's own voice, haloed by the water.
|
|
@@ -29570,29 +29254,357 @@ function baseInlandWaterLayers(opts = {}) {
|
|
|
29570
29254
|
id: "chrtbase-inland-label",
|
|
29571
29255
|
type: "symbol",
|
|
29572
29256
|
source: src,
|
|
29573
|
-
"source-layer": "inland_water_label",
|
|
29574
|
-
minzoom: 5,
|
|
29575
|
-
layout: {
|
|
29576
|
-
"text-field": ["get", "name"],
|
|
29577
|
-
"text-font": ["Open Sans Regular"],
|
|
29578
|
-
"text-size": ["interpolate", ["linear"], ["zoom"], 5, 9.5, 10, 12],
|
|
29579
|
-
"text-max-width": 7,
|
|
29580
|
-
"text-allow-overlap": false,
|
|
29581
|
-
// Zoom-scaled spacing for the anchor GRID: at z8.9 the 0.08-deg
|
|
29582
|
-
// anchors sit ~54 px apart and a flat padding let six copies of
|
|
29583
|
-
// "Lake Ontario" crowd one screen (owner-reported 2026-08-30).
|
|
29584
|
-
// Wide collision boxes at low zoom thin the grid to the repeat-
|
|
29585
|
-
// by-convention cadence; by z12 the anchors are ~850 px apart and
|
|
29586
|
-
// the padding relaxes to normal.
|
|
29587
|
-
"text-padding": ["interpolate", ["linear"], ["zoom"], 5, 80, 9, 64, 12, 16]
|
|
29588
|
-
},
|
|
29257
|
+
"source-layer": "inland_water_label",
|
|
29258
|
+
minzoom: 5,
|
|
29259
|
+
layout: {
|
|
29260
|
+
"text-field": ["get", "name"],
|
|
29261
|
+
"text-font": ["Open Sans Regular"],
|
|
29262
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 5, 9.5, 10, 12],
|
|
29263
|
+
"text-max-width": 7,
|
|
29264
|
+
"text-allow-overlap": false,
|
|
29265
|
+
// Zoom-scaled spacing for the anchor GRID: at z8.9 the 0.08-deg
|
|
29266
|
+
// anchors sit ~54 px apart and a flat padding let six copies of
|
|
29267
|
+
// "Lake Ontario" crowd one screen (owner-reported 2026-08-30).
|
|
29268
|
+
// Wide collision boxes at low zoom thin the grid to the repeat-
|
|
29269
|
+
// by-convention cadence; by z12 the anchors are ~850 px apart and
|
|
29270
|
+
// the padding relaxes to normal.
|
|
29271
|
+
"text-padding": ["interpolate", ["linear"], ["zoom"], 5, 80, 9, 64, 12, 16]
|
|
29272
|
+
},
|
|
29273
|
+
paint: {
|
|
29274
|
+
"text-color": T.inlandLabel,
|
|
29275
|
+
"text-halo-color": T.inlandHalo,
|
|
29276
|
+
"text-halo-width": 1.1
|
|
29277
|
+
}
|
|
29278
|
+
})
|
|
29279
|
+
];
|
|
29280
|
+
}
|
|
29281
|
+
|
|
29282
|
+
// src/atlas/land-layers.ts
|
|
29283
|
+
var LAND_SURFACE_MINZOOM = BAND_PRIORITY_RANGES["5"].minzoom;
|
|
29284
|
+
var LAND_SURFACE_LAYERS = (id) => id === "chrtland-base" || id === "chrtland-cover" || id === "chrtland-contour" || id === "chrtland-hillshade" || id === "chrtland-water" || id.startsWith("chrtland-fade-");
|
|
29285
|
+
var isLandGroundOverlay = (id) => LAND_SURFACE_LAYERS(id) && id !== "chrtland-base" || id === "chrtland-road";
|
|
29286
|
+
var FADE_PX = 80;
|
|
29287
|
+
var FADE_BANDS = 16;
|
|
29288
|
+
function fadeAlpha(r) {
|
|
29289
|
+
return Math.max(0, Math.min(1, (FADE_PX / 2 - Math.abs(r)) / FADE_PX));
|
|
29290
|
+
}
|
|
29291
|
+
function landBaseColor(palette) {
|
|
29292
|
+
return (LAND_THEMES[palette] ?? LAND_THEMES.DAY).base;
|
|
29293
|
+
}
|
|
29294
|
+
var LAND_THEMES = {
|
|
29295
|
+
DAY: {
|
|
29296
|
+
base: "#d4c69d",
|
|
29297
|
+
cover: { wood: "#bcc5a1", wetland: "#b6c0b1", urban: "#cac6bf", sand: "#dbd0af" },
|
|
29298
|
+
contour: "#958666",
|
|
29299
|
+
contourIndex: "#78694b",
|
|
29300
|
+
road: "#c5b691",
|
|
29301
|
+
roadMajor: "#beaa7c",
|
|
29302
|
+
label: "#5b4f3a",
|
|
29303
|
+
halo: "#ded6c3",
|
|
29304
|
+
shadow: "#6b5a3e",
|
|
29305
|
+
highlight: "#fffaf0",
|
|
29306
|
+
fade: "#e8f2f8",
|
|
29307
|
+
// Raised from 0.45 on 2026-08-23. ⚠ Above the ~0.5 that
|
|
29308
|
+
// hillshade-style.mjs warns "starts competing with depth areas" — a
|
|
29309
|
+
// deliberate, sighted choice made against rendered evidence, not a
|
|
29310
|
+
// default. If soundings or DEPARE ever read as fighting the terrain,
|
|
29311
|
+
// this number is the first thing to walk back.
|
|
29312
|
+
exaggeration: 0.8
|
|
29313
|
+
},
|
|
29314
|
+
DUSK: {
|
|
29315
|
+
base: "#4a4433",
|
|
29316
|
+
cover: { wood: "#414a38", wetland: "#3f4740", urban: "#4e4a42", sand: "#544c39" },
|
|
29317
|
+
contour: "#6b6250",
|
|
29318
|
+
contourIndex: "#837961",
|
|
29319
|
+
road: "#565040",
|
|
29320
|
+
roadMajor: "#63594440",
|
|
29321
|
+
label: "#c3b898",
|
|
29322
|
+
halo: "#2b2820",
|
|
29323
|
+
shadow: "#2e2a20",
|
|
29324
|
+
highlight: "#8a8068",
|
|
29325
|
+
fade: "#16202a",
|
|
29326
|
+
// Unchanged. DUSK was not the palette the 0.8 decision was made against.
|
|
29327
|
+
exaggeration: 0.45
|
|
29328
|
+
},
|
|
29329
|
+
NIGHT: {
|
|
29330
|
+
base: "#2a2620",
|
|
29331
|
+
cover: { wood: "#242a20", wetland: "#232823", urban: "#2c2925", sand: "#302b22" },
|
|
29332
|
+
contour: "#413b30",
|
|
29333
|
+
contourIndex: "#524a3b",
|
|
29334
|
+
road: "#332f27",
|
|
29335
|
+
roadMajor: "#3d382d",
|
|
29336
|
+
label: "#7d745e",
|
|
29337
|
+
halo: "#15130f",
|
|
29338
|
+
shadow: "#1a1712",
|
|
29339
|
+
highlight: "#4a4436",
|
|
29340
|
+
fade: "#07090b",
|
|
29341
|
+
// ⚠ DELIBERATELY NOT RAISED. See the type's note: a strong hillshade
|
|
29342
|
+
// under red night vision is a grey haze over exactly the contrast a
|
|
29343
|
+
// skipper is navigating by. Left at the shipped value rather than
|
|
29344
|
+
// lowered, because lowering it is a separate decision from this one.
|
|
29345
|
+
exaggeration: 0.45
|
|
29346
|
+
}
|
|
29347
|
+
};
|
|
29348
|
+
var FITS = ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]];
|
|
29349
|
+
var ANCHOR = ["coalesce", ["get", "anchor"], "top"];
|
|
29350
|
+
var anchorOffset = (em) => [
|
|
29351
|
+
"match",
|
|
29352
|
+
["get", "anchor"],
|
|
29353
|
+
"left",
|
|
29354
|
+
["literal", [0.6, 0]],
|
|
29355
|
+
"right",
|
|
29356
|
+
["literal", [-0.6, 0]],
|
|
29357
|
+
"bottom",
|
|
29358
|
+
["literal", [0, -em]],
|
|
29359
|
+
["literal", [0, em]]
|
|
29360
|
+
];
|
|
29361
|
+
var FONT = ["Open Sans Regular"];
|
|
29362
|
+
var FONT_ITALIC = ["Open Sans Italic"];
|
|
29363
|
+
function landLayers(opts = {}) {
|
|
29364
|
+
const palette = opts.palette ?? "DAY";
|
|
29365
|
+
const T = LAND_THEMES[palette] ?? LAND_THEMES.DAY;
|
|
29366
|
+
const src = opts.sourceId ?? LAND_REGION;
|
|
29367
|
+
const demSrc = opts.reliefSourceId ?? RELIEF_REGION;
|
|
29368
|
+
const L = (o) => o;
|
|
29369
|
+
const layers = [
|
|
29370
|
+
// 1. The land itself — LNDARE ∩ coverage, so it can never outrun the chart.
|
|
29371
|
+
L({
|
|
29372
|
+
id: "chrtland-base",
|
|
29373
|
+
type: "fill",
|
|
29374
|
+
source: src,
|
|
29375
|
+
"source-layer": "land_base",
|
|
29376
|
+
paint: { "fill-color": T.base }
|
|
29377
|
+
})
|
|
29378
|
+
];
|
|
29379
|
+
layers.push(L({
|
|
29380
|
+
id: "chrtland-cover",
|
|
29381
|
+
type: "fill",
|
|
29382
|
+
source: src,
|
|
29383
|
+
"source-layer": "land_cover",
|
|
29384
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29385
|
+
paint: {
|
|
29386
|
+
"fill-color": [
|
|
29387
|
+
"match",
|
|
29388
|
+
["get", "class"],
|
|
29389
|
+
"wood",
|
|
29390
|
+
T.cover.wood,
|
|
29391
|
+
"wetland",
|
|
29392
|
+
T.cover.wetland,
|
|
29393
|
+
"urban",
|
|
29394
|
+
T.cover.urban,
|
|
29395
|
+
"sand",
|
|
29396
|
+
T.cover.sand,
|
|
29397
|
+
T.base
|
|
29398
|
+
],
|
|
29399
|
+
"fill-opacity": 0.85
|
|
29400
|
+
}
|
|
29401
|
+
}));
|
|
29402
|
+
if (opts.relief) {
|
|
29403
|
+
layers.push(L({
|
|
29404
|
+
// No minzoom here: LAND_SURFACE_LAYERS floors it with the rest of the
|
|
29405
|
+
// surface, so the two can never drift apart again.
|
|
29406
|
+
id: "chrtland-hillshade",
|
|
29407
|
+
type: "hillshade",
|
|
29408
|
+
source: demSrc,
|
|
29589
29409
|
paint: {
|
|
29590
|
-
"
|
|
29591
|
-
"
|
|
29592
|
-
"
|
|
29410
|
+
"hillshade-exaggeration": T.exaggeration,
|
|
29411
|
+
"hillshade-shadow-color": T.shadow,
|
|
29412
|
+
"hillshade-highlight-color": T.highlight,
|
|
29413
|
+
"hillshade-accent-color": T.shadow
|
|
29593
29414
|
}
|
|
29594
|
-
})
|
|
29415
|
+
}));
|
|
29416
|
+
}
|
|
29417
|
+
const isIndexContour = [
|
|
29418
|
+
"any",
|
|
29419
|
+
["<=", ["coalesce", ["get", "index_z"], 99], ["zoom"]],
|
|
29420
|
+
["==", ["get", "is_index"], 1]
|
|
29595
29421
|
];
|
|
29422
|
+
layers.push(L({
|
|
29423
|
+
id: "chrtland-contour",
|
|
29424
|
+
type: "line",
|
|
29425
|
+
source: src,
|
|
29426
|
+
"source-layer": "land_contour",
|
|
29427
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29428
|
+
paint: {
|
|
29429
|
+
"line-color": ["case", isIndexContour, T.contourIndex, T.contour],
|
|
29430
|
+
"line-width": ["case", isIndexContour, 0.8, 0.4],
|
|
29431
|
+
"line-opacity": 0.7
|
|
29432
|
+
}
|
|
29433
|
+
}));
|
|
29434
|
+
layers.push(L({
|
|
29435
|
+
id: "chrtland-water",
|
|
29436
|
+
type: "fill",
|
|
29437
|
+
source: src,
|
|
29438
|
+
"source-layer": "land_water",
|
|
29439
|
+
filter: ["<=", ["coalesce", ["get", "min_z"], 0], ["zoom"]],
|
|
29440
|
+
paint: { "fill-color": inlandWaterColor(palette) }
|
|
29441
|
+
}));
|
|
29442
|
+
const d = FADE_PX / 2 / FADE_BANDS;
|
|
29443
|
+
for (let k = 0; k < FADE_BANDS; k++) {
|
|
29444
|
+
const width = k === 0 ? { "line-width": 2 * d } : { "line-width": d, "line-gap-width": 2 * k * d };
|
|
29445
|
+
layers.push(L({
|
|
29446
|
+
id: `chrtland-fade-${k}`,
|
|
29447
|
+
type: "line",
|
|
29448
|
+
source: src,
|
|
29449
|
+
"source-layer": "land_edge",
|
|
29450
|
+
layout: { "line-join": "bevel" },
|
|
29451
|
+
paint: { "line-color": T.fade, "line-blur": 0, "line-opacity": fadeAlpha(k * d + d / 2), ...width }
|
|
29452
|
+
}));
|
|
29453
|
+
}
|
|
29454
|
+
layers.push(L({
|
|
29455
|
+
id: "chrtland-road",
|
|
29456
|
+
type: "line",
|
|
29457
|
+
source: src,
|
|
29458
|
+
"source-layer": "land_road",
|
|
29459
|
+
minzoom: 10,
|
|
29460
|
+
paint: {
|
|
29461
|
+
"line-color": ["match", ["get", "kind"], "highway", T.roadMajor, T.road],
|
|
29462
|
+
"line-width": [
|
|
29463
|
+
"interpolate",
|
|
29464
|
+
["linear"],
|
|
29465
|
+
["zoom"],
|
|
29466
|
+
10,
|
|
29467
|
+
["match", ["get", "kind"], "highway", 0.8, 0.4],
|
|
29468
|
+
14,
|
|
29469
|
+
["match", ["get", "kind"], "highway", 2.4, 1.2]
|
|
29470
|
+
],
|
|
29471
|
+
"line-opacity": 0.8
|
|
29472
|
+
}
|
|
29473
|
+
}));
|
|
29474
|
+
layers.push(L({
|
|
29475
|
+
id: "chrtland-city-major",
|
|
29476
|
+
type: "symbol",
|
|
29477
|
+
source: src,
|
|
29478
|
+
"source-layer": "land_town",
|
|
29479
|
+
minzoom: 6.5,
|
|
29480
|
+
filter: [">=", ["coalesce", ["get", "prank"], 0], 10],
|
|
29481
|
+
layout: {
|
|
29482
|
+
"text-field": [
|
|
29483
|
+
"case",
|
|
29484
|
+
["==", ["get", "upcase"], true],
|
|
29485
|
+
["upcase", ["get", "name"]],
|
|
29486
|
+
["get", "name"]
|
|
29487
|
+
],
|
|
29488
|
+
"text-font": FONT,
|
|
29489
|
+
"text-size": [
|
|
29490
|
+
"interpolate",
|
|
29491
|
+
["linear"],
|
|
29492
|
+
["zoom"],
|
|
29493
|
+
6.5,
|
|
29494
|
+
11.5,
|
|
29495
|
+
9,
|
|
29496
|
+
["+", 10, ["*", 0.4, ["coalesce", ["get", "prank"], 10]]],
|
|
29497
|
+
13,
|
|
29498
|
+
["+", 13, ["*", 0.5, ["coalesce", ["get", "prank"], 10]]]
|
|
29499
|
+
],
|
|
29500
|
+
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0.02],
|
|
29501
|
+
"text-offset": anchorOffset(0.75),
|
|
29502
|
+
"text-anchor": ANCHOR,
|
|
29503
|
+
"text-padding": 10,
|
|
29504
|
+
"text-allow-overlap": false,
|
|
29505
|
+
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29506
|
+
},
|
|
29507
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.6 }
|
|
29508
|
+
}));
|
|
29509
|
+
layers.push(L({
|
|
29510
|
+
id: "chrtland-town-port",
|
|
29511
|
+
type: "symbol",
|
|
29512
|
+
source: src,
|
|
29513
|
+
"source-layer": "land_town",
|
|
29514
|
+
minzoom: 8.5,
|
|
29515
|
+
filter: [
|
|
29516
|
+
"all",
|
|
29517
|
+
["==", ["get", "enc_dup"], true],
|
|
29518
|
+
["<", ["coalesce", ["get", "prank"], 0], 10]
|
|
29519
|
+
],
|
|
29520
|
+
layout: {
|
|
29521
|
+
"text-field": ["get", "name"],
|
|
29522
|
+
"text-font": FONT,
|
|
29523
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 8.5, 11, 12, 13.5],
|
|
29524
|
+
"text-offset": anchorOffset(0.75),
|
|
29525
|
+
"text-anchor": ANCHOR,
|
|
29526
|
+
"text-padding": 8,
|
|
29527
|
+
"text-allow-overlap": false,
|
|
29528
|
+
// Within the tier, the bigger place wins the space: without this the
|
|
29529
|
+
// tie broke on data order and "West Gloucester" beat Gloucester.
|
|
29530
|
+
"symbol-sort-key": ["*", -1, ["coalesce", ["get", "pop"], 0]]
|
|
29531
|
+
},
|
|
29532
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.4 }
|
|
29533
|
+
}));
|
|
29534
|
+
layers.push(L({
|
|
29535
|
+
id: "chrtland-town",
|
|
29536
|
+
type: "symbol",
|
|
29537
|
+
source: src,
|
|
29538
|
+
"source-layer": "land_town",
|
|
29539
|
+
minzoom: 9,
|
|
29540
|
+
filter: [
|
|
29541
|
+
"all",
|
|
29542
|
+
FITS,
|
|
29543
|
+
["<", ["coalesce", ["get", "prank"], 0], 10],
|
|
29544
|
+
["!=", ["get", "enc_dup"], true]
|
|
29545
|
+
],
|
|
29546
|
+
layout: {
|
|
29547
|
+
"text-field": [
|
|
29548
|
+
"case",
|
|
29549
|
+
["==", ["get", "upcase"], true],
|
|
29550
|
+
["upcase", ["get", "name"]],
|
|
29551
|
+
["get", "name"]
|
|
29552
|
+
],
|
|
29553
|
+
"text-font": FONT,
|
|
29554
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 9, 10, 14, 13.5],
|
|
29555
|
+
"text-letter-spacing": ["case", ["==", ["get", "upcase"], true], 0.14, 0],
|
|
29556
|
+
"text-offset": anchorOffset(0.75),
|
|
29557
|
+
"text-anchor": ANCHOR,
|
|
29558
|
+
"text-padding": 6,
|
|
29559
|
+
"text-allow-overlap": false,
|
|
29560
|
+
"symbol-sort-key": 2
|
|
29561
|
+
},
|
|
29562
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29563
|
+
}));
|
|
29564
|
+
layers.push(L({
|
|
29565
|
+
id: "chrtland-summit",
|
|
29566
|
+
type: "symbol",
|
|
29567
|
+
source: src,
|
|
29568
|
+
"source-layer": "land_summit",
|
|
29569
|
+
minzoom: 11.5,
|
|
29570
|
+
filter: ["all", FITS, [">=", ["get", "peak_m"], 40]],
|
|
29571
|
+
layout: {
|
|
29572
|
+
"text-field": ["concat", ["get", "name"], "\n", ["to-string", ["get", "peak_m"]], " m"],
|
|
29573
|
+
"text-font": FONT,
|
|
29574
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 11.5, 8.5, 14, 11],
|
|
29575
|
+
"text-offset": anchorOffset(0.8),
|
|
29576
|
+
"text-anchor": ANCHOR,
|
|
29577
|
+
"text-padding": 5,
|
|
29578
|
+
"text-allow-overlap": false,
|
|
29579
|
+
"symbol-sort-key": 3
|
|
29580
|
+
},
|
|
29581
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29582
|
+
}));
|
|
29583
|
+
layers.push(L({
|
|
29584
|
+
id: "chrtland-poi",
|
|
29585
|
+
type: "symbol",
|
|
29586
|
+
source: src,
|
|
29587
|
+
"source-layer": "land_poi",
|
|
29588
|
+
minzoom: 13,
|
|
29589
|
+
filter: FITS,
|
|
29590
|
+
layout: {
|
|
29591
|
+
"text-field": ["get", "name"],
|
|
29592
|
+
"text-font": FONT_ITALIC,
|
|
29593
|
+
"text-size": ["interpolate", ["linear"], ["zoom"], 13, 8, 14, 9.5],
|
|
29594
|
+
"text-offset": anchorOffset(0.7),
|
|
29595
|
+
"text-anchor": ANCHOR,
|
|
29596
|
+
"text-padding": 5,
|
|
29597
|
+
"text-allow-overlap": false,
|
|
29598
|
+
"symbol-sort-key": 5
|
|
29599
|
+
},
|
|
29600
|
+
paint: { "text-color": T.label, "text-halo-color": T.halo, "text-halo-width": 1.2 }
|
|
29601
|
+
}));
|
|
29602
|
+
for (const layer of layers) {
|
|
29603
|
+
const l = layer;
|
|
29604
|
+
if (!LAND_SURFACE_LAYERS(l.id)) continue;
|
|
29605
|
+
l.minzoom = Math.max(l.minzoom ?? 0, LAND_SURFACE_MINZOOM);
|
|
29606
|
+
}
|
|
29607
|
+
return layers;
|
|
29596
29608
|
}
|
|
29597
29609
|
|
|
29598
29610
|
// src/atlas/band-collapse.ts
|
|
@@ -30295,21 +30307,37 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
30295
30307
|
];
|
|
30296
30308
|
}
|
|
30297
30309
|
{
|
|
30298
|
-
const
|
|
30299
|
-
|
|
30300
|
-
|
|
30310
|
+
const assembled = [
|
|
30311
|
+
restFinal[0],
|
|
30312
|
+
...baseBlock,
|
|
30313
|
+
...seaare,
|
|
30314
|
+
...ordered,
|
|
30315
|
+
...restFinal.slice(1)
|
|
30316
|
+
];
|
|
30317
|
+
const idOf = (l) => l.id;
|
|
30318
|
+
const isRepaint = (l) => /-overpair(-|$)/.test(idOf(l));
|
|
30301
30319
|
let lastRepaint = -1;
|
|
30302
|
-
|
|
30303
|
-
if (
|
|
30320
|
+
assembled.forEach((l, i) => {
|
|
30321
|
+
if (isRepaint(l)) lastRepaint = i;
|
|
30304
30322
|
});
|
|
30305
|
-
if (
|
|
30306
|
-
|
|
30307
|
-
|
|
30308
|
-
|
|
30309
|
-
|
|
30310
|
-
|
|
30323
|
+
if (lastRepaint === -1) return assembled;
|
|
30324
|
+
const surface = [];
|
|
30325
|
+
const kept = [];
|
|
30326
|
+
assembled.forEach((l, i) => {
|
|
30327
|
+
if (i < lastRepaint && isLandGroundOverlay(idOf(l))) surface.push(l);
|
|
30328
|
+
else kept.push(l);
|
|
30329
|
+
});
|
|
30330
|
+
if (surface.length === 0) return assembled;
|
|
30331
|
+
let landing = -1;
|
|
30332
|
+
kept.forEach((l, i) => {
|
|
30333
|
+
if (isRepaint(l)) landing = i;
|
|
30334
|
+
});
|
|
30335
|
+
return [
|
|
30336
|
+
...kept.slice(0, landing + 1),
|
|
30337
|
+
...surface,
|
|
30338
|
+
...kept.slice(landing + 1)
|
|
30339
|
+
];
|
|
30311
30340
|
}
|
|
30312
|
-
return [restFinal[0], ...baseBlock, ...seaare, ...ordered, ...restFinal.slice(1)];
|
|
30313
30341
|
})() : layers;
|
|
30314
30342
|
for (const id of [
|
|
30315
30343
|
"chrtbase-country-boundary",
|