@chrtco/sdk 0.7.3 → 0.7.4
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/atlas/browser.cjs.map +1 -1
- package/dist/atlas/browser.js.map +1 -1
- package/dist/index.cjs +934 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +934 -144
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1307,6 +1307,32 @@ var S52_LOOKUP = {
|
|
|
1307
1307
|
viewingGroup: 13050,
|
|
1308
1308
|
scamin: 45e3
|
|
1309
1309
|
},
|
|
1310
|
+
// Unsurveyed area — a polygon where no reliable hydrographic survey
|
|
1311
|
+
// exists. The IHO S-52 PresLib portrayal is the hatched pattern
|
|
1312
|
+
// UNSURV03 (diagonal lines over a faint grey wash); we don't carry
|
|
1313
|
+
// that sprite, so we lean on the existing OPAQUE_FILLS treatment in
|
|
1314
|
+
// `layer-builder.ts` to force a fully-opaque grey fill that visibly
|
|
1315
|
+
// suppresses anything underneath. The "no data here — don't assume
|
|
1316
|
+
// safe water" signal is the entire point; UNSARE rendering is a BASE
|
|
1317
|
+
// display-category obligation, not an optional cue.
|
|
1318
|
+
//
|
|
1319
|
+
// Note: `UNSARE` is already a member of `OPAQUE_FILLS` and
|
|
1320
|
+
// `OPAQUE_FILL_LAYERS` in `layer-builder.ts` and `style-resolver.ts`
|
|
1321
|
+
// — half-wired before this entry landed. Adding the lookup entry +
|
|
1322
|
+
// draw-order slot completes the wire-up. Surfaced by the
|
|
1323
|
+
// `Audit S-57 Layer Coverage (Weekly)` workflow (issue #575); 5
|
|
1324
|
+
// features in the NOAA corpus, all in remote-Alaska coverage gaps
|
|
1325
|
+
// where survey is genuinely absent.
|
|
1326
|
+
UNSARE: {
|
|
1327
|
+
objectClass: "UNSARE",
|
|
1328
|
+
name: "Unsurveyed Area",
|
|
1329
|
+
category: "Depths",
|
|
1330
|
+
displayCategory: "BASE",
|
|
1331
|
+
int1Ref: "I27",
|
|
1332
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 1 } },
|
|
1333
|
+
viewingGroup: 13050,
|
|
1334
|
+
scamin: 0
|
|
1335
|
+
},
|
|
1310
1336
|
// ── Land & Shoreline (INT1 Section C) ───────────────────
|
|
1311
1337
|
LNDARE: {
|
|
1312
1338
|
objectClass: "LNDARE",
|
|
@@ -1459,6 +1485,51 @@ var S52_LOOKUP = {
|
|
|
1459
1485
|
viewingGroup: 12050,
|
|
1460
1486
|
scamin: 45e3
|
|
1461
1487
|
},
|
|
1488
|
+
// Rapids — direct navigation hazard in narrows / river constrictions. S-52
|
|
1489
|
+
// INT1 C24 portrayal: a stylised wavy line representing turbulent water.
|
|
1490
|
+
// We use a blue dashed line (DEPVS) so the feature reads as a water
|
|
1491
|
+
// disturbance — same colour family as the depth tints, distinct from the
|
|
1492
|
+
// black coastal-construction line family. Surfaced by the weekly layer-
|
|
1493
|
+
// coverage audit (issue #575); 4 features in the NOAA corpus, all in
|
|
1494
|
+
// freshwater approaches where a small craft could be swept onto rocks.
|
|
1495
|
+
RAPIDS: {
|
|
1496
|
+
objectClass: "RAPIDS",
|
|
1497
|
+
name: "Rapids",
|
|
1498
|
+
category: "Hazards",
|
|
1499
|
+
displayCategory: "STANDARD",
|
|
1500
|
+
int1Ref: "C24",
|
|
1501
|
+
style: { type: "line", paint: { "line-color": "DEPVS", "line-width": 1, "line-dasharray": [3, 2] } },
|
|
1502
|
+
viewingGroup: 24020,
|
|
1503
|
+
scamin: 45e3
|
|
1504
|
+
},
|
|
1505
|
+
// Dyke — physical earth/stone embankment that confines water. Same
|
|
1506
|
+
// black-line family as SLCONS / FNCLNE / CAUSWY: solid CHBLK so the
|
|
1507
|
+
// structure reads as a hard man-made shoreline modification. INT1 F8.
|
|
1508
|
+
// Surfaced by the weekly layer-coverage audit (issue #575); 13 features
|
|
1509
|
+
// in the NOAA corpus.
|
|
1510
|
+
DYKCON: {
|
|
1511
|
+
objectClass: "DYKCON",
|
|
1512
|
+
name: "Dyke",
|
|
1513
|
+
category: "Land",
|
|
1514
|
+
displayCategory: "STANDARD",
|
|
1515
|
+
int1Ref: "F8",
|
|
1516
|
+
style: { type: "line", paint: { "line-color": "CHBLK", "line-width": 1 } },
|
|
1517
|
+
viewingGroup: 12410,
|
|
1518
|
+
scamin: 22e3
|
|
1519
|
+
},
|
|
1520
|
+
// Causeway — raised road or rail bed across tidal flats or shallow water
|
|
1521
|
+
// (Cape Cod, the Florida Keys, etc.). Black-line family alongside DYKCON.
|
|
1522
|
+
// INT1 F3. Surfaced by the weekly layer-coverage audit (issue #575).
|
|
1523
|
+
CAUSWY: {
|
|
1524
|
+
objectClass: "CAUSWY",
|
|
1525
|
+
name: "Causeway",
|
|
1526
|
+
category: "Infrastructure",
|
|
1527
|
+
displayCategory: "STANDARD",
|
|
1528
|
+
int1Ref: "F3",
|
|
1529
|
+
style: { type: "line", paint: { "line-color": "CHBLK", "line-width": 1 } },
|
|
1530
|
+
viewingGroup: 12410,
|
|
1531
|
+
scamin: 22e3
|
|
1532
|
+
},
|
|
1462
1533
|
TUNNEL: {
|
|
1463
1534
|
objectClass: "TUNNEL",
|
|
1464
1535
|
name: "Tunnel",
|
|
@@ -1656,6 +1727,13 @@ var S52_LOOKUP = {
|
|
|
1656
1727
|
scamin: 9e4
|
|
1657
1728
|
},
|
|
1658
1729
|
LNDELV: {
|
|
1730
|
+
// LineString variant (land contours) renders normally with the line
|
|
1731
|
+
// style below. Point variant ≈ spot elevation ("12m") on land — per
|
|
1732
|
+
// S-52 PresLib convention, marine displays suppress land spot heights
|
|
1733
|
+
// so they don't compete with safety-critical hydrography. The
|
|
1734
|
+
// `auditIgnore` flag silences the weekly layer-coverage audit for the
|
|
1735
|
+
// Point geom-type only; it does not disable the line rendering. See
|
|
1736
|
+
// #575 triage matrix for the full rationale.
|
|
1659
1737
|
objectClass: "LNDELV",
|
|
1660
1738
|
name: "Land Elevation",
|
|
1661
1739
|
category: "Land",
|
|
@@ -1663,7 +1741,8 @@ var S52_LOOKUP = {
|
|
|
1663
1741
|
int1Ref: "C10",
|
|
1664
1742
|
style: { type: "line", paint: { "line-color": "CHBRN", "line-width": 0.5 } },
|
|
1665
1743
|
viewingGroup: 12070,
|
|
1666
|
-
scamin: 22e3
|
|
1744
|
+
scamin: 22e3,
|
|
1745
|
+
auditIgnore: true
|
|
1667
1746
|
},
|
|
1668
1747
|
// ── Hazards (INT1 Section K) ────────────────────────────
|
|
1669
1748
|
OBSTRN: {
|
|
@@ -1749,7 +1828,15 @@ var S52_LOOKUP = {
|
|
|
1749
1828
|
int1Ref: "J1",
|
|
1750
1829
|
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0.15 } },
|
|
1751
1830
|
viewingGroup: 14010,
|
|
1752
|
-
scamin: 22e3
|
|
1831
|
+
scamin: 22e3,
|
|
1832
|
+
// Point variant (NOAA encodes 2,709 SBDARE Points) is rendered as a
|
|
1833
|
+
// seabed-quality text label ("S"/"M"/"R" per S-52 INT1 J) via the
|
|
1834
|
+
// labels.ts path — see layer-builder.ts SBDARE special-case routing.
|
|
1835
|
+
// The layer-coverage audit script only inspects MapLibre layer filters
|
|
1836
|
+
// from buildLayersForClass(), so it can't see that the Point variant
|
|
1837
|
+
// is in fact rendered. Matches the SOUNDG precedent (auditIgnore +
|
|
1838
|
+
// text-via-labels.ts rendering — see s52-lookup.ts SOUNDG entry).
|
|
1839
|
+
auditIgnore: true
|
|
1753
1840
|
},
|
|
1754
1841
|
WEDKLP: {
|
|
1755
1842
|
// Translucent green fill suggests kelp/vegetation; Point variant (the
|
|
@@ -1766,6 +1853,23 @@ var S52_LOOKUP = {
|
|
|
1766
1853
|
viewingGroup: 14010,
|
|
1767
1854
|
scamin: 22e3
|
|
1768
1855
|
},
|
|
1856
|
+
// Oil barrier — a deployed containment boom corralling spilled oil or
|
|
1857
|
+
// marking the perimeter of a spill-response operation. Operational
|
|
1858
|
+
// hazard: small craft must avoid crossing the line (and the polluted
|
|
1859
|
+
// water it contains). S-52 has no formal INT1 entry, but PresLib
|
|
1860
|
+
// convention for spill-response gear is magenta — matches the rest of
|
|
1861
|
+
// the regulated/operational-area portrayal family. Dashed line so it
|
|
1862
|
+
// reads as a temporary/operational marker rather than a permanent
|
|
1863
|
+
// structure. Surfaced by the weekly layer-coverage audit (issue #575).
|
|
1864
|
+
OILBAR: {
|
|
1865
|
+
objectClass: "OILBAR",
|
|
1866
|
+
name: "Oil Barrier",
|
|
1867
|
+
category: "Hazards",
|
|
1868
|
+
displayCategory: "STANDARD",
|
|
1869
|
+
style: { type: "line", paint: { "line-color": "CHMGD", "line-width": 1, "line-dasharray": [4, 2] } },
|
|
1870
|
+
viewingGroup: 24020,
|
|
1871
|
+
scamin: 45e3
|
|
1872
|
+
},
|
|
1769
1873
|
// ── Regulated Areas (INT1 Section N) ────────────────────
|
|
1770
1874
|
ACHARE: {
|
|
1771
1875
|
// Anchorages are conventionally rendered as a subtle filled region in
|
|
@@ -1939,6 +2043,196 @@ var S52_LOOKUP = {
|
|
|
1939
2043
|
viewingGroup: 26050,
|
|
1940
2044
|
scamin: 9e4
|
|
1941
2045
|
},
|
|
2046
|
+
// ── Jurisdictional zones (INT1 Section N) ───────────────
|
|
2047
|
+
// ADMARE / COSARE / CONZNE / EXEZNE / TESARE share an S-52 portrayal
|
|
2048
|
+
// family: magenta dashed boundary, no fill. These are vast offshore
|
|
2049
|
+
// polygons (EEZ extends 200nm, contiguous zone 24nm) where a flood fill
|
|
2050
|
+
// — even at 0.05 opacity — would visibly tint half the chart and stack
|
|
2051
|
+
// with overlapping jurisdictions into a purple wash. Same boundary-only
|
|
2052
|
+
// pattern as TESARE / RESARE / CTNARE via LINE_FROM_POLYGON_LAYERS.
|
|
2053
|
+
// Surfaced by the weekly layer-coverage audit (issue #575 rows 8–15).
|
|
2054
|
+
ADMARE: {
|
|
2055
|
+
// Administration area — state/national waters, the broadest
|
|
2056
|
+
// jurisdictional polygon class. INT1 N40 maps it into the same
|
|
2057
|
+
// magenta-dashed family as territorial-sea / EEZ / contiguous-zone.
|
|
2058
|
+
objectClass: "ADMARE",
|
|
2059
|
+
name: "Administration Area",
|
|
2060
|
+
category: "Regulated Areas",
|
|
2061
|
+
displayCategory: "STANDARD",
|
|
2062
|
+
int1Ref: "N40",
|
|
2063
|
+
style: {
|
|
2064
|
+
type: "line",
|
|
2065
|
+
paint: {
|
|
2066
|
+
"line-color": "CHMGD",
|
|
2067
|
+
"line-width": 1,
|
|
2068
|
+
"line-dasharray": [6, 4],
|
|
2069
|
+
"line-opacity": 0.6
|
|
2070
|
+
}
|
|
2071
|
+
},
|
|
2072
|
+
viewingGroup: 26010,
|
|
2073
|
+
scamin: 9e4
|
|
2074
|
+
},
|
|
2075
|
+
COSARE: {
|
|
2076
|
+
// Coastal area — jurisdictional polygon delineating a coastal-state
|
|
2077
|
+
// administrative region. Previously suppressed via META_LAYERS in
|
|
2078
|
+
// style-generator.ts; promoted here to render as a magenta dashed
|
|
2079
|
+
// boundary alongside the rest of the N-section jurisdiction family.
|
|
2080
|
+
objectClass: "COSARE",
|
|
2081
|
+
name: "Coastal Area",
|
|
2082
|
+
category: "Regulated Areas",
|
|
2083
|
+
displayCategory: "STANDARD",
|
|
2084
|
+
int1Ref: "N40",
|
|
2085
|
+
style: {
|
|
2086
|
+
type: "line",
|
|
2087
|
+
paint: {
|
|
2088
|
+
"line-color": "CHMGD",
|
|
2089
|
+
"line-width": 1,
|
|
2090
|
+
"line-dasharray": [6, 4],
|
|
2091
|
+
"line-opacity": 0.6
|
|
2092
|
+
}
|
|
2093
|
+
},
|
|
2094
|
+
viewingGroup: 26010,
|
|
2095
|
+
scamin: 9e4
|
|
2096
|
+
},
|
|
2097
|
+
CONZNE: {
|
|
2098
|
+
// Contiguous Zone — 24nm offshore boundary. Same magenta dashed
|
|
2099
|
+
// portrayal as territorial sea; boundary-only because the polygon is
|
|
2100
|
+
// vast and a flood fill would obscure huge swathes of chart data.
|
|
2101
|
+
objectClass: "CONZNE",
|
|
2102
|
+
name: "Contiguous Zone",
|
|
2103
|
+
category: "Regulated Areas",
|
|
2104
|
+
displayCategory: "STANDARD",
|
|
2105
|
+
int1Ref: "N44",
|
|
2106
|
+
style: {
|
|
2107
|
+
type: "line",
|
|
2108
|
+
paint: {
|
|
2109
|
+
"line-color": "CHMGD",
|
|
2110
|
+
"line-width": 1,
|
|
2111
|
+
"line-dasharray": [6, 4],
|
|
2112
|
+
"line-opacity": 0.6
|
|
2113
|
+
}
|
|
2114
|
+
},
|
|
2115
|
+
viewingGroup: 26010,
|
|
2116
|
+
scamin: 9e4
|
|
2117
|
+
},
|
|
2118
|
+
EXEZNE: {
|
|
2119
|
+
// Exclusive Economic Zone — 200nm offshore boundary. Largest of the
|
|
2120
|
+
// jurisdictional polygons; flood-filling even at 0.05 opacity would
|
|
2121
|
+
// tint half the chart at coastal zooms. Boundary-only is the only
|
|
2122
|
+
// sensible portrayal at scale.
|
|
2123
|
+
objectClass: "EXEZNE",
|
|
2124
|
+
name: "Exclusive Economic Zone",
|
|
2125
|
+
category: "Regulated Areas",
|
|
2126
|
+
displayCategory: "STANDARD",
|
|
2127
|
+
int1Ref: "N47",
|
|
2128
|
+
style: {
|
|
2129
|
+
type: "line",
|
|
2130
|
+
paint: {
|
|
2131
|
+
"line-color": "CHMGD",
|
|
2132
|
+
"line-width": 1,
|
|
2133
|
+
"line-dasharray": [6, 4],
|
|
2134
|
+
"line-opacity": 0.6
|
|
2135
|
+
}
|
|
2136
|
+
},
|
|
2137
|
+
viewingGroup: 26010,
|
|
2138
|
+
scamin: 9e4
|
|
2139
|
+
},
|
|
2140
|
+
// ── IMO routing measures (INT1 Section M) ───────────────
|
|
2141
|
+
// TSEZNE / DWRTPT / DWRTCL / TWRTPT are IMO-adopted routing measures
|
|
2142
|
+
// (Traffic Separation Scheme zones, deepwater routes, two-way routes).
|
|
2143
|
+
// S-52 portrayal: magenta dashed boundary for polygons, dashed centerline
|
|
2144
|
+
// for the LineString. The INT1 M-section spec calls for additional
|
|
2145
|
+
// diagonal hatching (TSSCRS01 sprite) on TSEZNE and "DW" centroid text
|
|
2146
|
+
// on DWRTPT — both are deferred follow-ups (TSSCRS01 not in the atlas
|
|
2147
|
+
// sprite set; centroid text belongs in labels.ts). Boundary visibility
|
|
2148
|
+
// is the priority cue here; routing-text augmentation comes later.
|
|
2149
|
+
TSEZNE: {
|
|
2150
|
+
// Traffic Separation Zone — the buffer band between opposing lanes of
|
|
2151
|
+
// a TSS. S-52 INT1 M14 calls for T-pattern diagonal hatching
|
|
2152
|
+
// (TSSCRS01) but that sprite isn't in our generated atlas; fall back
|
|
2153
|
+
// to a magenta dashed boundary so the zone is at least visible.
|
|
2154
|
+
objectClass: "TSEZNE",
|
|
2155
|
+
name: "Traffic Separation Zone",
|
|
2156
|
+
category: "Regulated Areas",
|
|
2157
|
+
displayCategory: "STANDARD",
|
|
2158
|
+
int1Ref: "M14",
|
|
2159
|
+
style: {
|
|
2160
|
+
type: "line",
|
|
2161
|
+
paint: {
|
|
2162
|
+
"line-color": "CHMGD",
|
|
2163
|
+
"line-width": 1.2,
|
|
2164
|
+
"line-dasharray": [4, 3],
|
|
2165
|
+
"line-opacity": 0.7
|
|
2166
|
+
}
|
|
2167
|
+
},
|
|
2168
|
+
viewingGroup: 26010,
|
|
2169
|
+
scamin: 9e4
|
|
2170
|
+
},
|
|
2171
|
+
DWRTPT: {
|
|
2172
|
+
// Deepwater Route Part — polygon segment of an IMO-adopted deepwater
|
|
2173
|
+
// route. S-52 INT1 M27 portrayal includes "DW" centroid text; that's
|
|
2174
|
+
// a labels.ts addition deferred to a follow-up. Boundary-only here.
|
|
2175
|
+
objectClass: "DWRTPT",
|
|
2176
|
+
name: "Deepwater Route Part",
|
|
2177
|
+
category: "Regulated Areas",
|
|
2178
|
+
displayCategory: "STANDARD",
|
|
2179
|
+
int1Ref: "M27",
|
|
2180
|
+
style: {
|
|
2181
|
+
type: "line",
|
|
2182
|
+
paint: {
|
|
2183
|
+
"line-color": "CHMGD",
|
|
2184
|
+
"line-width": 1.2,
|
|
2185
|
+
"line-dasharray": [4, 3],
|
|
2186
|
+
"line-opacity": 0.7
|
|
2187
|
+
}
|
|
2188
|
+
},
|
|
2189
|
+
viewingGroup: 26010,
|
|
2190
|
+
scamin: 9e4
|
|
2191
|
+
},
|
|
2192
|
+
DWRTCL: {
|
|
2193
|
+
// Deepwater Route Centerline — LineString feature (not a polygon
|
|
2194
|
+
// boundary) running down the middle of a DWRTPT. Same magenta dashed
|
|
2195
|
+
// style as MAGVAR isogonic lines but slightly heavier so the
|
|
2196
|
+
// route-axis cue reads against busy water.
|
|
2197
|
+
objectClass: "DWRTCL",
|
|
2198
|
+
name: "Deepwater Route Centerline",
|
|
2199
|
+
category: "Regulated Areas",
|
|
2200
|
+
displayCategory: "STANDARD",
|
|
2201
|
+
int1Ref: "M27",
|
|
2202
|
+
style: {
|
|
2203
|
+
type: "line",
|
|
2204
|
+
paint: {
|
|
2205
|
+
"line-color": "CHMGD",
|
|
2206
|
+
"line-width": 0.8,
|
|
2207
|
+
"line-dasharray": [6, 3],
|
|
2208
|
+
"line-opacity": 0.7
|
|
2209
|
+
}
|
|
2210
|
+
},
|
|
2211
|
+
viewingGroup: 26010,
|
|
2212
|
+
scamin: 9e4
|
|
2213
|
+
},
|
|
2214
|
+
TWRTPT: {
|
|
2215
|
+
// Two-Way Route Part — polygon segment of an IMO-adopted two-way
|
|
2216
|
+
// route. S-52 INT1 M28 portrayal includes paired arrow centroid
|
|
2217
|
+
// symbols (TWRTPT52 / TWRTPT53 sprites exist in the atlas but are a
|
|
2218
|
+
// labels.ts follow-up). Boundary-only here.
|
|
2219
|
+
objectClass: "TWRTPT",
|
|
2220
|
+
name: "Two-Way Route Part",
|
|
2221
|
+
category: "Regulated Areas",
|
|
2222
|
+
displayCategory: "STANDARD",
|
|
2223
|
+
int1Ref: "M28",
|
|
2224
|
+
style: {
|
|
2225
|
+
type: "line",
|
|
2226
|
+
paint: {
|
|
2227
|
+
"line-color": "CHMGD",
|
|
2228
|
+
"line-width": 1.2,
|
|
2229
|
+
"line-dasharray": [4, 3],
|
|
2230
|
+
"line-opacity": 0.7
|
|
2231
|
+
}
|
|
2232
|
+
},
|
|
2233
|
+
viewingGroup: 26010,
|
|
2234
|
+
scamin: 9e4
|
|
2235
|
+
},
|
|
1942
2236
|
// ── Infrastructure (INT1 Sections D, F, L) ──────────────
|
|
1943
2237
|
BRIDGE: {
|
|
1944
2238
|
objectClass: "BRIDGE",
|
|
@@ -2247,6 +2541,56 @@ var S52_LOOKUP = {
|
|
|
2247
2541
|
viewingGroup: 12410,
|
|
2248
2542
|
scamin: 22e3
|
|
2249
2543
|
},
|
|
2544
|
+
// Coast Guard station — emergency-response context. Mariners look for
|
|
2545
|
+
// these when navigating unfamiliar coastline or planning a distress-call
|
|
2546
|
+
// contingency. INT1 F62. Symbolised with the same generic tower glyph
|
|
2547
|
+
// (BCNTOW01) used by BUISGL and the CATLMK=17 LNDMRK variant — a
|
|
2548
|
+
// dedicated CGUSTA SVG is a reasonable follow-up but not required for
|
|
2549
|
+
// the structural-presence cue. Surfaced by the weekly layer-coverage
|
|
2550
|
+
// audit (issue #575); 17 Point features in the NOAA corpus.
|
|
2551
|
+
CGUSTA: {
|
|
2552
|
+
objectClass: "CGUSTA",
|
|
2553
|
+
name: "Coast Guard Station",
|
|
2554
|
+
category: "Infrastructure",
|
|
2555
|
+
displayCategory: "OTHER",
|
|
2556
|
+
int1Ref: "F62",
|
|
2557
|
+
style: { type: "symbol", paint: {}, layout: { "icon-size": 0.6, "icon-allow-overlap": true }, iconImage: "BCNTOW01" },
|
|
2558
|
+
viewingGroup: 12410,
|
|
2559
|
+
scamin: 22e3
|
|
2560
|
+
},
|
|
2561
|
+
// "New Object" — S-57 placeholder class for features the issuing HO has
|
|
2562
|
+
// identified but not yet classified into a more specific class. S-52
|
|
2563
|
+
// PresLib does NOT formally define a portrayal because the class is by
|
|
2564
|
+
// construction not-yet-portrayable, so any distinctive symbol is
|
|
2565
|
+
// permissible — we use a vivid magenta-filled circle with a bold black
|
|
2566
|
+
// stroke so a mariner sees clearly that "there is something unclassified
|
|
2567
|
+
// here." Hiding this class would amount to hiding the HO's own
|
|
2568
|
+
// uncertainty marker, which is the exact opposite of what a chart user
|
|
2569
|
+
// needs. displayCategory: STANDARD (not OTHER) so a default-display
|
|
2570
|
+
// mariner cannot accidentally suppress it; scamin: 0 so the marker
|
|
2571
|
+
// stays visible at every scale band. Surfaced by the weekly layer-
|
|
2572
|
+
// coverage audit (issue #575); 8 Point features in the NOAA corpus.
|
|
2573
|
+
// SAFETY CONTRACT: any future "clean up unused magenta point classes"
|
|
2574
|
+
// pass MUST NOT delete or hide this entry — read the comment block on
|
|
2575
|
+
// issue #575 row 22 before touching.
|
|
2576
|
+
NEWOBJ: {
|
|
2577
|
+
objectClass: "NEWOBJ",
|
|
2578
|
+
name: "New Object (Unclassified)",
|
|
2579
|
+
category: "Hazards",
|
|
2580
|
+
displayCategory: "STANDARD",
|
|
2581
|
+
style: {
|
|
2582
|
+
type: "circle",
|
|
2583
|
+
paint: {
|
|
2584
|
+
"circle-color": "CHMGD",
|
|
2585
|
+
"circle-radius": 5,
|
|
2586
|
+
"circle-stroke-color": "CHBLK",
|
|
2587
|
+
"circle-stroke-width": 1.2,
|
|
2588
|
+
"circle-opacity": 0.85
|
|
2589
|
+
}
|
|
2590
|
+
},
|
|
2591
|
+
viewingGroup: 24020,
|
|
2592
|
+
scamin: 0
|
|
2593
|
+
},
|
|
2250
2594
|
// ── Overhead & Underground (INT1 Section L) ─────────────
|
|
2251
2595
|
// Overhead cable — S-52 INT1 L31 portrayal: solid thin magenta line
|
|
2252
2596
|
// (not dashed) because overhead cables are an in-air navigation hazard
|
|
@@ -2298,6 +2642,11 @@ var S52_LOOKUP = {
|
|
|
2298
2642
|
// when the sprite image is missing; `fill-pattern` here is the default
|
|
2299
2643
|
// used if the conditional expression isn't applied for some reason
|
|
2300
2644
|
// (e.g. a consumer that bypasses `resolvePaint`).
|
|
2645
|
+
//
|
|
2646
|
+
// Polygon (vegetation fill) is the primary variant. The Point variant
|
|
2647
|
+
// ≈ a single marker tree; sub-marine-relevance, so `auditIgnore`
|
|
2648
|
+
// silences the audit for the Point geom-type without touching the
|
|
2649
|
+
// Polygon rendering. See #575 triage matrix.
|
|
2301
2650
|
style: {
|
|
2302
2651
|
type: "fill",
|
|
2303
2652
|
paint: { "fill-color": "LANDF", "fill-opacity": 0.6, "fill-pattern": "VEGATN03" }
|
|
@@ -2305,7 +2654,8 @@ var S52_LOOKUP = {
|
|
|
2305
2654
|
hasConditional: true,
|
|
2306
2655
|
conditionalAttributes: ["CATVEG"],
|
|
2307
2656
|
viewingGroup: 12050,
|
|
2308
|
-
scamin: 22e3
|
|
2657
|
+
scamin: 22e3,
|
|
2658
|
+
auditIgnore: true
|
|
2309
2659
|
},
|
|
2310
2660
|
SEAARE: {
|
|
2311
2661
|
// Cross-band water base. SEAARE polygons tile the sea below the
|
|
@@ -2484,6 +2834,42 @@ var S52_LOOKUP = {
|
|
|
2484
2834
|
viewingGroup: 23010,
|
|
2485
2835
|
scamin: 0
|
|
2486
2836
|
},
|
|
2837
|
+
// ── Audit-ignored stubs (non-metadata) ──────────────────
|
|
2838
|
+
// Classes whose non-rendering is a deliberate S-52 portrayal choice
|
|
2839
|
+
// rather than a real gap, but which aren't S-57 metadata. Each is
|
|
2840
|
+
// present here only so the weekly layer-coverage audit (#575) stops
|
|
2841
|
+
// flagging it as missing. Paint is a transparent fill — no visible
|
|
2842
|
+
// output. Swapping `auditIgnore: true` for a real style is a one-line
|
|
2843
|
+
// change if the call ever needs to be reversed.
|
|
2844
|
+
SLOTOP: {
|
|
2845
|
+
// Top of slope — land terrain feature, low marine relevance.
|
|
2846
|
+
objectClass: "SLOTOP",
|
|
2847
|
+
name: "Top of Slope",
|
|
2848
|
+
category: "Land",
|
|
2849
|
+
displayCategory: "OTHER",
|
|
2850
|
+
int1Ref: "C12",
|
|
2851
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2852
|
+
auditIgnore: true
|
|
2853
|
+
},
|
|
2854
|
+
SNDWAV: {
|
|
2855
|
+
// Sand waves — niche bathymetric texture feature, not a hazard.
|
|
2856
|
+
objectClass: "SNDWAV",
|
|
2857
|
+
name: "Sand Waves",
|
|
2858
|
+
category: "Depths",
|
|
2859
|
+
displayCategory: "OTHER",
|
|
2860
|
+
int1Ref: "J14",
|
|
2861
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2862
|
+
auditIgnore: true
|
|
2863
|
+
},
|
|
2864
|
+
CTRPNT: {
|
|
2865
|
+
// Centerline point — geometric helper, not a feature on the chart.
|
|
2866
|
+
objectClass: "CTRPNT",
|
|
2867
|
+
name: "Centerline Point",
|
|
2868
|
+
category: "Meta",
|
|
2869
|
+
displayCategory: "OTHER",
|
|
2870
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2871
|
+
auditIgnore: true
|
|
2872
|
+
},
|
|
2487
2873
|
// ── Meta (hidden by default) ────────────────────────────
|
|
2488
2874
|
// M_* and DSID are S-57 metadata classes — they describe the dataset
|
|
2489
2875
|
// (coverage extent, survey reliability, source publication, etc.) and
|
|
@@ -2522,6 +2908,17 @@ var S52_LOOKUP = {
|
|
|
2522
2908
|
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2523
2909
|
auditIgnore: true
|
|
2524
2910
|
},
|
|
2911
|
+
M_SDAT: {
|
|
2912
|
+
// Sounding Datum — S-57 metadata describing the vertical datum used
|
|
2913
|
+
// for soundings (typically LAT). Click-query attribute carrier; no
|
|
2914
|
+
// visible shape on its own.
|
|
2915
|
+
objectClass: "M_SDAT",
|
|
2916
|
+
name: "Sounding Datum",
|
|
2917
|
+
category: "Meta",
|
|
2918
|
+
displayCategory: "META",
|
|
2919
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2920
|
+
auditIgnore: true
|
|
2921
|
+
},
|
|
2525
2922
|
M_SREL: {
|
|
2526
2923
|
objectClass: "M_SREL",
|
|
2527
2924
|
name: "Survey Reliability",
|
|
@@ -2561,6 +2958,16 @@ var S52_DRAW_ORDER = [
|
|
|
2561
2958
|
// paired paint-spec change (fill-opacity 0 → 1, color → DEPDW).
|
|
2562
2959
|
"SEAARE",
|
|
2563
2960
|
"DEPARE",
|
|
2961
|
+
// 2a. Unsurveyed area — opaque grey wash painted ON TOP of any DEPARE
|
|
2962
|
+
// tile within its extent so depth-tier colours can never imply the area
|
|
2963
|
+
// is surveyed-and-safe. If both DEPARE and UNSARE cover the same pixel,
|
|
2964
|
+
// UNSARE wins on purpose: the hydrographic office classified the polygon
|
|
2965
|
+
// as unsurveyed, so any depth data within it is suspect at best. Sits
|
|
2966
|
+
// below dredged / swept (which represent active survey work) so those
|
|
2967
|
+
// appear if they overlap UNSARE — but in practice they don't, and the
|
|
2968
|
+
// ordering is the safer fallback. Surfaced by the weekly layer-coverage
|
|
2969
|
+
// audit (issue #575); see s52-lookup.ts UNSARE entry for context.
|
|
2970
|
+
"UNSARE",
|
|
2564
2971
|
// 3. Dredged / swept areas (fill)
|
|
2565
2972
|
"DRGARE",
|
|
2566
2973
|
"SWPARE",
|
|
@@ -2598,6 +3005,17 @@ var S52_DRAW_ORDER = [
|
|
|
2598
3005
|
"LOGPON",
|
|
2599
3006
|
"CBLARE",
|
|
2600
3007
|
"PIPARE",
|
|
3008
|
+
// 6a. Jurisdictional zones + IMO routing measures (boundary-only via
|
|
3009
|
+
// LINE_FROM_POLYGON_LAYERS). Slotted at the end of the regulated-area
|
|
3010
|
+
// band so the dashed magenta boundaries paint above the fill family
|
|
3011
|
+
// but below shoreline / depth-contour lines. Closes #575 rows 8–15.
|
|
3012
|
+
"ADMARE",
|
|
3013
|
+
"COSARE",
|
|
3014
|
+
"CONZNE",
|
|
3015
|
+
"EXEZNE",
|
|
3016
|
+
"TSEZNE",
|
|
3017
|
+
"DWRTPT",
|
|
3018
|
+
"TWRTPT",
|
|
2601
3019
|
// 7. Infrastructure areas (fill)
|
|
2602
3020
|
"PONTON",
|
|
2603
3021
|
"HULKES",
|
|
@@ -2607,8 +3025,13 @@ var S52_DRAW_ORDER = [
|
|
|
2607
3025
|
"PYLONS",
|
|
2608
3026
|
"FORSTC",
|
|
2609
3027
|
// 8. Coastline / shore (line)
|
|
3028
|
+
// DYKCON (dyke) and CAUSWY (causeway) join the SLCONS family — solid
|
|
3029
|
+
// black lines representing man-made shoreline modifications. Drawn in
|
|
3030
|
+
// the same band so they layer consistently with adjacent SLCONS edges.
|
|
2610
3031
|
"COALNE",
|
|
2611
3032
|
"SLCONS",
|
|
3033
|
+
"DYKCON",
|
|
3034
|
+
"CAUSWY",
|
|
2612
3035
|
"FNCLNE",
|
|
2613
3036
|
// 9. Depth contours (line)
|
|
2614
3037
|
"DEPCNT",
|
|
@@ -2619,13 +3042,20 @@ var S52_DRAW_ORDER = [
|
|
|
2619
3042
|
// routing and aids-to-nav win the visual hierarchy).
|
|
2620
3043
|
"MAGVAR",
|
|
2621
3044
|
// 10. Navigation lines (line)
|
|
3045
|
+
// RAPIDS and OILBAR are direct/operational water hazards. RAPIDS uses
|
|
3046
|
+
// the depth-blue palette (DEPVS dashed) so the feature reads as a
|
|
3047
|
+
// water-surface disturbance; OILBAR uses CHMGD to fit the operational-
|
|
3048
|
+
// hazard family alongside cables / pipelines.
|
|
2622
3049
|
"NAVLNE",
|
|
2623
3050
|
"TSSBND",
|
|
3051
|
+
"DWRTCL",
|
|
2624
3052
|
"ROADWY",
|
|
2625
3053
|
"RAILWY",
|
|
2626
3054
|
"TUNNEL",
|
|
2627
3055
|
"FERYRT",
|
|
2628
3056
|
"RECTRC",
|
|
3057
|
+
"RAPIDS",
|
|
3058
|
+
"OILBAR",
|
|
2629
3059
|
"PIPSOL",
|
|
2630
3060
|
"PIPOHD",
|
|
2631
3061
|
"CBLSUB",
|
|
@@ -2634,6 +3064,11 @@ var S52_DRAW_ORDER = [
|
|
|
2634
3064
|
"DAMCON",
|
|
2635
3065
|
"BERTHS",
|
|
2636
3066
|
// 11. Point features
|
|
3067
|
+
// CGUSTA (coast guard station, emergency-context) sits with the building
|
|
3068
|
+
// / landmark family — a structural-presence cue rather than a routing
|
|
3069
|
+
// signal. NEWOBJ ("something here we haven't classified yet") goes at
|
|
3070
|
+
// the END of the point list so the distinctive magenta marker stays on
|
|
3071
|
+
// top of neighbouring point features and cannot be visually swallowed.
|
|
2637
3072
|
"SOUNDG",
|
|
2638
3073
|
"MORFAC",
|
|
2639
3074
|
"PILPNT",
|
|
@@ -2647,6 +3082,8 @@ var S52_DRAW_ORDER = [
|
|
|
2647
3082
|
"CRANES",
|
|
2648
3083
|
"DISMAR",
|
|
2649
3084
|
"ACHBRT",
|
|
3085
|
+
"CGUSTA",
|
|
3086
|
+
"NEWOBJ",
|
|
2650
3087
|
// 12. Nav aids (on top)
|
|
2651
3088
|
"FOGSIG",
|
|
2652
3089
|
"RTPBCN",
|
|
@@ -5264,6 +5701,7 @@ var SYMBOL_MAP = {
|
|
|
5264
5701
|
PILBOP: "PILBOP02",
|
|
5265
5702
|
SISTAT: "SISTAT02",
|
|
5266
5703
|
SMCFAC: "ACHARE02",
|
|
5704
|
+
CGUSTA: "BCNTOW01",
|
|
5267
5705
|
// Land infrastructure
|
|
5268
5706
|
SILTNK: "TNKCON02",
|
|
5269
5707
|
BUISGL: "BCNTOW01",
|
|
@@ -5920,6 +6358,124 @@ function buildSeabedLabelExpression() {
|
|
|
5920
6358
|
const natsurJoined = ["slice", natsurParts, 1];
|
|
5921
6359
|
return ["concat", natquaPrefix, natsurJoined];
|
|
5922
6360
|
}
|
|
6361
|
+
function buildSeaAreaTierExpression() {
|
|
6362
|
+
const catsea = ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0];
|
|
6363
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6364
|
+
return [
|
|
6365
|
+
"case",
|
|
6366
|
+
// Tier 1 — Ocean (CATSEA=31 OR OBJNAM contains "Ocean", excluding
|
|
6367
|
+
// anchorage-area-style compound names which we filter on later).
|
|
6368
|
+
["==", ["to-number", catsea], 31],
|
|
6369
|
+
1,
|
|
6370
|
+
["any", ["==", ["to-number", catsea], 29], ["==", ["to-number", catsea], 30]],
|
|
6371
|
+
2,
|
|
6372
|
+
[
|
|
6373
|
+
"any",
|
|
6374
|
+
["==", ["to-number", catsea], 4],
|
|
6375
|
+
["==", ["to-number", catsea], 11],
|
|
6376
|
+
["==", ["to-number", catsea], 27],
|
|
6377
|
+
["==", ["to-number", catsea], 28]
|
|
6378
|
+
],
|
|
6379
|
+
3,
|
|
6380
|
+
// Tier 4 — Anchorage detail (must be checked before OBJNAM-substring
|
|
6381
|
+
// promotion so "Boston Harbor, MA …" anchorages don't bubble up).
|
|
6382
|
+
[">=", ["index-of", "Anchorage Area", objnam], 0],
|
|
6383
|
+
4,
|
|
6384
|
+
// OBJNAM-substring promotion shims (run AFTER tier 4 demotion):
|
|
6385
|
+
[">=", ["index-of", "Atlantic Ocean", objnam], 0],
|
|
6386
|
+
1,
|
|
6387
|
+
[">=", ["index-of", "Pacific Ocean", objnam], 0],
|
|
6388
|
+
1,
|
|
6389
|
+
[">=", ["index-of", "Arctic Ocean", objnam], 0],
|
|
6390
|
+
1,
|
|
6391
|
+
[">=", ["index-of", "Gulf of", objnam], 0],
|
|
6392
|
+
2,
|
|
6393
|
+
// Bay/Sound/Sea/Strait/Channel as a tier-3 shim (matches "Massachusetts
|
|
6394
|
+
// Bay", "Buzzards Bay", "Long Island Sound", "Block Island Sound",
|
|
6395
|
+
// "Vineyard Sound", "Cape Cod Bay", etc. without needing CATSEA).
|
|
6396
|
+
[">=", ["index-of", " Bay", objnam], 0],
|
|
6397
|
+
3,
|
|
6398
|
+
[">=", ["index-of", " Sound", objnam], 0],
|
|
6399
|
+
3,
|
|
6400
|
+
[">=", ["index-of", " Strait", objnam], 0],
|
|
6401
|
+
3,
|
|
6402
|
+
[">=", ["index-of", " Sea", objnam], 0],
|
|
6403
|
+
2,
|
|
6404
|
+
5
|
|
6405
|
+
];
|
|
6406
|
+
}
|
|
6407
|
+
function buildBuiltUpAreaTierExpression() {
|
|
6408
|
+
const catbua = ["coalesce", ["get", "CATBUA"], ["get", "catbua"], 0];
|
|
6409
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6410
|
+
const nameLen = ["length", objnam];
|
|
6411
|
+
return [
|
|
6412
|
+
"case",
|
|
6413
|
+
["==", ["to-number", catbua], 1],
|
|
6414
|
+
1,
|
|
6415
|
+
["==", ["to-number", catbua], 5],
|
|
6416
|
+
2,
|
|
6417
|
+
["<=", nameLen, 8],
|
|
6418
|
+
1,
|
|
6419
|
+
["<=", nameLen, 14],
|
|
6420
|
+
2,
|
|
6421
|
+
3
|
|
6422
|
+
];
|
|
6423
|
+
}
|
|
6424
|
+
function buildLandRegionTierExpression() {
|
|
6425
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6426
|
+
const nameLen = ["length", objnam];
|
|
6427
|
+
return [
|
|
6428
|
+
"case",
|
|
6429
|
+
["all", ["<=", nameLen, 12], ["==", ["index-of", ",", objnam], -1]],
|
|
6430
|
+
1,
|
|
6431
|
+
2
|
|
6432
|
+
];
|
|
6433
|
+
}
|
|
6434
|
+
function buildLandAreaTierExpression() {
|
|
6435
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6436
|
+
return [
|
|
6437
|
+
"case",
|
|
6438
|
+
["<=", ["length", objnam], 12],
|
|
6439
|
+
1,
|
|
6440
|
+
2
|
|
6441
|
+
];
|
|
6442
|
+
}
|
|
6443
|
+
function buildLakeTierExpression() {
|
|
6444
|
+
const catlak = ["coalesce", ["get", "CATLAK"], ["get", "catlak"], 0];
|
|
6445
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6446
|
+
return [
|
|
6447
|
+
"case",
|
|
6448
|
+
["==", ["to-number", catlak], 1],
|
|
6449
|
+
1,
|
|
6450
|
+
["any", ["==", ["to-number", catlak], 2], ["==", ["to-number", catlak], 3]],
|
|
6451
|
+
2,
|
|
6452
|
+
["<=", ["length", objnam], 12],
|
|
6453
|
+
1,
|
|
6454
|
+
2
|
|
6455
|
+
];
|
|
6456
|
+
}
|
|
6457
|
+
function buildRiverTierExpression() {
|
|
6458
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6459
|
+
return [
|
|
6460
|
+
"case",
|
|
6461
|
+
[
|
|
6462
|
+
"all",
|
|
6463
|
+
["<=", ["length", objnam], 15],
|
|
6464
|
+
["==", ["index-of", ",", objnam], -1]
|
|
6465
|
+
],
|
|
6466
|
+
1,
|
|
6467
|
+
2
|
|
6468
|
+
];
|
|
6469
|
+
}
|
|
6470
|
+
function buildAirportTierExpression() {
|
|
6471
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6472
|
+
return [
|
|
6473
|
+
"case",
|
|
6474
|
+
["<=", ["length", objnam], 25],
|
|
6475
|
+
1,
|
|
6476
|
+
2
|
|
6477
|
+
];
|
|
6478
|
+
}
|
|
5923
6479
|
var COLOR = {
|
|
5924
6480
|
WATER: "#9ec1d8",
|
|
5925
6481
|
WATER_DEEP: "#8fb8d0",
|
|
@@ -5940,6 +6496,30 @@ var ORIENTATION_BAND_SORT_KEY = [
|
|
|
5940
6496
|
["slice", ["coalesce", ["get", "_cell_id"], "??9???"], 2, 3],
|
|
5941
6497
|
9
|
|
5942
6498
|
];
|
|
6499
|
+
function orientationLabelLayout(extras = {}) {
|
|
6500
|
+
return {
|
|
6501
|
+
"text-anchor": "center",
|
|
6502
|
+
"text-allow-overlap": false,
|
|
6503
|
+
"text-ignore-placement": false,
|
|
6504
|
+
"text-optional": true,
|
|
6505
|
+
"text-padding": 15,
|
|
6506
|
+
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY,
|
|
6507
|
+
...extras
|
|
6508
|
+
};
|
|
6509
|
+
}
|
|
6510
|
+
var ORIENTATION_HALO_WIDTH = [
|
|
6511
|
+
"interpolate",
|
|
6512
|
+
["linear"],
|
|
6513
|
+
["zoom"],
|
|
6514
|
+
8,
|
|
6515
|
+
1.6,
|
|
6516
|
+
11,
|
|
6517
|
+
1.5,
|
|
6518
|
+
14,
|
|
6519
|
+
1,
|
|
6520
|
+
16,
|
|
6521
|
+
0.7
|
|
6522
|
+
];
|
|
5943
6523
|
var LABEL_BEHAVIOR = {
|
|
5944
6524
|
// Orientation labels — render once across all bands.
|
|
5945
6525
|
SEAARE: "orientation-cross-band",
|
|
@@ -6054,7 +6634,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6054
6634
|
}
|
|
6055
6635
|
};
|
|
6056
6636
|
}
|
|
6057
|
-
case "LNDRGN":
|
|
6637
|
+
case "LNDRGN": {
|
|
6638
|
+
const tierExpr = buildLandRegionTierExpression();
|
|
6639
|
+
const sizeAt = (t1, t2) => [
|
|
6640
|
+
"match",
|
|
6641
|
+
tierExpr,
|
|
6642
|
+
1,
|
|
6643
|
+
t1,
|
|
6644
|
+
2,
|
|
6645
|
+
t2,
|
|
6646
|
+
t2
|
|
6647
|
+
];
|
|
6058
6648
|
return {
|
|
6059
6649
|
type: "symbol",
|
|
6060
6650
|
textField: ["get", "OBJNAM"],
|
|
@@ -6062,27 +6652,28 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6062
6652
|
"interpolate",
|
|
6063
6653
|
["linear"],
|
|
6064
6654
|
["zoom"],
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6655
|
+
5,
|
|
6656
|
+
sizeAt(9, 0),
|
|
6657
|
+
7,
|
|
6658
|
+
sizeAt(11, 0),
|
|
6659
|
+
9,
|
|
6660
|
+
sizeAt(12, 0),
|
|
6661
|
+
11,
|
|
6662
|
+
sizeAt(12, 9),
|
|
6663
|
+
13,
|
|
6664
|
+
sizeAt(11, 11),
|
|
6665
|
+
16,
|
|
6666
|
+
sizeAt(10, 10)
|
|
6071
6667
|
],
|
|
6072
6668
|
textColor: DARK_BG,
|
|
6073
6669
|
textHaloColor: COLOR.LAND_REGION,
|
|
6074
|
-
textHaloWidth:
|
|
6670
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6075
6671
|
textOffset: [0, 0],
|
|
6076
6672
|
textFont: ["Open Sans Regular"],
|
|
6077
|
-
minzoom:
|
|
6078
|
-
layout:
|
|
6079
|
-
"text-anchor": "center",
|
|
6080
|
-
"text-allow-overlap": false,
|
|
6081
|
-
"text-padding": 6,
|
|
6082
|
-
"text-optional": true,
|
|
6083
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6084
|
-
}
|
|
6673
|
+
minzoom: 5,
|
|
6674
|
+
layout: orientationLabelLayout()
|
|
6085
6675
|
};
|
|
6676
|
+
}
|
|
6086
6677
|
case "LNDMRK":
|
|
6087
6678
|
return {
|
|
6088
6679
|
type: "symbol",
|
|
@@ -6211,40 +6802,72 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6211
6802
|
}
|
|
6212
6803
|
};
|
|
6213
6804
|
}
|
|
6214
|
-
case "SEAARE":
|
|
6805
|
+
case "SEAARE": {
|
|
6806
|
+
const tierExpr = buildSeaAreaTierExpression();
|
|
6807
|
+
const sizeAt = (t1, t2, t3, t4, def) => [
|
|
6808
|
+
"match",
|
|
6809
|
+
tierExpr,
|
|
6810
|
+
1,
|
|
6811
|
+
t1,
|
|
6812
|
+
2,
|
|
6813
|
+
t2,
|
|
6814
|
+
3,
|
|
6815
|
+
t3,
|
|
6816
|
+
4,
|
|
6817
|
+
t4,
|
|
6818
|
+
def
|
|
6819
|
+
];
|
|
6215
6820
|
return {
|
|
6216
6821
|
type: "symbol",
|
|
6217
6822
|
textField: ["get", "OBJNAM"],
|
|
6823
|
+
// Default tier (CATSEA=0, uncategorised: canyons, seamounts, fishing
|
|
6824
|
+
// banks etc.) is suppressed at overview/general/coastal scales because
|
|
6825
|
+
// it floods the overview with hundreds of small italic labels that
|
|
6826
|
+
// crowd out the headline Ocean/Sea/Gulf names. It becomes visible only
|
|
6827
|
+
// at approach scale (z9) when the user has zoomed in enough that
|
|
6828
|
+
// individual banks are useful context.
|
|
6218
6829
|
textSize: [
|
|
6219
6830
|
"interpolate",
|
|
6220
6831
|
["linear"],
|
|
6221
6832
|
["zoom"],
|
|
6833
|
+
3,
|
|
6834
|
+
sizeAt(14, 8, 0, 0, 0),
|
|
6222
6835
|
5,
|
|
6836
|
+
sizeAt(16, 13, 9, 0, 0),
|
|
6837
|
+
7,
|
|
6838
|
+
sizeAt(14, 14, 12, 0, 0),
|
|
6839
|
+
9,
|
|
6840
|
+
sizeAt(12, 13, 14, 0, 9),
|
|
6223
6841
|
11,
|
|
6224
|
-
|
|
6842
|
+
sizeAt(10, 12, 13, 0, 11),
|
|
6225
6843
|
13,
|
|
6226
|
-
11,
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
17
|
|
6844
|
+
sizeAt(9, 11, 12, 10, 11),
|
|
6845
|
+
16,
|
|
6846
|
+
sizeAt(9, 10, 11, 11, 10)
|
|
6230
6847
|
],
|
|
6231
6848
|
textColor: DARK_BG,
|
|
6232
6849
|
textHaloColor: COLOR.WATER_DEEP,
|
|
6233
|
-
textHaloWidth:
|
|
6850
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6234
6851
|
textOffset: [0, 0],
|
|
6235
6852
|
textFont: ["Open Sans Italic"],
|
|
6236
6853
|
minzoom: 5,
|
|
6237
|
-
layout: {
|
|
6238
|
-
"text-anchor": "center",
|
|
6239
|
-
"text-allow-overlap": false,
|
|
6240
|
-
"text-padding": 10,
|
|
6241
|
-
"text-optional": true,
|
|
6854
|
+
layout: orientationLabelLayout({
|
|
6242
6855
|
"text-letter-spacing": 0.15,
|
|
6243
|
-
"text-max-width": 9
|
|
6244
|
-
|
|
6245
|
-
}
|
|
6856
|
+
"text-max-width": 9
|
|
6857
|
+
})
|
|
6246
6858
|
};
|
|
6247
|
-
|
|
6859
|
+
}
|
|
6860
|
+
case "LAKARE": {
|
|
6861
|
+
const tierExpr = buildLakeTierExpression();
|
|
6862
|
+
const sizeAt = (t1, t2) => [
|
|
6863
|
+
"match",
|
|
6864
|
+
tierExpr,
|
|
6865
|
+
1,
|
|
6866
|
+
t1,
|
|
6867
|
+
2,
|
|
6868
|
+
t2,
|
|
6869
|
+
t2
|
|
6870
|
+
];
|
|
6248
6871
|
return {
|
|
6249
6872
|
type: "symbol",
|
|
6250
6873
|
textField: ["get", "OBJNAM"],
|
|
@@ -6252,28 +6875,37 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6252
6875
|
"interpolate",
|
|
6253
6876
|
["linear"],
|
|
6254
6877
|
["zoom"],
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6878
|
+
7,
|
|
6879
|
+
sizeAt(9, 0),
|
|
6880
|
+
9,
|
|
6881
|
+
sizeAt(11, 0),
|
|
6882
|
+
11,
|
|
6883
|
+
sizeAt(11, 9),
|
|
6884
|
+
13,
|
|
6885
|
+
sizeAt(10, 11),
|
|
6886
|
+
16,
|
|
6887
|
+
sizeAt(9, 10)
|
|
6261
6888
|
],
|
|
6262
6889
|
textColor: DARK_BG,
|
|
6263
6890
|
textHaloColor: COLOR.WATER,
|
|
6264
|
-
textHaloWidth:
|
|
6891
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6265
6892
|
textOffset: [0, 0],
|
|
6266
6893
|
textFont: ["Open Sans Italic"],
|
|
6267
|
-
minzoom:
|
|
6268
|
-
layout:
|
|
6269
|
-
"text-anchor": "center",
|
|
6270
|
-
"text-allow-overlap": false,
|
|
6271
|
-
"text-padding": 6,
|
|
6272
|
-
"text-optional": true,
|
|
6273
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6274
|
-
}
|
|
6894
|
+
minzoom: 7,
|
|
6895
|
+
layout: orientationLabelLayout()
|
|
6275
6896
|
};
|
|
6276
|
-
|
|
6897
|
+
}
|
|
6898
|
+
case "RIVERS": {
|
|
6899
|
+
const tierExpr = buildRiverTierExpression();
|
|
6900
|
+
const sizeAt = (t1, t2) => [
|
|
6901
|
+
"match",
|
|
6902
|
+
tierExpr,
|
|
6903
|
+
1,
|
|
6904
|
+
t1,
|
|
6905
|
+
2,
|
|
6906
|
+
t2,
|
|
6907
|
+
t2
|
|
6908
|
+
];
|
|
6277
6909
|
return {
|
|
6278
6910
|
type: "symbol",
|
|
6279
6911
|
textField: ["get", "OBJNAM"],
|
|
@@ -6281,27 +6913,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6281
6913
|
"interpolate",
|
|
6282
6914
|
["linear"],
|
|
6283
6915
|
["zoom"],
|
|
6916
|
+
7,
|
|
6917
|
+
sizeAt(9, 0),
|
|
6284
6918
|
9,
|
|
6285
|
-
|
|
6286
|
-
12,
|
|
6919
|
+
sizeAt(11, 0),
|
|
6287
6920
|
11,
|
|
6288
|
-
|
|
6289
|
-
13
|
|
6921
|
+
sizeAt(11, 9),
|
|
6922
|
+
13,
|
|
6923
|
+
sizeAt(10, 10),
|
|
6924
|
+
16,
|
|
6925
|
+
sizeAt(9, 10)
|
|
6290
6926
|
],
|
|
6291
6927
|
textColor: DARK_BG,
|
|
6292
6928
|
textHaloColor: COLOR.WATER,
|
|
6293
|
-
textHaloWidth:
|
|
6929
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6294
6930
|
textOffset: [0, 0],
|
|
6295
6931
|
textFont: ["Open Sans Italic"],
|
|
6296
|
-
minzoom:
|
|
6297
|
-
layout:
|
|
6298
|
-
"text-anchor": "center",
|
|
6299
|
-
"text-allow-overlap": false,
|
|
6300
|
-
"text-padding": 4,
|
|
6301
|
-
"text-optional": true,
|
|
6302
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6303
|
-
}
|
|
6932
|
+
minzoom: 7,
|
|
6933
|
+
layout: orientationLabelLayout()
|
|
6304
6934
|
};
|
|
6935
|
+
}
|
|
6305
6936
|
case "CANALS":
|
|
6306
6937
|
return {
|
|
6307
6938
|
type: "symbol",
|
|
@@ -6311,25 +6942,31 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6311
6942
|
["linear"],
|
|
6312
6943
|
["zoom"],
|
|
6313
6944
|
11,
|
|
6945
|
+
10,
|
|
6946
|
+
13,
|
|
6314
6947
|
9,
|
|
6315
|
-
|
|
6316
|
-
|
|
6948
|
+
16,
|
|
6949
|
+
9
|
|
6317
6950
|
],
|
|
6318
6951
|
textColor: DARK_BG,
|
|
6319
6952
|
textHaloColor: COLOR.WATER,
|
|
6320
|
-
textHaloWidth:
|
|
6953
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6321
6954
|
textOffset: [0, 0],
|
|
6322
6955
|
textFont: ["Open Sans Italic"],
|
|
6323
6956
|
minzoom: 11,
|
|
6324
|
-
layout:
|
|
6325
|
-
"text-anchor": "center",
|
|
6326
|
-
"text-allow-overlap": false,
|
|
6327
|
-
"text-padding": 4,
|
|
6328
|
-
"text-optional": true,
|
|
6329
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6330
|
-
}
|
|
6957
|
+
layout: orientationLabelLayout()
|
|
6331
6958
|
};
|
|
6332
|
-
case "LNDARE":
|
|
6959
|
+
case "LNDARE": {
|
|
6960
|
+
const tierExpr = buildLandAreaTierExpression();
|
|
6961
|
+
const sizeAt = (t1, t2) => [
|
|
6962
|
+
"match",
|
|
6963
|
+
tierExpr,
|
|
6964
|
+
1,
|
|
6965
|
+
t1,
|
|
6966
|
+
2,
|
|
6967
|
+
t2,
|
|
6968
|
+
t2
|
|
6969
|
+
];
|
|
6333
6970
|
return {
|
|
6334
6971
|
type: "symbol",
|
|
6335
6972
|
textField: ["get", "OBJNAM"],
|
|
@@ -6337,28 +6974,41 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6337
6974
|
"interpolate",
|
|
6338
6975
|
["linear"],
|
|
6339
6976
|
["zoom"],
|
|
6340
|
-
|
|
6977
|
+
5,
|
|
6978
|
+
sizeAt(8, 0),
|
|
6979
|
+
7,
|
|
6980
|
+
sizeAt(10, 0),
|
|
6341
6981
|
9,
|
|
6342
|
-
|
|
6982
|
+
sizeAt(11, 0),
|
|
6343
6983
|
11,
|
|
6344
|
-
|
|
6345
|
-
13
|
|
6984
|
+
sizeAt(11, 9),
|
|
6985
|
+
13,
|
|
6986
|
+
sizeAt(10, 10),
|
|
6987
|
+
16,
|
|
6988
|
+
sizeAt(9, 10)
|
|
6346
6989
|
],
|
|
6347
6990
|
textColor: DARK_BG,
|
|
6348
6991
|
textHaloColor: COLOR.LAND_NATURAL,
|
|
6349
|
-
textHaloWidth:
|
|
6992
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6350
6993
|
textOffset: [0, 0],
|
|
6351
6994
|
textFont: ["Open Sans Regular"],
|
|
6352
|
-
minzoom:
|
|
6353
|
-
layout:
|
|
6354
|
-
"text-anchor": "center",
|
|
6355
|
-
"text-allow-overlap": false,
|
|
6356
|
-
"text-padding": 6,
|
|
6357
|
-
"text-optional": true,
|
|
6358
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6359
|
-
}
|
|
6995
|
+
minzoom: 5,
|
|
6996
|
+
layout: orientationLabelLayout()
|
|
6360
6997
|
};
|
|
6361
|
-
|
|
6998
|
+
}
|
|
6999
|
+
case "BUAARE": {
|
|
7000
|
+
const tierExpr = buildBuiltUpAreaTierExpression();
|
|
7001
|
+
const sizeAt = (t1, t2, t3) => [
|
|
7002
|
+
"match",
|
|
7003
|
+
tierExpr,
|
|
7004
|
+
1,
|
|
7005
|
+
t1,
|
|
7006
|
+
2,
|
|
7007
|
+
t2,
|
|
7008
|
+
3,
|
|
7009
|
+
t3,
|
|
7010
|
+
t3
|
|
7011
|
+
];
|
|
6362
7012
|
return {
|
|
6363
7013
|
type: "symbol",
|
|
6364
7014
|
textField: ["get", "OBJNAM"],
|
|
@@ -6366,28 +7016,32 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6366
7016
|
"interpolate",
|
|
6367
7017
|
["linear"],
|
|
6368
7018
|
["zoom"],
|
|
7019
|
+
3,
|
|
7020
|
+
sizeAt(11, 0, 0),
|
|
7021
|
+
5,
|
|
7022
|
+
sizeAt(13, 0, 0),
|
|
6369
7023
|
7,
|
|
7024
|
+
sizeAt(13, 9, 0),
|
|
7025
|
+
9,
|
|
7026
|
+
sizeAt(12, 12, 0),
|
|
6370
7027
|
11,
|
|
6371
|
-
10,
|
|
7028
|
+
sizeAt(11, 12, 10),
|
|
6372
7029
|
13,
|
|
6373
|
-
|
|
6374
|
-
|
|
7030
|
+
sizeAt(10, 11, 12),
|
|
7031
|
+
16,
|
|
7032
|
+
sizeAt(10, 10, 11)
|
|
6375
7033
|
],
|
|
6376
7034
|
textColor: DARK_BG,
|
|
6377
7035
|
textHaloColor: COLOR.CITY,
|
|
6378
|
-
textHaloWidth:
|
|
7036
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6379
7037
|
textOffset: [0, 0],
|
|
6380
7038
|
textFont: ["Open Sans Regular"],
|
|
6381
|
-
minzoom:
|
|
6382
|
-
layout: {
|
|
6383
|
-
"text-
|
|
6384
|
-
|
|
6385
|
-
"text-padding": 8,
|
|
6386
|
-
"text-optional": true,
|
|
6387
|
-
"text-letter-spacing": 0.05,
|
|
6388
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6389
|
-
}
|
|
7039
|
+
minzoom: 3,
|
|
7040
|
+
layout: orientationLabelLayout({
|
|
7041
|
+
"text-letter-spacing": 0.05
|
|
7042
|
+
})
|
|
6390
7043
|
};
|
|
7044
|
+
}
|
|
6391
7045
|
case "BRIDGE":
|
|
6392
7046
|
return {
|
|
6393
7047
|
type: "symbol",
|
|
@@ -6455,7 +7109,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6455
7109
|
"text-optional": true
|
|
6456
7110
|
}
|
|
6457
7111
|
};
|
|
6458
|
-
case "AIRARE":
|
|
7112
|
+
case "AIRARE": {
|
|
7113
|
+
const tierExpr = buildAirportTierExpression();
|
|
7114
|
+
const sizeAt = (t1, t2) => [
|
|
7115
|
+
"match",
|
|
7116
|
+
tierExpr,
|
|
7117
|
+
1,
|
|
7118
|
+
t1,
|
|
7119
|
+
2,
|
|
7120
|
+
t2,
|
|
7121
|
+
t2
|
|
7122
|
+
];
|
|
6459
7123
|
return {
|
|
6460
7124
|
type: "symbol",
|
|
6461
7125
|
textField: ["get", "OBJNAM"],
|
|
@@ -6463,25 +7127,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6463
7127
|
"interpolate",
|
|
6464
7128
|
["linear"],
|
|
6465
7129
|
["zoom"],
|
|
7130
|
+
7,
|
|
7131
|
+
sizeAt(9, 0),
|
|
6466
7132
|
9,
|
|
6467
|
-
|
|
7133
|
+
sizeAt(11, 0),
|
|
7134
|
+
11,
|
|
7135
|
+
sizeAt(11, 9),
|
|
6468
7136
|
13,
|
|
6469
|
-
|
|
7137
|
+
sizeAt(10, 10),
|
|
7138
|
+
16,
|
|
7139
|
+
sizeAt(9, 9)
|
|
6470
7140
|
],
|
|
6471
7141
|
textColor: DARK_BG,
|
|
6472
7142
|
textHaloColor: COLOR.AIRPORT,
|
|
6473
|
-
textHaloWidth:
|
|
7143
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6474
7144
|
textOffset: [0, 0],
|
|
6475
7145
|
textFont: ["Open Sans Regular"],
|
|
6476
|
-
minzoom:
|
|
6477
|
-
layout:
|
|
6478
|
-
"text-anchor": "center",
|
|
6479
|
-
"text-allow-overlap": false,
|
|
6480
|
-
"text-padding": 5,
|
|
6481
|
-
"text-optional": true,
|
|
6482
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6483
|
-
}
|
|
7146
|
+
minzoom: 7,
|
|
7147
|
+
layout: orientationLabelLayout()
|
|
6484
7148
|
};
|
|
7149
|
+
}
|
|
6485
7150
|
case "SBDARE":
|
|
6486
7151
|
return {
|
|
6487
7152
|
type: "symbol",
|
|
@@ -6554,26 +7219,20 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6554
7219
|
"interpolate",
|
|
6555
7220
|
["linear"],
|
|
6556
7221
|
["zoom"],
|
|
7222
|
+
11,
|
|
7223
|
+
9,
|
|
7224
|
+
13,
|
|
6557
7225
|
8,
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
12,
|
|
6561
|
-
15,
|
|
6562
|
-
14
|
|
7226
|
+
16,
|
|
7227
|
+
8
|
|
6563
7228
|
],
|
|
6564
7229
|
textColor: "#c545c3",
|
|
6565
7230
|
textHaloColor: DARK_BG,
|
|
6566
|
-
textHaloWidth:
|
|
7231
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6567
7232
|
textOffset: [0, 0],
|
|
6568
7233
|
textFont: ["Open Sans Italic"],
|
|
6569
7234
|
minzoom: 8,
|
|
6570
|
-
layout:
|
|
6571
|
-
"text-anchor": "center",
|
|
6572
|
-
"text-allow-overlap": false,
|
|
6573
|
-
"text-padding": 6,
|
|
6574
|
-
"text-optional": true,
|
|
6575
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6576
|
-
}
|
|
7235
|
+
layout: orientationLabelLayout()
|
|
6577
7236
|
};
|
|
6578
7237
|
case "WEDKLP":
|
|
6579
7238
|
return {
|
|
@@ -8680,7 +9339,21 @@ var LINE_FROM_POLYGON_LAYERS = /* @__PURE__ */ new Set([
|
|
|
8680
9339
|
"MIPARE",
|
|
8681
9340
|
"TESARE",
|
|
8682
9341
|
"MAGVAR",
|
|
8683
|
-
"PRDARE"
|
|
9342
|
+
"PRDARE",
|
|
9343
|
+
"TUNNEL",
|
|
9344
|
+
// Jurisdictional zones (INT1 N40–N47) and IMO routing measures
|
|
9345
|
+
// (INT1 M14, M27, M28) — magenta dashed boundary, no fill. Vast
|
|
9346
|
+
// offshore polygons would tint half the chart if flood-filled, so
|
|
9347
|
+
// every member here renders as boundary-only. DWRTCL is not listed
|
|
9348
|
+
// because it's a native LineString class, not a polygon-as-line.
|
|
9349
|
+
// Closes issue #575 rows 8–15.
|
|
9350
|
+
"ADMARE",
|
|
9351
|
+
"COSARE",
|
|
9352
|
+
"CONZNE",
|
|
9353
|
+
"EXEZNE",
|
|
9354
|
+
"TSEZNE",
|
|
9355
|
+
"DWRTPT",
|
|
9356
|
+
"TWRTPT"
|
|
8684
9357
|
]);
|
|
8685
9358
|
var ZOOM_SCALED_LINES2 = {
|
|
8686
9359
|
DEPCNT: [8, 0.3, 14, 0.8],
|
|
@@ -9668,6 +10341,87 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
9668
10341
|
metadata: { "s52:objectClass": "RECTRC", "s52:role": "polygon" }
|
|
9669
10342
|
});
|
|
9670
10343
|
}
|
|
10344
|
+
if (objectClass === "PONTON" && resolved.type === "fill") {
|
|
10345
|
+
layers.push({
|
|
10346
|
+
id: `s52-PONTON-line`,
|
|
10347
|
+
type: "line",
|
|
10348
|
+
source: sourceId,
|
|
10349
|
+
"source-layer": "PONTON",
|
|
10350
|
+
filter: GEOM_FILTERS.line,
|
|
10351
|
+
paint: {
|
|
10352
|
+
"line-color": resolveColor("CHGRF", ct),
|
|
10353
|
+
"line-width": 1.5
|
|
10354
|
+
},
|
|
10355
|
+
metadata: { "s52:objectClass": "PONTON", "s52:role": "line" }
|
|
10356
|
+
});
|
|
10357
|
+
}
|
|
10358
|
+
if (objectClass === "SILTNK" && resolved.type === "symbol") {
|
|
10359
|
+
layers.push({
|
|
10360
|
+
id: `s52-SILTNK-symbol-polygon`,
|
|
10361
|
+
type: "symbol",
|
|
10362
|
+
source: sourceId,
|
|
10363
|
+
"source-layer": "SILTNK",
|
|
10364
|
+
filter: GEOM_FILTERS.fill,
|
|
10365
|
+
layout: {
|
|
10366
|
+
"icon-image": "TNKCON02",
|
|
10367
|
+
"icon-size": 0.6,
|
|
10368
|
+
"icon-allow-overlap": true,
|
|
10369
|
+
"icon-ignore-placement": false,
|
|
10370
|
+
"symbol-placement": "point"
|
|
10371
|
+
},
|
|
10372
|
+
paint: {},
|
|
10373
|
+
metadata: { "s52:objectClass": "SILTNK", "s52:role": "symbol-polygon" }
|
|
10374
|
+
});
|
|
10375
|
+
}
|
|
10376
|
+
if (objectClass === "ACHBRT" && resolved.type === "symbol") {
|
|
10377
|
+
layers.push({
|
|
10378
|
+
id: `s52-ACHBRT-symbol-polygon`,
|
|
10379
|
+
type: "symbol",
|
|
10380
|
+
source: sourceId,
|
|
10381
|
+
"source-layer": "ACHBRT",
|
|
10382
|
+
filter: GEOM_FILTERS.fill,
|
|
10383
|
+
layout: {
|
|
10384
|
+
"icon-image": "ACHARE02",
|
|
10385
|
+
"icon-size": 0.5,
|
|
10386
|
+
"icon-allow-overlap": true,
|
|
10387
|
+
"icon-ignore-placement": false,
|
|
10388
|
+
"symbol-placement": "point"
|
|
10389
|
+
},
|
|
10390
|
+
paint: {},
|
|
10391
|
+
metadata: { "s52:objectClass": "ACHBRT", "s52:role": "symbol-polygon" }
|
|
10392
|
+
});
|
|
10393
|
+
}
|
|
10394
|
+
if (objectClass === "BERTHS" && resolved.type === "line") {
|
|
10395
|
+
layers.push({
|
|
10396
|
+
id: `s52-BERTHS-circle`,
|
|
10397
|
+
type: "circle",
|
|
10398
|
+
source: sourceId,
|
|
10399
|
+
"source-layer": "BERTHS",
|
|
10400
|
+
filter: GEOM_FILTERS.circle,
|
|
10401
|
+
paint: {
|
|
10402
|
+
"circle-color": resolveColor("CHBLK", ct),
|
|
10403
|
+
"circle-radius": ["interpolate", ["linear"], ["zoom"], 12, 1.5, 14, 2.2, 17, 3],
|
|
10404
|
+
"circle-stroke-color": resolveColor("CHBLK", ct),
|
|
10405
|
+
"circle-stroke-width": 0.5
|
|
10406
|
+
},
|
|
10407
|
+
metadata: { "s52:objectClass": "BERTHS", "s52:role": "point" }
|
|
10408
|
+
});
|
|
10409
|
+
}
|
|
10410
|
+
if (objectClass === "TUNNEL" && resolved.type === "line") {
|
|
10411
|
+
layers.push({
|
|
10412
|
+
id: `s52-TUNNEL-line`,
|
|
10413
|
+
type: "line",
|
|
10414
|
+
source: sourceId,
|
|
10415
|
+
"source-layer": "TUNNEL",
|
|
10416
|
+
filter: GEOM_FILTERS.line,
|
|
10417
|
+
paint: {
|
|
10418
|
+
"line-color": resolveColor("CHGRD", ct),
|
|
10419
|
+
"line-width": 1,
|
|
10420
|
+
"line-dasharray": [2, 2]
|
|
10421
|
+
},
|
|
10422
|
+
metadata: { "s52:objectClass": "TUNNEL", "s52:role": "line" }
|
|
10423
|
+
});
|
|
10424
|
+
}
|
|
9671
10425
|
}
|
|
9672
10426
|
return layers;
|
|
9673
10427
|
}
|
|
@@ -9903,9 +10657,21 @@ var META_LAYERS = /* @__PURE__ */ new Set([
|
|
|
9903
10657
|
"M_CSCL",
|
|
9904
10658
|
"TS_FEB",
|
|
9905
10659
|
"TS_TIS",
|
|
9906
|
-
"COSARE",
|
|
9907
|
-
"NEWOBJ",
|
|
9908
10660
|
"LOCMAG"
|
|
10661
|
+
// COSARE was previously suppressed here as meta. The weekly layer-
|
|
10662
|
+
// coverage audit (issue #575) classified it as a jurisdictional polygon
|
|
10663
|
+
// (S-52 INT1 N40, same family as ADMARE / TESARE). It now has an
|
|
10664
|
+
// S52_LOOKUP entry and renders as a magenta dashed boundary; suppressing
|
|
10665
|
+
// it as meta would defeat that wire-up.
|
|
10666
|
+
//
|
|
10667
|
+
// NEWOBJ was likewise previously suppressed here. That was the source
|
|
10668
|
+
// of audit gap row 22: NEWOBJ is the S-57 placeholder for features the
|
|
10669
|
+
// HO has identified but not yet classified. Skipping it silently hid
|
|
10670
|
+
// the HO's own "we don't know what this is, but it is here" signal —
|
|
10671
|
+
// the opposite of what mariners need. The class now renders via its
|
|
10672
|
+
// S52_LOOKUP entry as a vivid magenta circle, displayCategory STANDARD,
|
|
10673
|
+
// scamin 0. Do not put it back here — see the lookup entry for the
|
|
10674
|
+
// safety contract.
|
|
9909
10675
|
]);
|
|
9910
10676
|
var PALETTE_NAMES = {
|
|
9911
10677
|
DAY: "DAY_BRIGHT",
|
|
@@ -9996,21 +10762,45 @@ function makeBandVariants(layer, B) {
|
|
|
9996
10762
|
}
|
|
9997
10763
|
return variants;
|
|
9998
10764
|
}
|
|
9999
|
-
|
|
10765
|
+
var CELL_BAND_OPACITY_CURVE = {
|
|
10766
|
+
"1": [[3, 0.5], [5, 0.3], [16, 0.15]],
|
|
10767
|
+
"2": [[5, 0.5], [7, 0.3], [16, 0.15]],
|
|
10768
|
+
"3": [[7, 0.55], [9, 0.35], [16, 0.18]],
|
|
10769
|
+
"4": [[9, 0.55], [11, 0.35], [16, 0.2]],
|
|
10770
|
+
"5": [[11, 0.6], [13, 0.35], [18, 0.25]],
|
|
10771
|
+
"6": [[13, 0.75], [16, 0.55], [22, 0.45]]
|
|
10772
|
+
};
|
|
10773
|
+
function fanOrientationLabelByCellBand(label) {
|
|
10774
|
+
const cellBandExpr = [
|
|
10775
|
+
"slice",
|
|
10776
|
+
["coalesce", ["get", "_cell_id"], "??9???"],
|
|
10777
|
+
2,
|
|
10778
|
+
3
|
|
10779
|
+
];
|
|
10000
10780
|
const variants = [];
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
if (D === "1") continue;
|
|
10008
|
-
variants.push({
|
|
10781
|
+
for (const code of BAND_DRAW_ORDER) {
|
|
10782
|
+
const range = BAND_PRIORITY_RANGES[code];
|
|
10783
|
+
const curve = CELL_BAND_OPACITY_CURVE[code];
|
|
10784
|
+
const opacityExpr = ["interpolate", ["linear"], ["zoom"]];
|
|
10785
|
+
for (const [z, o] of curve) opacityExpr.push(z, o);
|
|
10786
|
+
const variant = {
|
|
10009
10787
|
...label,
|
|
10010
|
-
id: `${label.id}-
|
|
10011
|
-
filter: combineWithBandFilter(
|
|
10012
|
-
|
|
10013
|
-
|
|
10788
|
+
id: `${label.id}-cell${code}`,
|
|
10789
|
+
filter: combineWithBandFilter(
|
|
10790
|
+
label.filter,
|
|
10791
|
+
["==", cellBandExpr, code]
|
|
10792
|
+
),
|
|
10793
|
+
minzoom: Math.max(
|
|
10794
|
+
label.minzoom ?? range.minzoom,
|
|
10795
|
+
range.minzoom
|
|
10796
|
+
),
|
|
10797
|
+
paint: {
|
|
10798
|
+
...label.paint ?? {},
|
|
10799
|
+
"text-opacity": opacityExpr
|
|
10800
|
+
}
|
|
10801
|
+
};
|
|
10802
|
+
delete variant.maxzoom;
|
|
10803
|
+
variants.push(variant);
|
|
10014
10804
|
}
|
|
10015
10805
|
return variants;
|
|
10016
10806
|
}
|
|
@@ -10134,7 +10924,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
10134
10924
|
for (const { objectClass, label } of bundles) {
|
|
10135
10925
|
if (!label) continue;
|
|
10136
10926
|
if (getLabelBehavior(objectClass) === "orientation-cross-band") {
|
|
10137
|
-
labelLayers.push(...
|
|
10927
|
+
labelLayers.push(...fanOrientationLabelByCellBand(label));
|
|
10138
10928
|
}
|
|
10139
10929
|
}
|
|
10140
10930
|
for (const code of BAND_DRAW_ORDER) {
|