@chrtco/sdk 0.10.54 → 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/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 num2 = m[1];
4619
+ const num3 = m[1];
4586
4620
  const colourAbbr = colourCode ? COLOUR_TABLE[colourCode]?.abbr : null;
4587
4621
  if (colourAbbr && colourAbbr !== "W") {
4588
- return `${colourAbbr} "${num2}"`;
4622
+ return `${colourAbbr} "${num3}"`;
4589
4623
  }
4590
- return `"${num2}"`;
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 dayboard = dayboardShapeCode || dayboardColours.length > 0 || dayboardPattern.length > 0 ? {
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 half = period / 2;
4798
- phases.push({ on: true, duration: half, color: hex });
4799
- phases.push({ on: false, duration: half });
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 board = pickSlaveOf(props, boards);
5701
- if (board?.properties) {
5702
- if (board.properties.TOPSHP != null) props._daymark_topshp = board.properties.TOPSHP;
5703
- if (board.properties.COLOUR != null) props._daymark_colour = board.properties.COLOUR;
5704
- if (board.properties.COLPAT != null) props._daymark_colpat = board.properties.COLPAT;
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 objectClass2 = layer.metadata?.["s52:objectClass"];
7276
- if (!objectClass2 || !CHRT_ICON_EXPRESSIONS[objectClass2]) continue;
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[objectClass2]();
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(objectClass2)) {
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 (objectClass2 === "LIGHTS") {
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 num2 = Number(value);
22534
+ const num3 = Number(value);
22501
22535
  return [
22502
22536
  "any",
22503
- ["==", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], -1], num2],
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(objectClass2) {
22549
- const lookup = S52_ATON_LOOKUPS[objectClass2];
22550
- if (!lookup) throw new Error(`s52-aton-expressions: no generated lookup for ${objectClass2}`);
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(objectClass2, ct, sourceId = DEFAULT_REGION, opts = {}) {
29513
- if (!S52_LOOKUP[objectClass2]) return [];
29514
- const entry = S52_LOOKUP[objectClass2];
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(objectClass2, entry?.style.type);
29550
+ const geomTypes = getGeomTypesForClass(objectClass5, entry?.style.type);
29517
29551
  for (const geomType of geomTypes) {
29518
- const resolved = resolveStyle(objectClass2, geomType, ct, { safetyContour: opts.safetyContour });
29519
- const layerId = `s52-${objectClass2}-${resolved.type}`;
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": objectClass2,
29558
+ "source-layer": objectClass5,
29525
29559
  paint: resolved.paint,
29526
29560
  metadata: {
29527
- "s52:objectClass": objectClass2,
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(objectClass2)) {
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(objectClass2)) {
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(objectClass2)) {
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[objectClass2]) {
29547
- const [z1, w1, z2, w2] = ZOOM_SCALED_LINES2[objectClass2];
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(objectClass2);
29552
- const childOffset = CHILD_ICON_OFFSETS[objectClass2];
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 (objectClass2 === "LIGHTS") {
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 (objectClass2 === "LNDMRK" && resolved.type === "symbol") {
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-${objectClass2}-wind-symbol`,
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-${objectClass2}-lighthouse-symbol`,
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-${objectClass2}-other-symbol`,
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-${objectClass2}-danger-ring`,
29845
+ id: `s52-${objectClass5}-danger-ring`,
29812
29846
  type: "symbol",
29813
29847
  source: sourceId,
29814
- "source-layer": objectClass2,
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": objectClass2, "s52:role": "isolated-danger-ring" }
29881
+ metadata: { "s52:objectClass": objectClass5, "s52:role": "isolated-danger-ring" }
29848
29882
  });
29849
29883
  }
29850
- if (resolved.type === "fill" && FILL_OUTLINE_LAYERS.has(objectClass2)) {
29851
- const outlineColor = objectClass2 === "DEPARE" ? resolveColor("CHGRD", ct) : resolveColor("CHGRF", ct);
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-${objectClass2}-outline`,
29887
+ id: `s52-${objectClass5}-outline`,
29854
29888
  type: "line",
29855
29889
  source: sourceId,
29856
- "source-layer": objectClass2,
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": objectClass2, "s52:role": "outline" }
29897
+ metadata: { "s52:objectClass": objectClass5, "s52:role": "outline" }
29864
29898
  });
29865
29899
  }
29866
- if (resolved.type === "fill" && REGULATED_AREA_BOUNDARY_LAYERS[objectClass2]) {
29867
- const lineStyle = REGULATED_AREA_BOUNDARY_LINESTYLES[objectClass2];
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[objectClass2], ct),
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-${objectClass2}-boundary`,
29909
+ id: `s52-${objectClass5}-boundary`,
29876
29910
  type: "line",
29877
29911
  source: sourceId,
29878
- "source-layer": objectClass2,
29912
+ "source-layer": objectClass5,
29879
29913
  filter: GEOM_FILTERS.fill,
29880
29914
  paint: boundaryPaint,
29881
29915
  metadata: {
29882
- "s52:objectClass": objectClass2,
29916
+ "s52:objectClass": objectClass5,
29883
29917
  "s52:role": "boundary",
29884
29918
  ...lineStyle ? { "s52:lineStyle": lineStyle } : {}
29885
29919
  }
29886
29920
  });
29887
29921
  }
29888
- if (objectClass2 === "ACHARE" && resolved.type === "fill") {
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 (objectClass2 === "DRGARE" && resolved.type === "fill") {
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 (objectClass2 === "ACHARE" && resolved.type === "fill") {
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 (objectClass2 === "LNDARE" && resolved.type === "fill") {
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 (objectClass2 === "LNDARE" && resolved.type === "fill") {
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 (objectClass2 === "BUAARE" && resolved.type === "fill") {
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 (objectClass2 === "RIVERS" && resolved.type === "fill") {
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 (objectClass2 === "BUISGL" && resolved.type === "circle") {
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 (objectClass2 === "BRIDGE" && resolved.type === "line") {
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 (objectClass2 === "PYLONS" && resolved.type === "fill") {
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 (objectClass2 === "WEDKLP" && resolved.type === "fill") {
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 (objectClass2 === "SLOGRD" && resolved.type === "fill") {
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 (objectClass2 === "RUNWAY" && resolved.type === "fill") {
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 (objectClass2 === "FORSTC" && resolved.type === "fill") {
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 (objectClass2 === "FSHFAC" && resolved.type === "fill") {
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 (objectClass2 === "OBSTRN" && resolved.type === "symbol") {
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 (objectClass2 === "SLCONS" && resolved.type === "line") {
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 (objectClass2 === "PRDARE" && resolved.type === "line") {
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 (objectClass2 === "CTNARE" && resolved.type === "line") {
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 (objectClass2 === "PONTON" && resolved.type === "line") {
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 (objectClass2 === "WRECKS" && resolved.type === "symbol") {
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 (objectClass2 === "WATTUR" && resolved.type === "symbol") {
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 (objectClass2 === "MAGVAR" && resolved.type === "line") {
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 (objectClass2 === "DMPGRD" && resolved.type === "fill") {
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 (objectClass2 === "DAMCON" && resolved.type === "line") {
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 (objectClass2 === "GATCON" && resolved.type === "line") {
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 (objectClass2 === "CANALS" && resolved.type === "line") {
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 (objectClass2 === "PILBOP" && resolved.type === "symbol") {
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 (objectClass2 === "HRBFAC" && resolved.type === "circle") {
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 (objectClass2 === "MARCUL" && resolved.type === "fill") {
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 (objectClass2 === "RECTRC" && resolved.type === "line") {
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 (objectClass2 === "PONTON" && resolved.type === "fill") {
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 (objectClass2 === "SILTNK" && resolved.type === "symbol") {
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 (objectClass2 === "ACHBRT" && resolved.type === "symbol") {
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 (objectClass2 === "BERTHS" && resolved.type === "line") {
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 (objectClass2 === "TUNNEL" && resolved.type === "line") {
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(objectClass2, ct, sourceId = DEFAULT_REGION, depthUnits = "meters", labelOpts = {}) {
30617
- if (!LABELED_LAYERS.has(objectClass2)) return null;
30618
- const config = getLabelConfig(objectClass2, {
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 (objectClass2 === "LIGHTS") {
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 (objectClass2 === "SOUNDG") {
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 (objectClass2 === "DEPCNT") {
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 (objectClass2 === "UWTROC" || objectClass2 === "OBSTRN" || objectClass2 === "WRECKS") {
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" && (objectClass2 === "UWTROC" || objectClass2 === "OBSTRN" || objectClass2 === "WRECKS")) {
30710
+ } else if (labelOpts.dangerDepthRounding === "down" && (objectClass5 === "UWTROC" || objectClass5 === "OBSTRN" || objectClass5 === "WRECKS")) {
30677
30711
  textField = dangerDepthMetresDown();
30678
30712
  }
30679
- const labelPriority = getLabelPriority(objectClass2);
30713
+ const labelPriority = getLabelPriority(objectClass5);
30680
30714
  const layer = {
30681
- id: `s52-${objectClass2}-label`,
30715
+ id: `s52-${objectClass5}-label`,
30682
30716
  type: "symbol",
30683
30717
  source: sourceId,
30684
- "source-layer": objectClass2,
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": objectClass2,
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 (objectClass2 === "LIGHTS") {
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 (objectClass2 === "DEPCNT") {
30756
+ if (objectClass5 === "DEPCNT") {
30723
30757
  layer.filter = GEOM_FILTERS.line;
30724
30758
  }
30725
- if (objectClass2 === "CBLOHD" || objectClass2 === "PIPOHD") {
30759
+ if (objectClass5 === "CBLOHD" || objectClass5 === "PIPOHD") {
30726
30760
  layer.filter = GEOM_FILTERS.line;
30727
30761
  }
30728
- if (objectClass2 === "SBDARE") {
30762
+ if (objectClass5 === "SBDARE") {
30729
30763
  delete layer.filter;
30730
30764
  }
30731
- if (objectClass2 === "MAGVAR") {
30765
+ if (objectClass5 === "MAGVAR") {
30732
30766
  delete layer.filter;
30733
30767
  }
30734
- if (getLabelBehavior(objectClass2) === "orientation-cross-band") {
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(objectClass2, defaultType) {
30740
- if (SYMBOL_MAP[objectClass2] && defaultType === "symbol") {
30773
+ function getGeomTypesForClass(objectClass5, defaultType) {
30774
+ if (SYMBOL_MAP[objectClass5] && defaultType === "symbol") {
30741
30775
  return ["symbol"];
30742
30776
  }
30743
- if (objectClass2 === "SOUNDG") {
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 R = SECTOR_ARC_RADIUS;
30826
- const outline = annularSectorPath(end, R - OUTLINE_WIDTH / 2, R + OUTLINE_WIDTH / 2, box);
30827
- const inner = annularSectorPath(end, R - core / 2, R + core / 2, box);
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(objectClass2) {
31368
- const lookup = S52_ATON_LOOKUPS_PAPER[objectClass2];
31369
- if (!lookup) throw new Error(`raster-style: no paper lookup for ${objectClass2}`);
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 objectClass2 = metadata2?.["s52:objectClass"];
31384
- if (typeof objectClass2 !== "string" || !classes.has(objectClass2)) continue;
31385
- layout["icon-image"] = rasterAtonIconExpression(objectClass2);
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"] = "raster";
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", "raster"];
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
- raster: {
31408
- label: "CHRTraster",
31409
- description: "Paper-chart portrayal \u2014 the traditional raster-chart look"
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
- return SYMBOL_FAMILIES.find((f) => f === lower) ?? null;
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(objectClass2, family) {
31418
- const s52 = getIconExpression(objectClass2);
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(objectClass2 === "DAYMAR" ? daymarkShapeIconExpression() : s52);
31908
+ return rewriteIconToS101(objectClass5 === "DAYMAR" ? daymarkShapeIconExpression() : s52);
31424
31909
  case "chrt": {
31425
- const build = CHRT_ICON_EXPRESSIONS[objectClass2];
31910
+ const build = CHRT_ICON_EXPRESSIONS[objectClass5];
31426
31911
  return build ? build() : s52;
31427
31912
  }
31428
- case "raster":
31429
- return RASTER_ATON_CLASSES.includes(objectClass2) ? rasterAtonIconExpression(objectClass2) : s52;
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 = {
@@ -31569,9 +32923,9 @@ function factsOf(layer) {
31569
32923
  const meta = l.metadata ?? {};
31570
32924
  const isBasemap = source !== void 0 && BASEMAP_SOURCES.has(source);
31571
32925
  const cls = meta["s52:objectClass"];
31572
- const objectClass2 = isBasemap ? void 0 : (typeof cls === "string" ? cls : sourceLayer)?.toUpperCase();
32926
+ const objectClass5 = isBasemap ? void 0 : (typeof cls === "string" ? cls : sourceLayer)?.toUpperCase();
31573
32927
  const p = meta["chrt:labelPriority"];
31574
- return { source, sourceLayer, objectClass: objectClass2, labelPriority: typeof p === "number" ? p : void 0 };
32928
+ return { source, sourceLayer, objectClass: objectClass5, labelPriority: typeof p === "number" ? p : void 0 };
31575
32929
  }
31576
32930
  function textSliderFor(layer) {
31577
32931
  const f = factsOf(layer);
@@ -32681,8 +34035,41 @@ var SYMBOL_SET_LABELS = {
32681
34035
  s52: "S-52",
32682
34036
  s101: "S-101",
32683
34037
  chrt: "House",
32684
- raster: "CHRTraster"
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"
32685
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
+ }
32686
34073
  var DOMINANCE_EXEMPT_CLASSES = /* @__PURE__ */ new Set([
32687
34074
  "LNDARE",
32688
34075
  // Safety-critical nav-aid point classes (S-52 viewing groups 24020,
@@ -32787,7 +34174,7 @@ var ORIENTATION_OPACITY_SCALE = {
32787
34174
  };
32788
34175
  var ORIENTATION_OPACITY_MAX = 0.92;
32789
34176
  var ORIENTATION_BOOST_MINZOOM = 11;
32790
- function fanOrientationLabelByCellBand(label, bandFan, objectClass2) {
34177
+ function fanOrientationLabelByCellBand(label, bandFan, objectClass5) {
32791
34178
  const cellBandExpr = [
32792
34179
  "slice",
32793
34180
  ["coalesce", ["get", "_cell_id"], "??9???"],
@@ -32795,7 +34182,7 @@ function fanOrientationLabelByCellBand(label, bandFan, objectClass2) {
32795
34182
  3
32796
34183
  ];
32797
34184
  const variants = [];
32798
- const scale = objectClass2 ? ORIENTATION_OPACITY_SCALE[objectClass2] ?? 1 : 1;
34185
+ const scale = objectClass5 ? ORIENTATION_OPACITY_SCALE[objectClass5] ?? 1 : 1;
32799
34186
  for (const code of BAND_DRAW_ORDER) {
32800
34187
  const range = BAND_PRIORITY_RANGES[code];
32801
34188
  const curve = CELL_BAND_OPACITY_CURVE[code];
@@ -32959,6 +34346,9 @@ function makeCollapsedChartLabel(label, cascade, requestedSet, lockedBounds) {
32959
34346
  return collapsed;
32960
34347
  }
32961
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
+ }
32962
34352
  const seafloor = Boolean(opts.seafloor && opts.land) && seafloorLayers(palette).length > 0;
32963
34353
  const sources = buildSources({ ...opts, seafloor });
32964
34354
  const sourceId = opts.region ?? DEFAULT_REGION;
@@ -33017,14 +34407,14 @@ function generateStyle(palette = "DAY", opts = {}) {
33017
34407
  const bandFan = opts.bandFan ?? "collapsed";
33018
34408
  const lockedBounds = opts.chartMode?.lockedBounds;
33019
34409
  const bundles = [];
33020
- for (const objectClass2 of orderedClasses) {
33021
- if (META_LAYERS.has(objectClass2)) continue;
34410
+ for (const objectClass5 of orderedClasses) {
34411
+ if (META_LAYERS.has(objectClass5)) continue;
33022
34412
  bundles.push({
33023
- objectClass: objectClass2,
33024
- featureLayers: buildLayersForClass(objectClass2, palette, sourceId, {
34413
+ objectClass: objectClass5,
34414
+ featureLayers: buildLayersForClass(objectClass5, palette, sourceId, {
33025
34415
  safetyContour: opts.safetyContour
33026
34416
  }),
33027
- label: buildLabelLayer2(objectClass2, palette, sourceId, opts.depthUnits ?? "meters", {
34417
+ label: buildLabelLayer2(objectClass5, palette, sourceId, opts.depthUnits ?? "meters", {
33028
34418
  safetyContour: opts.safetyContour,
33029
34419
  twoShadeSoundings: opts.twoShadeSoundings,
33030
34420
  soundingFontWeight: opts.soundingFontWeight,
@@ -33180,17 +34570,17 @@ function generateStyle(palette = "DAY", opts = {}) {
33180
34570
  if (opts.labels === "placename") {
33181
34571
  labelLayers.push(...buildPlaceNameLayers(sourceId, palette));
33182
34572
  } else {
33183
- for (const { objectClass: objectClass2, label } of bundles) {
34573
+ for (const { objectClass: objectClass5, label } of bundles) {
33184
34574
  if (!label) continue;
33185
- if (getLabelBehavior(objectClass2) === "orientation-cross-band") {
33186
- if (objectClass2 === "LNDARE" || objectClass2 === "SEAARE") {
34575
+ if (getLabelBehavior(objectClass5) === "orientation-cross-band") {
34576
+ if (objectClass5 === "LNDARE" || objectClass5 === "SEAARE") {
33187
34577
  const Z = ISLAND_LABEL_HOIST_MINZOOM;
33188
- const { hoist, watermark } = objectClass2 === "LNDARE" ? splitOrientationFan(
33189
- fanOrientationLabelByCellBand(label, bandFan, objectClass2),
34578
+ const { hoist, watermark } = objectClass5 === "LNDARE" ? splitOrientationFan(
34579
+ fanOrientationLabelByCellBand(label, bandFan, objectClass5),
33190
34580
  [">=", ["zoom"], Z],
33191
34581
  ["<", ["zoom"], Z]
33192
34582
  ) : splitOrientationFan(
33193
- fanOrientationLabelByCellBand(label, bandFan, objectClass2),
34583
+ fanOrientationLabelByCellBand(label, bandFan, objectClass5),
33194
34584
  ["<=", buildSeaAreaTierExpression(), MAJOR_WATER_TIER_MAX],
33195
34585
  [">", buildSeaAreaTierExpression(), MAJOR_WATER_TIER_MAX],
33196
34586
  { "text-padding": MAJOR_WATER_TEXT_PADDING }
@@ -33199,7 +34589,7 @@ function generateStyle(palette = "DAY", opts = {}) {
33199
34589
  labelLayers.push(...watermark);
33200
34590
  continue;
33201
34591
  }
33202
- labelLayers.push(...fanOrientationLabelByCellBand(label, bandFan, objectClass2));
34592
+ labelLayers.push(...fanOrientationLabelByCellBand(label, bandFan, objectClass5));
33203
34593
  }
33204
34594
  }
33205
34595
  }
@@ -33244,7 +34634,7 @@ function generateStyle(palette = "DAY", opts = {}) {
33244
34634
  hoistLighthouseNames(labelLayers);
33245
34635
  layers.push(...labelLayers);
33246
34636
  }
33247
- const symbolSet = opts.symbolSet ?? "s52";
34637
+ const symbolSet = normalizeSymbolFamily(opts.symbolSet ?? "s52");
33248
34638
  const spriteBase = `${opts.tileBaseUrl ?? "https://tiles.chrt.co"}/v1/sprites`;
33249
34639
  const glyphsBase = `${opts.tileBaseUrl ?? "https://tiles.chrt.co"}/v1/glyphs`;
33250
34640
  const isLndareFill = (l) => /^s52-LNDARE-fill-band\d+$/.test(l.id);
@@ -33452,7 +34842,7 @@ function generateStyle(palette = "DAY", opts = {}) {
33452
34842
  // palettes for their OWN glyphs, but both fall back to s52 artwork for
33453
34843
  // classes they don't remap — and that artwork carries colour tokens.
33454
34844
  ...symbolSet !== "s101" && {
33455
- sprite: `${spriteBase}/${symbolSet}-${palette.toLowerCase()}`
34845
+ sprite: `${spriteBase}/${SPRITE_SHEET_FAMILY[symbolSet]}-${palette.toLowerCase()}`
33456
34846
  },
33457
34847
  // ⚠ DEPLOY ORDER. This URL is baked into the style by callers on BOTH
33458
34848
  // sides: the tile-worker's /v1/styles route AND the app's own
@@ -33473,7 +34863,7 @@ function generateStyle(palette = "DAY", opts = {}) {
33473
34863
  glyphs: `${glyphsBase}/{fontstack}/{range}.pbf`,
33474
34864
  layers: finalLayers
33475
34865
  };
33476
- const familyStyle = symbolSet === "s101" ? applyS101SymbolSet(style) : symbolSet === "chrt" ? applyChrtSymbolSet(style, palette) : symbolSet === "raster" ? applyRasterSymbolSet(style) : style;
34866
+ const familyStyle = applySymbolFamily(style, symbolSet, palette);
33477
34867
  const einked = applyEinkPortrayal(familyStyle, palette, { safetyContour: opts.safetyContour });
33478
34868
  const placed = opts.dangerDepthPlacers === true ? addDangerDepthPlacers(einked.layers) : einked.layers;
33479
34869
  const portrayed = placed === einked.layers ? einked : {
@@ -33482,8 +34872,14 @@ function generateStyle(palette = "DAY", opts = {}) {
33482
34872
  // The placers are emitted layers: the count is of what the style carries.
33483
34873
  metadata: { ...einked.metadata, "chrt:layer-count": placed.length }
33484
34874
  };
33485
- const sized = applyChartSymbolScales(portrayed.layers, opts.symbolScales, opts.soundingsRule);
33486
- return sized === portrayed.layers ? portrayed : { ...portrayed, layers: sized };
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);
33487
34883
  }
33488
34884
  function generateStyleJSON(palette = "DAY", opts = {}) {
33489
34885
  return JSON.stringify(generateStyle(palette, opts), null, 2);
@@ -34250,7 +35646,8 @@ var Chrt = class {
34250
35646
  *
34251
35647
  * @remarks `symbolSet` picks the artwork family: `"s101"` for the
34252
35648
  * official S-101 Portrayal Catalogue symbols, `"chrt"` for the CHRT house
34253
- * set, `"raster"` for CHRTraster (the traditional paper-chart portrayal);
35649
+ * set, `"int1"` for INT-1 (the IHO INT 1 paper-chart symbols; `"raster"`,
35650
+ * its id before 2026-11, still means it);
34254
35651
  * default is the S-52 set. Load the matching images from
34255
35652
  * `@chrtco/sdk/atlas/browser` (`loadS101SymbolImages`,
34256
35653
  * `loadChrtSymbolImages`, `loadChrtRasterSymbolImages`). Generated
@@ -34390,6 +35787,7 @@ var Chrt = class {
34390
35787
  BUILD_PARAM,
34391
35788
  CHART_BAND_CODES,
34392
35789
  CHART_CASCADE_CODES,
35790
+ CHART_LOOKS,
34393
35791
  CHART_SECTIONS,
34394
35792
  CHART_SOUNDINGS_RULE,
34395
35793
  CHART_SYMBOL_SCALE,
@@ -34406,6 +35804,9 @@ var Chrt = class {
34406
35804
  CHRT_ICON_PREFIX,
34407
35805
  CHRT_SDF_GLYPHS,
34408
35806
  CHRT_STYLE_MODES,
35807
+ CLASSIC_FONTS,
35808
+ CLASSIC_MARK_NAMES,
35809
+ CLASSIC_TONES,
34409
35810
  COARSE_MARK_FLOOR,
34410
35811
  COARSE_MARK_HELD_HAZARDS,
34411
35812
  Chrt,
@@ -34434,6 +35835,7 @@ var Chrt = class {
34434
35835
  EINK_DOTS_PATTERN,
34435
35836
  EINK_HATCH_PATTERN,
34436
35837
  EINK_MONO_GREYS,
35838
+ ENGRAVED_LOOKS,
34437
35839
  HAZARD_LABEL_PRIORITY,
34438
35840
  INSPECT_CLASS_RANK,
34439
35841
  INSPECT_RANK_DEVIATIONS,
@@ -34452,9 +35854,14 @@ var Chrt = class {
34452
35854
  LAND_BUILD_MAXZOOM,
34453
35855
  LAND_REGION,
34454
35856
  LAND_TEXT_CLASSES,
35857
+ LEGACY_SYMBOL_FAMILY_ALIASES,
34455
35858
  LIGHTHOUSE_NAME_FILTER,
34456
35859
  LIGHTHOUSE_NAME_LABEL_PRIORITY,
34457
35860
  LIGHT_LABEL_FEET_PER_METRE,
35861
+ LOOK_FONTS,
35862
+ LOOK_IMAGE_NAMES,
35863
+ LOOK_TONES,
35864
+ LOOK_WATERLINES_SOURCE,
34458
35865
  MAPLIBRE_DEFAULT_TEXT_PADDING_PX,
34459
35866
  NAUTICAL_SYMBOLS,
34460
35867
  NAV_AID_LAYER_GROUPS,
@@ -34518,6 +35925,9 @@ var Chrt = class {
34518
35925
  SOUNDING_PADDING_PER_FACTOR,
34519
35926
  STANDARD_CHART_SYMBOL_SCALES,
34520
35927
  STATUS_EXTINGUISHED,
35928
+ STYLE_CATALOGUE,
35929
+ STYLE_LOOKS,
35930
+ STYLE_THEMES,
34521
35931
  SYMBOL_ANNOTATION_TEXT_CLASSES,
34522
35932
  SYMBOL_FAMILIES,
34523
35933
  SYMBOL_FAMILY_META,
@@ -34525,6 +35935,8 @@ var Chrt = class {
34525
35935
  SYMBOL_MAP,
34526
35936
  TileAuth,
34527
35937
  TileTokenError,
35938
+ WASH_TINTS,
35939
+ WASH_TONES,
34528
35940
  WATER_BODY_LAYER_GROUPS,
34529
35941
  WATER_TEXT_CLASSES,
34530
35942
  WeatherEndpoint,
@@ -34568,6 +35980,14 @@ var Chrt = class {
34568
35980
  chrtHouseColor,
34569
35981
  chrtLightTintExpression,
34570
35982
  clampChartSymbolScale,
35983
+ classicDrawing,
35984
+ classicIconExpression,
35985
+ classicInkFor,
35986
+ classicMarkId,
35987
+ classicMarkImage,
35988
+ classicMarkImages,
35989
+ classicMarkInk,
35990
+ classicMarkSvgs,
34571
35991
  collectCandidates,
34572
35992
  collectClickCandidates,
34573
35993
  combineWithBandFilter,
@@ -34590,6 +36010,7 @@ var Chrt = class {
34590
36010
  deriveMarinerName,
34591
36011
  drapeHalves,
34592
36012
  drapedFirst,
36013
+ drawingSvg,
34593
36014
  extinguishedLightExpression,
34594
36015
  extractNavAidDesignation,
34595
36016
  featureIdentity,
@@ -34634,6 +36055,7 @@ var Chrt = class {
34634
36055
  isDrapeable,
34635
36056
  isEinkColorTable,
34636
36057
  isEinkGreyTable,
36058
+ isEngravedLook,
34637
36059
  isExtinguishedLight,
34638
36060
  isLabelLayerVisible,
34639
36061
  isMapLive,
@@ -34658,10 +36080,15 @@ var Chrt = class {
34658
36080
  lightFillExpression,
34659
36081
  lightHeightText,
34660
36082
  lightsIconExpression,
36083
+ lookImageId,
36084
+ lookImages,
36085
+ lookOfImageId,
34661
36086
  normalizeStyleMode,
36087
+ normalizeSymbolFamily,
34662
36088
  normalizeTheme,
34663
36089
  opaqueSplitBaseOf,
34664
36090
  paginate,
36091
+ parseChartLook,
34665
36092
  parseListCodes,
34666
36093
  parseSigseqTerms,
34667
36094
  parseSymbolFamily,
@@ -34695,12 +36122,16 @@ var Chrt = class {
34695
36122
  soundingPaddingValue,
34696
36123
  splitOpaqueDepthAreas,
34697
36124
  stepChartSymbolScale,
36125
+ styleLook,
34698
36126
  styleModeBand,
34699
36127
  terrainStackCount,
34700
36128
  textSliderFor,
34701
36129
  themeChrtGlyph,
34702
36130
  tileTemplate,
34703
36131
  uncoveredSectorArcs,
36132
+ withClassicMarks,
36133
+ withLook,
36134
+ withWaterLines,
34704
36135
  withinBboxFilter,
34705
36136
  worldMinusBboxPolygon
34706
36137
  });