@chrtco/sdk 0.10.53 → 0.10.55
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 +28 -0
- package/README.md +16 -3
- package/dist/atlas/browser.cjs +673 -17
- package/dist/atlas/browser.cjs.map +1 -1
- package/dist/atlas/browser.d.cts +36 -2
- package/dist/atlas/browser.d.ts +36 -2
- package/dist/atlas/browser.js +670 -16
- package/dist/atlas/browser.js.map +1 -1
- package/dist/index.cjs +1593 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +338 -8
- package/dist/index.d.ts +338 -8
- package/dist/index.js +1559 -159
- package/dist/index.js.map +1 -1
- package/dist/{symbol-families-De7sN-p5.d.cts → symbol-family-ids-elOgiCo8.d.cts} +27 -25
- package/dist/{symbol-families-De7sN-p5.d.ts → symbol-family-ids-elOgiCo8.d.ts} +27 -25
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ __export(index_exports, {
|
|
|
44
44
|
BUILD_PARAM: () => BUILD_PARAM,
|
|
45
45
|
CHART_BAND_CODES: () => CHART_BAND_CODES,
|
|
46
46
|
CHART_CASCADE_CODES: () => CHART_CASCADE_CODES,
|
|
47
|
+
CHART_LOOKS: () => CHART_LOOKS,
|
|
47
48
|
CHART_SECTIONS: () => CHART_SECTIONS,
|
|
48
49
|
CHART_SOUNDINGS_RULE: () => CHART_SOUNDINGS_RULE,
|
|
49
50
|
CHART_SYMBOL_SCALE: () => CHART_SYMBOL_SCALE,
|
|
@@ -60,6 +61,9 @@ __export(index_exports, {
|
|
|
60
61
|
CHRT_ICON_PREFIX: () => CHRT_ICON_PREFIX,
|
|
61
62
|
CHRT_SDF_GLYPHS: () => CHRT_SDF_GLYPHS,
|
|
62
63
|
CHRT_STYLE_MODES: () => CHRT_STYLE_MODES,
|
|
64
|
+
CLASSIC_FONTS: () => CLASSIC_FONTS,
|
|
65
|
+
CLASSIC_MARK_NAMES: () => CLASSIC_MARK_NAMES,
|
|
66
|
+
CLASSIC_TONES: () => CLASSIC_TONES,
|
|
63
67
|
COARSE_MARK_FLOOR: () => COARSE_MARK_FLOOR,
|
|
64
68
|
COARSE_MARK_HELD_HAZARDS: () => COARSE_MARK_HELD_HAZARDS,
|
|
65
69
|
Chrt: () => Chrt,
|
|
@@ -88,6 +92,7 @@ __export(index_exports, {
|
|
|
88
92
|
EINK_DOTS_PATTERN: () => EINK_DOTS_PATTERN,
|
|
89
93
|
EINK_HATCH_PATTERN: () => EINK_HATCH_PATTERN,
|
|
90
94
|
EINK_MONO_GREYS: () => EINK_MONO_GREYS,
|
|
95
|
+
ENGRAVED_LOOKS: () => ENGRAVED_LOOKS,
|
|
91
96
|
HAZARD_LABEL_PRIORITY: () => HAZARD_LABEL_PRIORITY,
|
|
92
97
|
INSPECT_CLASS_RANK: () => INSPECT_CLASS_RANK,
|
|
93
98
|
INSPECT_RANK_DEVIATIONS: () => INSPECT_RANK_DEVIATIONS,
|
|
@@ -106,9 +111,14 @@ __export(index_exports, {
|
|
|
106
111
|
LAND_BUILD_MAXZOOM: () => LAND_BUILD_MAXZOOM,
|
|
107
112
|
LAND_REGION: () => LAND_REGION,
|
|
108
113
|
LAND_TEXT_CLASSES: () => LAND_TEXT_CLASSES,
|
|
114
|
+
LEGACY_SYMBOL_FAMILY_ALIASES: () => LEGACY_SYMBOL_FAMILY_ALIASES,
|
|
109
115
|
LIGHTHOUSE_NAME_FILTER: () => LIGHTHOUSE_NAME_FILTER,
|
|
110
116
|
LIGHTHOUSE_NAME_LABEL_PRIORITY: () => LIGHTHOUSE_NAME_LABEL_PRIORITY,
|
|
111
117
|
LIGHT_LABEL_FEET_PER_METRE: () => LIGHT_LABEL_FEET_PER_METRE,
|
|
118
|
+
LOOK_FONTS: () => LOOK_FONTS,
|
|
119
|
+
LOOK_IMAGE_NAMES: () => LOOK_IMAGE_NAMES,
|
|
120
|
+
LOOK_TONES: () => LOOK_TONES,
|
|
121
|
+
LOOK_WATERLINES_SOURCE: () => LOOK_WATERLINES_SOURCE,
|
|
112
122
|
MAPLIBRE_DEFAULT_TEXT_PADDING_PX: () => MAPLIBRE_DEFAULT_TEXT_PADDING_PX,
|
|
113
123
|
NAUTICAL_SYMBOLS: () => NAUTICAL_SYMBOLS,
|
|
114
124
|
NAV_AID_LAYER_GROUPS: () => NAV_AID_LAYER_GROUPS,
|
|
@@ -172,6 +182,9 @@ __export(index_exports, {
|
|
|
172
182
|
SOUNDING_PADDING_PER_FACTOR: () => SOUNDING_PADDING_PER_FACTOR,
|
|
173
183
|
STANDARD_CHART_SYMBOL_SCALES: () => STANDARD_CHART_SYMBOL_SCALES,
|
|
174
184
|
STATUS_EXTINGUISHED: () => STATUS_EXTINGUISHED,
|
|
185
|
+
STYLE_CATALOGUE: () => STYLE_CATALOGUE,
|
|
186
|
+
STYLE_LOOKS: () => STYLE_LOOKS,
|
|
187
|
+
STYLE_THEMES: () => STYLE_THEMES,
|
|
175
188
|
SYMBOL_ANNOTATION_TEXT_CLASSES: () => SYMBOL_ANNOTATION_TEXT_CLASSES,
|
|
176
189
|
SYMBOL_FAMILIES: () => SYMBOL_FAMILIES,
|
|
177
190
|
SYMBOL_FAMILY_META: () => SYMBOL_FAMILY_META,
|
|
@@ -179,6 +192,8 @@ __export(index_exports, {
|
|
|
179
192
|
SYMBOL_MAP: () => SYMBOL_MAP,
|
|
180
193
|
TileAuth: () => TileAuth,
|
|
181
194
|
TileTokenError: () => TileTokenError,
|
|
195
|
+
WASH_TINTS: () => WASH_TINTS,
|
|
196
|
+
WASH_TONES: () => WASH_TONES,
|
|
182
197
|
WATER_BODY_LAYER_GROUPS: () => WATER_BODY_LAYER_GROUPS,
|
|
183
198
|
WATER_TEXT_CLASSES: () => WATER_TEXT_CLASSES,
|
|
184
199
|
WeatherEndpoint: () => WeatherEndpoint,
|
|
@@ -222,6 +237,14 @@ __export(index_exports, {
|
|
|
222
237
|
chrtHouseColor: () => chrtHouseColor,
|
|
223
238
|
chrtLightTintExpression: () => chrtLightTintExpression,
|
|
224
239
|
clampChartSymbolScale: () => clampChartSymbolScale,
|
|
240
|
+
classicDrawing: () => classicDrawing,
|
|
241
|
+
classicIconExpression: () => classicIconExpression,
|
|
242
|
+
classicInkFor: () => classicInkFor,
|
|
243
|
+
classicMarkId: () => classicMarkId,
|
|
244
|
+
classicMarkImage: () => classicMarkImage,
|
|
245
|
+
classicMarkImages: () => classicMarkImages,
|
|
246
|
+
classicMarkInk: () => classicMarkInk,
|
|
247
|
+
classicMarkSvgs: () => classicMarkSvgs,
|
|
225
248
|
collectCandidates: () => collectCandidates,
|
|
226
249
|
collectClickCandidates: () => collectClickCandidates,
|
|
227
250
|
combineWithBandFilter: () => combineWithBandFilter,
|
|
@@ -244,6 +267,7 @@ __export(index_exports, {
|
|
|
244
267
|
deriveMarinerName: () => deriveMarinerName,
|
|
245
268
|
drapeHalves: () => drapeHalves,
|
|
246
269
|
drapedFirst: () => drapedFirst,
|
|
270
|
+
drawingSvg: () => drawingSvg,
|
|
247
271
|
extinguishedLightExpression: () => extinguishedLightExpression,
|
|
248
272
|
extractNavAidDesignation: () => extractNavAidDesignation,
|
|
249
273
|
featureIdentity: () => featureIdentity,
|
|
@@ -288,6 +312,7 @@ __export(index_exports, {
|
|
|
288
312
|
isDrapeable: () => isDrapeable,
|
|
289
313
|
isEinkColorTable: () => isEinkColorTable,
|
|
290
314
|
isEinkGreyTable: () => isEinkGreyTable,
|
|
315
|
+
isEngravedLook: () => isEngravedLook,
|
|
291
316
|
isExtinguishedLight: () => isExtinguishedLight,
|
|
292
317
|
isLabelLayerVisible: () => isLabelLayerVisible,
|
|
293
318
|
isMapLive: () => isMapLive,
|
|
@@ -312,10 +337,15 @@ __export(index_exports, {
|
|
|
312
337
|
lightFillExpression: () => lightFillExpression,
|
|
313
338
|
lightHeightText: () => lightHeightText,
|
|
314
339
|
lightsIconExpression: () => lightsIconExpression,
|
|
340
|
+
lookImageId: () => lookImageId,
|
|
341
|
+
lookImages: () => lookImages,
|
|
342
|
+
lookOfImageId: () => lookOfImageId,
|
|
315
343
|
normalizeStyleMode: () => normalizeStyleMode,
|
|
344
|
+
normalizeSymbolFamily: () => normalizeSymbolFamily,
|
|
316
345
|
normalizeTheme: () => normalizeTheme,
|
|
317
346
|
opaqueSplitBaseOf: () => opaqueSplitBaseOf,
|
|
318
347
|
paginate: () => paginate,
|
|
348
|
+
parseChartLook: () => parseChartLook,
|
|
319
349
|
parseListCodes: () => parseListCodes,
|
|
320
350
|
parseSigseqTerms: () => parseSigseqTerms,
|
|
321
351
|
parseSymbolFamily: () => parseSymbolFamily,
|
|
@@ -349,12 +379,16 @@ __export(index_exports, {
|
|
|
349
379
|
soundingPaddingValue: () => soundingPaddingValue,
|
|
350
380
|
splitOpaqueDepthAreas: () => splitOpaqueDepthAreas,
|
|
351
381
|
stepChartSymbolScale: () => stepChartSymbolScale,
|
|
382
|
+
styleLook: () => styleLook,
|
|
352
383
|
styleModeBand: () => styleModeBand,
|
|
353
384
|
terrainStackCount: () => terrainStackCount,
|
|
354
385
|
textSliderFor: () => textSliderFor,
|
|
355
386
|
themeChrtGlyph: () => themeChrtGlyph,
|
|
356
387
|
tileTemplate: () => tileTemplate,
|
|
357
388
|
uncoveredSectorArcs: () => uncoveredSectorArcs,
|
|
389
|
+
withClassicMarks: () => withClassicMarks,
|
|
390
|
+
withLook: () => withLook,
|
|
391
|
+
withWaterLines: () => withWaterLines,
|
|
358
392
|
withinBboxFilter: () => withinBboxFilter,
|
|
359
393
|
worldMinusBboxPolygon: () => worldMinusBboxPolygon
|
|
360
394
|
});
|
|
@@ -4582,12 +4616,12 @@ function deriveMarinerName(objnam, colourCode) {
|
|
|
4582
4616
|
if (!objnam) return "";
|
|
4583
4617
|
const m = objnam.match(/(\d+[A-Z]?)\s*$/);
|
|
4584
4618
|
if (!m) return objnam;
|
|
4585
|
-
const
|
|
4619
|
+
const num3 = m[1];
|
|
4586
4620
|
const colourAbbr = colourCode ? COLOUR_TABLE[colourCode]?.abbr : null;
|
|
4587
4621
|
if (colourAbbr && colourAbbr !== "W") {
|
|
4588
|
-
return `${colourAbbr} "${
|
|
4622
|
+
return `${colourAbbr} "${num3}"`;
|
|
4589
4623
|
}
|
|
4590
|
-
return `"${
|
|
4624
|
+
return `"${num3}"`;
|
|
4591
4625
|
}
|
|
4592
4626
|
function getTopmarkMeaning(topshpCode, rawLayer) {
|
|
4593
4627
|
if (topshpCode == null) return null;
|
|
@@ -4640,7 +4674,7 @@ function decodeNavAidProps(layerName, props, coords, opts = {}) {
|
|
|
4640
4674
|
const dayboardColours = isDayboard ? [] : listNames(props._daymark_colour, COLOUR_NAME_TABLE);
|
|
4641
4675
|
const dayboardPattern = isDayboard ? [] : listNames(props._daymark_colpat, COLPAT_TABLE);
|
|
4642
4676
|
const dayboardCount = Number(props._daymark_count);
|
|
4643
|
-
const
|
|
4677
|
+
const dayboard2 = dayboardShapeCode || dayboardColours.length > 0 || dayboardPattern.length > 0 ? {
|
|
4644
4678
|
shape: dayboardShapeCode ? TOPSHP_TABLE[dayboardShapeCode] ?? null : null,
|
|
4645
4679
|
colour: dayboardColours.length > 0 ? dayboardColours.join(", ") : null,
|
|
4646
4680
|
pattern: dayboardPattern.length > 0 ? dayboardPattern.join(", ") : null,
|
|
@@ -4699,7 +4733,7 @@ function decodeNavAidProps(layerName, props, coords, opts = {}) {
|
|
|
4699
4733
|
shape,
|
|
4700
4734
|
topmark,
|
|
4701
4735
|
topmarkMeaning,
|
|
4702
|
-
dayboard,
|
|
4736
|
+
dayboard: dayboard2,
|
|
4703
4737
|
colourPattern: colourPatternNames.length > 0 ? colourPatternNames.join(", ") : null,
|
|
4704
4738
|
construction: constructionNames.length > 0 ? constructionNames.join(", ") : null,
|
|
4705
4739
|
lightCharacter: litchrEntry?.abbr ?? null,
|
|
@@ -4794,9 +4828,9 @@ function buildFlashPattern(decoded) {
|
|
|
4794
4828
|
break;
|
|
4795
4829
|
}
|
|
4796
4830
|
case "Iso": {
|
|
4797
|
-
const
|
|
4798
|
-
phases.push({ on: true, duration:
|
|
4799
|
-
phases.push({ on: false, duration:
|
|
4831
|
+
const half2 = period / 2;
|
|
4832
|
+
phases.push({ on: true, duration: half2, color: hex });
|
|
4833
|
+
phases.push({ on: false, duration: half2 });
|
|
4800
4834
|
break;
|
|
4801
4835
|
}
|
|
4802
4836
|
case "Q": {
|
|
@@ -5697,11 +5731,11 @@ function decodeClickedNavAid(map, feature, e, navAidLayers) {
|
|
|
5697
5731
|
}
|
|
5698
5732
|
if (rawLayer !== "DAYMAR" && !CHILD_LAYERS.has(rawLayer) && props._daymark_topshp == null && props._daymark_colour == null) {
|
|
5699
5733
|
const boards = query(map, bboxAround(e.point, 10), existingLayers(map, ["enc-DAYMAR"]));
|
|
5700
|
-
const
|
|
5701
|
-
if (
|
|
5702
|
-
if (
|
|
5703
|
-
if (
|
|
5704
|
-
if (
|
|
5734
|
+
const board2 = pickSlaveOf(props, boards);
|
|
5735
|
+
if (board2?.properties) {
|
|
5736
|
+
if (board2.properties.TOPSHP != null) props._daymark_topshp = board2.properties.TOPSHP;
|
|
5737
|
+
if (board2.properties.COLOUR != null) props._daymark_colour = board2.properties.COLOUR;
|
|
5738
|
+
if (board2.properties.COLPAT != null) props._daymark_colpat = board2.properties.COLPAT;
|
|
5705
5739
|
}
|
|
5706
5740
|
}
|
|
5707
5741
|
const lightLayerIds = existingLayers(
|
|
@@ -7272,19 +7306,19 @@ function applyChrtSymbolSet(style, palette = "DAY") {
|
|
|
7272
7306
|
continue;
|
|
7273
7307
|
}
|
|
7274
7308
|
if (layer.type !== "symbol") continue;
|
|
7275
|
-
const
|
|
7276
|
-
if (!
|
|
7309
|
+
const objectClass5 = layer.metadata?.["s52:objectClass"];
|
|
7310
|
+
if (!objectClass5 || !CHRT_ICON_EXPRESSIONS[objectClass5]) continue;
|
|
7277
7311
|
if (layer.metadata?.["chrt:sectorLight"] === true) continue;
|
|
7278
7312
|
const layout = layer.layout;
|
|
7279
7313
|
if (!layout || layout["icon-image"] == null) continue;
|
|
7280
|
-
layout["icon-image"] = CHRT_ICON_EXPRESSIONS[
|
|
7314
|
+
layout["icon-image"] = CHRT_ICON_EXPRESSIONS[objectClass5]();
|
|
7281
7315
|
const paint = layer.paint ?? {};
|
|
7282
7316
|
const haloColor = palette === "EINK_MONO" ? chrtHouseColor(HOUSE_BLACK, palette) : palette === "EINK_NIGHT" ? "#000000" : CHRT_HALO.color;
|
|
7283
|
-
if (CHRT_TINTED_CLASSES.has(
|
|
7317
|
+
if (CHRT_TINTED_CLASSES.has(objectClass5)) {
|
|
7284
7318
|
paint["icon-color"] = chrtAtonTintExpression(palette);
|
|
7285
7319
|
paint["icon-halo-color"] = haloColor;
|
|
7286
7320
|
paint["icon-halo-width"] = CHRT_HALO.width;
|
|
7287
|
-
} else if (
|
|
7321
|
+
} else if (objectClass5 === "LIGHTS") {
|
|
7288
7322
|
paint["icon-color"] = chrtLightTintExpression(palette);
|
|
7289
7323
|
paint["icon-halo-color"] = haloColor;
|
|
7290
7324
|
paint["icon-halo-width"] = CHRT_HALO.width;
|
|
@@ -22497,10 +22531,10 @@ var ATTR_TYPES = {
|
|
|
22497
22531
|
INFORM: "S"
|
|
22498
22532
|
};
|
|
22499
22533
|
function scalarMatch(attr, value) {
|
|
22500
|
-
const
|
|
22534
|
+
const num3 = Number(value);
|
|
22501
22535
|
return [
|
|
22502
22536
|
"any",
|
|
22503
|
-
["==", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], -1],
|
|
22537
|
+
["==", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], -1], num3],
|
|
22504
22538
|
["==", ["to-string", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], ""]], value]
|
|
22505
22539
|
];
|
|
22506
22540
|
}
|
|
@@ -22545,9 +22579,9 @@ function compileAtonExpression(lookup, mapSymbol = (name) => name) {
|
|
|
22545
22579
|
expr.push(fallback);
|
|
22546
22580
|
return expr;
|
|
22547
22581
|
}
|
|
22548
|
-
function atonIconExpression(
|
|
22549
|
-
const lookup = S52_ATON_LOOKUPS[
|
|
22550
|
-
if (!lookup) throw new Error(`s52-aton-expressions: no generated lookup for ${
|
|
22582
|
+
function atonIconExpression(objectClass5) {
|
|
22583
|
+
const lookup = S52_ATON_LOOKUPS[objectClass5];
|
|
22584
|
+
if (!lookup) throw new Error(`s52-aton-expressions: no generated lookup for ${objectClass5}`);
|
|
22551
22585
|
return compileAtonExpression(lookup);
|
|
22552
22586
|
}
|
|
22553
22587
|
function lightsIconExpression() {
|
|
@@ -29509,47 +29543,47 @@ var EXTINGUISHED_FLARE_OPACITY = 0.35;
|
|
|
29509
29543
|
function buildLightLabelExpression(depthUnits) {
|
|
29510
29544
|
return lightDescriptionExpression({ units: depthUnits });
|
|
29511
29545
|
}
|
|
29512
|
-
function buildLayersForClass(
|
|
29513
|
-
if (!S52_LOOKUP[
|
|
29514
|
-
const entry = S52_LOOKUP[
|
|
29546
|
+
function buildLayersForClass(objectClass5, ct, sourceId = DEFAULT_REGION, opts = {}) {
|
|
29547
|
+
if (!S52_LOOKUP[objectClass5]) return [];
|
|
29548
|
+
const entry = S52_LOOKUP[objectClass5];
|
|
29515
29549
|
const layers = [];
|
|
29516
|
-
const geomTypes = getGeomTypesForClass(
|
|
29550
|
+
const geomTypes = getGeomTypesForClass(objectClass5, entry?.style.type);
|
|
29517
29551
|
for (const geomType of geomTypes) {
|
|
29518
|
-
const resolved = resolveStyle(
|
|
29519
|
-
const layerId = `s52-${
|
|
29552
|
+
const resolved = resolveStyle(objectClass5, geomType, ct, { safetyContour: opts.safetyContour });
|
|
29553
|
+
const layerId = `s52-${objectClass5}-${resolved.type}`;
|
|
29520
29554
|
const layer = {
|
|
29521
29555
|
id: layerId,
|
|
29522
29556
|
type: resolved.type,
|
|
29523
29557
|
source: sourceId,
|
|
29524
|
-
"source-layer":
|
|
29558
|
+
"source-layer": objectClass5,
|
|
29525
29559
|
paint: resolved.paint,
|
|
29526
29560
|
metadata: {
|
|
29527
|
-
"s52:objectClass":
|
|
29561
|
+
"s52:objectClass": objectClass5,
|
|
29528
29562
|
"s52:displayCategory": entry?.displayCategory ?? "OTHER",
|
|
29529
29563
|
"s52:category": entry?.category ?? "Meta"
|
|
29530
29564
|
}
|
|
29531
29565
|
};
|
|
29532
|
-
if (resolved.type === "line" && LINE_FROM_POLYGON_LAYERS.has(
|
|
29566
|
+
if (resolved.type === "line" && LINE_FROM_POLYGON_LAYERS.has(objectClass5)) {
|
|
29533
29567
|
layer.filter = GEOM_FILTERS.fill;
|
|
29534
29568
|
} else if (GEOM_FILTERS[resolved.type]) {
|
|
29535
29569
|
layer.filter = GEOM_FILTERS[resolved.type];
|
|
29536
29570
|
}
|
|
29537
|
-
if (SCAMIN_DECLUTTER_CLASSES.has(
|
|
29571
|
+
if (SCAMIN_DECLUTTER_CLASSES.has(objectClass5)) {
|
|
29538
29572
|
layer.filter = layer.filter ? ["all", layer.filter, scaminZoomGateFilter()] : ["all", scaminZoomGateFilter()];
|
|
29539
29573
|
}
|
|
29540
29574
|
if (resolved.minzoom) {
|
|
29541
29575
|
layer.minzoom = resolved.minzoom;
|
|
29542
29576
|
}
|
|
29543
|
-
if (resolved.type === "fill" && OPAQUE_FILLS.has(
|
|
29577
|
+
if (resolved.type === "fill" && OPAQUE_FILLS.has(objectClass5)) {
|
|
29544
29578
|
layer.paint["fill-opacity"] = 1;
|
|
29545
29579
|
}
|
|
29546
|
-
if (resolved.type === "line" && ZOOM_SCALED_LINES2[
|
|
29547
|
-
const [z1, w1, z2, w2] = ZOOM_SCALED_LINES2[
|
|
29580
|
+
if (resolved.type === "line" && ZOOM_SCALED_LINES2[objectClass5]) {
|
|
29581
|
+
const [z1, w1, z2, w2] = ZOOM_SCALED_LINES2[objectClass5];
|
|
29548
29582
|
layer.paint["line-width"] = ["interpolate", ["linear"], ["zoom"], z1, w1, z2, w2];
|
|
29549
29583
|
}
|
|
29550
29584
|
if (resolved.type === "symbol") {
|
|
29551
|
-
const iconExpr = getIconExpression(
|
|
29552
|
-
const childOffset = CHILD_ICON_OFFSETS[
|
|
29585
|
+
const iconExpr = getIconExpression(objectClass5);
|
|
29586
|
+
const childOffset = CHILD_ICON_OFFSETS[objectClass5];
|
|
29553
29587
|
const isSafetyCritical = SAFETY_GROUPS.has(entry?.viewingGroup ?? 0);
|
|
29554
29588
|
const safetyCriticalIconSize = [
|
|
29555
29589
|
"interpolate",
|
|
@@ -29712,7 +29746,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29712
29746
|
]
|
|
29713
29747
|
};
|
|
29714
29748
|
}
|
|
29715
|
-
if (
|
|
29749
|
+
if (objectClass5 === "LIGHTS") {
|
|
29716
29750
|
layer.layout = {
|
|
29717
29751
|
...layer.layout,
|
|
29718
29752
|
"icon-allow-overlap": true,
|
|
@@ -29762,14 +29796,14 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29762
29796
|
} else if (resolved.layout) {
|
|
29763
29797
|
layer.layout = resolved.layout;
|
|
29764
29798
|
}
|
|
29765
|
-
if (
|
|
29799
|
+
if (objectClass5 === "LNDMRK" && resolved.type === "symbol") {
|
|
29766
29800
|
const baseFilterParts = layer.filter && layer.filter[0] === "all" ? layer.filter.slice(1) : layer.filter ? [layer.filter] : [];
|
|
29767
29801
|
const isWind = listAttrHas("CATLMK", ["18", "19"]);
|
|
29768
29802
|
const isLighthouse = listAttrHas("CATLMK", ["17"]);
|
|
29769
29803
|
const scaminFloor = scaminToMinZoom(entry?.scamin);
|
|
29770
29804
|
const windLayer = {
|
|
29771
29805
|
...layer,
|
|
29772
|
-
id: `s52-${
|
|
29806
|
+
id: `s52-${objectClass5}-wind-symbol`,
|
|
29773
29807
|
filter: ["all", ...baseFilterParts, isWind],
|
|
29774
29808
|
// Explicit, not inherited: turbines share exact coordinates with
|
|
29775
29809
|
// their aviation-light LIGHTS feature; without allow-overlap the
|
|
@@ -29782,7 +29816,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29782
29816
|
delete windLayer.minzoom;
|
|
29783
29817
|
const lighthouseLayer = {
|
|
29784
29818
|
...layer,
|
|
29785
|
-
id: `s52-${
|
|
29819
|
+
id: `s52-${objectClass5}-lighthouse-symbol`,
|
|
29786
29820
|
filter: ["all", ...baseFilterParts, isLighthouse, ["!", isWind]],
|
|
29787
29821
|
layout: {
|
|
29788
29822
|
...layer.layout ?? {},
|
|
@@ -29793,7 +29827,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29793
29827
|
delete lighthouseLayer.minzoom;
|
|
29794
29828
|
const otherLayer = {
|
|
29795
29829
|
...layer,
|
|
29796
|
-
id: `s52-${
|
|
29830
|
+
id: `s52-${objectClass5}-other-symbol`,
|
|
29797
29831
|
filter: ["all", ...baseFilterParts, ["!", isWind], ["!", isLighthouse]]
|
|
29798
29832
|
};
|
|
29799
29833
|
if (scaminFloor !== void 0) {
|
|
@@ -29808,10 +29842,10 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29808
29842
|
const valsouNum = ["to-number", ["coalesce", ["get", "VALSOU"], ["get", "valsou"], 999], 999];
|
|
29809
29843
|
const watlevNum = ["to-number", ["coalesce", ["get", "WATLEV"], ["get", "watlev"], 0], 0];
|
|
29810
29844
|
layers.push({
|
|
29811
|
-
id: `s52-${
|
|
29845
|
+
id: `s52-${objectClass5}-danger-ring`,
|
|
29812
29846
|
type: "symbol",
|
|
29813
29847
|
source: sourceId,
|
|
29814
|
-
"source-layer":
|
|
29848
|
+
"source-layer": objectClass5,
|
|
29815
29849
|
filter: [
|
|
29816
29850
|
"all",
|
|
29817
29851
|
GEOM_FILTERS.symbol,
|
|
@@ -29844,48 +29878,48 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29844
29878
|
},
|
|
29845
29879
|
paint: {},
|
|
29846
29880
|
minzoom: 13,
|
|
29847
|
-
metadata: { "s52:objectClass":
|
|
29881
|
+
metadata: { "s52:objectClass": objectClass5, "s52:role": "isolated-danger-ring" }
|
|
29848
29882
|
});
|
|
29849
29883
|
}
|
|
29850
|
-
if (resolved.type === "fill" && FILL_OUTLINE_LAYERS.has(
|
|
29851
|
-
const outlineColor =
|
|
29884
|
+
if (resolved.type === "fill" && FILL_OUTLINE_LAYERS.has(objectClass5)) {
|
|
29885
|
+
const outlineColor = objectClass5 === "DEPARE" ? resolveColor("CHGRD", ct) : resolveColor("CHGRF", ct);
|
|
29852
29886
|
layers.push({
|
|
29853
|
-
id: `s52-${
|
|
29887
|
+
id: `s52-${objectClass5}-outline`,
|
|
29854
29888
|
type: "line",
|
|
29855
29889
|
source: sourceId,
|
|
29856
|
-
"source-layer":
|
|
29890
|
+
"source-layer": objectClass5,
|
|
29857
29891
|
filter: GEOM_FILTERS.fill,
|
|
29858
29892
|
paint: {
|
|
29859
29893
|
"line-color": outlineColor,
|
|
29860
29894
|
"line-width": 0.3,
|
|
29861
29895
|
"line-opacity": 0.4
|
|
29862
29896
|
},
|
|
29863
|
-
metadata: { "s52:objectClass":
|
|
29897
|
+
metadata: { "s52:objectClass": objectClass5, "s52:role": "outline" }
|
|
29864
29898
|
});
|
|
29865
29899
|
}
|
|
29866
|
-
if (resolved.type === "fill" && REGULATED_AREA_BOUNDARY_LAYERS[
|
|
29867
|
-
const lineStyle = REGULATED_AREA_BOUNDARY_LINESTYLES[
|
|
29900
|
+
if (resolved.type === "fill" && REGULATED_AREA_BOUNDARY_LAYERS[objectClass5]) {
|
|
29901
|
+
const lineStyle = REGULATED_AREA_BOUNDARY_LINESTYLES[objectClass5];
|
|
29868
29902
|
const boundaryPaint = lineStyle ? lineStylePaint(lineStyle) : {
|
|
29869
|
-
"line-color": resolveColor(REGULATED_AREA_BOUNDARY_LAYERS[
|
|
29903
|
+
"line-color": resolveColor(REGULATED_AREA_BOUNDARY_LAYERS[objectClass5], ct),
|
|
29870
29904
|
"line-width": 1,
|
|
29871
29905
|
"line-dasharray": [4, 2],
|
|
29872
29906
|
"line-opacity": 0.85
|
|
29873
29907
|
};
|
|
29874
29908
|
layers.push({
|
|
29875
|
-
id: `s52-${
|
|
29909
|
+
id: `s52-${objectClass5}-boundary`,
|
|
29876
29910
|
type: "line",
|
|
29877
29911
|
source: sourceId,
|
|
29878
|
-
"source-layer":
|
|
29912
|
+
"source-layer": objectClass5,
|
|
29879
29913
|
filter: GEOM_FILTERS.fill,
|
|
29880
29914
|
paint: boundaryPaint,
|
|
29881
29915
|
metadata: {
|
|
29882
|
-
"s52:objectClass":
|
|
29916
|
+
"s52:objectClass": objectClass5,
|
|
29883
29917
|
"s52:role": "boundary",
|
|
29884
29918
|
...lineStyle ? { "s52:lineStyle": lineStyle } : {}
|
|
29885
29919
|
}
|
|
29886
29920
|
});
|
|
29887
29921
|
}
|
|
29888
|
-
if (
|
|
29922
|
+
if (objectClass5 === "ACHARE" && resolved.type === "fill") {
|
|
29889
29923
|
layers.push({
|
|
29890
29924
|
id: "s52-ACHARE-boundary",
|
|
29891
29925
|
type: "line",
|
|
@@ -29901,7 +29935,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29901
29935
|
metadata: { "s52:objectClass": "ACHARE", "s52:role": "boundary" }
|
|
29902
29936
|
});
|
|
29903
29937
|
}
|
|
29904
|
-
if (
|
|
29938
|
+
if (objectClass5 === "DRGARE" && resolved.type === "fill") {
|
|
29905
29939
|
layers.push({
|
|
29906
29940
|
id: "s52-DRGARE-boundary",
|
|
29907
29941
|
type: "line",
|
|
@@ -29917,7 +29951,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29917
29951
|
metadata: { "s52:objectClass": "DRGARE", "s52:role": "boundary" }
|
|
29918
29952
|
});
|
|
29919
29953
|
}
|
|
29920
|
-
if (
|
|
29954
|
+
if (objectClass5 === "ACHARE" && resolved.type === "fill") {
|
|
29921
29955
|
layers.push({
|
|
29922
29956
|
id: "s52-ACHARE-anchor-icon",
|
|
29923
29957
|
type: "symbol",
|
|
@@ -29946,7 +29980,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29946
29980
|
metadata: { "s52:objectClass": "ACHARE", "s52:role": "centroid-icon" }
|
|
29947
29981
|
});
|
|
29948
29982
|
}
|
|
29949
|
-
if (
|
|
29983
|
+
if (objectClass5 === "LNDARE" && resolved.type === "fill") {
|
|
29950
29984
|
layers.push({
|
|
29951
29985
|
id: `s52-LNDARE-point`,
|
|
29952
29986
|
type: "circle",
|
|
@@ -29962,7 +29996,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29962
29996
|
metadata: { "s52:objectClass": "LNDARE", "s52:role": "point" }
|
|
29963
29997
|
});
|
|
29964
29998
|
}
|
|
29965
|
-
if (
|
|
29999
|
+
if (objectClass5 === "LNDARE" && resolved.type === "fill") {
|
|
29966
30000
|
layers.push({
|
|
29967
30001
|
id: `s52-LNDARE-line`,
|
|
29968
30002
|
type: "line",
|
|
@@ -29976,7 +30010,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29976
30010
|
metadata: { "s52:objectClass": "LNDARE", "s52:role": "line" }
|
|
29977
30011
|
});
|
|
29978
30012
|
}
|
|
29979
|
-
if (
|
|
30013
|
+
if (objectClass5 === "BUAARE" && resolved.type === "fill") {
|
|
29980
30014
|
layers.push({
|
|
29981
30015
|
id: `s52-BUAARE-point`,
|
|
29982
30016
|
type: "circle",
|
|
@@ -29992,7 +30026,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
29992
30026
|
metadata: { "s52:objectClass": "BUAARE", "s52:role": "point" }
|
|
29993
30027
|
});
|
|
29994
30028
|
}
|
|
29995
|
-
if (
|
|
30029
|
+
if (objectClass5 === "RIVERS" && resolved.type === "fill") {
|
|
29996
30030
|
layers.push({
|
|
29997
30031
|
id: `s52-RIVERS-line`,
|
|
29998
30032
|
type: "line",
|
|
@@ -30006,7 +30040,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30006
30040
|
metadata: { "s52:objectClass": "RIVERS", "s52:role": "line" }
|
|
30007
30041
|
});
|
|
30008
30042
|
}
|
|
30009
|
-
if (
|
|
30043
|
+
if (objectClass5 === "BUISGL" && resolved.type === "circle") {
|
|
30010
30044
|
layers.push({
|
|
30011
30045
|
id: `s52-BUISGL-polygon`,
|
|
30012
30046
|
type: "fill",
|
|
@@ -30032,7 +30066,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30032
30066
|
metadata: { "s52:objectClass": "BUISGL", "s52:role": "polygon-outline" }
|
|
30033
30067
|
});
|
|
30034
30068
|
}
|
|
30035
|
-
if (
|
|
30069
|
+
if (objectClass5 === "BRIDGE" && resolved.type === "line") {
|
|
30036
30070
|
layers.push({
|
|
30037
30071
|
id: `s52-BRIDGE-polygon`,
|
|
30038
30072
|
type: "fill",
|
|
@@ -30058,7 +30092,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30058
30092
|
metadata: { "s52:objectClass": "BRIDGE", "s52:role": "polygon-outline" }
|
|
30059
30093
|
});
|
|
30060
30094
|
}
|
|
30061
|
-
if (
|
|
30095
|
+
if (objectClass5 === "PYLONS" && resolved.type === "fill") {
|
|
30062
30096
|
layers.push({
|
|
30063
30097
|
id: `s52-PYLONS-point`,
|
|
30064
30098
|
type: "circle",
|
|
@@ -30074,7 +30108,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30074
30108
|
metadata: { "s52:objectClass": "PYLONS", "s52:role": "point" }
|
|
30075
30109
|
});
|
|
30076
30110
|
}
|
|
30077
|
-
if (
|
|
30111
|
+
if (objectClass5 === "WEDKLP" && resolved.type === "fill") {
|
|
30078
30112
|
layers.push({
|
|
30079
30113
|
id: `s52-WEDKLP-point`,
|
|
30080
30114
|
type: "circle",
|
|
@@ -30091,7 +30125,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30091
30125
|
metadata: { "s52:objectClass": "WEDKLP", "s52:role": "point" }
|
|
30092
30126
|
});
|
|
30093
30127
|
}
|
|
30094
|
-
if (
|
|
30128
|
+
if (objectClass5 === "SLOGRD" && resolved.type === "fill") {
|
|
30095
30129
|
layers.push({
|
|
30096
30130
|
id: `s52-SLOGRD-point`,
|
|
30097
30131
|
type: "circle",
|
|
@@ -30108,7 +30142,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30108
30142
|
metadata: { "s52:objectClass": "SLOGRD", "s52:role": "point" }
|
|
30109
30143
|
});
|
|
30110
30144
|
}
|
|
30111
|
-
if (
|
|
30145
|
+
if (objectClass5 === "RUNWAY" && resolved.type === "fill") {
|
|
30112
30146
|
layers.push({
|
|
30113
30147
|
id: `s52-RUNWAY-line`,
|
|
30114
30148
|
type: "line",
|
|
@@ -30122,7 +30156,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30122
30156
|
metadata: { "s52:objectClass": "RUNWAY", "s52:role": "line" }
|
|
30123
30157
|
});
|
|
30124
30158
|
}
|
|
30125
|
-
if (
|
|
30159
|
+
if (objectClass5 === "FORSTC" && resolved.type === "fill") {
|
|
30126
30160
|
layers.push({
|
|
30127
30161
|
id: `s52-FORSTC-line`,
|
|
30128
30162
|
type: "line",
|
|
@@ -30136,7 +30170,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30136
30170
|
metadata: { "s52:objectClass": "FORSTC", "s52:role": "line" }
|
|
30137
30171
|
});
|
|
30138
30172
|
}
|
|
30139
|
-
if (
|
|
30173
|
+
if (objectClass5 === "FSHFAC" && resolved.type === "fill") {
|
|
30140
30174
|
layers.push({
|
|
30141
30175
|
id: `s52-FSHFAC-point`,
|
|
30142
30176
|
type: "circle",
|
|
@@ -30152,7 +30186,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30152
30186
|
metadata: { "s52:objectClass": "FSHFAC", "s52:role": "point" }
|
|
30153
30187
|
});
|
|
30154
30188
|
}
|
|
30155
|
-
if (
|
|
30189
|
+
if (objectClass5 === "OBSTRN" && resolved.type === "symbol") {
|
|
30156
30190
|
layers.push({
|
|
30157
30191
|
id: `s52-OBSTRN-polygon`,
|
|
30158
30192
|
type: "fill",
|
|
@@ -30192,7 +30226,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30192
30226
|
metadata: { "s52:objectClass": "OBSTRN", "s52:role": "line" }
|
|
30193
30227
|
});
|
|
30194
30228
|
}
|
|
30195
|
-
if (
|
|
30229
|
+
if (objectClass5 === "SLCONS" && resolved.type === "line") {
|
|
30196
30230
|
layers.push({
|
|
30197
30231
|
id: `s52-SLCONS-polygon`,
|
|
30198
30232
|
type: "fill",
|
|
@@ -30232,7 +30266,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30232
30266
|
metadata: { "s52:objectClass": "SLCONS", "s52:role": "point" }
|
|
30233
30267
|
});
|
|
30234
30268
|
}
|
|
30235
|
-
if (
|
|
30269
|
+
if (objectClass5 === "PRDARE" && resolved.type === "line") {
|
|
30236
30270
|
layers.push({
|
|
30237
30271
|
id: `s52-PRDARE-point`,
|
|
30238
30272
|
type: "circle",
|
|
@@ -30249,7 +30283,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30249
30283
|
metadata: { "s52:objectClass": "PRDARE", "s52:role": "point" }
|
|
30250
30284
|
});
|
|
30251
30285
|
}
|
|
30252
|
-
if (
|
|
30286
|
+
if (objectClass5 === "CTNARE" && resolved.type === "line") {
|
|
30253
30287
|
layers.push({
|
|
30254
30288
|
id: `s52-CTNARE-point`,
|
|
30255
30289
|
type: "circle",
|
|
@@ -30265,7 +30299,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30265
30299
|
metadata: { "s52:objectClass": "CTNARE", "s52:role": "point" }
|
|
30266
30300
|
});
|
|
30267
30301
|
}
|
|
30268
|
-
if (
|
|
30302
|
+
if (objectClass5 === "PONTON" && resolved.type === "line") {
|
|
30269
30303
|
layers.push({
|
|
30270
30304
|
id: `s52-PONTON-polygon`,
|
|
30271
30305
|
type: "fill",
|
|
@@ -30291,7 +30325,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30291
30325
|
metadata: { "s52:objectClass": "PONTON", "s52:role": "polygon-outline" }
|
|
30292
30326
|
});
|
|
30293
30327
|
}
|
|
30294
|
-
if (
|
|
30328
|
+
if (objectClass5 === "WRECKS" && resolved.type === "symbol") {
|
|
30295
30329
|
layers.push({
|
|
30296
30330
|
id: `s52-WRECKS-polygon`,
|
|
30297
30331
|
type: "fill",
|
|
@@ -30318,7 +30352,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30318
30352
|
metadata: { "s52:objectClass": "WRECKS", "s52:role": "polygon-outline" }
|
|
30319
30353
|
});
|
|
30320
30354
|
}
|
|
30321
|
-
if (
|
|
30355
|
+
if (objectClass5 === "WATTUR" && resolved.type === "symbol") {
|
|
30322
30356
|
layers.push({
|
|
30323
30357
|
id: `s52-WATTUR-polygon`,
|
|
30324
30358
|
type: "fill",
|
|
@@ -30332,7 +30366,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30332
30366
|
metadata: { "s52:objectClass": "WATTUR", "s52:role": "polygon" }
|
|
30333
30367
|
});
|
|
30334
30368
|
}
|
|
30335
|
-
if (
|
|
30369
|
+
if (objectClass5 === "MAGVAR" && resolved.type === "line") {
|
|
30336
30370
|
layers.push({
|
|
30337
30371
|
id: "s52-MAGVAR-point",
|
|
30338
30372
|
type: "circle",
|
|
@@ -30349,7 +30383,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30349
30383
|
metadata: { "s52:objectClass": "MAGVAR", "s52:role": "point" }
|
|
30350
30384
|
});
|
|
30351
30385
|
}
|
|
30352
|
-
if (
|
|
30386
|
+
if (objectClass5 === "DMPGRD" && resolved.type === "fill") {
|
|
30353
30387
|
layers.push({
|
|
30354
30388
|
id: `s52-DMPGRD-point`,
|
|
30355
30389
|
type: "circle",
|
|
@@ -30366,7 +30400,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30366
30400
|
metadata: { "s52:objectClass": "DMPGRD", "s52:role": "point" }
|
|
30367
30401
|
});
|
|
30368
30402
|
}
|
|
30369
|
-
if (
|
|
30403
|
+
if (objectClass5 === "DAMCON" && resolved.type === "line") {
|
|
30370
30404
|
layers.push({
|
|
30371
30405
|
id: `s52-DAMCON-polygon`,
|
|
30372
30406
|
type: "fill",
|
|
@@ -30392,7 +30426,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30392
30426
|
metadata: { "s52:objectClass": "DAMCON", "s52:role": "outline" }
|
|
30393
30427
|
});
|
|
30394
30428
|
}
|
|
30395
|
-
if (
|
|
30429
|
+
if (objectClass5 === "GATCON" && resolved.type === "line") {
|
|
30396
30430
|
layers.push({
|
|
30397
30431
|
id: `s52-GATCON-polygon`,
|
|
30398
30432
|
type: "fill",
|
|
@@ -30418,7 +30452,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30418
30452
|
metadata: { "s52:objectClass": "GATCON", "s52:role": "outline" }
|
|
30419
30453
|
});
|
|
30420
30454
|
}
|
|
30421
|
-
if (
|
|
30455
|
+
if (objectClass5 === "CANALS" && resolved.type === "line") {
|
|
30422
30456
|
layers.push({
|
|
30423
30457
|
id: `s52-CANALS-polygon`,
|
|
30424
30458
|
type: "fill",
|
|
@@ -30432,7 +30466,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30432
30466
|
metadata: { "s52:objectClass": "CANALS", "s52:role": "polygon" }
|
|
30433
30467
|
});
|
|
30434
30468
|
}
|
|
30435
|
-
if (
|
|
30469
|
+
if (objectClass5 === "PILBOP" && resolved.type === "symbol") {
|
|
30436
30470
|
layers.push({
|
|
30437
30471
|
id: `s52-PILBOP-polygon`,
|
|
30438
30472
|
type: "fill",
|
|
@@ -30459,7 +30493,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30459
30493
|
metadata: { "s52:objectClass": "PILBOP", "s52:role": "outline" }
|
|
30460
30494
|
});
|
|
30461
30495
|
}
|
|
30462
|
-
if (
|
|
30496
|
+
if (objectClass5 === "HRBFAC" && resolved.type === "circle") {
|
|
30463
30497
|
layers.push({
|
|
30464
30498
|
id: `s52-HRBFAC-polygon`,
|
|
30465
30499
|
type: "fill",
|
|
@@ -30473,7 +30507,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30473
30507
|
metadata: { "s52:objectClass": "HRBFAC", "s52:role": "polygon" }
|
|
30474
30508
|
});
|
|
30475
30509
|
}
|
|
30476
|
-
if (
|
|
30510
|
+
if (objectClass5 === "MARCUL" && resolved.type === "fill") {
|
|
30477
30511
|
layers.push({
|
|
30478
30512
|
id: `s52-MARCUL-point`,
|
|
30479
30513
|
type: "circle",
|
|
@@ -30503,7 +30537,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30503
30537
|
metadata: { "s52:objectClass": "MARCUL", "s52:role": "line" }
|
|
30504
30538
|
});
|
|
30505
30539
|
}
|
|
30506
|
-
if (
|
|
30540
|
+
if (objectClass5 === "RECTRC" && resolved.type === "line") {
|
|
30507
30541
|
layers.push({
|
|
30508
30542
|
id: `s52-RECTRC-polygon`,
|
|
30509
30543
|
type: "fill",
|
|
@@ -30517,7 +30551,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30517
30551
|
metadata: { "s52:objectClass": "RECTRC", "s52:role": "polygon" }
|
|
30518
30552
|
});
|
|
30519
30553
|
}
|
|
30520
|
-
if (
|
|
30554
|
+
if (objectClass5 === "PONTON" && resolved.type === "fill") {
|
|
30521
30555
|
layers.push({
|
|
30522
30556
|
id: `s52-PONTON-line`,
|
|
30523
30557
|
type: "line",
|
|
@@ -30531,7 +30565,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30531
30565
|
metadata: { "s52:objectClass": "PONTON", "s52:role": "line" }
|
|
30532
30566
|
});
|
|
30533
30567
|
}
|
|
30534
|
-
if (
|
|
30568
|
+
if (objectClass5 === "SILTNK" && resolved.type === "symbol") {
|
|
30535
30569
|
layers.push({
|
|
30536
30570
|
id: `s52-SILTNK-symbol-polygon`,
|
|
30537
30571
|
type: "symbol",
|
|
@@ -30549,7 +30583,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30549
30583
|
metadata: { "s52:objectClass": "SILTNK", "s52:role": "symbol-polygon" }
|
|
30550
30584
|
});
|
|
30551
30585
|
}
|
|
30552
|
-
if (
|
|
30586
|
+
if (objectClass5 === "ACHBRT" && resolved.type === "symbol") {
|
|
30553
30587
|
layers.push({
|
|
30554
30588
|
id: `s52-ACHBRT-symbol-polygon`,
|
|
30555
30589
|
type: "symbol",
|
|
@@ -30567,7 +30601,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30567
30601
|
metadata: { "s52:objectClass": "ACHBRT", "s52:role": "symbol-polygon" }
|
|
30568
30602
|
});
|
|
30569
30603
|
}
|
|
30570
|
-
if (
|
|
30604
|
+
if (objectClass5 === "BERTHS" && resolved.type === "line") {
|
|
30571
30605
|
layers.push({
|
|
30572
30606
|
id: `s52-BERTHS-circle`,
|
|
30573
30607
|
type: "circle",
|
|
@@ -30583,7 +30617,7 @@ function buildLayersForClass(objectClass2, ct, sourceId = DEFAULT_REGION, opts =
|
|
|
30583
30617
|
metadata: { "s52:objectClass": "BERTHS", "s52:role": "point" }
|
|
30584
30618
|
});
|
|
30585
30619
|
}
|
|
30586
|
-
if (
|
|
30620
|
+
if (objectClass5 === "TUNNEL" && resolved.type === "line") {
|
|
30587
30621
|
layers.push({
|
|
30588
30622
|
// NOT `s52-TUNNEL-line` — that id is already taken by the main layer
|
|
30589
30623
|
// (`s52-${objectClass}-${resolved.type}`), and duplicate layer ids
|
|
@@ -30613,9 +30647,9 @@ function dangerDepthMetresDown() {
|
|
|
30613
30647
|
""
|
|
30614
30648
|
];
|
|
30615
30649
|
}
|
|
30616
|
-
function buildLabelLayer2(
|
|
30617
|
-
if (!LABELED_LAYERS.has(
|
|
30618
|
-
const config = getLabelConfig(
|
|
30650
|
+
function buildLabelLayer2(objectClass5, ct, sourceId = DEFAULT_REGION, depthUnits = "meters", labelOpts = {}) {
|
|
30651
|
+
if (!LABELED_LAYERS.has(objectClass5)) return null;
|
|
30652
|
+
const config = getLabelConfig(objectClass5, {
|
|
30619
30653
|
colorTable: ct,
|
|
30620
30654
|
safetyContour: labelOpts.safetyContour,
|
|
30621
30655
|
twoShadeSoundings: labelOpts.twoShadeSoundings,
|
|
@@ -30623,7 +30657,7 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30623
30657
|
});
|
|
30624
30658
|
if (!config) return null;
|
|
30625
30659
|
let textField = config.textField;
|
|
30626
|
-
if (
|
|
30660
|
+
if (objectClass5 === "LIGHTS") {
|
|
30627
30661
|
textField = buildLightLabelExpression(depthUnits);
|
|
30628
30662
|
}
|
|
30629
30663
|
if (typeof textField !== "string" && Array.isArray(textField)) {
|
|
@@ -30633,7 +30667,7 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30633
30667
|
}
|
|
30634
30668
|
}
|
|
30635
30669
|
if (depthUnits === "feet") {
|
|
30636
|
-
if (
|
|
30670
|
+
if (objectClass5 === "SOUNDG") {
|
|
30637
30671
|
textField = [
|
|
30638
30672
|
"concat",
|
|
30639
30673
|
[
|
|
@@ -30650,13 +30684,13 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30650
30684
|
],
|
|
30651
30685
|
""
|
|
30652
30686
|
];
|
|
30653
|
-
} else if (
|
|
30687
|
+
} else if (objectClass5 === "DEPCNT") {
|
|
30654
30688
|
textField = [
|
|
30655
30689
|
"concat",
|
|
30656
30690
|
["round", ["*", ["to-number", ["get", "VALDCO"]], 3.28084]],
|
|
30657
30691
|
"ft"
|
|
30658
30692
|
];
|
|
30659
|
-
} else if (
|
|
30693
|
+
} else if (objectClass5 === "UWTROC" || objectClass5 === "OBSTRN" || objectClass5 === "WRECKS") {
|
|
30660
30694
|
const valsouFt = [
|
|
30661
30695
|
"to-number",
|
|
30662
30696
|
["coalesce", ["get", "VALSOU"], ["get", "valsou"], 0],
|
|
@@ -30673,15 +30707,15 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30673
30707
|
""
|
|
30674
30708
|
];
|
|
30675
30709
|
}
|
|
30676
|
-
} else if (labelOpts.dangerDepthRounding === "down" && (
|
|
30710
|
+
} else if (labelOpts.dangerDepthRounding === "down" && (objectClass5 === "UWTROC" || objectClass5 === "OBSTRN" || objectClass5 === "WRECKS")) {
|
|
30677
30711
|
textField = dangerDepthMetresDown();
|
|
30678
30712
|
}
|
|
30679
|
-
const labelPriority = getLabelPriority(
|
|
30713
|
+
const labelPriority = getLabelPriority(objectClass5);
|
|
30680
30714
|
const layer = {
|
|
30681
|
-
id: `s52-${
|
|
30715
|
+
id: `s52-${objectClass5}-label`,
|
|
30682
30716
|
type: "symbol",
|
|
30683
30717
|
source: sourceId,
|
|
30684
|
-
"source-layer":
|
|
30718
|
+
"source-layer": objectClass5,
|
|
30685
30719
|
filter: GEOM_FILTERS.symbol,
|
|
30686
30720
|
layout: {
|
|
30687
30721
|
"text-field": textField,
|
|
@@ -30701,14 +30735,14 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30701
30735
|
"text-halo-width": config.textHaloWidth
|
|
30702
30736
|
},
|
|
30703
30737
|
metadata: {
|
|
30704
|
-
"s52:objectClass":
|
|
30738
|
+
"s52:objectClass": objectClass5,
|
|
30705
30739
|
"chrt:labelPriority": labelPriority
|
|
30706
30740
|
}
|
|
30707
30741
|
};
|
|
30708
30742
|
if (config.minzoom) {
|
|
30709
30743
|
layer.minzoom = config.minzoom;
|
|
30710
30744
|
}
|
|
30711
|
-
if (
|
|
30745
|
+
if (objectClass5 === "LIGHTS") {
|
|
30712
30746
|
layer.layout = {
|
|
30713
30747
|
...layer.layout,
|
|
30714
30748
|
"text-offset": [
|
|
@@ -30719,28 +30753,28 @@ function buildLabelLayer2(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnit
|
|
|
30719
30753
|
]
|
|
30720
30754
|
};
|
|
30721
30755
|
}
|
|
30722
|
-
if (
|
|
30756
|
+
if (objectClass5 === "DEPCNT") {
|
|
30723
30757
|
layer.filter = GEOM_FILTERS.line;
|
|
30724
30758
|
}
|
|
30725
|
-
if (
|
|
30759
|
+
if (objectClass5 === "CBLOHD" || objectClass5 === "PIPOHD") {
|
|
30726
30760
|
layer.filter = GEOM_FILTERS.line;
|
|
30727
30761
|
}
|
|
30728
|
-
if (
|
|
30762
|
+
if (objectClass5 === "SBDARE") {
|
|
30729
30763
|
delete layer.filter;
|
|
30730
30764
|
}
|
|
30731
|
-
if (
|
|
30765
|
+
if (objectClass5 === "MAGVAR") {
|
|
30732
30766
|
delete layer.filter;
|
|
30733
30767
|
}
|
|
30734
|
-
if (getLabelBehavior(
|
|
30768
|
+
if (getLabelBehavior(objectClass5) === "orientation-cross-band") {
|
|
30735
30769
|
layer.filter = LABEL_ANCHOR_FILTER;
|
|
30736
30770
|
}
|
|
30737
30771
|
return layer;
|
|
30738
30772
|
}
|
|
30739
|
-
function getGeomTypesForClass(
|
|
30740
|
-
if (SYMBOL_MAP[
|
|
30773
|
+
function getGeomTypesForClass(objectClass5, defaultType) {
|
|
30774
|
+
if (SYMBOL_MAP[objectClass5] && defaultType === "symbol") {
|
|
30741
30775
|
return ["symbol"];
|
|
30742
30776
|
}
|
|
30743
|
-
if (
|
|
30777
|
+
if (objectClass5 === "SOUNDG") {
|
|
30744
30778
|
return ["circle"];
|
|
30745
30779
|
}
|
|
30746
30780
|
if (defaultType) {
|
|
@@ -30822,9 +30856,9 @@ function arcSegmentSvg(token, sweepDeg) {
|
|
|
30822
30856
|
const box = segmentBox(sweepDeg);
|
|
30823
30857
|
const end = sweepDeg + JOINT_OVERLAP_DEG;
|
|
30824
30858
|
const core = token === "CHBRN" ? OBSCURED_CORE_WIDTH : CORE_WIDTH;
|
|
30825
|
-
const
|
|
30826
|
-
const outline = annularSectorPath(end,
|
|
30827
|
-
const inner = annularSectorPath(end,
|
|
30859
|
+
const R2 = SECTOR_ARC_RADIUS;
|
|
30860
|
+
const outline = annularSectorPath(end, R2 - OUTLINE_WIDTH / 2, R2 + OUTLINE_WIDTH / 2, box);
|
|
30861
|
+
const inner = annularSectorPath(end, R2 - core / 2, R2 + core / 2, box);
|
|
30828
30862
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="${box.w}" height="${box.h}" viewBox="0 0 ${box.w} ${box.h}"><path d="${outline}" fill="CHBLK"/><path d="${inner}" fill="${token}"/></svg>`;
|
|
30829
30863
|
}
|
|
30830
30864
|
function legSvg() {
|
|
@@ -31364,9 +31398,9 @@ var RASTER_ATON_CLASSES = Object.keys(
|
|
|
31364
31398
|
if (!s52) return true;
|
|
31365
31399
|
return JSON.stringify({ r: paper.rows, d: paper.defaultSymbol }) !== JSON.stringify({ r: s52.rows, d: s52.defaultSymbol });
|
|
31366
31400
|
});
|
|
31367
|
-
function rasterAtonIconExpression(
|
|
31368
|
-
const lookup = S52_ATON_LOOKUPS_PAPER[
|
|
31369
|
-
if (!lookup) throw new Error(`raster-style: no paper lookup for ${
|
|
31401
|
+
function rasterAtonIconExpression(objectClass5) {
|
|
31402
|
+
const lookup = S52_ATON_LOOKUPS_PAPER[objectClass5];
|
|
31403
|
+
if (!lookup) throw new Error(`raster-style: no paper lookup for ${objectClass5}`);
|
|
31370
31404
|
return compileAtonExpression(lookup, resolveRasterImage);
|
|
31371
31405
|
}
|
|
31372
31406
|
function getRasterSvg(name, table = "DAY") {
|
|
@@ -31380,17 +31414,461 @@ function applyRasterSymbolSet(style) {
|
|
|
31380
31414
|
const layout = layer.layout;
|
|
31381
31415
|
if (!layout || layout["icon-image"] == null) continue;
|
|
31382
31416
|
const metadata2 = layer.metadata;
|
|
31383
|
-
const
|
|
31384
|
-
if (typeof
|
|
31385
|
-
layout["icon-image"] = rasterAtonIconExpression(
|
|
31417
|
+
const objectClass5 = metadata2?.["s52:objectClass"];
|
|
31418
|
+
if (typeof objectClass5 !== "string" || !classes.has(objectClass5)) continue;
|
|
31419
|
+
layout["icon-image"] = rasterAtonIconExpression(objectClass5);
|
|
31386
31420
|
}
|
|
31387
31421
|
const metadata = style.metadata;
|
|
31388
|
-
metadata["chrt:symbol-set"] = "
|
|
31422
|
+
metadata["chrt:symbol-set"] = "int1";
|
|
31389
31423
|
return style;
|
|
31390
31424
|
}
|
|
31391
31425
|
|
|
31426
|
+
// src/atlas/symbol-family-ids.ts
|
|
31427
|
+
var LEGACY_SYMBOL_FAMILY_ALIASES = { raster: "int1" };
|
|
31428
|
+
function normalizeSymbolFamily(family) {
|
|
31429
|
+
return family === "raster" ? LEGACY_SYMBOL_FAMILY_ALIASES.raster : family;
|
|
31430
|
+
}
|
|
31431
|
+
|
|
31432
|
+
// src/atlas/look-painter.ts
|
|
31433
|
+
function painter(w, h) {
|
|
31434
|
+
const acc = new Float32Array(w * h * 4);
|
|
31435
|
+
const over = (x, y, c, cov) => {
|
|
31436
|
+
if (x < 0 || y < 0 || x >= w || y >= h || cov <= 0) return;
|
|
31437
|
+
const k = (y * w + x) * 4;
|
|
31438
|
+
const a = c[3] / 255 * Math.min(1, cov);
|
|
31439
|
+
acc[k] = c[0] * a + acc[k] * (1 - a);
|
|
31440
|
+
acc[k + 1] = c[1] * a + acc[k + 1] * (1 - a);
|
|
31441
|
+
acc[k + 2] = c[2] * a + acc[k + 2] * (1 - a);
|
|
31442
|
+
acc[k + 3] = a + acc[k + 3] * (1 - a);
|
|
31443
|
+
};
|
|
31444
|
+
const dot = (cx, cy, r, c) => {
|
|
31445
|
+
for (let y = Math.floor(cy - r - 1); y <= Math.ceil(cy + r + 1); y++) {
|
|
31446
|
+
for (let x = Math.floor(cx - r - 1); x <= Math.ceil(cx + r + 1); x++) over(x, y, c, r + 0.5 - Math.hypot(x + 0.5 - cx, y + 0.5 - cy));
|
|
31447
|
+
}
|
|
31448
|
+
};
|
|
31449
|
+
const stroke = (pts, r, c) => {
|
|
31450
|
+
const cov = new Float32Array(w * h);
|
|
31451
|
+
for (let i = 1; i < pts.length; i++) {
|
|
31452
|
+
const [x0, y0] = pts[i - 1];
|
|
31453
|
+
const [x1, y1] = pts[i];
|
|
31454
|
+
const n = Math.max(1, Math.ceil(Math.hypot(x1 - x0, y1 - y0) * 2));
|
|
31455
|
+
for (let t = 0; t <= n; t++) {
|
|
31456
|
+
const cx = x0 + (x1 - x0) * t / n;
|
|
31457
|
+
const cy = y0 + (y1 - y0) * t / n;
|
|
31458
|
+
for (let y = Math.floor(cy - r - 1); y <= Math.ceil(cy + r + 1); y++) {
|
|
31459
|
+
for (let x = Math.floor(cx - r - 1); x <= Math.ceil(cx + r + 1); x++) {
|
|
31460
|
+
if (x < 0 || y < 0 || x >= w || y >= h) continue;
|
|
31461
|
+
const v = Math.max(0, Math.min(1, r + 0.5 - Math.hypot(x + 0.5 - cx, y + 0.5 - cy)));
|
|
31462
|
+
if (v > cov[y * w + x]) cov[y * w + x] = v;
|
|
31463
|
+
}
|
|
31464
|
+
}
|
|
31465
|
+
}
|
|
31466
|
+
}
|
|
31467
|
+
for (let k = 0; k < cov.length; k++) if (cov[k] > 0) over(k % w, Math.floor(k / w), c, cov[k]);
|
|
31468
|
+
};
|
|
31469
|
+
const fill = (pts, c) => {
|
|
31470
|
+
const y0 = Math.max(0, Math.floor(Math.min(...pts.map((p) => p[1]))));
|
|
31471
|
+
const y1 = Math.min(h - 1, Math.ceil(Math.max(...pts.map((p) => p[1]))));
|
|
31472
|
+
const x0 = Math.max(0, Math.floor(Math.min(...pts.map((p) => p[0]))));
|
|
31473
|
+
const x1 = Math.min(w - 1, Math.ceil(Math.max(...pts.map((p) => p[0]))));
|
|
31474
|
+
for (let y = y0; y <= y1; y++) {
|
|
31475
|
+
for (let x = x0; x <= x1; x++) {
|
|
31476
|
+
let inside = 0;
|
|
31477
|
+
for (let sy = 0; sy < 4; sy++) for (let sx = 0; sx < 4; sx++) {
|
|
31478
|
+
const px = x + (sx + 0.5) / 4;
|
|
31479
|
+
const py = y + (sy + 0.5) / 4;
|
|
31480
|
+
let odd = false;
|
|
31481
|
+
for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {
|
|
31482
|
+
const [xi, yi] = pts[i];
|
|
31483
|
+
const [xj, yj] = pts[j];
|
|
31484
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) odd = !odd;
|
|
31485
|
+
}
|
|
31486
|
+
if (odd) inside++;
|
|
31487
|
+
}
|
|
31488
|
+
over(x, y, c, inside / 16);
|
|
31489
|
+
}
|
|
31490
|
+
}
|
|
31491
|
+
};
|
|
31492
|
+
const data = () => {
|
|
31493
|
+
const out = new Uint8Array(w * h * 4);
|
|
31494
|
+
for (let k = 0; k < w * h; k++) {
|
|
31495
|
+
const a = acc[k * 4 + 3];
|
|
31496
|
+
if (a <= 0) continue;
|
|
31497
|
+
out[k * 4] = Math.round(acc[k * 4] / a);
|
|
31498
|
+
out[k * 4 + 1] = Math.round(acc[k * 4 + 1] / a);
|
|
31499
|
+
out[k * 4 + 2] = Math.round(acc[k * 4 + 2] / a);
|
|
31500
|
+
out[k * 4 + 3] = Math.round(a * 255);
|
|
31501
|
+
}
|
|
31502
|
+
return out;
|
|
31503
|
+
};
|
|
31504
|
+
return { dot, stroke, fill, data };
|
|
31505
|
+
}
|
|
31506
|
+
function turn([x, y], cx, cy, deg) {
|
|
31507
|
+
const r = deg * Math.PI / 180;
|
|
31508
|
+
const dx = x - cx;
|
|
31509
|
+
const dy = y - cy;
|
|
31510
|
+
return [cx + dx * Math.cos(r) - dy * Math.sin(r), cy + dx * Math.sin(r) + dy * Math.cos(r)];
|
|
31511
|
+
}
|
|
31512
|
+
|
|
31513
|
+
// src/atlas/uschart1-marks.ts
|
|
31514
|
+
var CLASSIC_MARK_TONES = {
|
|
31515
|
+
color: { magenta: "#953699", green: "#068b00", ink: "#000000", open: "#ffffff" },
|
|
31516
|
+
// A laser printer's greys: red lighter than green, so a banded mark still
|
|
31517
|
+
// shows its bands. The label (R, G) says which is which, as it always does.
|
|
31518
|
+
mono: { magenta: "#8c8c8c", green: "#4d4d4d", ink: "#000000", open: "#ffffff" }
|
|
31519
|
+
};
|
|
31520
|
+
var PREFIX = { color: "chrt-look-cl-", mono: "chrt-look-cm-" };
|
|
31521
|
+
function classicMarkId(ink, name) {
|
|
31522
|
+
return PREFIX[ink] + name;
|
|
31523
|
+
}
|
|
31524
|
+
function classicMarkInk(id) {
|
|
31525
|
+
for (const ink of ["color", "mono"]) {
|
|
31526
|
+
if (id.startsWith(PREFIX[ink]) && CLASSIC_MARK_NAMES.includes(id.slice(PREFIX[ink].length))) return ink;
|
|
31527
|
+
}
|
|
31528
|
+
return null;
|
|
31529
|
+
}
|
|
31530
|
+
var COLOURS = ["red", "green", "black", "yellow", "white"];
|
|
31531
|
+
var BOARDS = ["triangle-up", "triangle-down", "square", "rhombus"];
|
|
31532
|
+
var BOARD_TOPSHP_SHAPE = [
|
|
31533
|
+
[1, "triangle-up"],
|
|
31534
|
+
[24, "triangle-up"],
|
|
31535
|
+
[29, "triangle-up"],
|
|
31536
|
+
[2, "triangle-down"],
|
|
31537
|
+
[25, "triangle-down"],
|
|
31538
|
+
[12, "rhombus"],
|
|
31539
|
+
[11, "rhombus"],
|
|
31540
|
+
[31, "rhombus"]
|
|
31541
|
+
];
|
|
31542
|
+
var paints = COLOURS.flatMap((a) => [
|
|
31543
|
+
a,
|
|
31544
|
+
...COLOURS.filter((b) => b !== a).flatMap((b) => [`${a}-${b}-h`, `${a}-${b}-v`])
|
|
31545
|
+
]);
|
|
31546
|
+
var BUOY_NAMES = paints.map((p) => `buoy-${p}`);
|
|
31547
|
+
var BOARD_NAMES = BOARDS.flatMap((s) => paints.map((p) => `board-${s}-${p}`));
|
|
31548
|
+
var CLASSIC_MARK_NAMES = ["flare", "disc", ...BUOY_NAMES, ...BOARD_NAMES];
|
|
31549
|
+
function objectClass2(l) {
|
|
31550
|
+
const m = l.metadata;
|
|
31551
|
+
const c = (typeof m === "object" && m !== null ? m["s52:objectClass"] : void 0) ?? l["source-layer"] ?? "";
|
|
31552
|
+
return String(c).toUpperCase();
|
|
31553
|
+
}
|
|
31554
|
+
var DROPPED = /^s52-LIGHTS-lamp-(glow|core)$/;
|
|
31555
|
+
var FLARES = /* @__PURE__ */ new Set(["LIGHTS11", "LIGHTS12", "LIGHTS13", "LITDEF11", "raster:LIGHTS11", "raster:LIGHTS12", "raster:LIGHTS13", "raster:LITDEF11"]);
|
|
31556
|
+
var BUOYS = /* @__PURE__ */ new Set(["BOYLAT", "BOYCAR", "BOYISD", "BOYSAW", "BOYSPP"]);
|
|
31557
|
+
var BEACONS = /* @__PURE__ */ new Set(["BCNLAT", "BCNCAR", "BCNISD", "BCNSAW", "BCNSPP"]);
|
|
31558
|
+
var HAS_HEIGHT = ["any", ["has", "HEIGHT"], ["has", "height"]];
|
|
31559
|
+
var num2 = (attr) => ["to-number", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], 0], 0];
|
|
31560
|
+
var LOZENGE_BUOY = ["!", ["in", num2("BOYSHP"), ["literal", [7, 8]]]];
|
|
31561
|
+
var DAYBEACON = ["!", ["in", num2("BCNSHP"), ["literal", [3, 4, 6]]]];
|
|
31562
|
+
var SHAPE_LETTERS = [
|
|
31563
|
+
[1, "N"],
|
|
31564
|
+
[2, "C"],
|
|
31565
|
+
[3, "SP"],
|
|
31566
|
+
[4, "P"],
|
|
31567
|
+
[5, "S"]
|
|
31568
|
+
];
|
|
31569
|
+
function withShapeLetter(field) {
|
|
31570
|
+
const lbl = ["var", "clLabel"];
|
|
31571
|
+
const shp = ["var", "clShape"];
|
|
31572
|
+
return [
|
|
31573
|
+
"let",
|
|
31574
|
+
"clLabel",
|
|
31575
|
+
["to-string", field],
|
|
31576
|
+
[
|
|
31577
|
+
"let",
|
|
31578
|
+
"clShape",
|
|
31579
|
+
["match", num2("BOYSHP"), ...SHAPE_LETTERS.flat(), ""],
|
|
31580
|
+
[
|
|
31581
|
+
"case",
|
|
31582
|
+
["==", shp, ""],
|
|
31583
|
+
lbl,
|
|
31584
|
+
["==", lbl, ""],
|
|
31585
|
+
shp,
|
|
31586
|
+
// A colour letter and a space first ("R \"2\""): the shape goes after it.
|
|
31587
|
+
["all", [">=", ["length", lbl], 2], ["==", ["slice", lbl, 1, 2], " "], ["in", ["slice", lbl, 0, 1], "RGY"]],
|
|
31588
|
+
["concat", ["slice", lbl, 0, 2], shp, " ", ["slice", lbl, 2]],
|
|
31589
|
+
["concat", shp, " ", lbl]
|
|
31590
|
+
]
|
|
31591
|
+
]
|
|
31592
|
+
];
|
|
31593
|
+
}
|
|
31594
|
+
function colourName(code) {
|
|
31595
|
+
return ["match", code, "1", "white", "2", "black", "3", "red", "4", "green", "6", "yellow", "white"];
|
|
31596
|
+
}
|
|
31597
|
+
function withColours(inner) {
|
|
31598
|
+
const raw = ["to-string", ["coalesce", ["get", "COLOUR"], ["get", "colour"], ""]];
|
|
31599
|
+
const body = ["case", ["==", ["slice", ["var", "raw"], 0, 2], '["'], ["slice", ["var", "raw"], 2], ["==", ["slice", ["var", "raw"], 0, 1], "["], ["slice", ["var", "raw"], 1], ["var", "raw"]];
|
|
31600
|
+
const firstOf = (s) => ["case", ["all", ["!=", ["slice", s, 1, 2], ""], ["in", ["slice", s, 1, 2], "0123456789"]], "x", ["slice", s, 0, 1]];
|
|
31601
|
+
const after = [
|
|
31602
|
+
"let",
|
|
31603
|
+
"at",
|
|
31604
|
+
["index-of", ",", ["var", "body"]],
|
|
31605
|
+
["case", ["<", ["var", "at"], 0], "", ["slice", ["var", "body"], ["+", ["var", "at"], 1]]]
|
|
31606
|
+
];
|
|
31607
|
+
const second = ["case", ["==", ["slice", ["var", "rest"], 0, 1], '"'], ["slice", ["var", "rest"], 1], ["var", "rest"]];
|
|
31608
|
+
const pat = ["to-string", ["coalesce", ["get", "COLPAT"], ["get", "colpat"], ""]];
|
|
31609
|
+
const stripes = ["any", ["==", pat, "2"], [">=", ["index-of", "2", pat], 0]];
|
|
31610
|
+
return [
|
|
31611
|
+
"let",
|
|
31612
|
+
"raw",
|
|
31613
|
+
raw,
|
|
31614
|
+
[
|
|
31615
|
+
"let",
|
|
31616
|
+
"body",
|
|
31617
|
+
body,
|
|
31618
|
+
[
|
|
31619
|
+
"let",
|
|
31620
|
+
"rest",
|
|
31621
|
+
after,
|
|
31622
|
+
[
|
|
31623
|
+
"let",
|
|
31624
|
+
"c1",
|
|
31625
|
+
colourName(firstOf(["var", "body"])),
|
|
31626
|
+
[
|
|
31627
|
+
"let",
|
|
31628
|
+
"c2",
|
|
31629
|
+
["case", ["==", ["var", "rest"], ""], ["var", "c1"], colourName(firstOf(second))],
|
|
31630
|
+
[
|
|
31631
|
+
"let",
|
|
31632
|
+
"split",
|
|
31633
|
+
["case", stripes, "-v", "-h"],
|
|
31634
|
+
inner
|
|
31635
|
+
]
|
|
31636
|
+
]
|
|
31637
|
+
]
|
|
31638
|
+
]
|
|
31639
|
+
]
|
|
31640
|
+
];
|
|
31641
|
+
}
|
|
31642
|
+
function painted(prefix, kind) {
|
|
31643
|
+
return [
|
|
31644
|
+
"case",
|
|
31645
|
+
["==", ["var", "c1"], ["var", "c2"]],
|
|
31646
|
+
["concat", prefix, kind, "-", ["var", "c1"]],
|
|
31647
|
+
["concat", prefix, kind, "-", ["var", "c1"], "-", ["var", "c2"], ["var", "split"]]
|
|
31648
|
+
];
|
|
31649
|
+
}
|
|
31650
|
+
function lozenge(ink, plain) {
|
|
31651
|
+
return ["case", LOZENGE_BUOY, withColours(painted(PREFIX[ink], "buoy")), plain];
|
|
31652
|
+
}
|
|
31653
|
+
function daybeacon(ink, plain) {
|
|
31654
|
+
const lateral = ["any", ["==", ["var", "c1"], "red"], ["==", ["var", "c1"], "green"]];
|
|
31655
|
+
const shape = ["case", ["==", ["var", "c1"], "red"], "triangle-up", "square"];
|
|
31656
|
+
return withColours(["case", ["all", DAYBEACON, lateral], painted(PREFIX[ink], ["concat", "board-", shape]), plain]);
|
|
31657
|
+
}
|
|
31658
|
+
function dayboard(ink) {
|
|
31659
|
+
const shape = ["match", num2("TOPSHP"), ...BOARD_TOPSHP_SHAPE.flatMap(([code, s]) => [code, s]), "square"];
|
|
31660
|
+
return withColours(painted(PREFIX[ink], ["concat", "board-", shape]));
|
|
31661
|
+
}
|
|
31662
|
+
function withClassicMarks(style, ink) {
|
|
31663
|
+
const out = [];
|
|
31664
|
+
const discs = [];
|
|
31665
|
+
for (const layer of style.layers) {
|
|
31666
|
+
if (DROPPED.test(layer.id)) continue;
|
|
31667
|
+
const cls = objectClass2(layer);
|
|
31668
|
+
const layout = layer.layout;
|
|
31669
|
+
if (layer.type !== "symbol" || !layout) {
|
|
31670
|
+
out.push(layer);
|
|
31671
|
+
continue;
|
|
31672
|
+
}
|
|
31673
|
+
if (layout["text-field"] !== void 0 && BUOYS.has(cls) && /-label/.test(layer.id)) {
|
|
31674
|
+
out.push({ ...layer, layout: { ...layout, "text-field": withShapeLetter(layout["text-field"]) } });
|
|
31675
|
+
continue;
|
|
31676
|
+
}
|
|
31677
|
+
if (layout["icon-image"] === void 0 || !/-symbol/.test(layer.id)) {
|
|
31678
|
+
out.push(layer);
|
|
31679
|
+
continue;
|
|
31680
|
+
}
|
|
31681
|
+
if (BUOYS.has(cls)) out.push({ ...layer, layout: { ...layout, "icon-image": lozenge(ink, layout["icon-image"]) } });
|
|
31682
|
+
else if (BEACONS.has(cls)) out.push({ ...layer, layout: { ...layout, "icon-image": daybeacon(ink, layout["icon-image"]) } });
|
|
31683
|
+
else if (cls === "DAYMAR") out.push({ ...layer, layout: { ...layout, "icon-image": dayboard(ink), "icon-offset": [0, 0] } });
|
|
31684
|
+
else if (cls === "LIGHTS") {
|
|
31685
|
+
discs.push({
|
|
31686
|
+
...layer,
|
|
31687
|
+
id: `${layer.id}-look-disc`,
|
|
31688
|
+
filter: ["all", layer.filter ?? true, ["!", HAS_HEIGHT]],
|
|
31689
|
+
layout: { ...layout, "icon-image": classicMarkId(ink, "disc"), "icon-offset": [0, 0], "icon-rotate": 0 }
|
|
31690
|
+
});
|
|
31691
|
+
out.push({
|
|
31692
|
+
...layer,
|
|
31693
|
+
filter: ["all", layer.filter ?? true, HAS_HEIGHT],
|
|
31694
|
+
layout: { ...layout, "icon-image": replaceLiteral(layout["icon-image"], FLARES, classicMarkId(ink, "flare")) }
|
|
31695
|
+
});
|
|
31696
|
+
} else out.push(layer);
|
|
31697
|
+
}
|
|
31698
|
+
const at = out.findIndex((l) => /^s52-(BOY|BCN)[A-Z]{3}-symbol/.test(l.id));
|
|
31699
|
+
out.splice(at < 0 ? out.length : at, 0, ...discs);
|
|
31700
|
+
return {
|
|
31701
|
+
...style,
|
|
31702
|
+
layers: out,
|
|
31703
|
+
metadata: { ...typeof style.metadata === "object" && style.metadata !== null ? style.metadata : {}, "chrt:classic-marks": ink }
|
|
31704
|
+
};
|
|
31705
|
+
}
|
|
31706
|
+
function classicInkFor(palette) {
|
|
31707
|
+
if (palette === "DAY" || palette === "EINK_COLOR") return "color";
|
|
31708
|
+
if (palette === "EINK_MONO") return "mono";
|
|
31709
|
+
return null;
|
|
31710
|
+
}
|
|
31711
|
+
function classicIconExpression(cls, ink, plain) {
|
|
31712
|
+
const c = cls.toUpperCase();
|
|
31713
|
+
if (BUOYS.has(c)) return lozenge(ink, plain);
|
|
31714
|
+
if (BEACONS.has(c)) return daybeacon(ink, plain);
|
|
31715
|
+
if (c === "DAYMAR") return dayboard(ink);
|
|
31716
|
+
return plain;
|
|
31717
|
+
}
|
|
31718
|
+
function replaceLiteral(v, from, to) {
|
|
31719
|
+
if (typeof v === "string") return from.has(v) ? to : v;
|
|
31720
|
+
if (Array.isArray(v)) return v.map((e) => replaceLiteral(e, from, to));
|
|
31721
|
+
return v;
|
|
31722
|
+
}
|
|
31723
|
+
var R = 2;
|
|
31724
|
+
var S = 64 * R;
|
|
31725
|
+
var C0 = S / 2;
|
|
31726
|
+
var BUOY_LENGTH = 12.5;
|
|
31727
|
+
var BUOY_HALF_WIDTH = 3.4;
|
|
31728
|
+
var DISC_RADIUS = 8.5;
|
|
31729
|
+
var BOARD_SIDE = 8;
|
|
31730
|
+
var SB = 96 * R;
|
|
31731
|
+
var CB = SB / 2;
|
|
31732
|
+
var FLARE_SCALE = 0.6;
|
|
31733
|
+
var FLARE_ANCHOR = 18;
|
|
31734
|
+
function paintOf(ink, c) {
|
|
31735
|
+
const t = CLASSIC_MARK_TONES[ink];
|
|
31736
|
+
return c === "red" ? t.magenta : c === "green" ? t.green : c === "black" ? t.ink : t.open;
|
|
31737
|
+
}
|
|
31738
|
+
function circle(cx, cy, r) {
|
|
31739
|
+
return Array.from({ length: 33 }, (_, i) => [cx + r * Math.cos(i / 32 * 2 * Math.PI), cy + r * Math.sin(i / 32 * 2 * Math.PI)]);
|
|
31740
|
+
}
|
|
31741
|
+
function flare(ink) {
|
|
31742
|
+
const path = [[16.3, 28], [11.8, 7.1], [11.8, 4.9], [12.4, 3.5], [13.2, 3], [14.3, 2.1], [16, 1.9], [17.4, 2.1], [18.5, 2.4], [19.6, 3.2], [20.2, 4.6], [20.4, 5.7], [20.4, 6.9]];
|
|
31743
|
+
const k = 0.9698;
|
|
31744
|
+
const place = ([x, y]) => {
|
|
31745
|
+
const [rx, ry] = turn([(x - 16.3) * 0.9 * FLARE_SCALE, (y - 28) * 0.9 * FLARE_SCALE], 0, 0, 135);
|
|
31746
|
+
return [((rx + 10 - 16.1) * k + 16) * 2 * R, ((ry + 10 - 14.95) * k + 16) * 2 * R];
|
|
31747
|
+
};
|
|
31748
|
+
const t = CLASSIC_MARK_TONES[ink];
|
|
31749
|
+
return { width: S, height: S, pixelRatio: R, ops: [{ fill: path.map(place), c: t.magenta }, { dot: [FLARE_ANCHOR * R, FLARE_ANCHOR * R], r: 2.6 * R, c: t.ink }] };
|
|
31750
|
+
}
|
|
31751
|
+
function disc(ink) {
|
|
31752
|
+
return { width: S, height: S, pixelRatio: R, ops: [{ fill: circle(C0, C0, DISC_RADIUS * R), c: CLASSIC_MARK_TONES[ink].magenta }] };
|
|
31753
|
+
}
|
|
31754
|
+
function buoy(ink, c1, c2, split) {
|
|
31755
|
+
const ops = [];
|
|
31756
|
+
const t = CLASSIC_MARK_TONES[ink];
|
|
31757
|
+
const L = BUOY_LENGTH;
|
|
31758
|
+
const W = BUOY_HALF_WIDTH;
|
|
31759
|
+
const lean = 45;
|
|
31760
|
+
const at = (a, b) => turn([CB + b * R, CB - a * R], CB, CB, lean);
|
|
31761
|
+
const foot = 1.6;
|
|
31762
|
+
const outline = [at(foot, 0), at(foot + L / 2, -W), at(foot + L, 0), at(foot + L / 2, W)];
|
|
31763
|
+
if (split === null) ops.push({ fill: outline, c: paintOf(ink, c1) });
|
|
31764
|
+
else if (split === "h") {
|
|
31765
|
+
ops.push({ fill: [at(foot, 0), at(foot + L / 2, -W), at(foot + L / 2, W)], c: paintOf(ink, c2) });
|
|
31766
|
+
ops.push({ fill: [at(foot + L / 2, -W), at(foot + L, 0), at(foot + L / 2, W)], c: paintOf(ink, c1) });
|
|
31767
|
+
} else {
|
|
31768
|
+
ops.push({ fill: [at(foot, 0), at(foot + L / 2, -W), at(foot + L, 0)], c: paintOf(ink, c1) });
|
|
31769
|
+
ops.push({ fill: [at(foot, 0), at(foot + L, 0), at(foot + L / 2, W)], c: paintOf(ink, c2) });
|
|
31770
|
+
}
|
|
31771
|
+
ops.push({ stroke: [...outline, outline[0]], r: 0.35 * R, c: t.ink });
|
|
31772
|
+
if (split === "v") ops.push({ stroke: [at(foot, 0), at(foot + L, 0)], r: 0.3 * R, c: t.ink });
|
|
31773
|
+
if (split === "h") ops.push({ stroke: [at(foot + L / 2, -W), at(foot + L / 2, W)], r: 0.3 * R, c: t.ink });
|
|
31774
|
+
const ring = circle(CB, CB, 2 * R);
|
|
31775
|
+
ops.push({ fill: ring, c: t.open });
|
|
31776
|
+
ops.push({ stroke: ring, r: 0.35 * R, c: t.ink });
|
|
31777
|
+
return { width: SB, height: SB, pixelRatio: R, ops };
|
|
31778
|
+
}
|
|
31779
|
+
function boardOutline(shape) {
|
|
31780
|
+
const h = BOARD_SIDE / 2 * R;
|
|
31781
|
+
switch (shape) {
|
|
31782
|
+
case "triangle-up":
|
|
31783
|
+
return [[C0 - h, C0 + h * 0.58], [C0 + h, C0 + h * 0.58], [C0, C0 - h * 1.15]];
|
|
31784
|
+
case "triangle-down":
|
|
31785
|
+
return [[C0 - h, C0 - h * 0.58], [C0, C0 + h * 1.15], [C0 + h, C0 - h * 0.58]];
|
|
31786
|
+
case "square":
|
|
31787
|
+
return [[C0 - h * 0.85, C0 - h * 0.85], [C0 + h * 0.85, C0 - h * 0.85], [C0 + h * 0.85, C0 + h * 0.85], [C0 - h * 0.85, C0 + h * 0.85]];
|
|
31788
|
+
case "rhombus":
|
|
31789
|
+
return [[C0, C0 - h * 1.2], [C0 + h * 1.2, C0], [C0, C0 + h * 1.2], [C0 - h * 1.2, C0]];
|
|
31790
|
+
}
|
|
31791
|
+
}
|
|
31792
|
+
function half(pts, axis, first) {
|
|
31793
|
+
const inside = (p) => first ? p[axis] <= C0 : p[axis] >= C0;
|
|
31794
|
+
const out = [];
|
|
31795
|
+
for (let i = 0; i < pts.length; i++) {
|
|
31796
|
+
const a = pts[i];
|
|
31797
|
+
const b = pts[(i + 1) % pts.length];
|
|
31798
|
+
if (inside(a)) out.push(a);
|
|
31799
|
+
if (inside(a) !== inside(b)) {
|
|
31800
|
+
const t = (C0 - a[axis]) / (b[axis] - a[axis]);
|
|
31801
|
+
out.push([a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t]);
|
|
31802
|
+
}
|
|
31803
|
+
}
|
|
31804
|
+
return out;
|
|
31805
|
+
}
|
|
31806
|
+
function chord(pts, axis) {
|
|
31807
|
+
const top = half(pts, axis, true);
|
|
31808
|
+
return top.filter((p) => Math.abs(p[axis] - C0) < 1e-9);
|
|
31809
|
+
}
|
|
31810
|
+
function board(ink, shape, c1, c2, split) {
|
|
31811
|
+
const pts = boardOutline(shape);
|
|
31812
|
+
const ops = [];
|
|
31813
|
+
if (split === null) ops.push({ fill: pts, c: paintOf(ink, c1) });
|
|
31814
|
+
else {
|
|
31815
|
+
const axis = split === "h" ? 1 : 0;
|
|
31816
|
+
ops.push({ fill: half(pts, axis, true), c: paintOf(ink, c1) });
|
|
31817
|
+
ops.push({ fill: half(pts, axis, false), c: paintOf(ink, c2) });
|
|
31818
|
+
}
|
|
31819
|
+
const ink0 = CLASSIC_MARK_TONES[ink].ink;
|
|
31820
|
+
ops.push({ stroke: [...pts, pts[0]], r: 0.45 * R, c: ink0 });
|
|
31821
|
+
if (split !== null) ops.push({ stroke: chord(pts, split === "h" ? 1 : 0), r: 0.3 * R, c: ink0 });
|
|
31822
|
+
return { width: S, height: S, pixelRatio: R, ops };
|
|
31823
|
+
}
|
|
31824
|
+
function classicDrawing(ink, name) {
|
|
31825
|
+
if (name === "flare") return flare(ink);
|
|
31826
|
+
if (name === "disc") return disc(ink);
|
|
31827
|
+
const m = /^(buoy|board-(triangle-up|triangle-down|square|rhombus))-([a-z]+)(?:-([a-z]+)-([hv]))?$/.exec(name);
|
|
31828
|
+
if (!m || !CLASSIC_MARK_NAMES.includes(name)) throw new Error(`classic-marks: no mark ${name}`);
|
|
31829
|
+
const c1 = m[3];
|
|
31830
|
+
const c2 = m[4] ?? m[3];
|
|
31831
|
+
const split = m[5] ?? null;
|
|
31832
|
+
return m[1] === "buoy" ? buoy(ink, c1, c2, split) : board(ink, m[2], c1, c2, split);
|
|
31833
|
+
}
|
|
31834
|
+
function rgba(hex) {
|
|
31835
|
+
return [parseInt(hex.slice(1, 3), 16), parseInt(hex.slice(3, 5), 16), parseInt(hex.slice(5, 7), 16), 255];
|
|
31836
|
+
}
|
|
31837
|
+
function paintDrawing(d) {
|
|
31838
|
+
const p = painter(d.width, d.height);
|
|
31839
|
+
for (const op of d.ops) {
|
|
31840
|
+
if ("fill" in op) p.fill(op.fill, rgba(op.c));
|
|
31841
|
+
else if ("stroke" in op) p.stroke(op.stroke, op.r, rgba(op.c));
|
|
31842
|
+
else p.dot(op.dot[0], op.dot[1], op.r, rgba(op.c));
|
|
31843
|
+
}
|
|
31844
|
+
return p.data();
|
|
31845
|
+
}
|
|
31846
|
+
function drawingSvg(d) {
|
|
31847
|
+
const f = (n) => String(Math.round(n * 100) / 100);
|
|
31848
|
+
const pts = (ps) => ps.map(([x, y]) => `${f(x)},${f(y)}`).join(" ");
|
|
31849
|
+
const body = d.ops.map(
|
|
31850
|
+
(op) => "fill" in op ? `<polygon points="${pts(op.fill)}" fill="${op.c}"/>` : "stroke" in op ? `<polyline points="${pts(op.stroke)}" fill="none" stroke="${op.c}" stroke-width="${f(op.r * 2)}" stroke-linecap="round" stroke-linejoin="round"/>` : `<circle cx="${f(op.dot[0])}" cy="${f(op.dot[1])}" r="${f(op.r)}" fill="${op.c}"/>`
|
|
31851
|
+
).join("");
|
|
31852
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${d.width}" height="${d.height}" viewBox="0 0 ${d.width} ${d.height}">${body}</svg>`;
|
|
31853
|
+
}
|
|
31854
|
+
function classicMarkSvgs(ink) {
|
|
31855
|
+
return CLASSIC_MARK_NAMES.map((name) => {
|
|
31856
|
+
const d = classicDrawing(ink, name);
|
|
31857
|
+
return { id: classicMarkId(ink, name), svg: drawingSvg(d), width: d.width, height: d.height, pixelRatio: d.pixelRatio };
|
|
31858
|
+
});
|
|
31859
|
+
}
|
|
31860
|
+
function classicMarkImage(id) {
|
|
31861
|
+
const ink = classicMarkInk(id);
|
|
31862
|
+
if (!ink) throw new Error(`classic-marks: no mark ${id}`);
|
|
31863
|
+
const d = classicDrawing(ink, id.slice(PREFIX[ink].length));
|
|
31864
|
+
return { id, width: d.width, height: d.height, pixelRatio: d.pixelRatio, data: paintDrawing(d) };
|
|
31865
|
+
}
|
|
31866
|
+
function classicMarkImages(ink) {
|
|
31867
|
+
return CLASSIC_MARK_NAMES.map((name) => classicMarkImage(classicMarkId(ink, name)));
|
|
31868
|
+
}
|
|
31869
|
+
|
|
31392
31870
|
// src/atlas/symbol-families.ts
|
|
31393
|
-
var SYMBOL_FAMILIES = ["s52", "s101", "chrt", "
|
|
31871
|
+
var SYMBOL_FAMILIES = ["s52", "s101", "chrt", "int1", "uschart1"];
|
|
31394
31872
|
var SYMBOL_FAMILY_META = {
|
|
31395
31873
|
s52: {
|
|
31396
31874
|
label: "S-52",
|
|
@@ -31404,32 +31882,908 @@ var SYMBOL_FAMILY_META = {
|
|
|
31404
31882
|
label: "CHRT",
|
|
31405
31883
|
description: "CHRT house set \u2014 colour-true, simplified, badged"
|
|
31406
31884
|
},
|
|
31407
|
-
|
|
31408
|
-
label: "
|
|
31409
|
-
description: "Paper-chart portrayal \u2014 the
|
|
31885
|
+
int1: {
|
|
31886
|
+
label: "INT-1",
|
|
31887
|
+
description: "Paper-chart portrayal \u2014 the IHO INT 1 symbols, as paper charts draw them"
|
|
31888
|
+
},
|
|
31889
|
+
uschart1: {
|
|
31890
|
+
label: "U.S. Chart No. 1",
|
|
31891
|
+
description: "INT-1 with the aids as U.S. Chart No. 1 draws them \u2014 diamond buoys, filled daybeacons"
|
|
31410
31892
|
}
|
|
31411
31893
|
};
|
|
31412
31894
|
function parseSymbolFamily(raw) {
|
|
31413
31895
|
if (!raw) return null;
|
|
31414
31896
|
const lower = raw.toLowerCase();
|
|
31415
|
-
|
|
31897
|
+
const family = SYMBOL_FAMILIES.find((f) => f === lower);
|
|
31898
|
+
if (family) return family;
|
|
31899
|
+
return Object.hasOwn(LEGACY_SYMBOL_FAMILY_ALIASES, lower) ? LEGACY_SYMBOL_FAMILY_ALIASES[lower] : null;
|
|
31416
31900
|
}
|
|
31417
|
-
function iconExpressionForFamily(
|
|
31418
|
-
const s52 = getIconExpression(
|
|
31901
|
+
function iconExpressionForFamily(objectClass5, family, palette = "DAY") {
|
|
31902
|
+
const s52 = getIconExpression(objectClass5);
|
|
31903
|
+
const int1 = RASTER_ATON_CLASSES.includes(objectClass5) ? rasterAtonIconExpression(objectClass5) : s52;
|
|
31419
31904
|
switch (family) {
|
|
31420
31905
|
case "s52":
|
|
31421
31906
|
return s52;
|
|
31422
31907
|
case "s101":
|
|
31423
|
-
return rewriteIconToS101(
|
|
31908
|
+
return rewriteIconToS101(objectClass5 === "DAYMAR" ? daymarkShapeIconExpression() : s52);
|
|
31424
31909
|
case "chrt": {
|
|
31425
|
-
const build = CHRT_ICON_EXPRESSIONS[
|
|
31910
|
+
const build = CHRT_ICON_EXPRESSIONS[objectClass5];
|
|
31426
31911
|
return build ? build() : s52;
|
|
31427
31912
|
}
|
|
31428
|
-
case "
|
|
31429
|
-
return
|
|
31913
|
+
case "int1":
|
|
31914
|
+
return int1;
|
|
31915
|
+
case "uschart1": {
|
|
31916
|
+
const ink = classicInkFor(palette);
|
|
31917
|
+
return ink === null ? int1 : classicIconExpression(objectClass5, ink, int1);
|
|
31918
|
+
}
|
|
31430
31919
|
}
|
|
31431
31920
|
}
|
|
31432
31921
|
|
|
31922
|
+
// src/atlas/look-paper.ts
|
|
31923
|
+
var CLASSIC_TONES = {
|
|
31924
|
+
/** Land. */
|
|
31925
|
+
land: "#ebe2c8",
|
|
31926
|
+
/** The blue tint, to the 18 ft curve. */
|
|
31927
|
+
shallow: "#d8f0f5",
|
|
31928
|
+
/** Deep water: the paper. */
|
|
31929
|
+
deep: "#ffffff",
|
|
31930
|
+
/** The foreshore, and salt marsh. */
|
|
31931
|
+
drying: "#c1d1af",
|
|
31932
|
+
/** Magenta: lights, flares, discs, limits, cautions, red aids. */
|
|
31933
|
+
magenta: "#953699",
|
|
31934
|
+
/** Green aids. */
|
|
31935
|
+
green: "#068b00",
|
|
31936
|
+
/** Black: line-work, lettering, soundings, land contours. */
|
|
31937
|
+
ink: "#000000",
|
|
31938
|
+
/** Depth contours and their values. */
|
|
31939
|
+
contour: "#5f5f5f"
|
|
31940
|
+
};
|
|
31941
|
+
var CLASSIC_BLUE_TO_M = 5.5;
|
|
31942
|
+
var CLASSIC_FONTS = {
|
|
31943
|
+
roman: "Open Sans Regular",
|
|
31944
|
+
italic: "Open Sans Italic",
|
|
31945
|
+
bold: "Open Sans Semibold"
|
|
31946
|
+
};
|
|
31947
|
+
var CLASSIC_IMAGE_NAMES = ["hatch", ...CLASSIC_MARK_NAMES];
|
|
31948
|
+
var PREFIX2 = "chrt-look-cl-";
|
|
31949
|
+
function objectClass3(l) {
|
|
31950
|
+
const m = l.metadata;
|
|
31951
|
+
const c = (typeof m === "object" && m !== null ? m["s52:objectClass"] : void 0) ?? l["source-layer"] ?? "";
|
|
31952
|
+
return String(c).toUpperCase();
|
|
31953
|
+
}
|
|
31954
|
+
var DAY_TO_CLASSIC = {
|
|
31955
|
+
// Land: LANDA, CHRTland's land and its cover but wetland, slopes.
|
|
31956
|
+
"#d4c69d": CLASSIC_TONES.land,
|
|
31957
|
+
"#e6d1a1": CLASSIC_TONES.land,
|
|
31958
|
+
"#bcc5a1": CLASSIC_TONES.land,
|
|
31959
|
+
"#cac6bf": CLASSIC_TONES.land,
|
|
31960
|
+
"#dbd0af": CLASSIC_TONES.land,
|
|
31961
|
+
"#c8b078": CLASSIC_TONES.land,
|
|
31962
|
+
// Marsh.
|
|
31963
|
+
"#b6c0b1": CLASSIC_TONES.drying,
|
|
31964
|
+
// The drying foreshore (DEPIT).
|
|
31965
|
+
"#009678": CLASSIC_TONES.drying,
|
|
31966
|
+
// Inland water and the shallow depth tints (DEPVS, DEPMS, DEPMD) where
|
|
31967
|
+
// other classes use them: lakes, rivers, canals, locks, swept areas.
|
|
31968
|
+
"#7fbfdf": CLASSIC_TONES.shallow,
|
|
31969
|
+
"#a7d4e8": CLASSIC_TONES.shallow,
|
|
31970
|
+
"#cae7f3": CLASSIC_TONES.shallow,
|
|
31971
|
+
"#b9cfdd": CLASSIC_TONES.shallow,
|
|
31972
|
+
// Deep water (DEPDW).
|
|
31973
|
+
"#ecf7fc": CLASSIC_TONES.deep,
|
|
31974
|
+
// Magentas (CHMGD, CHMGF).
|
|
31975
|
+
"#d200d2": CLASSIC_TONES.magenta,
|
|
31976
|
+
"#c545c3": CLASSIC_TONES.magenta,
|
|
31977
|
+
// Brown structures (CHBRN): buildings, bridges, dams, in black.
|
|
31978
|
+
"#ab7948": CLASSIC_TONES.ink,
|
|
31979
|
+
// Black and the near-blacks of the lettering.
|
|
31980
|
+
"#000000": CLASSIC_TONES.ink,
|
|
31981
|
+
"#1a1d23": CLASSIC_TONES.ink,
|
|
31982
|
+
"#4a5560": CLASSIC_TONES.ink,
|
|
31983
|
+
"#5b4f3a": CLASSIC_TONES.ink,
|
|
31984
|
+
"#bfa88a": CLASSIC_TONES.ink,
|
|
31985
|
+
// Depth contours and area outlines.
|
|
31986
|
+
"#555555": CLASSIC_TONES.contour,
|
|
31987
|
+
// CHRTland's contours: black, as the paper chart's.
|
|
31988
|
+
"#958666": CLASSIC_TONES.ink,
|
|
31989
|
+
"#78694b": CLASSIC_TONES.ink
|
|
31990
|
+
};
|
|
31991
|
+
function recolour(v) {
|
|
31992
|
+
if (typeof v === "string") return DAY_TO_CLASSIC[v.toLowerCase()] ?? v;
|
|
31993
|
+
if (Array.isArray(v)) return v.map(recolour);
|
|
31994
|
+
return v;
|
|
31995
|
+
}
|
|
31996
|
+
var WATER_TEXT = /* @__PURE__ */ new Set(["SEAARE", "DEPCNT", "RIVERS", "LAKARE", "CANALS", "SBDARE", "WEDKLP", "DRGARE", "FAIRWY", "ACHARE"]);
|
|
31997
|
+
var LAND_NAMES = /^s52-(LNDARE|LNDRGN)-label-/;
|
|
31998
|
+
var SPACED_CAPS = /^s52-(SEAARE|LNDARE|LNDRGN)-label-.*-major$/;
|
|
31999
|
+
var INK_FILLS = /* @__PURE__ */ new Set(["BUISGL"]);
|
|
32000
|
+
var STRUCTURE_FILLS = /* @__PURE__ */ new Set(["SLCONS", "PONTON", "FLODOC", "DRYDOC", "BRIDGE", "PYLONS", "DAMCON", "GATCON", "FORSTC"]);
|
|
32001
|
+
var UNTINTED = /* @__PURE__ */ new Set([
|
|
32002
|
+
"ACHARE",
|
|
32003
|
+
"FAIRWY",
|
|
32004
|
+
"TSSLPT",
|
|
32005
|
+
"TSSRON",
|
|
32006
|
+
"ISTZNE",
|
|
32007
|
+
"PRCARE",
|
|
32008
|
+
"DMPGRD",
|
|
32009
|
+
"HRBARE",
|
|
32010
|
+
"TERMNL",
|
|
32011
|
+
"HRBFAC",
|
|
32012
|
+
"PILBOP",
|
|
32013
|
+
"RECTRC",
|
|
32014
|
+
"SBDARE",
|
|
32015
|
+
"AIRARE",
|
|
32016
|
+
"RUNWAY",
|
|
32017
|
+
"MARCUL",
|
|
32018
|
+
"FSHFAC",
|
|
32019
|
+
"OSPARE",
|
|
32020
|
+
"LOGPON",
|
|
32021
|
+
"SWPARE",
|
|
32022
|
+
"CBLARE",
|
|
32023
|
+
"PIPARE",
|
|
32024
|
+
"BUAARE"
|
|
32025
|
+
]);
|
|
32026
|
+
var AIDS = /* @__PURE__ */ new Set([
|
|
32027
|
+
"BOYLAT",
|
|
32028
|
+
"BOYCAR",
|
|
32029
|
+
"BOYISD",
|
|
32030
|
+
"BOYSAW",
|
|
32031
|
+
"BOYSPP",
|
|
32032
|
+
"BOYINB",
|
|
32033
|
+
"BCNLAT",
|
|
32034
|
+
"BCNCAR",
|
|
32035
|
+
"BCNISD",
|
|
32036
|
+
"BCNSAW",
|
|
32037
|
+
"BCNSPP",
|
|
32038
|
+
"LIGHTS",
|
|
32039
|
+
"LITFLT",
|
|
32040
|
+
"LITVES",
|
|
32041
|
+
"FOGSIG",
|
|
32042
|
+
"RTPBCN",
|
|
32043
|
+
"RDOSTA"
|
|
32044
|
+
]);
|
|
32045
|
+
function depthTint() {
|
|
32046
|
+
const d1 = ["coalesce", ["get", "DRVAL1"], ["get", "drval1"], -1];
|
|
32047
|
+
const d2 = ["coalesce", ["get", "DRVAL2"], ["get", "drval2"], 0];
|
|
32048
|
+
const deepest = ["coalesce", ["get", "DRVAL2"], ["get", "drval2"], d1];
|
|
32049
|
+
return [
|
|
32050
|
+
"case",
|
|
32051
|
+
["all", ["<", d1, 0], ["<=", d2, 0]],
|
|
32052
|
+
CLASSIC_TONES.drying,
|
|
32053
|
+
["<=", deepest, CLASSIC_BLUE_TO_M + 0.05],
|
|
32054
|
+
CLASSIC_TONES.shallow,
|
|
32055
|
+
CLASSIC_TONES.deep
|
|
32056
|
+
];
|
|
32057
|
+
}
|
|
32058
|
+
function withClassic(style) {
|
|
32059
|
+
const out = [];
|
|
32060
|
+
for (const layer of style.layers) {
|
|
32061
|
+
const cls = objectClass3(layer);
|
|
32062
|
+
const paint = {};
|
|
32063
|
+
for (const [k, v] of Object.entries(layer.paint ?? {})) paint[k] = /color$/.test(k) ? recolour(v) : v;
|
|
32064
|
+
const layout = { ...layer.layout ?? {} };
|
|
32065
|
+
switch (layer.type) {
|
|
32066
|
+
case "fill":
|
|
32067
|
+
if (INK_FILLS.has(cls)) {
|
|
32068
|
+
paint["fill-pattern"] = `${PREFIX2}hatch`;
|
|
32069
|
+
paint["fill-opacity"] = 1;
|
|
32070
|
+
} else if (cls === "DEPARE" && /-fill-band\d$/.test(layer.id)) {
|
|
32071
|
+
paint["fill-color"] = depthTint();
|
|
32072
|
+
} else if (cls === "DRGARE" && /-fill-band\d$/.test(layer.id)) {
|
|
32073
|
+
paint["fill-color"] = CLASSIC_TONES.deep;
|
|
32074
|
+
} else if (STRUCTURE_FILLS.has(cls)) {
|
|
32075
|
+
paint["fill-color"] = CLASSIC_TONES.land;
|
|
32076
|
+
paint["fill-opacity"] = 1;
|
|
32077
|
+
} else if (UNTINTED.has(cls)) {
|
|
32078
|
+
paint["fill-opacity"] = 0;
|
|
32079
|
+
delete paint["fill-pattern"];
|
|
32080
|
+
}
|
|
32081
|
+
break;
|
|
32082
|
+
case "line":
|
|
32083
|
+
if (layer.id === "chrtland-road") {
|
|
32084
|
+
out.push(...doubleRoad({ ...layer, paint, layout }));
|
|
32085
|
+
continue;
|
|
32086
|
+
}
|
|
32087
|
+
if (cls === "COALNE" || cls === "SLCONS") paint["line-color"] = CLASSIC_TONES.ink;
|
|
32088
|
+
if (cls === "DEPCNT") paint["line-width"] = 0.6;
|
|
32089
|
+
if (cls === "DRGARE" && /-boundary-/.test(layer.id)) {
|
|
32090
|
+
Object.assign(paint, { "line-color": CLASSIC_TONES.ink, "line-width": 1.1, "line-opacity": 0.8, "line-dasharray": [8, 6] });
|
|
32091
|
+
}
|
|
32092
|
+
break;
|
|
32093
|
+
case "symbol":
|
|
32094
|
+
if (paint["text-color"] !== void 0) paint["text-color"] = recolour(paint["text-color"]);
|
|
32095
|
+
if (paint["text-halo-width"] !== void 0) paint["text-halo-width"] = 0;
|
|
32096
|
+
if (layout["text-font"] !== void 0) {
|
|
32097
|
+
const was = JSON.stringify(layout["text-font"]);
|
|
32098
|
+
const italic = WATER_TEXT.has(cls) || AIDS.has(cls) && /-label/.test(layer.id) || was.includes("Italic");
|
|
32099
|
+
layout["text-font"] = [italic ? CLASSIC_FONTS.italic : SPACED_CAPS.test(layer.id) ? CLASSIC_FONTS.bold : CLASSIC_FONTS.roman];
|
|
32100
|
+
if (cls === "LIGHTS" && /-label/.test(layer.id)) layout["text-font"] = ["case", HAS_HEIGHT, ["literal", [CLASSIC_FONTS.roman]], ["literal", [CLASSIC_FONTS.italic]]];
|
|
32101
|
+
if (SPACED_CAPS.test(layer.id)) {
|
|
32102
|
+
layout["text-transform"] = "uppercase";
|
|
32103
|
+
layout["text-letter-spacing"] = 0.25;
|
|
32104
|
+
} else if (LAND_NAMES.test(layer.id)) {
|
|
32105
|
+
layout["text-letter-spacing"] = 0.12;
|
|
32106
|
+
}
|
|
32107
|
+
if (cls === "SOUNDG") paint["text-color"] = CLASSIC_TONES.ink;
|
|
32108
|
+
if (cls === "DEPCNT") {
|
|
32109
|
+
paint["text-color"] = CLASSIC_TONES.contour;
|
|
32110
|
+
layout["text-field"] = withoutUnit(layout["text-field"]);
|
|
32111
|
+
}
|
|
32112
|
+
}
|
|
32113
|
+
break;
|
|
32114
|
+
}
|
|
32115
|
+
out.push({ ...layer, paint, ...Object.keys(layout).length > 0 ? { layout } : {} });
|
|
32116
|
+
}
|
|
32117
|
+
return withClassicMarks({
|
|
32118
|
+
...style,
|
|
32119
|
+
layers: out,
|
|
32120
|
+
metadata: { ...typeof style.metadata === "object" && style.metadata !== null ? style.metadata : {}, "chrt:look": "paper" }
|
|
32121
|
+
}, "color");
|
|
32122
|
+
}
|
|
32123
|
+
function withoutUnit(field) {
|
|
32124
|
+
if (Array.isArray(field) && field[0] === "concat" && field.length === 3 && (field[2] === "ft" || field[2] === "m")) return ["to-string", field[1]];
|
|
32125
|
+
return field;
|
|
32126
|
+
}
|
|
32127
|
+
function scaled(v, f) {
|
|
32128
|
+
if (typeof v === "number") return v * f;
|
|
32129
|
+
if (Array.isArray(v) && (v[0] === "interpolate" || v[0] === "step")) {
|
|
32130
|
+
const head = v[0] === "interpolate" ? 3 : 2;
|
|
32131
|
+
return v.map((e, i) => i >= head && (i - head) % 2 === 1 || v[0] === "step" && i === 2 ? scaled(e, f) : e);
|
|
32132
|
+
}
|
|
32133
|
+
return ["*", v, f];
|
|
32134
|
+
}
|
|
32135
|
+
function doubleRoad(l) {
|
|
32136
|
+
const w = l.paint?.["line-width"] ?? 1;
|
|
32137
|
+
return [
|
|
32138
|
+
{ ...l, paint: { "line-color": CLASSIC_TONES.ink, "line-width": scaled(w, 1.6), "line-opacity": 1 } },
|
|
32139
|
+
{ ...l, id: `${l.id}-look-core`, paint: { "line-color": CLASSIC_TONES.land, "line-width": scaled(w, 0.8), "line-opacity": 1 } }
|
|
32140
|
+
];
|
|
32141
|
+
}
|
|
32142
|
+
var HATCH_RATIO = 4;
|
|
32143
|
+
function hatch() {
|
|
32144
|
+
const d = 12;
|
|
32145
|
+
const w = d * 2;
|
|
32146
|
+
const half2 = 0.9;
|
|
32147
|
+
const data = new Uint8Array(w * w * 4);
|
|
32148
|
+
for (let y = 0; y < w; y++) {
|
|
32149
|
+
for (let x = 0; x < w; x++) {
|
|
32150
|
+
const t = (x + y + 1) % d;
|
|
32151
|
+
const dist = Math.min(t, d - t) / Math.SQRT2;
|
|
32152
|
+
const cov = Math.max(0, Math.min(1, half2 + 0.5 - dist));
|
|
32153
|
+
data[(y * w + x) * 4 + 3] = Math.round(cov * 255);
|
|
32154
|
+
}
|
|
32155
|
+
}
|
|
32156
|
+
return { size: w, data };
|
|
32157
|
+
}
|
|
32158
|
+
function classicImages() {
|
|
32159
|
+
const h = hatch();
|
|
32160
|
+
return [
|
|
32161
|
+
{ name: "hatch", width: h.size, height: h.size, pixelRatio: HATCH_RATIO, data: h.data },
|
|
32162
|
+
...classicMarkImages("color").map((i) => ({ name: i.id.slice(PREFIX2.length), width: i.width, height: i.height, pixelRatio: i.pixelRatio, data: i.data }))
|
|
32163
|
+
];
|
|
32164
|
+
}
|
|
32165
|
+
|
|
32166
|
+
// src/atlas/look-wash-tones.ts
|
|
32167
|
+
var SHALLOW_M = 5.49;
|
|
32168
|
+
var WASH_TONES = {
|
|
32169
|
+
paper: [250, 244, 222],
|
|
32170
|
+
land: [165, 186, 118],
|
|
32171
|
+
// A clear light blue against the shore (owner, 2026-11-02): the 1860 sheet's grey-blue read grey-green on the cream.
|
|
32172
|
+
water: [128, 178, 222],
|
|
32173
|
+
flat: [226, 206, 150],
|
|
32174
|
+
town: [186, 72, 52],
|
|
32175
|
+
road: [192, 124, 72]
|
|
32176
|
+
};
|
|
32177
|
+
function washOver(under, tone, a) {
|
|
32178
|
+
const k = Math.max(0, Math.min(1, a));
|
|
32179
|
+
return [0, 1, 2].map((i) => under[i] * (1 - k * (1 - tone[i] / 255)));
|
|
32180
|
+
}
|
|
32181
|
+
function rgbHex(rgb) {
|
|
32182
|
+
return `#${rgb.map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0")).join("")}`;
|
|
32183
|
+
}
|
|
32184
|
+
var WASH_TINTS = (() => {
|
|
32185
|
+
const paper = WASH_TONES.paper;
|
|
32186
|
+
const land = washOver(paper, WASH_TONES.land, 0.6);
|
|
32187
|
+
return {
|
|
32188
|
+
paper: rgbHex(paper),
|
|
32189
|
+
land: rgbHex(land),
|
|
32190
|
+
/** Water to the 18 ft curve. */
|
|
32191
|
+
shallow: rgbHex(washOver(paper, WASH_TONES.water, 0.4)),
|
|
32192
|
+
/** A pond or lake. */
|
|
32193
|
+
lake: rgbHex(washOver(paper, WASH_TONES.water, 0.26)),
|
|
32194
|
+
/** Drying flats. */
|
|
32195
|
+
flat: rgbHex(washOver(paper, WASH_TONES.flat, 0.375)),
|
|
32196
|
+
/** A town, laid over the land. */
|
|
32197
|
+
town: rgbHex(washOver(land, WASH_TONES.town, 0.42)),
|
|
32198
|
+
/** A road's core, over the land. */
|
|
32199
|
+
road: rgbHex(washOver(land, WASH_TONES.road, 0.45))
|
|
32200
|
+
};
|
|
32201
|
+
})();
|
|
32202
|
+
|
|
32203
|
+
// src/atlas/chart-look.ts
|
|
32204
|
+
var CHART_LOOKS = ["paper", "engraved", "handcolored"];
|
|
32205
|
+
var ENGRAVED_LOOKS = ["engraved", "handcolored"];
|
|
32206
|
+
function isEngravedLook(look) {
|
|
32207
|
+
return look === "engraved" || look === "handcolored";
|
|
32208
|
+
}
|
|
32209
|
+
function parseChartLook(raw) {
|
|
32210
|
+
if (!raw) return null;
|
|
32211
|
+
const lower = raw.toLowerCase();
|
|
32212
|
+
return CHART_LOOKS.find((l) => l === lower) ?? null;
|
|
32213
|
+
}
|
|
32214
|
+
function styleLook(style) {
|
|
32215
|
+
const m = style?.metadata?.["chrt:look"];
|
|
32216
|
+
return typeof m === "string" ? parseChartLook(m) : null;
|
|
32217
|
+
}
|
|
32218
|
+
var LOOK_TONES = {
|
|
32219
|
+
// Black on white: the sheet prints in black alone (DeviceGray).
|
|
32220
|
+
engraved: { ink: "#000000", paper: "#ffffff" },
|
|
32221
|
+
// The 1860 sheet's ink, a warm black (#382d20, sampled), on white; the wash,
|
|
32222
|
+
// multiplied over it, tones the paper and colours the land and water
|
|
32223
|
+
// (look-wash-tones.ts WASH_TONES).
|
|
32224
|
+
handcolored: { ink: "#382d20", paper: "#ffffff" }
|
|
32225
|
+
};
|
|
32226
|
+
var LOOK_FONTS = {
|
|
32227
|
+
roman: "Old Standard TT Regular",
|
|
32228
|
+
italic: "Old Standard TT Italic",
|
|
32229
|
+
bold: "Old Standard TT Bold"
|
|
32230
|
+
};
|
|
32231
|
+
var LOOK_WATERLINES_SOURCE = "chrt-look-waterlines";
|
|
32232
|
+
var LOOK_IMAGE_NAMES = [
|
|
32233
|
+
"stipple-flats",
|
|
32234
|
+
"stipple-1fm",
|
|
32235
|
+
"stipple-2fm",
|
|
32236
|
+
"stipple-3fm",
|
|
32237
|
+
"marsh",
|
|
32238
|
+
"woods",
|
|
32239
|
+
// The Survey's symbols (lookSymbols).
|
|
32240
|
+
"buoy-nun-red",
|
|
32241
|
+
"buoy-nun-green",
|
|
32242
|
+
"buoy-nun-black",
|
|
32243
|
+
"buoy-nun-yellow",
|
|
32244
|
+
"buoy-can-red",
|
|
32245
|
+
"buoy-can-green",
|
|
32246
|
+
"buoy-can-black",
|
|
32247
|
+
"buoy-can-yellow",
|
|
32248
|
+
"buoy-spar-red",
|
|
32249
|
+
"buoy-spar-green",
|
|
32250
|
+
"buoy-spar-black",
|
|
32251
|
+
"buoy-spar-yellow",
|
|
32252
|
+
"buoy-other-red",
|
|
32253
|
+
"buoy-other-green",
|
|
32254
|
+
"buoy-other-black",
|
|
32255
|
+
"buoy-other-yellow",
|
|
32256
|
+
"beacon",
|
|
32257
|
+
"light",
|
|
32258
|
+
"light-major",
|
|
32259
|
+
"lightship",
|
|
32260
|
+
"landmark",
|
|
32261
|
+
"anchor",
|
|
32262
|
+
"fog"
|
|
32263
|
+
];
|
|
32264
|
+
var IMAGE_PREFIX = { engraved: "chrt-look-en-", handcolored: "chrt-look-hc-", paper: "chrt-look-cl-" };
|
|
32265
|
+
function lookImageId(look, name) {
|
|
32266
|
+
return IMAGE_PREFIX[look] + name;
|
|
32267
|
+
}
|
|
32268
|
+
function imageNames(look) {
|
|
32269
|
+
return look === "paper" ? CLASSIC_IMAGE_NAMES : LOOK_IMAGE_NAMES;
|
|
32270
|
+
}
|
|
32271
|
+
function lookOfImageId(id) {
|
|
32272
|
+
for (const look of Object.keys(IMAGE_PREFIX)) {
|
|
32273
|
+
if (id.startsWith(IMAGE_PREFIX[look]) && imageNames(look).includes(id.slice(IMAGE_PREFIX[look].length))) return look;
|
|
32274
|
+
}
|
|
32275
|
+
return null;
|
|
32276
|
+
}
|
|
32277
|
+
var FATHOM_M = 1.8288;
|
|
32278
|
+
var LINE_FINENESS = 0.62;
|
|
32279
|
+
var LINE_MAX = 1.15;
|
|
32280
|
+
var WATER_TEXT2 = /* @__PURE__ */ new Set(["SEAARE", "DEPCNT", "RIVERS", "LAKARE", "CANALS", "SBDARE", "WEDKLP", "DRGARE", "FAIRWY"]);
|
|
32281
|
+
var SPACED_CAPS2 = /^s52-(SEAARE|LNDARE|LNDRGN)-label-.*-major$/;
|
|
32282
|
+
var LAND_FILLS = /* @__PURE__ */ new Set(["LNDARE", "SLCONS", "PONTON", "HULKES", "FLODOC", "DRYDOC", "BRIDGE", "CAUSWY", "DYKCON", "LOKBSN", "BUAARE"]);
|
|
32283
|
+
var INK_FILLS2 = /* @__PURE__ */ new Set(["BUISGL"]);
|
|
32284
|
+
var DROPPED2 = /^s52-LIGHTS-lamp-(glow|core)$/;
|
|
32285
|
+
function objectClass4(l) {
|
|
32286
|
+
const m = l.metadata;
|
|
32287
|
+
const c = (typeof m === "object" && m !== null ? m["s52:objectClass"] : void 0) ?? l["source-layer"] ?? "";
|
|
32288
|
+
return String(c).toUpperCase();
|
|
32289
|
+
}
|
|
32290
|
+
function luminance(c) {
|
|
32291
|
+
let r, g2, b;
|
|
32292
|
+
const hex = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(c);
|
|
32293
|
+
if (hex) {
|
|
32294
|
+
const h = hex[1].length === 3 ? [...hex[1]].map((d) => d + d).join("") : hex[1];
|
|
32295
|
+
r = parseInt(h.slice(0, 2), 16);
|
|
32296
|
+
g2 = parseInt(h.slice(2, 4), 16);
|
|
32297
|
+
b = parseInt(h.slice(4, 6), 16);
|
|
32298
|
+
} else {
|
|
32299
|
+
const rgb = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i.exec(c);
|
|
32300
|
+
if (!rgb) return null;
|
|
32301
|
+
r = Number(rgb[1]);
|
|
32302
|
+
g2 = Number(rgb[2]);
|
|
32303
|
+
b = Number(rgb[3]);
|
|
32304
|
+
}
|
|
32305
|
+
return (0.2126 * r + 0.7152 * g2 + 0.0722 * b) / 255;
|
|
32306
|
+
}
|
|
32307
|
+
function mapColours(v, to) {
|
|
32308
|
+
if (typeof v === "string") {
|
|
32309
|
+
const lum = luminance(v);
|
|
32310
|
+
return lum === null ? v : to(lum);
|
|
32311
|
+
}
|
|
32312
|
+
if (Array.isArray(v)) return v.map((e) => mapColours(e, to));
|
|
32313
|
+
return v;
|
|
32314
|
+
}
|
|
32315
|
+
function scaled2(v, f, max = Infinity) {
|
|
32316
|
+
if (typeof v === "number") return Math.min(v * f, max);
|
|
32317
|
+
if (Array.isArray(v) && v[0] === "interpolate" && Array.isArray(v[2]) && v[2][0] === "zoom") {
|
|
32318
|
+
return [v[0], v[1], v[2], ...v.slice(3).map((e, i) => i % 2 === 1 ? scaled2(e, f, max) : e)];
|
|
32319
|
+
}
|
|
32320
|
+
if (Array.isArray(v) && v[0] === "step" && Array.isArray(v[1]) && v[1][0] === "zoom") {
|
|
32321
|
+
return [v[0], v[1], scaled2(v[2], f, max), ...v.slice(3).map((e, i) => i % 2 === 1 ? scaled2(e, f, max) : e)];
|
|
32322
|
+
}
|
|
32323
|
+
if (v === void 0) return v;
|
|
32324
|
+
return max === Infinity ? ["*", v, f] : ["min", ["*", v, f], max];
|
|
32325
|
+
}
|
|
32326
|
+
function washTint(cls, id, tints) {
|
|
32327
|
+
if (cls === "DEPARE" && /^s52-DEPARE-fill-band\d$/.test(id)) {
|
|
32328
|
+
const d1 = ["coalesce", ["get", "DRVAL1"], ["get", "drval1"], 0];
|
|
32329
|
+
const d2 = ["coalesce", ["get", "DRVAL2"], ["get", "drval2"], 99];
|
|
32330
|
+
return ["case", ["<", d1, 0], tints.flat, ["<=", d2, SHALLOW_M + 0.01], tints.shallow, tints.paper];
|
|
32331
|
+
}
|
|
32332
|
+
if (cls === "LAKARE" || id === "chrtland-water" || id === "paper-base-lakes") return tints.lake;
|
|
32333
|
+
return null;
|
|
32334
|
+
}
|
|
32335
|
+
function withLook(style, look, opts = {}) {
|
|
32336
|
+
if (look === "paper") return withClassic(style);
|
|
32337
|
+
const tone = LOOK_TONES[look];
|
|
32338
|
+
const ink = tone.ink;
|
|
32339
|
+
const tints = look === "handcolored" && opts.tints !== false ? WASH_TINTS : null;
|
|
32340
|
+
const paper = tints ? tints.paper : tone.paper;
|
|
32341
|
+
const lineInk = (lum) => lum > 0.92 ? paper : ink;
|
|
32342
|
+
const out = [];
|
|
32343
|
+
for (const layer of style.layers) {
|
|
32344
|
+
if (DROPPED2.test(layer.id)) continue;
|
|
32345
|
+
const cls = objectClass4(layer);
|
|
32346
|
+
const paint = { ...layer.paint ?? {} };
|
|
32347
|
+
const layout = { ...layer.layout ?? {} };
|
|
32348
|
+
let next = layer;
|
|
32349
|
+
switch (layer.type) {
|
|
32350
|
+
case "background":
|
|
32351
|
+
paint["background-color"] = paper;
|
|
32352
|
+
break;
|
|
32353
|
+
case "hillshade":
|
|
32354
|
+
continue;
|
|
32355
|
+
case "fill": {
|
|
32356
|
+
if (paint["fill-pattern"] !== void 0) break;
|
|
32357
|
+
const land = LAND_FILLS.has(cls) || layer.id === "chrtland-base" || layer.id === "paper-base-earth";
|
|
32358
|
+
const wash = tints ? washTint(cls, layer.id, tints) : null;
|
|
32359
|
+
if (INK_FILLS2.has(cls) || land) {
|
|
32360
|
+
paint["fill-color"] = INK_FILLS2.has(cls) ? ink : tints ? cls === "BUAARE" ? tints.town : tints.land : paper;
|
|
32361
|
+
paint["fill-opacity"] = 1;
|
|
32362
|
+
} else if (wash !== null) {
|
|
32363
|
+
paint["fill-color"] = wash;
|
|
32364
|
+
paint["fill-opacity"] = 1;
|
|
32365
|
+
} else {
|
|
32366
|
+
paint["fill-opacity"] = 0;
|
|
32367
|
+
}
|
|
32368
|
+
if (paint["fill-outline-color"] !== void 0) paint["fill-outline-color"] = ink;
|
|
32369
|
+
break;
|
|
32370
|
+
}
|
|
32371
|
+
case "line":
|
|
32372
|
+
if (paint["line-pattern"] !== void 0 && layer.source !== void 0 && layer.source !== "CHRT_LAND") {
|
|
32373
|
+
delete paint["line-pattern"];
|
|
32374
|
+
paint["line-color"] = ink;
|
|
32375
|
+
paint["line-width"] = 0.55;
|
|
32376
|
+
paint["line-dasharray"] = [5, 2.5];
|
|
32377
|
+
break;
|
|
32378
|
+
}
|
|
32379
|
+
if (paint["line-color"] !== void 0) paint["line-color"] = mapColours(paint["line-color"], lineInk);
|
|
32380
|
+
if (paint["line-width"] !== void 0 && layer.id !== "chrtland-road") paint["line-width"] = scaled2(paint["line-width"], LINE_FINENESS, LINE_MAX);
|
|
32381
|
+
if (cls === "DEPCNT" || cls === "DEPARE" && /-outline-/.test(layer.id)) {
|
|
32382
|
+
paint["line-dasharray"] = [0.6, 2.2];
|
|
32383
|
+
layout["line-cap"] = "round";
|
|
32384
|
+
}
|
|
32385
|
+
break;
|
|
32386
|
+
case "circle":
|
|
32387
|
+
if (paint["circle-color"] !== void 0) paint["circle-color"] = mapColours(paint["circle-color"], (lum) => lum < 0.35 ? ink : paper);
|
|
32388
|
+
if (paint["circle-stroke-color"] !== void 0) paint["circle-stroke-color"] = ink;
|
|
32389
|
+
break;
|
|
32390
|
+
case "symbol":
|
|
32391
|
+
if (paint["text-color"] !== void 0) paint["text-color"] = mapColours(paint["text-color"], lineInk);
|
|
32392
|
+
if (paint["text-halo-color"] !== void 0) paint["text-halo-color"] = paper;
|
|
32393
|
+
if (layout["text-font"] !== void 0) {
|
|
32394
|
+
const italic = WATER_TEXT2.has(cls) || JSON.stringify(layout["text-font"]).includes("Italic");
|
|
32395
|
+
layout["text-font"] = [italic ? LOOK_FONTS.italic : LOOK_FONTS.roman];
|
|
32396
|
+
if (SPACED_CAPS2.test(layer.id)) {
|
|
32397
|
+
layout["text-transform"] = "uppercase";
|
|
32398
|
+
layout["text-letter-spacing"] = 0.14;
|
|
32399
|
+
}
|
|
32400
|
+
}
|
|
32401
|
+
if (layout["icon-image"] !== void 0) Object.assign(layout, oldSymbol(layer.id, cls, look, layout));
|
|
32402
|
+
break;
|
|
32403
|
+
}
|
|
32404
|
+
next = { ...layer, paint, ...Object.keys(layout).length > 0 ? { layout } : {} };
|
|
32405
|
+
if (layer.id === "chrtland-cover") {
|
|
32406
|
+
out.push(...landCover(next, look));
|
|
32407
|
+
continue;
|
|
32408
|
+
}
|
|
32409
|
+
if (layer.id === "chrtland-contour" || layer.id === "chrtland-contour-index") {
|
|
32410
|
+
out.push(contourLine(next, look), hachures(next, ink));
|
|
32411
|
+
continue;
|
|
32412
|
+
}
|
|
32413
|
+
if (layer.id === "chrtland-road") {
|
|
32414
|
+
out.push(...doubleRoad2(next, ink, tints ? tints.road : paper));
|
|
32415
|
+
continue;
|
|
32416
|
+
}
|
|
32417
|
+
if (cls === "DEPARE" && layer.type === "fill" && /^s52-DEPARE-fill-band\d$/.test(layer.id)) {
|
|
32418
|
+
out.push(next, flats(next, look));
|
|
32419
|
+
continue;
|
|
32420
|
+
}
|
|
32421
|
+
out.push(next);
|
|
32422
|
+
}
|
|
32423
|
+
const under = /* @__PURE__ */ new Set(["chrt-background", "paper-base-water", "paper-base-earth", "paper-base-lakes", "paper-base-coast", "paper-coverage-ground", "chrtland-base", "chrtland-water"]);
|
|
32424
|
+
let at = 0;
|
|
32425
|
+
for (const [i, l] of out.entries()) if (under.has(l.id) || l.type === "fill" && /^s52-(DEPARE|LNDARE|LAKARE|SEAARE|UNSARE|DRGARE)-fill-band\d$/.test(l.id)) at = i + 1;
|
|
32426
|
+
out.splice(at, 0, {
|
|
32427
|
+
id: LOOK_WATERLINES_SOURCE,
|
|
32428
|
+
type: "line",
|
|
32429
|
+
source: LOOK_WATERLINES_SOURCE,
|
|
32430
|
+
layout: { "line-join": "round", "line-cap": "round" },
|
|
32431
|
+
// Each line's width rides on it (engraving.ts): finer away from the shore.
|
|
32432
|
+
paint: { "line-color": ink, "line-width": ["coalesce", ["get", "w"], 0.3] }
|
|
32433
|
+
});
|
|
32434
|
+
return {
|
|
32435
|
+
...style,
|
|
32436
|
+
// The black & white sheet's symbols, the same INT-1 shapes in black, on
|
|
32437
|
+
// both looks: the day sheet's magenta anchors and light flares read as a
|
|
32438
|
+
// modern chart under the wash.
|
|
32439
|
+
...typeof style.sprite === "string" ? { sprite: style.sprite.replace(/-day$/, "-eink_mono") } : {},
|
|
32440
|
+
sources: {
|
|
32441
|
+
...style.sources,
|
|
32442
|
+
[LOOK_WATERLINES_SOURCE]: { type: "geojson", data: { type: "FeatureCollection", features: [] } }
|
|
32443
|
+
},
|
|
32444
|
+
layers: out,
|
|
32445
|
+
metadata: { ...typeof style.metadata === "object" && style.metadata !== null ? style.metadata : {}, "chrt:look": look }
|
|
32446
|
+
};
|
|
32447
|
+
}
|
|
32448
|
+
function flats(l, look) {
|
|
32449
|
+
const id = (n) => lookImageId(look, n);
|
|
32450
|
+
const d1 = ["coalesce", ["get", "DRVAL1"], ["get", "drval1"], 0];
|
|
32451
|
+
const d2 = ["coalesce", ["get", "DRVAL2"], ["get", "drval2"], 99];
|
|
32452
|
+
return {
|
|
32453
|
+
id: `${l.id}-look-flats`,
|
|
32454
|
+
type: "fill",
|
|
32455
|
+
source: l.source,
|
|
32456
|
+
"source-layer": l["source-layer"],
|
|
32457
|
+
...l.minzoom !== void 0 ? { minzoom: l.minzoom } : {},
|
|
32458
|
+
filter: ["all", l.filter ?? true, ["any", ["<", d1, 0], ["<=", d2, FATHOM_M * 3 + 0.01]]],
|
|
32459
|
+
paint: {
|
|
32460
|
+
"fill-pattern": [
|
|
32461
|
+
"case",
|
|
32462
|
+
["<", d1, 0],
|
|
32463
|
+
id("stipple-flats"),
|
|
32464
|
+
["<=", d2, FATHOM_M + 0.01],
|
|
32465
|
+
id("stipple-1fm"),
|
|
32466
|
+
["<=", d2, FATHOM_M * 2 + 0.01],
|
|
32467
|
+
id("stipple-2fm"),
|
|
32468
|
+
id("stipple-3fm")
|
|
32469
|
+
]
|
|
32470
|
+
},
|
|
32471
|
+
metadata: l.metadata
|
|
32472
|
+
};
|
|
32473
|
+
}
|
|
32474
|
+
function landCover(l, look) {
|
|
32475
|
+
const sign = (cls, image) => ({
|
|
32476
|
+
id: `chrtland-cover-look-${cls}`,
|
|
32477
|
+
type: "fill",
|
|
32478
|
+
source: l.source,
|
|
32479
|
+
"source-layer": l["source-layer"],
|
|
32480
|
+
...l.minzoom !== void 0 ? { minzoom: l.minzoom } : {},
|
|
32481
|
+
filter: ["all", l.filter ?? true, ["==", ["get", "class"], cls]],
|
|
32482
|
+
paint: { "fill-pattern": lookImageId(look, image) }
|
|
32483
|
+
});
|
|
32484
|
+
return [sign("wood", "woods"), sign("wetland", "marsh"), sign("sand", "stipple-2fm")];
|
|
32485
|
+
}
|
|
32486
|
+
function contourLine(l, look) {
|
|
32487
|
+
const index = l.id === "chrtland-contour-index";
|
|
32488
|
+
return {
|
|
32489
|
+
...l,
|
|
32490
|
+
id: `${l.id}-look-line`,
|
|
32491
|
+
paint: {
|
|
32492
|
+
"line-color": look === "handcolored" ? CONTOUR_BROWN : LOOK_TONES[look].ink,
|
|
32493
|
+
"line-width": index ? 0.85 : 0.5,
|
|
32494
|
+
"line-opacity": 0.95
|
|
32495
|
+
},
|
|
32496
|
+
layout: { "line-join": "round", "line-cap": "round" }
|
|
32497
|
+
};
|
|
32498
|
+
}
|
|
32499
|
+
var CONTOUR_BROWN = "#8a5a34";
|
|
32500
|
+
function hachures(l, ink) {
|
|
32501
|
+
const index = l.id === "chrtland-contour-index";
|
|
32502
|
+
const width = index ? 7 : 6.5;
|
|
32503
|
+
return {
|
|
32504
|
+
...l,
|
|
32505
|
+
paint: { "line-color": ink, "line-width": width, "line-dasharray": [0.07, 0.19], "line-opacity": index ? 0.75 : 0.65 },
|
|
32506
|
+
layout: { "line-join": "bevel", "line-cap": "butt" }
|
|
32507
|
+
};
|
|
32508
|
+
}
|
|
32509
|
+
function doubleRoad2(l, ink, paper) {
|
|
32510
|
+
const w = l.paint?.["line-width"] ?? 1;
|
|
32511
|
+
return [
|
|
32512
|
+
{ ...l, paint: { "line-color": ink, "line-width": scaled2(w, 1.4), "line-opacity": 1 } },
|
|
32513
|
+
{ ...l, id: `${l.id}-look-core`, paint: { "line-color": paper, "line-width": scaled2(w, 0.75), "line-opacity": 1 } }
|
|
32514
|
+
];
|
|
32515
|
+
}
|
|
32516
|
+
var BUOYS2 = /* @__PURE__ */ new Set(["BOYLAT", "BOYCAR", "BOYISD", "BOYSAW", "BOYSPP", "BOYINB"]);
|
|
32517
|
+
var BEACONS2 = /* @__PURE__ */ new Set(["BCNLAT", "BCNCAR", "BCNISD", "BCNSAW", "BCNSPP"]);
|
|
32518
|
+
function holds(attr, code) {
|
|
32519
|
+
const v = ["to-string", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], ""]];
|
|
32520
|
+
const c = String(code);
|
|
32521
|
+
return ["any", ["==", v, c], ...[`"${c}"`, `[${c},`, `[${c}]`, `,${c},`, `,${c}]`].map((frag) => [">=", ["index-of", frag, v], 0])];
|
|
32522
|
+
}
|
|
32523
|
+
function buoyColour() {
|
|
32524
|
+
return ["case", holds("COLOUR", 3), "red", holds("COLOUR", 4), "green", holds("COLOUR", 2), "black", "yellow"];
|
|
32525
|
+
}
|
|
32526
|
+
function oldSymbol(id, cls, look, layout) {
|
|
32527
|
+
const img = (name) => typeof name === "string" ? lookImageId(look, name) : ["concat", IMAGE_PREFIX[look], name];
|
|
32528
|
+
if (BUOYS2.has(cls)) {
|
|
32529
|
+
const shape = ["match", ["to-number", ["coalesce", ["get", "BOYSHP"], ["get", "boyshp"], 0], 0], 1, "nun", 2, "can", 5, "spar", "other"];
|
|
32530
|
+
return { "icon-image": img(["concat", "buoy-", shape, "-", buoyColour()]), "icon-offset": [0, 0] };
|
|
32531
|
+
}
|
|
32532
|
+
if (BEACONS2.has(cls)) return { "icon-image": img("beacon"), "icon-offset": [0, 0] };
|
|
32533
|
+
if (cls === "TOPMAR") return { "icon-offset": [6, -18] };
|
|
32534
|
+
if (cls === "LIGHTS" && /-symbol/.test(id)) return { "icon-image": img(/-major/.test(id) ? "light-major" : "light"), "icon-offset": [0, 0], "icon-rotate": 0 };
|
|
32535
|
+
if (cls === "LITFLT" || cls === "LITVES") return { "icon-image": img("lightship"), "icon-offset": [0, 0] };
|
|
32536
|
+
if (cls === "LNDMRK" && /-symbol/.test(id)) return { "icon-image": img("landmark"), "icon-offset": [0, 0] };
|
|
32537
|
+
if (cls === "ACHARE" && /anchor/.test(id)) return { "icon-image": img("anchor") };
|
|
32538
|
+
if (cls === "FOGSIG" && /-symbol/.test(id)) return { "icon-image": img("fog") };
|
|
32539
|
+
void layout;
|
|
32540
|
+
return {};
|
|
32541
|
+
}
|
|
32542
|
+
var PAINT = {
|
|
32543
|
+
red: [184, 69, 47, 255],
|
|
32544
|
+
green: [79, 122, 58, 255],
|
|
32545
|
+
yellow: [214, 176, 72, 255],
|
|
32546
|
+
light: [232, 196, 92, 210]
|
|
32547
|
+
};
|
|
32548
|
+
function lookSymbols(look, ink) {
|
|
32549
|
+
const R2 = 2;
|
|
32550
|
+
const S2 = 64 * R2;
|
|
32551
|
+
const c0 = S2 / 2;
|
|
32552
|
+
const out = [];
|
|
32553
|
+
const coloured = look === "handcolored";
|
|
32554
|
+
const tilt = 28;
|
|
32555
|
+
const line = 0.75 * R2;
|
|
32556
|
+
const B = 1.55;
|
|
32557
|
+
const shapes = {
|
|
32558
|
+
nun: [[0, 0], [-3.2, -6], [0, -16], [3.2, -6]],
|
|
32559
|
+
can: [[-3.4, 0], [-3.4, -9], [3.4, -9], [3.4, 0]],
|
|
32560
|
+
spar: [[-0.9, 0], [-0.9, -16], [0.9, -16], [0.9, 0]],
|
|
32561
|
+
other: Array.from({ length: 20 }, (_, i) => [4.2 * Math.sin(i / 20 * 2 * Math.PI), -5 - 4.6 * Math.cos(i / 20 * 2 * Math.PI)])
|
|
32562
|
+
};
|
|
32563
|
+
for (const shape of ["nun", "can", "spar", "other"]) {
|
|
32564
|
+
for (const colour of ["red", "green", "black", "yellow"]) {
|
|
32565
|
+
const p = painter(S2, S2);
|
|
32566
|
+
const pts = shapes[shape].map(([x, y]) => turn([c0 + x * B * R2, c0 + y * B * R2], c0, c0, tilt));
|
|
32567
|
+
const solid = colour === "black" || colour === "green";
|
|
32568
|
+
if (coloured) p.fill(pts, colour === "black" ? ink : PAINT[colour]);
|
|
32569
|
+
else if (solid) p.fill(pts, ink);
|
|
32570
|
+
p.stroke([...pts, pts[0]], line / 2, ink);
|
|
32571
|
+
p.dot(c0, c0, 1.1 * R2, ink);
|
|
32572
|
+
out.push({ name: `buoy-${shape}-${colour}`, data: p.data(), size: S2 });
|
|
32573
|
+
}
|
|
32574
|
+
}
|
|
32575
|
+
{
|
|
32576
|
+
const p = painter(S2, S2);
|
|
32577
|
+
p.stroke([[c0, c0], [c0, c0 - 22 * R2]], 0.6 * R2, ink);
|
|
32578
|
+
p.dot(c0, c0 - 22 * R2, 2.2 * R2, ink);
|
|
32579
|
+
p.dot(c0, c0, 1.2 * R2, ink);
|
|
32580
|
+
out.push({ name: "beacon", data: p.data(), size: S2 });
|
|
32581
|
+
}
|
|
32582
|
+
for (const [name, r, rays] of [["light", 13, 12], ["light-major", 18, 16]]) {
|
|
32583
|
+
const p = painter(S2, S2);
|
|
32584
|
+
if (coloured) p.dot(c0, c0, r * 0.75 * R2, PAINT.light);
|
|
32585
|
+
for (let i = 0; i < rays; i++) {
|
|
32586
|
+
const a = i / rays * 2 * Math.PI;
|
|
32587
|
+
const len = i % 2 === 0 ? r : r * 0.62;
|
|
32588
|
+
p.stroke([[c0 + Math.cos(a) * 3 * R2, c0 + Math.sin(a) * 3 * R2], [c0 + Math.cos(a) * len * R2, c0 + Math.sin(a) * len * R2]], 0.38 * R2, ink);
|
|
32589
|
+
}
|
|
32590
|
+
p.dot(c0, c0, 2.8 * R2, ink);
|
|
32591
|
+
out.push({ name, data: p.data(), size: S2 });
|
|
32592
|
+
}
|
|
32593
|
+
{
|
|
32594
|
+
const p = painter(S2, S2);
|
|
32595
|
+
const hull = [[-8, 0], [8, 0], [5.5, 3.2], [-5.5, 3.2]].map(([x, y]) => [c0 + x * R2, c0 + y * R2]);
|
|
32596
|
+
p.fill(hull, coloured ? PAINT.red : ink);
|
|
32597
|
+
p.stroke([...hull, hull[0]], 0.35 * R2, ink);
|
|
32598
|
+
p.stroke([[c0, c0], [c0, c0 - 11 * R2]], 0.45 * R2, ink);
|
|
32599
|
+
for (let i = 0; i < 8; i++) {
|
|
32600
|
+
const a = i / 8 * 2 * Math.PI;
|
|
32601
|
+
p.stroke([[c0, c0 - 11 * R2], [c0 + Math.cos(a) * 3.6 * R2, c0 - 11 * R2 + Math.sin(a) * 3.6 * R2]], 0.28 * R2, ink);
|
|
32602
|
+
}
|
|
32603
|
+
out.push({ name: "lightship", data: p.data(), size: S2 });
|
|
32604
|
+
}
|
|
32605
|
+
{
|
|
32606
|
+
const p = painter(S2, S2);
|
|
32607
|
+
const ring = Array.from({ length: 33 }, (_, i) => [c0 + 4.6 * R2 * Math.cos(i / 32 * 2 * Math.PI), c0 + 4.6 * R2 * Math.sin(i / 32 * 2 * Math.PI)]);
|
|
32608
|
+
p.stroke(ring, 0.45 * R2, ink);
|
|
32609
|
+
p.dot(c0, c0, 1.2 * R2, ink);
|
|
32610
|
+
out.push({ name: "landmark", data: p.data(), size: S2 });
|
|
32611
|
+
}
|
|
32612
|
+
{
|
|
32613
|
+
const p = painter(S2, S2);
|
|
32614
|
+
const y0 = c0 - 7 * R2;
|
|
32615
|
+
p.stroke([[c0, y0], [c0, c0 + 7 * R2]], 0.5 * R2, ink);
|
|
32616
|
+
p.stroke([[c0 - 3.5 * R2, y0 + 2.2 * R2], [c0 + 3.5 * R2, y0 + 2.2 * R2]], 0.45 * R2, ink);
|
|
32617
|
+
const ring = Array.from({ length: 17 }, (_, i) => [c0 + 1.3 * R2 * Math.cos(i / 16 * 2 * Math.PI), y0 - 1.3 * R2 + 1.3 * R2 * Math.sin(i / 16 * 2 * Math.PI)]);
|
|
32618
|
+
p.stroke(ring, 0.35 * R2, ink);
|
|
32619
|
+
const arm = Array.from({ length: 13 }, (_, i) => {
|
|
32620
|
+
const a = Math.PI * (0.15 + 0.7 * (i / 12));
|
|
32621
|
+
return [c0 + 5.5 * R2 * Math.cos(a), c0 + 1.5 * R2 + 5.5 * R2 * Math.sin(a)];
|
|
32622
|
+
});
|
|
32623
|
+
p.stroke(arm, 0.5 * R2, ink);
|
|
32624
|
+
p.stroke([arm[0], [arm[0][0] + 1.6 * R2, arm[0][1] - 1.4 * R2]], 0.45 * R2, ink);
|
|
32625
|
+
p.stroke([arm[12], [arm[12][0] - 1.6 * R2, arm[12][1] - 1.4 * R2]], 0.45 * R2, ink);
|
|
32626
|
+
out.push({ name: "anchor", data: p.data(), size: S2 });
|
|
32627
|
+
}
|
|
32628
|
+
{
|
|
32629
|
+
const p = painter(S2, S2);
|
|
32630
|
+
for (const r of [6, 9, 12]) {
|
|
32631
|
+
const arc = Array.from({ length: 13 }, (_, i) => {
|
|
32632
|
+
const a = (-115 + 50 * i / 12) * (Math.PI / 180);
|
|
32633
|
+
return [c0 + r * R2 * Math.cos(a), c0 + r * R2 * Math.sin(a)];
|
|
32634
|
+
});
|
|
32635
|
+
p.stroke(arc, 0.42 * R2, ink);
|
|
32636
|
+
}
|
|
32637
|
+
out.push({ name: "fog", data: p.data(), size: S2 });
|
|
32638
|
+
}
|
|
32639
|
+
return out;
|
|
32640
|
+
}
|
|
32641
|
+
var IMAGE_RATIO = 4;
|
|
32642
|
+
function hash(a, b, seed) {
|
|
32643
|
+
let h = a * 374761393 + b * 668265263 + seed * 2147483647 | 0;
|
|
32644
|
+
h = Math.imul(h ^ h >>> 13, 1274126177);
|
|
32645
|
+
return ((h ^ h >>> 16) >>> 0) / 4294967296;
|
|
32646
|
+
}
|
|
32647
|
+
function canvas(w, h) {
|
|
32648
|
+
const data = new Uint8Array(w * h * 4);
|
|
32649
|
+
const put = (x, y, a) => {
|
|
32650
|
+
const xi = (x % w + w) % w;
|
|
32651
|
+
const yi = (y % h + h) % h;
|
|
32652
|
+
const k = (yi * w + xi) * 4 + 3;
|
|
32653
|
+
data[k] = Math.min(255, Math.max(data[k], Math.round(a * 255)));
|
|
32654
|
+
};
|
|
32655
|
+
const dot = (cx, cy, r, a = 1) => {
|
|
32656
|
+
for (let y = Math.floor(cy - r - 1); y <= Math.ceil(cy + r + 1); y++) {
|
|
32657
|
+
for (let x = Math.floor(cx - r - 1); x <= Math.ceil(cx + r + 1); x++) {
|
|
32658
|
+
const d = Math.hypot(x + 0.5 - cx, y + 0.5 - cy);
|
|
32659
|
+
const cov = Math.max(0, Math.min(1, r + 0.5 - d));
|
|
32660
|
+
if (cov > 0) put(x, y, cov * a);
|
|
32661
|
+
}
|
|
32662
|
+
}
|
|
32663
|
+
};
|
|
32664
|
+
const line = (x0, y0, x1, y1, r) => {
|
|
32665
|
+
const n = Math.max(1, Math.ceil(Math.hypot(x1 - x0, y1 - y0) * 2));
|
|
32666
|
+
for (let i = 0; i <= n; i++) dot(x0 + (x1 - x0) * i / n, y0 + (y1 - y0) * i / n, r);
|
|
32667
|
+
};
|
|
32668
|
+
return { data, dot, line };
|
|
32669
|
+
}
|
|
32670
|
+
function lookImages(look) {
|
|
32671
|
+
if (look === "paper") return classicImages().map((i) => ({ ...i, id: lookImageId("paper", i.name) }));
|
|
32672
|
+
const [ir, ig, ib] = [1, 3, 5].map((i) => parseInt(LOOK_TONES[look].ink.slice(i, i + 2), 16));
|
|
32673
|
+
const finish = (name, w, h, data) => {
|
|
32674
|
+
for (let k = 0; k < data.length; k += 4) {
|
|
32675
|
+
data[k] = ir;
|
|
32676
|
+
data[k + 1] = ig;
|
|
32677
|
+
data[k + 2] = ib;
|
|
32678
|
+
}
|
|
32679
|
+
return { id: lookImageId(look, name), width: w, height: h, pixelRatio: IMAGE_RATIO, data };
|
|
32680
|
+
};
|
|
32681
|
+
const out = [];
|
|
32682
|
+
for (const [id, step, r, seed] of [
|
|
32683
|
+
["stipple-flats", 5, 0.95, 1],
|
|
32684
|
+
["stipple-1fm", 6, 0.9, 2],
|
|
32685
|
+
["stipple-2fm", 8, 0.85, 3],
|
|
32686
|
+
["stipple-3fm", 11, 0.8, 4]
|
|
32687
|
+
]) {
|
|
32688
|
+
const n = 8;
|
|
32689
|
+
const w = step * n;
|
|
32690
|
+
const c = canvas(w, w);
|
|
32691
|
+
for (let j = 0; j < n; j++) for (let i = 0; i < n; i++) {
|
|
32692
|
+
c.dot((i + 0.2 + 0.6 * hash(i, j, seed)) * step, (j + 0.2 + 0.6 * hash(j, i, seed + 7)) * step, r * (0.8 + 0.4 * hash(i, j, seed + 3)));
|
|
32693
|
+
}
|
|
32694
|
+
out.push(finish(id, w, w, c.data));
|
|
32695
|
+
}
|
|
32696
|
+
{
|
|
32697
|
+
const w = 96;
|
|
32698
|
+
const h = 64;
|
|
32699
|
+
const c = canvas(w, h);
|
|
32700
|
+
for (const [x, y] of [[16, 22], [64, 22], [40, 54], [88, 54]]) {
|
|
32701
|
+
c.line(x - 9, y, x + 9, y, 0.55);
|
|
32702
|
+
c.line(x, y, x, y - 9, 0.5);
|
|
32703
|
+
c.line(x - 3, y, x - 7, y - 7, 0.45);
|
|
32704
|
+
c.line(x + 3, y, x + 7, y - 7, 0.45);
|
|
32705
|
+
}
|
|
32706
|
+
out.push(finish("marsh", w, h, c.data));
|
|
32707
|
+
}
|
|
32708
|
+
{
|
|
32709
|
+
const n = 6;
|
|
32710
|
+
const step = 12;
|
|
32711
|
+
const w = n * step;
|
|
32712
|
+
const c = canvas(w, w);
|
|
32713
|
+
for (let j = 0; j < n; j++) for (let i = 0; i < n; i++) {
|
|
32714
|
+
const x = (i + 0.25 + 0.5 * hash(i, j, 31)) * step;
|
|
32715
|
+
const y = (j + 0.25 + 0.5 * hash(j, i, 37)) * step;
|
|
32716
|
+
for (let a = 0; a < 2 * Math.PI; a += 0.25) c.dot(x + 2.4 * Math.cos(a), y + 2.4 * Math.sin(a), 0.4);
|
|
32717
|
+
c.line(x + 1.5, y + 3, x + 3, y + 2.4, 0.55);
|
|
32718
|
+
}
|
|
32719
|
+
out.push(finish("woods", w, w, c.data));
|
|
32720
|
+
}
|
|
32721
|
+
for (const sym of lookSymbols(look, [ir, ig, ib, 255])) {
|
|
32722
|
+
out.push({ id: lookImageId(look, sym.name), width: sym.size, height: sym.size, pixelRatio: 2, data: sym.data });
|
|
32723
|
+
}
|
|
32724
|
+
return out;
|
|
32725
|
+
}
|
|
32726
|
+
function withWaterLines(style, data) {
|
|
32727
|
+
if (!style.sources[LOOK_WATERLINES_SOURCE]) return style;
|
|
32728
|
+
return { ...style, sources: { ...style.sources, [LOOK_WATERLINES_SOURCE]: { type: "geojson", data } } };
|
|
32729
|
+
}
|
|
32730
|
+
|
|
32731
|
+
// src/atlas/style-catalogue.ts
|
|
32732
|
+
var STYLE_THEMES = [
|
|
32733
|
+
{ id: "day", colorTable: "DAY", label: "Day", description: "The S-52 day palette", group: "screen" },
|
|
32734
|
+
{ id: "dusk", colorTable: "DUSK", label: "Dusk", description: "The S-52 dusk palette, dimmed for twilight", group: "screen" },
|
|
32735
|
+
{ id: "night", colorTable: "NIGHT", label: "Night", description: "The S-52 night palette, dark to keep night vision", group: "screen" },
|
|
32736
|
+
{
|
|
32737
|
+
id: "eink_color",
|
|
32738
|
+
colorTable: "EINK_COLOR",
|
|
32739
|
+
label: "E-ink color",
|
|
32740
|
+
description: "For colour e-ink screens: heavier lines and a heavy safety contour",
|
|
32741
|
+
group: "eink"
|
|
32742
|
+
},
|
|
32743
|
+
{
|
|
32744
|
+
id: "eink_mono",
|
|
32745
|
+
colorTable: "EINK_MONO",
|
|
32746
|
+
label: "E-ink",
|
|
32747
|
+
description: "For monochrome e-ink screens: four greys, depth steps by pattern",
|
|
32748
|
+
group: "eink"
|
|
32749
|
+
},
|
|
32750
|
+
{
|
|
32751
|
+
id: "eink_night",
|
|
32752
|
+
colorTable: "EINK_NIGHT",
|
|
32753
|
+
label: "E-ink night",
|
|
32754
|
+
description: "For any e-ink screen at night: the e-ink greys on a black page",
|
|
32755
|
+
group: "eink"
|
|
32756
|
+
}
|
|
32757
|
+
];
|
|
32758
|
+
var STYLE_LOOKS = [
|
|
32759
|
+
{
|
|
32760
|
+
id: "paper",
|
|
32761
|
+
label: "Paper",
|
|
32762
|
+
description: "The U.S. paper chart as last printed: buff land, blue to the 18 ft curve, magenta lights and red aids",
|
|
32763
|
+
colorTable: "DAY",
|
|
32764
|
+
fonts: Object.values(CLASSIC_FONTS)
|
|
32765
|
+
},
|
|
32766
|
+
{
|
|
32767
|
+
id: "engraved",
|
|
32768
|
+
label: "Engraved",
|
|
32769
|
+
description: "The 1860s Coast Survey engraving, in black: stippled shallows, hachured hills, engraved lettering",
|
|
32770
|
+
colorTable: "DAY",
|
|
32771
|
+
fonts: Object.values(LOOK_FONTS)
|
|
32772
|
+
},
|
|
32773
|
+
{
|
|
32774
|
+
id: "handcolored",
|
|
32775
|
+
label: "Hand-colored",
|
|
32776
|
+
description: "The engraving in a warm ink, washed in the colourist's watercolours",
|
|
32777
|
+
colorTable: "DAY",
|
|
32778
|
+
fonts: Object.values(LOOK_FONTS)
|
|
32779
|
+
}
|
|
32780
|
+
];
|
|
32781
|
+
var STYLE_CATALOGUE = {
|
|
32782
|
+
themes: STYLE_THEMES,
|
|
32783
|
+
looks: STYLE_LOOKS,
|
|
32784
|
+
symbolFamilies: SYMBOL_FAMILIES.map((id) => ({ id, ...SYMBOL_FAMILY_META[id] }))
|
|
32785
|
+
};
|
|
32786
|
+
|
|
31433
32787
|
// src/atlas/chart-symbol-sizing.ts
|
|
31434
32788
|
var CHART_SYMBOL_SIZES = ["landLabels", "waterLabels", "depthNumbers", "waypoints", "chartIcons"];
|
|
31435
32789
|
var CHART_SYMBOL_SIZE_WIRE = {
|
|
@@ -31550,7 +32904,10 @@ var SERVED_FONT_STACKS = [
|
|
|
31550
32904
|
"Open Sans Semibold",
|
|
31551
32905
|
"Old Standard TT Regular",
|
|
31552
32906
|
"Old Standard TT Italic",
|
|
31553
|
-
"Old Standard TT Bold"
|
|
32907
|
+
"Old Standard TT Bold",
|
|
32908
|
+
"Liberation Sans Regular",
|
|
32909
|
+
"Liberation Sans Italic",
|
|
32910
|
+
"Liberation Sans Bold"
|
|
31554
32911
|
];
|
|
31555
32912
|
function semiboldFontStack(font) {
|
|
31556
32913
|
if (!Array.isArray(font) || !font.every((face) => typeof face === "string")) return font;
|
|
@@ -31566,9 +32923,9 @@ function factsOf(layer) {
|
|
|
31566
32923
|
const meta = l.metadata ?? {};
|
|
31567
32924
|
const isBasemap = source !== void 0 && BASEMAP_SOURCES.has(source);
|
|
31568
32925
|
const cls = meta["s52:objectClass"];
|
|
31569
|
-
const
|
|
32926
|
+
const objectClass5 = isBasemap ? void 0 : (typeof cls === "string" ? cls : sourceLayer)?.toUpperCase();
|
|
31570
32927
|
const p = meta["chrt:labelPriority"];
|
|
31571
|
-
return { source, sourceLayer, objectClass:
|
|
32928
|
+
return { source, sourceLayer, objectClass: objectClass5, labelPriority: typeof p === "number" ? p : void 0 };
|
|
31572
32929
|
}
|
|
31573
32930
|
function textSliderFor(layer) {
|
|
31574
32931
|
const f = factsOf(layer);
|
|
@@ -32678,8 +34035,41 @@ var SYMBOL_SET_LABELS = {
|
|
|
32678
34035
|
s52: "S-52",
|
|
32679
34036
|
s101: "S-101",
|
|
32680
34037
|
chrt: "House",
|
|
32681
|
-
|
|
34038
|
+
int1: "INT-1",
|
|
34039
|
+
uschart1: "U.S. Chart No. 1"
|
|
34040
|
+
};
|
|
34041
|
+
var SPRITE_SHEET_FAMILY = {
|
|
34042
|
+
s52: "s52",
|
|
34043
|
+
chrt: "chrt",
|
|
34044
|
+
int1: "raster",
|
|
34045
|
+
uschart1: "raster"
|
|
32682
34046
|
};
|
|
34047
|
+
function applySymbolFamily(style, family, palette) {
|
|
34048
|
+
switch (family) {
|
|
34049
|
+
case "s52":
|
|
34050
|
+
return style;
|
|
34051
|
+
case "s101":
|
|
34052
|
+
return applyS101SymbolSet(style);
|
|
34053
|
+
// `palette` is passed so the house dash can resolve its S-52 colour tokens
|
|
34054
|
+
// against the active table — the LC strips it replaces carry their colour in
|
|
34055
|
+
// the sprite, so there is no paint colour left to inherit.
|
|
34056
|
+
case "chrt":
|
|
34057
|
+
return applyChrtSymbolSet(style, palette);
|
|
34058
|
+
case "int1":
|
|
34059
|
+
return applyRasterSymbolSet(style);
|
|
34060
|
+
// INT-1's artwork here; its aids are redrawn once the style is portrayed
|
|
34061
|
+
// (withUsChart1Marks), as CHRTpaper draws them.
|
|
34062
|
+
case "uschart1": {
|
|
34063
|
+
const int1 = applyRasterSymbolSet(style);
|
|
34064
|
+
int1.metadata["chrt:symbol-set"] = "uschart1";
|
|
34065
|
+
return int1;
|
|
34066
|
+
}
|
|
34067
|
+
default: {
|
|
34068
|
+
const unhandled = family;
|
|
34069
|
+
throw new Error(`no symbol family ${String(unhandled)}`);
|
|
34070
|
+
}
|
|
34071
|
+
}
|
|
34072
|
+
}
|
|
32683
34073
|
var DOMINANCE_EXEMPT_CLASSES = /* @__PURE__ */ new Set([
|
|
32684
34074
|
"LNDARE",
|
|
32685
34075
|
// Safety-critical nav-aid point classes (S-52 viewing groups 24020,
|
|
@@ -32784,7 +34174,7 @@ var ORIENTATION_OPACITY_SCALE = {
|
|
|
32784
34174
|
};
|
|
32785
34175
|
var ORIENTATION_OPACITY_MAX = 0.92;
|
|
32786
34176
|
var ORIENTATION_BOOST_MINZOOM = 11;
|
|
32787
|
-
function fanOrientationLabelByCellBand(label, bandFan,
|
|
34177
|
+
function fanOrientationLabelByCellBand(label, bandFan, objectClass5) {
|
|
32788
34178
|
const cellBandExpr = [
|
|
32789
34179
|
"slice",
|
|
32790
34180
|
["coalesce", ["get", "_cell_id"], "??9???"],
|
|
@@ -32792,7 +34182,7 @@ function fanOrientationLabelByCellBand(label, bandFan, objectClass2) {
|
|
|
32792
34182
|
3
|
|
32793
34183
|
];
|
|
32794
34184
|
const variants = [];
|
|
32795
|
-
const scale =
|
|
34185
|
+
const scale = objectClass5 ? ORIENTATION_OPACITY_SCALE[objectClass5] ?? 1 : 1;
|
|
32796
34186
|
for (const code of BAND_DRAW_ORDER) {
|
|
32797
34187
|
const range = BAND_PRIORITY_RANGES[code];
|
|
32798
34188
|
const curve = CELL_BAND_OPACITY_CURVE[code];
|
|
@@ -32956,6 +34346,9 @@ function makeCollapsedChartLabel(label, cascade, requestedSet, lockedBounds) {
|
|
|
32956
34346
|
return collapsed;
|
|
32957
34347
|
}
|
|
32958
34348
|
function generateStyle(palette = "DAY", opts = {}) {
|
|
34349
|
+
if (opts.look !== void 0 && palette !== "DAY") {
|
|
34350
|
+
throw new RangeError(`generateStyle: the ${opts.look} look draws over the DAY palette, not ${palette}`);
|
|
34351
|
+
}
|
|
32959
34352
|
const seafloor = Boolean(opts.seafloor && opts.land) && seafloorLayers(palette).length > 0;
|
|
32960
34353
|
const sources = buildSources({ ...opts, seafloor });
|
|
32961
34354
|
const sourceId = opts.region ?? DEFAULT_REGION;
|
|
@@ -33014,14 +34407,14 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33014
34407
|
const bandFan = opts.bandFan ?? "collapsed";
|
|
33015
34408
|
const lockedBounds = opts.chartMode?.lockedBounds;
|
|
33016
34409
|
const bundles = [];
|
|
33017
|
-
for (const
|
|
33018
|
-
if (META_LAYERS.has(
|
|
34410
|
+
for (const objectClass5 of orderedClasses) {
|
|
34411
|
+
if (META_LAYERS.has(objectClass5)) continue;
|
|
33019
34412
|
bundles.push({
|
|
33020
|
-
objectClass:
|
|
33021
|
-
featureLayers: buildLayersForClass(
|
|
34413
|
+
objectClass: objectClass5,
|
|
34414
|
+
featureLayers: buildLayersForClass(objectClass5, palette, sourceId, {
|
|
33022
34415
|
safetyContour: opts.safetyContour
|
|
33023
34416
|
}),
|
|
33024
|
-
label: buildLabelLayer2(
|
|
34417
|
+
label: buildLabelLayer2(objectClass5, palette, sourceId, opts.depthUnits ?? "meters", {
|
|
33025
34418
|
safetyContour: opts.safetyContour,
|
|
33026
34419
|
twoShadeSoundings: opts.twoShadeSoundings,
|
|
33027
34420
|
soundingFontWeight: opts.soundingFontWeight,
|
|
@@ -33177,17 +34570,17 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33177
34570
|
if (opts.labels === "placename") {
|
|
33178
34571
|
labelLayers.push(...buildPlaceNameLayers(sourceId, palette));
|
|
33179
34572
|
} else {
|
|
33180
|
-
for (const { objectClass:
|
|
34573
|
+
for (const { objectClass: objectClass5, label } of bundles) {
|
|
33181
34574
|
if (!label) continue;
|
|
33182
|
-
if (getLabelBehavior(
|
|
33183
|
-
if (
|
|
34575
|
+
if (getLabelBehavior(objectClass5) === "orientation-cross-band") {
|
|
34576
|
+
if (objectClass5 === "LNDARE" || objectClass5 === "SEAARE") {
|
|
33184
34577
|
const Z = ISLAND_LABEL_HOIST_MINZOOM;
|
|
33185
|
-
const { hoist, watermark } =
|
|
33186
|
-
fanOrientationLabelByCellBand(label, bandFan,
|
|
34578
|
+
const { hoist, watermark } = objectClass5 === "LNDARE" ? splitOrientationFan(
|
|
34579
|
+
fanOrientationLabelByCellBand(label, bandFan, objectClass5),
|
|
33187
34580
|
[">=", ["zoom"], Z],
|
|
33188
34581
|
["<", ["zoom"], Z]
|
|
33189
34582
|
) : splitOrientationFan(
|
|
33190
|
-
fanOrientationLabelByCellBand(label, bandFan,
|
|
34583
|
+
fanOrientationLabelByCellBand(label, bandFan, objectClass5),
|
|
33191
34584
|
["<=", buildSeaAreaTierExpression(), MAJOR_WATER_TIER_MAX],
|
|
33192
34585
|
[">", buildSeaAreaTierExpression(), MAJOR_WATER_TIER_MAX],
|
|
33193
34586
|
{ "text-padding": MAJOR_WATER_TEXT_PADDING }
|
|
@@ -33196,7 +34589,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33196
34589
|
labelLayers.push(...watermark);
|
|
33197
34590
|
continue;
|
|
33198
34591
|
}
|
|
33199
|
-
labelLayers.push(...fanOrientationLabelByCellBand(label, bandFan,
|
|
34592
|
+
labelLayers.push(...fanOrientationLabelByCellBand(label, bandFan, objectClass5));
|
|
33200
34593
|
}
|
|
33201
34594
|
}
|
|
33202
34595
|
}
|
|
@@ -33241,7 +34634,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33241
34634
|
hoistLighthouseNames(labelLayers);
|
|
33242
34635
|
layers.push(...labelLayers);
|
|
33243
34636
|
}
|
|
33244
|
-
const symbolSet = opts.symbolSet ?? "s52";
|
|
34637
|
+
const symbolSet = normalizeSymbolFamily(opts.symbolSet ?? "s52");
|
|
33245
34638
|
const spriteBase = `${opts.tileBaseUrl ?? "https://tiles.chrt.co"}/v1/sprites`;
|
|
33246
34639
|
const glyphsBase = `${opts.tileBaseUrl ?? "https://tiles.chrt.co"}/v1/glyphs`;
|
|
33247
34640
|
const isLndareFill = (l) => /^s52-LNDARE-fill-band\d+$/.test(l.id);
|
|
@@ -33449,7 +34842,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33449
34842
|
// palettes for their OWN glyphs, but both fall back to s52 artwork for
|
|
33450
34843
|
// classes they don't remap — and that artwork carries colour tokens.
|
|
33451
34844
|
...symbolSet !== "s101" && {
|
|
33452
|
-
sprite: `${spriteBase}/${symbolSet}-${palette.toLowerCase()}`
|
|
34845
|
+
sprite: `${spriteBase}/${SPRITE_SHEET_FAMILY[symbolSet]}-${palette.toLowerCase()}`
|
|
33453
34846
|
},
|
|
33454
34847
|
// ⚠ DEPLOY ORDER. This URL is baked into the style by callers on BOTH
|
|
33455
34848
|
// sides: the tile-worker's /v1/styles route AND the app's own
|
|
@@ -33470,7 +34863,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33470
34863
|
glyphs: `${glyphsBase}/{fontstack}/{range}.pbf`,
|
|
33471
34864
|
layers: finalLayers
|
|
33472
34865
|
};
|
|
33473
|
-
const familyStyle =
|
|
34866
|
+
const familyStyle = applySymbolFamily(style, symbolSet, palette);
|
|
33474
34867
|
const einked = applyEinkPortrayal(familyStyle, palette, { safetyContour: opts.safetyContour });
|
|
33475
34868
|
const placed = opts.dangerDepthPlacers === true ? addDangerDepthPlacers(einked.layers) : einked.layers;
|
|
33476
34869
|
const portrayed = placed === einked.layers ? einked : {
|
|
@@ -33479,8 +34872,14 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
33479
34872
|
// The placers are emitted layers: the count is of what the style carries.
|
|
33480
34873
|
metadata: { ...einked.metadata, "chrt:layer-count": placed.length }
|
|
33481
34874
|
};
|
|
33482
|
-
const
|
|
33483
|
-
|
|
34875
|
+
const marked = symbolSet === "uschart1" && opts.look === void 0 ? withUsChart1Marks(portrayed, palette) : portrayed;
|
|
34876
|
+
const sized = applyChartSymbolScales(marked.layers, opts.symbolScales, opts.soundingsRule);
|
|
34877
|
+
const sizedStyle = sized === marked.layers ? marked : { ...marked, layers: sized };
|
|
34878
|
+
return opts.look === void 0 ? sizedStyle : withLook(sizedStyle, opts.look);
|
|
34879
|
+
}
|
|
34880
|
+
function withUsChart1Marks(style, palette) {
|
|
34881
|
+
const ink = classicInkFor(palette);
|
|
34882
|
+
return ink === null ? style : withClassicMarks(style, ink);
|
|
33484
34883
|
}
|
|
33485
34884
|
function generateStyleJSON(palette = "DAY", opts = {}) {
|
|
33486
34885
|
return JSON.stringify(generateStyle(palette, opts), null, 2);
|
|
@@ -34247,7 +35646,8 @@ var Chrt = class {
|
|
|
34247
35646
|
*
|
|
34248
35647
|
* @remarks `symbolSet` picks the artwork family: `"s101"` for the
|
|
34249
35648
|
* official S-101 Portrayal Catalogue symbols, `"chrt"` for the CHRT house
|
|
34250
|
-
* set, `"
|
|
35649
|
+
* set, `"int1"` for INT-1 (the IHO INT 1 paper-chart symbols; `"raster"`,
|
|
35650
|
+
* its id before 2026-11, still means it);
|
|
34251
35651
|
* default is the S-52 set. Load the matching images from
|
|
34252
35652
|
* `@chrtco/sdk/atlas/browser` (`loadS101SymbolImages`,
|
|
34253
35653
|
* `loadChrtSymbolImages`, `loadChrtRasterSymbolImages`). Generated
|
|
@@ -34387,6 +35787,7 @@ var Chrt = class {
|
|
|
34387
35787
|
BUILD_PARAM,
|
|
34388
35788
|
CHART_BAND_CODES,
|
|
34389
35789
|
CHART_CASCADE_CODES,
|
|
35790
|
+
CHART_LOOKS,
|
|
34390
35791
|
CHART_SECTIONS,
|
|
34391
35792
|
CHART_SOUNDINGS_RULE,
|
|
34392
35793
|
CHART_SYMBOL_SCALE,
|
|
@@ -34403,6 +35804,9 @@ var Chrt = class {
|
|
|
34403
35804
|
CHRT_ICON_PREFIX,
|
|
34404
35805
|
CHRT_SDF_GLYPHS,
|
|
34405
35806
|
CHRT_STYLE_MODES,
|
|
35807
|
+
CLASSIC_FONTS,
|
|
35808
|
+
CLASSIC_MARK_NAMES,
|
|
35809
|
+
CLASSIC_TONES,
|
|
34406
35810
|
COARSE_MARK_FLOOR,
|
|
34407
35811
|
COARSE_MARK_HELD_HAZARDS,
|
|
34408
35812
|
Chrt,
|
|
@@ -34431,6 +35835,7 @@ var Chrt = class {
|
|
|
34431
35835
|
EINK_DOTS_PATTERN,
|
|
34432
35836
|
EINK_HATCH_PATTERN,
|
|
34433
35837
|
EINK_MONO_GREYS,
|
|
35838
|
+
ENGRAVED_LOOKS,
|
|
34434
35839
|
HAZARD_LABEL_PRIORITY,
|
|
34435
35840
|
INSPECT_CLASS_RANK,
|
|
34436
35841
|
INSPECT_RANK_DEVIATIONS,
|
|
@@ -34449,9 +35854,14 @@ var Chrt = class {
|
|
|
34449
35854
|
LAND_BUILD_MAXZOOM,
|
|
34450
35855
|
LAND_REGION,
|
|
34451
35856
|
LAND_TEXT_CLASSES,
|
|
35857
|
+
LEGACY_SYMBOL_FAMILY_ALIASES,
|
|
34452
35858
|
LIGHTHOUSE_NAME_FILTER,
|
|
34453
35859
|
LIGHTHOUSE_NAME_LABEL_PRIORITY,
|
|
34454
35860
|
LIGHT_LABEL_FEET_PER_METRE,
|
|
35861
|
+
LOOK_FONTS,
|
|
35862
|
+
LOOK_IMAGE_NAMES,
|
|
35863
|
+
LOOK_TONES,
|
|
35864
|
+
LOOK_WATERLINES_SOURCE,
|
|
34455
35865
|
MAPLIBRE_DEFAULT_TEXT_PADDING_PX,
|
|
34456
35866
|
NAUTICAL_SYMBOLS,
|
|
34457
35867
|
NAV_AID_LAYER_GROUPS,
|
|
@@ -34515,6 +35925,9 @@ var Chrt = class {
|
|
|
34515
35925
|
SOUNDING_PADDING_PER_FACTOR,
|
|
34516
35926
|
STANDARD_CHART_SYMBOL_SCALES,
|
|
34517
35927
|
STATUS_EXTINGUISHED,
|
|
35928
|
+
STYLE_CATALOGUE,
|
|
35929
|
+
STYLE_LOOKS,
|
|
35930
|
+
STYLE_THEMES,
|
|
34518
35931
|
SYMBOL_ANNOTATION_TEXT_CLASSES,
|
|
34519
35932
|
SYMBOL_FAMILIES,
|
|
34520
35933
|
SYMBOL_FAMILY_META,
|
|
@@ -34522,6 +35935,8 @@ var Chrt = class {
|
|
|
34522
35935
|
SYMBOL_MAP,
|
|
34523
35936
|
TileAuth,
|
|
34524
35937
|
TileTokenError,
|
|
35938
|
+
WASH_TINTS,
|
|
35939
|
+
WASH_TONES,
|
|
34525
35940
|
WATER_BODY_LAYER_GROUPS,
|
|
34526
35941
|
WATER_TEXT_CLASSES,
|
|
34527
35942
|
WeatherEndpoint,
|
|
@@ -34565,6 +35980,14 @@ var Chrt = class {
|
|
|
34565
35980
|
chrtHouseColor,
|
|
34566
35981
|
chrtLightTintExpression,
|
|
34567
35982
|
clampChartSymbolScale,
|
|
35983
|
+
classicDrawing,
|
|
35984
|
+
classicIconExpression,
|
|
35985
|
+
classicInkFor,
|
|
35986
|
+
classicMarkId,
|
|
35987
|
+
classicMarkImage,
|
|
35988
|
+
classicMarkImages,
|
|
35989
|
+
classicMarkInk,
|
|
35990
|
+
classicMarkSvgs,
|
|
34568
35991
|
collectCandidates,
|
|
34569
35992
|
collectClickCandidates,
|
|
34570
35993
|
combineWithBandFilter,
|
|
@@ -34587,6 +36010,7 @@ var Chrt = class {
|
|
|
34587
36010
|
deriveMarinerName,
|
|
34588
36011
|
drapeHalves,
|
|
34589
36012
|
drapedFirst,
|
|
36013
|
+
drawingSvg,
|
|
34590
36014
|
extinguishedLightExpression,
|
|
34591
36015
|
extractNavAidDesignation,
|
|
34592
36016
|
featureIdentity,
|
|
@@ -34631,6 +36055,7 @@ var Chrt = class {
|
|
|
34631
36055
|
isDrapeable,
|
|
34632
36056
|
isEinkColorTable,
|
|
34633
36057
|
isEinkGreyTable,
|
|
36058
|
+
isEngravedLook,
|
|
34634
36059
|
isExtinguishedLight,
|
|
34635
36060
|
isLabelLayerVisible,
|
|
34636
36061
|
isMapLive,
|
|
@@ -34655,10 +36080,15 @@ var Chrt = class {
|
|
|
34655
36080
|
lightFillExpression,
|
|
34656
36081
|
lightHeightText,
|
|
34657
36082
|
lightsIconExpression,
|
|
36083
|
+
lookImageId,
|
|
36084
|
+
lookImages,
|
|
36085
|
+
lookOfImageId,
|
|
34658
36086
|
normalizeStyleMode,
|
|
36087
|
+
normalizeSymbolFamily,
|
|
34659
36088
|
normalizeTheme,
|
|
34660
36089
|
opaqueSplitBaseOf,
|
|
34661
36090
|
paginate,
|
|
36091
|
+
parseChartLook,
|
|
34662
36092
|
parseListCodes,
|
|
34663
36093
|
parseSigseqTerms,
|
|
34664
36094
|
parseSymbolFamily,
|
|
@@ -34692,12 +36122,16 @@ var Chrt = class {
|
|
|
34692
36122
|
soundingPaddingValue,
|
|
34693
36123
|
splitOpaqueDepthAreas,
|
|
34694
36124
|
stepChartSymbolScale,
|
|
36125
|
+
styleLook,
|
|
34695
36126
|
styleModeBand,
|
|
34696
36127
|
terrainStackCount,
|
|
34697
36128
|
textSliderFor,
|
|
34698
36129
|
themeChrtGlyph,
|
|
34699
36130
|
tileTemplate,
|
|
34700
36131
|
uncoveredSectorArcs,
|
|
36132
|
+
withClassicMarks,
|
|
36133
|
+
withLook,
|
|
36134
|
+
withWaterLines,
|
|
34701
36135
|
withinBboxFilter,
|
|
34702
36136
|
worldMinusBboxPolygon
|
|
34703
36137
|
});
|