@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.cjs
CHANGED
|
@@ -1412,6 +1412,32 @@ var S52_LOOKUP = {
|
|
|
1412
1412
|
viewingGroup: 13050,
|
|
1413
1413
|
scamin: 45e3
|
|
1414
1414
|
},
|
|
1415
|
+
// Unsurveyed area — a polygon where no reliable hydrographic survey
|
|
1416
|
+
// exists. The IHO S-52 PresLib portrayal is the hatched pattern
|
|
1417
|
+
// UNSURV03 (diagonal lines over a faint grey wash); we don't carry
|
|
1418
|
+
// that sprite, so we lean on the existing OPAQUE_FILLS treatment in
|
|
1419
|
+
// `layer-builder.ts` to force a fully-opaque grey fill that visibly
|
|
1420
|
+
// suppresses anything underneath. The "no data here — don't assume
|
|
1421
|
+
// safe water" signal is the entire point; UNSARE rendering is a BASE
|
|
1422
|
+
// display-category obligation, not an optional cue.
|
|
1423
|
+
//
|
|
1424
|
+
// Note: `UNSARE` is already a member of `OPAQUE_FILLS` and
|
|
1425
|
+
// `OPAQUE_FILL_LAYERS` in `layer-builder.ts` and `style-resolver.ts`
|
|
1426
|
+
// — half-wired before this entry landed. Adding the lookup entry +
|
|
1427
|
+
// draw-order slot completes the wire-up. Surfaced by the
|
|
1428
|
+
// `Audit S-57 Layer Coverage (Weekly)` workflow (issue #575); 5
|
|
1429
|
+
// features in the NOAA corpus, all in remote-Alaska coverage gaps
|
|
1430
|
+
// where survey is genuinely absent.
|
|
1431
|
+
UNSARE: {
|
|
1432
|
+
objectClass: "UNSARE",
|
|
1433
|
+
name: "Unsurveyed Area",
|
|
1434
|
+
category: "Depths",
|
|
1435
|
+
displayCategory: "BASE",
|
|
1436
|
+
int1Ref: "I27",
|
|
1437
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 1 } },
|
|
1438
|
+
viewingGroup: 13050,
|
|
1439
|
+
scamin: 0
|
|
1440
|
+
},
|
|
1415
1441
|
// ── Land & Shoreline (INT1 Section C) ───────────────────
|
|
1416
1442
|
LNDARE: {
|
|
1417
1443
|
objectClass: "LNDARE",
|
|
@@ -1564,6 +1590,51 @@ var S52_LOOKUP = {
|
|
|
1564
1590
|
viewingGroup: 12050,
|
|
1565
1591
|
scamin: 45e3
|
|
1566
1592
|
},
|
|
1593
|
+
// Rapids — direct navigation hazard in narrows / river constrictions. S-52
|
|
1594
|
+
// INT1 C24 portrayal: a stylised wavy line representing turbulent water.
|
|
1595
|
+
// We use a blue dashed line (DEPVS) so the feature reads as a water
|
|
1596
|
+
// disturbance — same colour family as the depth tints, distinct from the
|
|
1597
|
+
// black coastal-construction line family. Surfaced by the weekly layer-
|
|
1598
|
+
// coverage audit (issue #575); 4 features in the NOAA corpus, all in
|
|
1599
|
+
// freshwater approaches where a small craft could be swept onto rocks.
|
|
1600
|
+
RAPIDS: {
|
|
1601
|
+
objectClass: "RAPIDS",
|
|
1602
|
+
name: "Rapids",
|
|
1603
|
+
category: "Hazards",
|
|
1604
|
+
displayCategory: "STANDARD",
|
|
1605
|
+
int1Ref: "C24",
|
|
1606
|
+
style: { type: "line", paint: { "line-color": "DEPVS", "line-width": 1, "line-dasharray": [3, 2] } },
|
|
1607
|
+
viewingGroup: 24020,
|
|
1608
|
+
scamin: 45e3
|
|
1609
|
+
},
|
|
1610
|
+
// Dyke — physical earth/stone embankment that confines water. Same
|
|
1611
|
+
// black-line family as SLCONS / FNCLNE / CAUSWY: solid CHBLK so the
|
|
1612
|
+
// structure reads as a hard man-made shoreline modification. INT1 F8.
|
|
1613
|
+
// Surfaced by the weekly layer-coverage audit (issue #575); 13 features
|
|
1614
|
+
// in the NOAA corpus.
|
|
1615
|
+
DYKCON: {
|
|
1616
|
+
objectClass: "DYKCON",
|
|
1617
|
+
name: "Dyke",
|
|
1618
|
+
category: "Land",
|
|
1619
|
+
displayCategory: "STANDARD",
|
|
1620
|
+
int1Ref: "F8",
|
|
1621
|
+
style: { type: "line", paint: { "line-color": "CHBLK", "line-width": 1 } },
|
|
1622
|
+
viewingGroup: 12410,
|
|
1623
|
+
scamin: 22e3
|
|
1624
|
+
},
|
|
1625
|
+
// Causeway — raised road or rail bed across tidal flats or shallow water
|
|
1626
|
+
// (Cape Cod, the Florida Keys, etc.). Black-line family alongside DYKCON.
|
|
1627
|
+
// INT1 F3. Surfaced by the weekly layer-coverage audit (issue #575).
|
|
1628
|
+
CAUSWY: {
|
|
1629
|
+
objectClass: "CAUSWY",
|
|
1630
|
+
name: "Causeway",
|
|
1631
|
+
category: "Infrastructure",
|
|
1632
|
+
displayCategory: "STANDARD",
|
|
1633
|
+
int1Ref: "F3",
|
|
1634
|
+
style: { type: "line", paint: { "line-color": "CHBLK", "line-width": 1 } },
|
|
1635
|
+
viewingGroup: 12410,
|
|
1636
|
+
scamin: 22e3
|
|
1637
|
+
},
|
|
1567
1638
|
TUNNEL: {
|
|
1568
1639
|
objectClass: "TUNNEL",
|
|
1569
1640
|
name: "Tunnel",
|
|
@@ -1761,6 +1832,13 @@ var S52_LOOKUP = {
|
|
|
1761
1832
|
scamin: 9e4
|
|
1762
1833
|
},
|
|
1763
1834
|
LNDELV: {
|
|
1835
|
+
// LineString variant (land contours) renders normally with the line
|
|
1836
|
+
// style below. Point variant ≈ spot elevation ("12m") on land — per
|
|
1837
|
+
// S-52 PresLib convention, marine displays suppress land spot heights
|
|
1838
|
+
// so they don't compete with safety-critical hydrography. The
|
|
1839
|
+
// `auditIgnore` flag silences the weekly layer-coverage audit for the
|
|
1840
|
+
// Point geom-type only; it does not disable the line rendering. See
|
|
1841
|
+
// #575 triage matrix for the full rationale.
|
|
1764
1842
|
objectClass: "LNDELV",
|
|
1765
1843
|
name: "Land Elevation",
|
|
1766
1844
|
category: "Land",
|
|
@@ -1768,7 +1846,8 @@ var S52_LOOKUP = {
|
|
|
1768
1846
|
int1Ref: "C10",
|
|
1769
1847
|
style: { type: "line", paint: { "line-color": "CHBRN", "line-width": 0.5 } },
|
|
1770
1848
|
viewingGroup: 12070,
|
|
1771
|
-
scamin: 22e3
|
|
1849
|
+
scamin: 22e3,
|
|
1850
|
+
auditIgnore: true
|
|
1772
1851
|
},
|
|
1773
1852
|
// ── Hazards (INT1 Section K) ────────────────────────────
|
|
1774
1853
|
OBSTRN: {
|
|
@@ -1854,7 +1933,15 @@ var S52_LOOKUP = {
|
|
|
1854
1933
|
int1Ref: "J1",
|
|
1855
1934
|
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0.15 } },
|
|
1856
1935
|
viewingGroup: 14010,
|
|
1857
|
-
scamin: 22e3
|
|
1936
|
+
scamin: 22e3,
|
|
1937
|
+
// Point variant (NOAA encodes 2,709 SBDARE Points) is rendered as a
|
|
1938
|
+
// seabed-quality text label ("S"/"M"/"R" per S-52 INT1 J) via the
|
|
1939
|
+
// labels.ts path — see layer-builder.ts SBDARE special-case routing.
|
|
1940
|
+
// The layer-coverage audit script only inspects MapLibre layer filters
|
|
1941
|
+
// from buildLayersForClass(), so it can't see that the Point variant
|
|
1942
|
+
// is in fact rendered. Matches the SOUNDG precedent (auditIgnore +
|
|
1943
|
+
// text-via-labels.ts rendering — see s52-lookup.ts SOUNDG entry).
|
|
1944
|
+
auditIgnore: true
|
|
1858
1945
|
},
|
|
1859
1946
|
WEDKLP: {
|
|
1860
1947
|
// Translucent green fill suggests kelp/vegetation; Point variant (the
|
|
@@ -1871,6 +1958,23 @@ var S52_LOOKUP = {
|
|
|
1871
1958
|
viewingGroup: 14010,
|
|
1872
1959
|
scamin: 22e3
|
|
1873
1960
|
},
|
|
1961
|
+
// Oil barrier — a deployed containment boom corralling spilled oil or
|
|
1962
|
+
// marking the perimeter of a spill-response operation. Operational
|
|
1963
|
+
// hazard: small craft must avoid crossing the line (and the polluted
|
|
1964
|
+
// water it contains). S-52 has no formal INT1 entry, but PresLib
|
|
1965
|
+
// convention for spill-response gear is magenta — matches the rest of
|
|
1966
|
+
// the regulated/operational-area portrayal family. Dashed line so it
|
|
1967
|
+
// reads as a temporary/operational marker rather than a permanent
|
|
1968
|
+
// structure. Surfaced by the weekly layer-coverage audit (issue #575).
|
|
1969
|
+
OILBAR: {
|
|
1970
|
+
objectClass: "OILBAR",
|
|
1971
|
+
name: "Oil Barrier",
|
|
1972
|
+
category: "Hazards",
|
|
1973
|
+
displayCategory: "STANDARD",
|
|
1974
|
+
style: { type: "line", paint: { "line-color": "CHMGD", "line-width": 1, "line-dasharray": [4, 2] } },
|
|
1975
|
+
viewingGroup: 24020,
|
|
1976
|
+
scamin: 45e3
|
|
1977
|
+
},
|
|
1874
1978
|
// ── Regulated Areas (INT1 Section N) ────────────────────
|
|
1875
1979
|
ACHARE: {
|
|
1876
1980
|
// Anchorages are conventionally rendered as a subtle filled region in
|
|
@@ -2044,6 +2148,196 @@ var S52_LOOKUP = {
|
|
|
2044
2148
|
viewingGroup: 26050,
|
|
2045
2149
|
scamin: 9e4
|
|
2046
2150
|
},
|
|
2151
|
+
// ── Jurisdictional zones (INT1 Section N) ───────────────
|
|
2152
|
+
// ADMARE / COSARE / CONZNE / EXEZNE / TESARE share an S-52 portrayal
|
|
2153
|
+
// family: magenta dashed boundary, no fill. These are vast offshore
|
|
2154
|
+
// polygons (EEZ extends 200nm, contiguous zone 24nm) where a flood fill
|
|
2155
|
+
// — even at 0.05 opacity — would visibly tint half the chart and stack
|
|
2156
|
+
// with overlapping jurisdictions into a purple wash. Same boundary-only
|
|
2157
|
+
// pattern as TESARE / RESARE / CTNARE via LINE_FROM_POLYGON_LAYERS.
|
|
2158
|
+
// Surfaced by the weekly layer-coverage audit (issue #575 rows 8–15).
|
|
2159
|
+
ADMARE: {
|
|
2160
|
+
// Administration area — state/national waters, the broadest
|
|
2161
|
+
// jurisdictional polygon class. INT1 N40 maps it into the same
|
|
2162
|
+
// magenta-dashed family as territorial-sea / EEZ / contiguous-zone.
|
|
2163
|
+
objectClass: "ADMARE",
|
|
2164
|
+
name: "Administration Area",
|
|
2165
|
+
category: "Regulated Areas",
|
|
2166
|
+
displayCategory: "STANDARD",
|
|
2167
|
+
int1Ref: "N40",
|
|
2168
|
+
style: {
|
|
2169
|
+
type: "line",
|
|
2170
|
+
paint: {
|
|
2171
|
+
"line-color": "CHMGD",
|
|
2172
|
+
"line-width": 1,
|
|
2173
|
+
"line-dasharray": [6, 4],
|
|
2174
|
+
"line-opacity": 0.6
|
|
2175
|
+
}
|
|
2176
|
+
},
|
|
2177
|
+
viewingGroup: 26010,
|
|
2178
|
+
scamin: 9e4
|
|
2179
|
+
},
|
|
2180
|
+
COSARE: {
|
|
2181
|
+
// Coastal area — jurisdictional polygon delineating a coastal-state
|
|
2182
|
+
// administrative region. Previously suppressed via META_LAYERS in
|
|
2183
|
+
// style-generator.ts; promoted here to render as a magenta dashed
|
|
2184
|
+
// boundary alongside the rest of the N-section jurisdiction family.
|
|
2185
|
+
objectClass: "COSARE",
|
|
2186
|
+
name: "Coastal Area",
|
|
2187
|
+
category: "Regulated Areas",
|
|
2188
|
+
displayCategory: "STANDARD",
|
|
2189
|
+
int1Ref: "N40",
|
|
2190
|
+
style: {
|
|
2191
|
+
type: "line",
|
|
2192
|
+
paint: {
|
|
2193
|
+
"line-color": "CHMGD",
|
|
2194
|
+
"line-width": 1,
|
|
2195
|
+
"line-dasharray": [6, 4],
|
|
2196
|
+
"line-opacity": 0.6
|
|
2197
|
+
}
|
|
2198
|
+
},
|
|
2199
|
+
viewingGroup: 26010,
|
|
2200
|
+
scamin: 9e4
|
|
2201
|
+
},
|
|
2202
|
+
CONZNE: {
|
|
2203
|
+
// Contiguous Zone — 24nm offshore boundary. Same magenta dashed
|
|
2204
|
+
// portrayal as territorial sea; boundary-only because the polygon is
|
|
2205
|
+
// vast and a flood fill would obscure huge swathes of chart data.
|
|
2206
|
+
objectClass: "CONZNE",
|
|
2207
|
+
name: "Contiguous Zone",
|
|
2208
|
+
category: "Regulated Areas",
|
|
2209
|
+
displayCategory: "STANDARD",
|
|
2210
|
+
int1Ref: "N44",
|
|
2211
|
+
style: {
|
|
2212
|
+
type: "line",
|
|
2213
|
+
paint: {
|
|
2214
|
+
"line-color": "CHMGD",
|
|
2215
|
+
"line-width": 1,
|
|
2216
|
+
"line-dasharray": [6, 4],
|
|
2217
|
+
"line-opacity": 0.6
|
|
2218
|
+
}
|
|
2219
|
+
},
|
|
2220
|
+
viewingGroup: 26010,
|
|
2221
|
+
scamin: 9e4
|
|
2222
|
+
},
|
|
2223
|
+
EXEZNE: {
|
|
2224
|
+
// Exclusive Economic Zone — 200nm offshore boundary. Largest of the
|
|
2225
|
+
// jurisdictional polygons; flood-filling even at 0.05 opacity would
|
|
2226
|
+
// tint half the chart at coastal zooms. Boundary-only is the only
|
|
2227
|
+
// sensible portrayal at scale.
|
|
2228
|
+
objectClass: "EXEZNE",
|
|
2229
|
+
name: "Exclusive Economic Zone",
|
|
2230
|
+
category: "Regulated Areas",
|
|
2231
|
+
displayCategory: "STANDARD",
|
|
2232
|
+
int1Ref: "N47",
|
|
2233
|
+
style: {
|
|
2234
|
+
type: "line",
|
|
2235
|
+
paint: {
|
|
2236
|
+
"line-color": "CHMGD",
|
|
2237
|
+
"line-width": 1,
|
|
2238
|
+
"line-dasharray": [6, 4],
|
|
2239
|
+
"line-opacity": 0.6
|
|
2240
|
+
}
|
|
2241
|
+
},
|
|
2242
|
+
viewingGroup: 26010,
|
|
2243
|
+
scamin: 9e4
|
|
2244
|
+
},
|
|
2245
|
+
// ── IMO routing measures (INT1 Section M) ───────────────
|
|
2246
|
+
// TSEZNE / DWRTPT / DWRTCL / TWRTPT are IMO-adopted routing measures
|
|
2247
|
+
// (Traffic Separation Scheme zones, deepwater routes, two-way routes).
|
|
2248
|
+
// S-52 portrayal: magenta dashed boundary for polygons, dashed centerline
|
|
2249
|
+
// for the LineString. The INT1 M-section spec calls for additional
|
|
2250
|
+
// diagonal hatching (TSSCRS01 sprite) on TSEZNE and "DW" centroid text
|
|
2251
|
+
// on DWRTPT — both are deferred follow-ups (TSSCRS01 not in the atlas
|
|
2252
|
+
// sprite set; centroid text belongs in labels.ts). Boundary visibility
|
|
2253
|
+
// is the priority cue here; routing-text augmentation comes later.
|
|
2254
|
+
TSEZNE: {
|
|
2255
|
+
// Traffic Separation Zone — the buffer band between opposing lanes of
|
|
2256
|
+
// a TSS. S-52 INT1 M14 calls for T-pattern diagonal hatching
|
|
2257
|
+
// (TSSCRS01) but that sprite isn't in our generated atlas; fall back
|
|
2258
|
+
// to a magenta dashed boundary so the zone is at least visible.
|
|
2259
|
+
objectClass: "TSEZNE",
|
|
2260
|
+
name: "Traffic Separation Zone",
|
|
2261
|
+
category: "Regulated Areas",
|
|
2262
|
+
displayCategory: "STANDARD",
|
|
2263
|
+
int1Ref: "M14",
|
|
2264
|
+
style: {
|
|
2265
|
+
type: "line",
|
|
2266
|
+
paint: {
|
|
2267
|
+
"line-color": "CHMGD",
|
|
2268
|
+
"line-width": 1.2,
|
|
2269
|
+
"line-dasharray": [4, 3],
|
|
2270
|
+
"line-opacity": 0.7
|
|
2271
|
+
}
|
|
2272
|
+
},
|
|
2273
|
+
viewingGroup: 26010,
|
|
2274
|
+
scamin: 9e4
|
|
2275
|
+
},
|
|
2276
|
+
DWRTPT: {
|
|
2277
|
+
// Deepwater Route Part — polygon segment of an IMO-adopted deepwater
|
|
2278
|
+
// route. S-52 INT1 M27 portrayal includes "DW" centroid text; that's
|
|
2279
|
+
// a labels.ts addition deferred to a follow-up. Boundary-only here.
|
|
2280
|
+
objectClass: "DWRTPT",
|
|
2281
|
+
name: "Deepwater Route Part",
|
|
2282
|
+
category: "Regulated Areas",
|
|
2283
|
+
displayCategory: "STANDARD",
|
|
2284
|
+
int1Ref: "M27",
|
|
2285
|
+
style: {
|
|
2286
|
+
type: "line",
|
|
2287
|
+
paint: {
|
|
2288
|
+
"line-color": "CHMGD",
|
|
2289
|
+
"line-width": 1.2,
|
|
2290
|
+
"line-dasharray": [4, 3],
|
|
2291
|
+
"line-opacity": 0.7
|
|
2292
|
+
}
|
|
2293
|
+
},
|
|
2294
|
+
viewingGroup: 26010,
|
|
2295
|
+
scamin: 9e4
|
|
2296
|
+
},
|
|
2297
|
+
DWRTCL: {
|
|
2298
|
+
// Deepwater Route Centerline — LineString feature (not a polygon
|
|
2299
|
+
// boundary) running down the middle of a DWRTPT. Same magenta dashed
|
|
2300
|
+
// style as MAGVAR isogonic lines but slightly heavier so the
|
|
2301
|
+
// route-axis cue reads against busy water.
|
|
2302
|
+
objectClass: "DWRTCL",
|
|
2303
|
+
name: "Deepwater Route Centerline",
|
|
2304
|
+
category: "Regulated Areas",
|
|
2305
|
+
displayCategory: "STANDARD",
|
|
2306
|
+
int1Ref: "M27",
|
|
2307
|
+
style: {
|
|
2308
|
+
type: "line",
|
|
2309
|
+
paint: {
|
|
2310
|
+
"line-color": "CHMGD",
|
|
2311
|
+
"line-width": 0.8,
|
|
2312
|
+
"line-dasharray": [6, 3],
|
|
2313
|
+
"line-opacity": 0.7
|
|
2314
|
+
}
|
|
2315
|
+
},
|
|
2316
|
+
viewingGroup: 26010,
|
|
2317
|
+
scamin: 9e4
|
|
2318
|
+
},
|
|
2319
|
+
TWRTPT: {
|
|
2320
|
+
// Two-Way Route Part — polygon segment of an IMO-adopted two-way
|
|
2321
|
+
// route. S-52 INT1 M28 portrayal includes paired arrow centroid
|
|
2322
|
+
// symbols (TWRTPT52 / TWRTPT53 sprites exist in the atlas but are a
|
|
2323
|
+
// labels.ts follow-up). Boundary-only here.
|
|
2324
|
+
objectClass: "TWRTPT",
|
|
2325
|
+
name: "Two-Way Route Part",
|
|
2326
|
+
category: "Regulated Areas",
|
|
2327
|
+
displayCategory: "STANDARD",
|
|
2328
|
+
int1Ref: "M28",
|
|
2329
|
+
style: {
|
|
2330
|
+
type: "line",
|
|
2331
|
+
paint: {
|
|
2332
|
+
"line-color": "CHMGD",
|
|
2333
|
+
"line-width": 1.2,
|
|
2334
|
+
"line-dasharray": [4, 3],
|
|
2335
|
+
"line-opacity": 0.7
|
|
2336
|
+
}
|
|
2337
|
+
},
|
|
2338
|
+
viewingGroup: 26010,
|
|
2339
|
+
scamin: 9e4
|
|
2340
|
+
},
|
|
2047
2341
|
// ── Infrastructure (INT1 Sections D, F, L) ──────────────
|
|
2048
2342
|
BRIDGE: {
|
|
2049
2343
|
objectClass: "BRIDGE",
|
|
@@ -2352,6 +2646,56 @@ var S52_LOOKUP = {
|
|
|
2352
2646
|
viewingGroup: 12410,
|
|
2353
2647
|
scamin: 22e3
|
|
2354
2648
|
},
|
|
2649
|
+
// Coast Guard station — emergency-response context. Mariners look for
|
|
2650
|
+
// these when navigating unfamiliar coastline or planning a distress-call
|
|
2651
|
+
// contingency. INT1 F62. Symbolised with the same generic tower glyph
|
|
2652
|
+
// (BCNTOW01) used by BUISGL and the CATLMK=17 LNDMRK variant — a
|
|
2653
|
+
// dedicated CGUSTA SVG is a reasonable follow-up but not required for
|
|
2654
|
+
// the structural-presence cue. Surfaced by the weekly layer-coverage
|
|
2655
|
+
// audit (issue #575); 17 Point features in the NOAA corpus.
|
|
2656
|
+
CGUSTA: {
|
|
2657
|
+
objectClass: "CGUSTA",
|
|
2658
|
+
name: "Coast Guard Station",
|
|
2659
|
+
category: "Infrastructure",
|
|
2660
|
+
displayCategory: "OTHER",
|
|
2661
|
+
int1Ref: "F62",
|
|
2662
|
+
style: { type: "symbol", paint: {}, layout: { "icon-size": 0.6, "icon-allow-overlap": true }, iconImage: "BCNTOW01" },
|
|
2663
|
+
viewingGroup: 12410,
|
|
2664
|
+
scamin: 22e3
|
|
2665
|
+
},
|
|
2666
|
+
// "New Object" — S-57 placeholder class for features the issuing HO has
|
|
2667
|
+
// identified but not yet classified into a more specific class. S-52
|
|
2668
|
+
// PresLib does NOT formally define a portrayal because the class is by
|
|
2669
|
+
// construction not-yet-portrayable, so any distinctive symbol is
|
|
2670
|
+
// permissible — we use a vivid magenta-filled circle with a bold black
|
|
2671
|
+
// stroke so a mariner sees clearly that "there is something unclassified
|
|
2672
|
+
// here." Hiding this class would amount to hiding the HO's own
|
|
2673
|
+
// uncertainty marker, which is the exact opposite of what a chart user
|
|
2674
|
+
// needs. displayCategory: STANDARD (not OTHER) so a default-display
|
|
2675
|
+
// mariner cannot accidentally suppress it; scamin: 0 so the marker
|
|
2676
|
+
// stays visible at every scale band. Surfaced by the weekly layer-
|
|
2677
|
+
// coverage audit (issue #575); 8 Point features in the NOAA corpus.
|
|
2678
|
+
// SAFETY CONTRACT: any future "clean up unused magenta point classes"
|
|
2679
|
+
// pass MUST NOT delete or hide this entry — read the comment block on
|
|
2680
|
+
// issue #575 row 22 before touching.
|
|
2681
|
+
NEWOBJ: {
|
|
2682
|
+
objectClass: "NEWOBJ",
|
|
2683
|
+
name: "New Object (Unclassified)",
|
|
2684
|
+
category: "Hazards",
|
|
2685
|
+
displayCategory: "STANDARD",
|
|
2686
|
+
style: {
|
|
2687
|
+
type: "circle",
|
|
2688
|
+
paint: {
|
|
2689
|
+
"circle-color": "CHMGD",
|
|
2690
|
+
"circle-radius": 5,
|
|
2691
|
+
"circle-stroke-color": "CHBLK",
|
|
2692
|
+
"circle-stroke-width": 1.2,
|
|
2693
|
+
"circle-opacity": 0.85
|
|
2694
|
+
}
|
|
2695
|
+
},
|
|
2696
|
+
viewingGroup: 24020,
|
|
2697
|
+
scamin: 0
|
|
2698
|
+
},
|
|
2355
2699
|
// ── Overhead & Underground (INT1 Section L) ─────────────
|
|
2356
2700
|
// Overhead cable — S-52 INT1 L31 portrayal: solid thin magenta line
|
|
2357
2701
|
// (not dashed) because overhead cables are an in-air navigation hazard
|
|
@@ -2403,6 +2747,11 @@ var S52_LOOKUP = {
|
|
|
2403
2747
|
// when the sprite image is missing; `fill-pattern` here is the default
|
|
2404
2748
|
// used if the conditional expression isn't applied for some reason
|
|
2405
2749
|
// (e.g. a consumer that bypasses `resolvePaint`).
|
|
2750
|
+
//
|
|
2751
|
+
// Polygon (vegetation fill) is the primary variant. The Point variant
|
|
2752
|
+
// ≈ a single marker tree; sub-marine-relevance, so `auditIgnore`
|
|
2753
|
+
// silences the audit for the Point geom-type without touching the
|
|
2754
|
+
// Polygon rendering. See #575 triage matrix.
|
|
2406
2755
|
style: {
|
|
2407
2756
|
type: "fill",
|
|
2408
2757
|
paint: { "fill-color": "LANDF", "fill-opacity": 0.6, "fill-pattern": "VEGATN03" }
|
|
@@ -2410,7 +2759,8 @@ var S52_LOOKUP = {
|
|
|
2410
2759
|
hasConditional: true,
|
|
2411
2760
|
conditionalAttributes: ["CATVEG"],
|
|
2412
2761
|
viewingGroup: 12050,
|
|
2413
|
-
scamin: 22e3
|
|
2762
|
+
scamin: 22e3,
|
|
2763
|
+
auditIgnore: true
|
|
2414
2764
|
},
|
|
2415
2765
|
SEAARE: {
|
|
2416
2766
|
// Cross-band water base. SEAARE polygons tile the sea below the
|
|
@@ -2589,6 +2939,42 @@ var S52_LOOKUP = {
|
|
|
2589
2939
|
viewingGroup: 23010,
|
|
2590
2940
|
scamin: 0
|
|
2591
2941
|
},
|
|
2942
|
+
// ── Audit-ignored stubs (non-metadata) ──────────────────
|
|
2943
|
+
// Classes whose non-rendering is a deliberate S-52 portrayal choice
|
|
2944
|
+
// rather than a real gap, but which aren't S-57 metadata. Each is
|
|
2945
|
+
// present here only so the weekly layer-coverage audit (#575) stops
|
|
2946
|
+
// flagging it as missing. Paint is a transparent fill — no visible
|
|
2947
|
+
// output. Swapping `auditIgnore: true` for a real style is a one-line
|
|
2948
|
+
// change if the call ever needs to be reversed.
|
|
2949
|
+
SLOTOP: {
|
|
2950
|
+
// Top of slope — land terrain feature, low marine relevance.
|
|
2951
|
+
objectClass: "SLOTOP",
|
|
2952
|
+
name: "Top of Slope",
|
|
2953
|
+
category: "Land",
|
|
2954
|
+
displayCategory: "OTHER",
|
|
2955
|
+
int1Ref: "C12",
|
|
2956
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2957
|
+
auditIgnore: true
|
|
2958
|
+
},
|
|
2959
|
+
SNDWAV: {
|
|
2960
|
+
// Sand waves — niche bathymetric texture feature, not a hazard.
|
|
2961
|
+
objectClass: "SNDWAV",
|
|
2962
|
+
name: "Sand Waves",
|
|
2963
|
+
category: "Depths",
|
|
2964
|
+
displayCategory: "OTHER",
|
|
2965
|
+
int1Ref: "J14",
|
|
2966
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2967
|
+
auditIgnore: true
|
|
2968
|
+
},
|
|
2969
|
+
CTRPNT: {
|
|
2970
|
+
// Centerline point — geometric helper, not a feature on the chart.
|
|
2971
|
+
objectClass: "CTRPNT",
|
|
2972
|
+
name: "Centerline Point",
|
|
2973
|
+
category: "Meta",
|
|
2974
|
+
displayCategory: "OTHER",
|
|
2975
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2976
|
+
auditIgnore: true
|
|
2977
|
+
},
|
|
2592
2978
|
// ── Meta (hidden by default) ────────────────────────────
|
|
2593
2979
|
// M_* and DSID are S-57 metadata classes — they describe the dataset
|
|
2594
2980
|
// (coverage extent, survey reliability, source publication, etc.) and
|
|
@@ -2627,6 +3013,17 @@ var S52_LOOKUP = {
|
|
|
2627
3013
|
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
2628
3014
|
auditIgnore: true
|
|
2629
3015
|
},
|
|
3016
|
+
M_SDAT: {
|
|
3017
|
+
// Sounding Datum — S-57 metadata describing the vertical datum used
|
|
3018
|
+
// for soundings (typically LAT). Click-query attribute carrier; no
|
|
3019
|
+
// visible shape on its own.
|
|
3020
|
+
objectClass: "M_SDAT",
|
|
3021
|
+
name: "Sounding Datum",
|
|
3022
|
+
category: "Meta",
|
|
3023
|
+
displayCategory: "META",
|
|
3024
|
+
style: { type: "fill", paint: { "fill-color": "CHGRF", "fill-opacity": 0 } },
|
|
3025
|
+
auditIgnore: true
|
|
3026
|
+
},
|
|
2630
3027
|
M_SREL: {
|
|
2631
3028
|
objectClass: "M_SREL",
|
|
2632
3029
|
name: "Survey Reliability",
|
|
@@ -2666,6 +3063,16 @@ var S52_DRAW_ORDER = [
|
|
|
2666
3063
|
// paired paint-spec change (fill-opacity 0 → 1, color → DEPDW).
|
|
2667
3064
|
"SEAARE",
|
|
2668
3065
|
"DEPARE",
|
|
3066
|
+
// 2a. Unsurveyed area — opaque grey wash painted ON TOP of any DEPARE
|
|
3067
|
+
// tile within its extent so depth-tier colours can never imply the area
|
|
3068
|
+
// is surveyed-and-safe. If both DEPARE and UNSARE cover the same pixel,
|
|
3069
|
+
// UNSARE wins on purpose: the hydrographic office classified the polygon
|
|
3070
|
+
// as unsurveyed, so any depth data within it is suspect at best. Sits
|
|
3071
|
+
// below dredged / swept (which represent active survey work) so those
|
|
3072
|
+
// appear if they overlap UNSARE — but in practice they don't, and the
|
|
3073
|
+
// ordering is the safer fallback. Surfaced by the weekly layer-coverage
|
|
3074
|
+
// audit (issue #575); see s52-lookup.ts UNSARE entry for context.
|
|
3075
|
+
"UNSARE",
|
|
2669
3076
|
// 3. Dredged / swept areas (fill)
|
|
2670
3077
|
"DRGARE",
|
|
2671
3078
|
"SWPARE",
|
|
@@ -2703,6 +3110,17 @@ var S52_DRAW_ORDER = [
|
|
|
2703
3110
|
"LOGPON",
|
|
2704
3111
|
"CBLARE",
|
|
2705
3112
|
"PIPARE",
|
|
3113
|
+
// 6a. Jurisdictional zones + IMO routing measures (boundary-only via
|
|
3114
|
+
// LINE_FROM_POLYGON_LAYERS). Slotted at the end of the regulated-area
|
|
3115
|
+
// band so the dashed magenta boundaries paint above the fill family
|
|
3116
|
+
// but below shoreline / depth-contour lines. Closes #575 rows 8–15.
|
|
3117
|
+
"ADMARE",
|
|
3118
|
+
"COSARE",
|
|
3119
|
+
"CONZNE",
|
|
3120
|
+
"EXEZNE",
|
|
3121
|
+
"TSEZNE",
|
|
3122
|
+
"DWRTPT",
|
|
3123
|
+
"TWRTPT",
|
|
2706
3124
|
// 7. Infrastructure areas (fill)
|
|
2707
3125
|
"PONTON",
|
|
2708
3126
|
"HULKES",
|
|
@@ -2712,8 +3130,13 @@ var S52_DRAW_ORDER = [
|
|
|
2712
3130
|
"PYLONS",
|
|
2713
3131
|
"FORSTC",
|
|
2714
3132
|
// 8. Coastline / shore (line)
|
|
3133
|
+
// DYKCON (dyke) and CAUSWY (causeway) join the SLCONS family — solid
|
|
3134
|
+
// black lines representing man-made shoreline modifications. Drawn in
|
|
3135
|
+
// the same band so they layer consistently with adjacent SLCONS edges.
|
|
2715
3136
|
"COALNE",
|
|
2716
3137
|
"SLCONS",
|
|
3138
|
+
"DYKCON",
|
|
3139
|
+
"CAUSWY",
|
|
2717
3140
|
"FNCLNE",
|
|
2718
3141
|
// 9. Depth contours (line)
|
|
2719
3142
|
"DEPCNT",
|
|
@@ -2724,13 +3147,20 @@ var S52_DRAW_ORDER = [
|
|
|
2724
3147
|
// routing and aids-to-nav win the visual hierarchy).
|
|
2725
3148
|
"MAGVAR",
|
|
2726
3149
|
// 10. Navigation lines (line)
|
|
3150
|
+
// RAPIDS and OILBAR are direct/operational water hazards. RAPIDS uses
|
|
3151
|
+
// the depth-blue palette (DEPVS dashed) so the feature reads as a
|
|
3152
|
+
// water-surface disturbance; OILBAR uses CHMGD to fit the operational-
|
|
3153
|
+
// hazard family alongside cables / pipelines.
|
|
2727
3154
|
"NAVLNE",
|
|
2728
3155
|
"TSSBND",
|
|
3156
|
+
"DWRTCL",
|
|
2729
3157
|
"ROADWY",
|
|
2730
3158
|
"RAILWY",
|
|
2731
3159
|
"TUNNEL",
|
|
2732
3160
|
"FERYRT",
|
|
2733
3161
|
"RECTRC",
|
|
3162
|
+
"RAPIDS",
|
|
3163
|
+
"OILBAR",
|
|
2734
3164
|
"PIPSOL",
|
|
2735
3165
|
"PIPOHD",
|
|
2736
3166
|
"CBLSUB",
|
|
@@ -2739,6 +3169,11 @@ var S52_DRAW_ORDER = [
|
|
|
2739
3169
|
"DAMCON",
|
|
2740
3170
|
"BERTHS",
|
|
2741
3171
|
// 11. Point features
|
|
3172
|
+
// CGUSTA (coast guard station, emergency-context) sits with the building
|
|
3173
|
+
// / landmark family — a structural-presence cue rather than a routing
|
|
3174
|
+
// signal. NEWOBJ ("something here we haven't classified yet") goes at
|
|
3175
|
+
// the END of the point list so the distinctive magenta marker stays on
|
|
3176
|
+
// top of neighbouring point features and cannot be visually swallowed.
|
|
2742
3177
|
"SOUNDG",
|
|
2743
3178
|
"MORFAC",
|
|
2744
3179
|
"PILPNT",
|
|
@@ -2752,6 +3187,8 @@ var S52_DRAW_ORDER = [
|
|
|
2752
3187
|
"CRANES",
|
|
2753
3188
|
"DISMAR",
|
|
2754
3189
|
"ACHBRT",
|
|
3190
|
+
"CGUSTA",
|
|
3191
|
+
"NEWOBJ",
|
|
2755
3192
|
// 12. Nav aids (on top)
|
|
2756
3193
|
"FOGSIG",
|
|
2757
3194
|
"RTPBCN",
|
|
@@ -5369,6 +5806,7 @@ var SYMBOL_MAP = {
|
|
|
5369
5806
|
PILBOP: "PILBOP02",
|
|
5370
5807
|
SISTAT: "SISTAT02",
|
|
5371
5808
|
SMCFAC: "ACHARE02",
|
|
5809
|
+
CGUSTA: "BCNTOW01",
|
|
5372
5810
|
// Land infrastructure
|
|
5373
5811
|
SILTNK: "TNKCON02",
|
|
5374
5812
|
BUISGL: "BCNTOW01",
|
|
@@ -6025,6 +6463,124 @@ function buildSeabedLabelExpression() {
|
|
|
6025
6463
|
const natsurJoined = ["slice", natsurParts, 1];
|
|
6026
6464
|
return ["concat", natquaPrefix, natsurJoined];
|
|
6027
6465
|
}
|
|
6466
|
+
function buildSeaAreaTierExpression() {
|
|
6467
|
+
const catsea = ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0];
|
|
6468
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6469
|
+
return [
|
|
6470
|
+
"case",
|
|
6471
|
+
// Tier 1 — Ocean (CATSEA=31 OR OBJNAM contains "Ocean", excluding
|
|
6472
|
+
// anchorage-area-style compound names which we filter on later).
|
|
6473
|
+
["==", ["to-number", catsea], 31],
|
|
6474
|
+
1,
|
|
6475
|
+
["any", ["==", ["to-number", catsea], 29], ["==", ["to-number", catsea], 30]],
|
|
6476
|
+
2,
|
|
6477
|
+
[
|
|
6478
|
+
"any",
|
|
6479
|
+
["==", ["to-number", catsea], 4],
|
|
6480
|
+
["==", ["to-number", catsea], 11],
|
|
6481
|
+
["==", ["to-number", catsea], 27],
|
|
6482
|
+
["==", ["to-number", catsea], 28]
|
|
6483
|
+
],
|
|
6484
|
+
3,
|
|
6485
|
+
// Tier 4 — Anchorage detail (must be checked before OBJNAM-substring
|
|
6486
|
+
// promotion so "Boston Harbor, MA …" anchorages don't bubble up).
|
|
6487
|
+
[">=", ["index-of", "Anchorage Area", objnam], 0],
|
|
6488
|
+
4,
|
|
6489
|
+
// OBJNAM-substring promotion shims (run AFTER tier 4 demotion):
|
|
6490
|
+
[">=", ["index-of", "Atlantic Ocean", objnam], 0],
|
|
6491
|
+
1,
|
|
6492
|
+
[">=", ["index-of", "Pacific Ocean", objnam], 0],
|
|
6493
|
+
1,
|
|
6494
|
+
[">=", ["index-of", "Arctic Ocean", objnam], 0],
|
|
6495
|
+
1,
|
|
6496
|
+
[">=", ["index-of", "Gulf of", objnam], 0],
|
|
6497
|
+
2,
|
|
6498
|
+
// Bay/Sound/Sea/Strait/Channel as a tier-3 shim (matches "Massachusetts
|
|
6499
|
+
// Bay", "Buzzards Bay", "Long Island Sound", "Block Island Sound",
|
|
6500
|
+
// "Vineyard Sound", "Cape Cod Bay", etc. without needing CATSEA).
|
|
6501
|
+
[">=", ["index-of", " Bay", objnam], 0],
|
|
6502
|
+
3,
|
|
6503
|
+
[">=", ["index-of", " Sound", objnam], 0],
|
|
6504
|
+
3,
|
|
6505
|
+
[">=", ["index-of", " Strait", objnam], 0],
|
|
6506
|
+
3,
|
|
6507
|
+
[">=", ["index-of", " Sea", objnam], 0],
|
|
6508
|
+
2,
|
|
6509
|
+
5
|
|
6510
|
+
];
|
|
6511
|
+
}
|
|
6512
|
+
function buildBuiltUpAreaTierExpression() {
|
|
6513
|
+
const catbua = ["coalesce", ["get", "CATBUA"], ["get", "catbua"], 0];
|
|
6514
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6515
|
+
const nameLen = ["length", objnam];
|
|
6516
|
+
return [
|
|
6517
|
+
"case",
|
|
6518
|
+
["==", ["to-number", catbua], 1],
|
|
6519
|
+
1,
|
|
6520
|
+
["==", ["to-number", catbua], 5],
|
|
6521
|
+
2,
|
|
6522
|
+
["<=", nameLen, 8],
|
|
6523
|
+
1,
|
|
6524
|
+
["<=", nameLen, 14],
|
|
6525
|
+
2,
|
|
6526
|
+
3
|
|
6527
|
+
];
|
|
6528
|
+
}
|
|
6529
|
+
function buildLandRegionTierExpression() {
|
|
6530
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6531
|
+
const nameLen = ["length", objnam];
|
|
6532
|
+
return [
|
|
6533
|
+
"case",
|
|
6534
|
+
["all", ["<=", nameLen, 12], ["==", ["index-of", ",", objnam], -1]],
|
|
6535
|
+
1,
|
|
6536
|
+
2
|
|
6537
|
+
];
|
|
6538
|
+
}
|
|
6539
|
+
function buildLandAreaTierExpression() {
|
|
6540
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6541
|
+
return [
|
|
6542
|
+
"case",
|
|
6543
|
+
["<=", ["length", objnam], 12],
|
|
6544
|
+
1,
|
|
6545
|
+
2
|
|
6546
|
+
];
|
|
6547
|
+
}
|
|
6548
|
+
function buildLakeTierExpression() {
|
|
6549
|
+
const catlak = ["coalesce", ["get", "CATLAK"], ["get", "catlak"], 0];
|
|
6550
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6551
|
+
return [
|
|
6552
|
+
"case",
|
|
6553
|
+
["==", ["to-number", catlak], 1],
|
|
6554
|
+
1,
|
|
6555
|
+
["any", ["==", ["to-number", catlak], 2], ["==", ["to-number", catlak], 3]],
|
|
6556
|
+
2,
|
|
6557
|
+
["<=", ["length", objnam], 12],
|
|
6558
|
+
1,
|
|
6559
|
+
2
|
|
6560
|
+
];
|
|
6561
|
+
}
|
|
6562
|
+
function buildRiverTierExpression() {
|
|
6563
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6564
|
+
return [
|
|
6565
|
+
"case",
|
|
6566
|
+
[
|
|
6567
|
+
"all",
|
|
6568
|
+
["<=", ["length", objnam], 15],
|
|
6569
|
+
["==", ["index-of", ",", objnam], -1]
|
|
6570
|
+
],
|
|
6571
|
+
1,
|
|
6572
|
+
2
|
|
6573
|
+
];
|
|
6574
|
+
}
|
|
6575
|
+
function buildAirportTierExpression() {
|
|
6576
|
+
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6577
|
+
return [
|
|
6578
|
+
"case",
|
|
6579
|
+
["<=", ["length", objnam], 25],
|
|
6580
|
+
1,
|
|
6581
|
+
2
|
|
6582
|
+
];
|
|
6583
|
+
}
|
|
6028
6584
|
var COLOR = {
|
|
6029
6585
|
WATER: "#9ec1d8",
|
|
6030
6586
|
WATER_DEEP: "#8fb8d0",
|
|
@@ -6045,6 +6601,30 @@ var ORIENTATION_BAND_SORT_KEY = [
|
|
|
6045
6601
|
["slice", ["coalesce", ["get", "_cell_id"], "??9???"], 2, 3],
|
|
6046
6602
|
9
|
|
6047
6603
|
];
|
|
6604
|
+
function orientationLabelLayout(extras = {}) {
|
|
6605
|
+
return {
|
|
6606
|
+
"text-anchor": "center",
|
|
6607
|
+
"text-allow-overlap": false,
|
|
6608
|
+
"text-ignore-placement": false,
|
|
6609
|
+
"text-optional": true,
|
|
6610
|
+
"text-padding": 15,
|
|
6611
|
+
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY,
|
|
6612
|
+
...extras
|
|
6613
|
+
};
|
|
6614
|
+
}
|
|
6615
|
+
var ORIENTATION_HALO_WIDTH = [
|
|
6616
|
+
"interpolate",
|
|
6617
|
+
["linear"],
|
|
6618
|
+
["zoom"],
|
|
6619
|
+
8,
|
|
6620
|
+
1.6,
|
|
6621
|
+
11,
|
|
6622
|
+
1.5,
|
|
6623
|
+
14,
|
|
6624
|
+
1,
|
|
6625
|
+
16,
|
|
6626
|
+
0.7
|
|
6627
|
+
];
|
|
6048
6628
|
var LABEL_BEHAVIOR = {
|
|
6049
6629
|
// Orientation labels — render once across all bands.
|
|
6050
6630
|
SEAARE: "orientation-cross-band",
|
|
@@ -6159,7 +6739,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6159
6739
|
}
|
|
6160
6740
|
};
|
|
6161
6741
|
}
|
|
6162
|
-
case "LNDRGN":
|
|
6742
|
+
case "LNDRGN": {
|
|
6743
|
+
const tierExpr = buildLandRegionTierExpression();
|
|
6744
|
+
const sizeAt = (t1, t2) => [
|
|
6745
|
+
"match",
|
|
6746
|
+
tierExpr,
|
|
6747
|
+
1,
|
|
6748
|
+
t1,
|
|
6749
|
+
2,
|
|
6750
|
+
t2,
|
|
6751
|
+
t2
|
|
6752
|
+
];
|
|
6163
6753
|
return {
|
|
6164
6754
|
type: "symbol",
|
|
6165
6755
|
textField: ["get", "OBJNAM"],
|
|
@@ -6167,27 +6757,28 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6167
6757
|
"interpolate",
|
|
6168
6758
|
["linear"],
|
|
6169
6759
|
["zoom"],
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6760
|
+
5,
|
|
6761
|
+
sizeAt(9, 0),
|
|
6762
|
+
7,
|
|
6763
|
+
sizeAt(11, 0),
|
|
6764
|
+
9,
|
|
6765
|
+
sizeAt(12, 0),
|
|
6766
|
+
11,
|
|
6767
|
+
sizeAt(12, 9),
|
|
6768
|
+
13,
|
|
6769
|
+
sizeAt(11, 11),
|
|
6770
|
+
16,
|
|
6771
|
+
sizeAt(10, 10)
|
|
6176
6772
|
],
|
|
6177
6773
|
textColor: DARK_BG,
|
|
6178
6774
|
textHaloColor: COLOR.LAND_REGION,
|
|
6179
|
-
textHaloWidth:
|
|
6775
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6180
6776
|
textOffset: [0, 0],
|
|
6181
6777
|
textFont: ["Open Sans Regular"],
|
|
6182
|
-
minzoom:
|
|
6183
|
-
layout:
|
|
6184
|
-
"text-anchor": "center",
|
|
6185
|
-
"text-allow-overlap": false,
|
|
6186
|
-
"text-padding": 6,
|
|
6187
|
-
"text-optional": true,
|
|
6188
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6189
|
-
}
|
|
6778
|
+
minzoom: 5,
|
|
6779
|
+
layout: orientationLabelLayout()
|
|
6190
6780
|
};
|
|
6781
|
+
}
|
|
6191
6782
|
case "LNDMRK":
|
|
6192
6783
|
return {
|
|
6193
6784
|
type: "symbol",
|
|
@@ -6316,40 +6907,72 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6316
6907
|
}
|
|
6317
6908
|
};
|
|
6318
6909
|
}
|
|
6319
|
-
case "SEAARE":
|
|
6910
|
+
case "SEAARE": {
|
|
6911
|
+
const tierExpr = buildSeaAreaTierExpression();
|
|
6912
|
+
const sizeAt = (t1, t2, t3, t4, def) => [
|
|
6913
|
+
"match",
|
|
6914
|
+
tierExpr,
|
|
6915
|
+
1,
|
|
6916
|
+
t1,
|
|
6917
|
+
2,
|
|
6918
|
+
t2,
|
|
6919
|
+
3,
|
|
6920
|
+
t3,
|
|
6921
|
+
4,
|
|
6922
|
+
t4,
|
|
6923
|
+
def
|
|
6924
|
+
];
|
|
6320
6925
|
return {
|
|
6321
6926
|
type: "symbol",
|
|
6322
6927
|
textField: ["get", "OBJNAM"],
|
|
6928
|
+
// Default tier (CATSEA=0, uncategorised: canyons, seamounts, fishing
|
|
6929
|
+
// banks etc.) is suppressed at overview/general/coastal scales because
|
|
6930
|
+
// it floods the overview with hundreds of small italic labels that
|
|
6931
|
+
// crowd out the headline Ocean/Sea/Gulf names. It becomes visible only
|
|
6932
|
+
// at approach scale (z9) when the user has zoomed in enough that
|
|
6933
|
+
// individual banks are useful context.
|
|
6323
6934
|
textSize: [
|
|
6324
6935
|
"interpolate",
|
|
6325
6936
|
["linear"],
|
|
6326
6937
|
["zoom"],
|
|
6938
|
+
3,
|
|
6939
|
+
sizeAt(14, 8, 0, 0, 0),
|
|
6327
6940
|
5,
|
|
6941
|
+
sizeAt(16, 13, 9, 0, 0),
|
|
6942
|
+
7,
|
|
6943
|
+
sizeAt(14, 14, 12, 0, 0),
|
|
6944
|
+
9,
|
|
6945
|
+
sizeAt(12, 13, 14, 0, 9),
|
|
6328
6946
|
11,
|
|
6329
|
-
|
|
6947
|
+
sizeAt(10, 12, 13, 0, 11),
|
|
6330
6948
|
13,
|
|
6331
|
-
11,
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
17
|
|
6949
|
+
sizeAt(9, 11, 12, 10, 11),
|
|
6950
|
+
16,
|
|
6951
|
+
sizeAt(9, 10, 11, 11, 10)
|
|
6335
6952
|
],
|
|
6336
6953
|
textColor: DARK_BG,
|
|
6337
6954
|
textHaloColor: COLOR.WATER_DEEP,
|
|
6338
|
-
textHaloWidth:
|
|
6955
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6339
6956
|
textOffset: [0, 0],
|
|
6340
6957
|
textFont: ["Open Sans Italic"],
|
|
6341
6958
|
minzoom: 5,
|
|
6342
|
-
layout: {
|
|
6343
|
-
"text-anchor": "center",
|
|
6344
|
-
"text-allow-overlap": false,
|
|
6345
|
-
"text-padding": 10,
|
|
6346
|
-
"text-optional": true,
|
|
6959
|
+
layout: orientationLabelLayout({
|
|
6347
6960
|
"text-letter-spacing": 0.15,
|
|
6348
|
-
"text-max-width": 9
|
|
6349
|
-
|
|
6350
|
-
}
|
|
6961
|
+
"text-max-width": 9
|
|
6962
|
+
})
|
|
6351
6963
|
};
|
|
6352
|
-
|
|
6964
|
+
}
|
|
6965
|
+
case "LAKARE": {
|
|
6966
|
+
const tierExpr = buildLakeTierExpression();
|
|
6967
|
+
const sizeAt = (t1, t2) => [
|
|
6968
|
+
"match",
|
|
6969
|
+
tierExpr,
|
|
6970
|
+
1,
|
|
6971
|
+
t1,
|
|
6972
|
+
2,
|
|
6973
|
+
t2,
|
|
6974
|
+
t2
|
|
6975
|
+
];
|
|
6353
6976
|
return {
|
|
6354
6977
|
type: "symbol",
|
|
6355
6978
|
textField: ["get", "OBJNAM"],
|
|
@@ -6357,28 +6980,37 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6357
6980
|
"interpolate",
|
|
6358
6981
|
["linear"],
|
|
6359
6982
|
["zoom"],
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6983
|
+
7,
|
|
6984
|
+
sizeAt(9, 0),
|
|
6985
|
+
9,
|
|
6986
|
+
sizeAt(11, 0),
|
|
6987
|
+
11,
|
|
6988
|
+
sizeAt(11, 9),
|
|
6989
|
+
13,
|
|
6990
|
+
sizeAt(10, 11),
|
|
6991
|
+
16,
|
|
6992
|
+
sizeAt(9, 10)
|
|
6366
6993
|
],
|
|
6367
6994
|
textColor: DARK_BG,
|
|
6368
6995
|
textHaloColor: COLOR.WATER,
|
|
6369
|
-
textHaloWidth:
|
|
6996
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6370
6997
|
textOffset: [0, 0],
|
|
6371
6998
|
textFont: ["Open Sans Italic"],
|
|
6372
|
-
minzoom:
|
|
6373
|
-
layout:
|
|
6374
|
-
"text-anchor": "center",
|
|
6375
|
-
"text-allow-overlap": false,
|
|
6376
|
-
"text-padding": 6,
|
|
6377
|
-
"text-optional": true,
|
|
6378
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6379
|
-
}
|
|
6999
|
+
minzoom: 7,
|
|
7000
|
+
layout: orientationLabelLayout()
|
|
6380
7001
|
};
|
|
6381
|
-
|
|
7002
|
+
}
|
|
7003
|
+
case "RIVERS": {
|
|
7004
|
+
const tierExpr = buildRiverTierExpression();
|
|
7005
|
+
const sizeAt = (t1, t2) => [
|
|
7006
|
+
"match",
|
|
7007
|
+
tierExpr,
|
|
7008
|
+
1,
|
|
7009
|
+
t1,
|
|
7010
|
+
2,
|
|
7011
|
+
t2,
|
|
7012
|
+
t2
|
|
7013
|
+
];
|
|
6382
7014
|
return {
|
|
6383
7015
|
type: "symbol",
|
|
6384
7016
|
textField: ["get", "OBJNAM"],
|
|
@@ -6386,27 +7018,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6386
7018
|
"interpolate",
|
|
6387
7019
|
["linear"],
|
|
6388
7020
|
["zoom"],
|
|
7021
|
+
7,
|
|
7022
|
+
sizeAt(9, 0),
|
|
6389
7023
|
9,
|
|
6390
|
-
|
|
6391
|
-
12,
|
|
7024
|
+
sizeAt(11, 0),
|
|
6392
7025
|
11,
|
|
6393
|
-
|
|
6394
|
-
13
|
|
7026
|
+
sizeAt(11, 9),
|
|
7027
|
+
13,
|
|
7028
|
+
sizeAt(10, 10),
|
|
7029
|
+
16,
|
|
7030
|
+
sizeAt(9, 10)
|
|
6395
7031
|
],
|
|
6396
7032
|
textColor: DARK_BG,
|
|
6397
7033
|
textHaloColor: COLOR.WATER,
|
|
6398
|
-
textHaloWidth:
|
|
7034
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6399
7035
|
textOffset: [0, 0],
|
|
6400
7036
|
textFont: ["Open Sans Italic"],
|
|
6401
|
-
minzoom:
|
|
6402
|
-
layout:
|
|
6403
|
-
"text-anchor": "center",
|
|
6404
|
-
"text-allow-overlap": false,
|
|
6405
|
-
"text-padding": 4,
|
|
6406
|
-
"text-optional": true,
|
|
6407
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6408
|
-
}
|
|
7037
|
+
minzoom: 7,
|
|
7038
|
+
layout: orientationLabelLayout()
|
|
6409
7039
|
};
|
|
7040
|
+
}
|
|
6410
7041
|
case "CANALS":
|
|
6411
7042
|
return {
|
|
6412
7043
|
type: "symbol",
|
|
@@ -6416,25 +7047,31 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6416
7047
|
["linear"],
|
|
6417
7048
|
["zoom"],
|
|
6418
7049
|
11,
|
|
7050
|
+
10,
|
|
7051
|
+
13,
|
|
6419
7052
|
9,
|
|
6420
|
-
|
|
6421
|
-
|
|
7053
|
+
16,
|
|
7054
|
+
9
|
|
6422
7055
|
],
|
|
6423
7056
|
textColor: DARK_BG,
|
|
6424
7057
|
textHaloColor: COLOR.WATER,
|
|
6425
|
-
textHaloWidth:
|
|
7058
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6426
7059
|
textOffset: [0, 0],
|
|
6427
7060
|
textFont: ["Open Sans Italic"],
|
|
6428
7061
|
minzoom: 11,
|
|
6429
|
-
layout:
|
|
6430
|
-
"text-anchor": "center",
|
|
6431
|
-
"text-allow-overlap": false,
|
|
6432
|
-
"text-padding": 4,
|
|
6433
|
-
"text-optional": true,
|
|
6434
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6435
|
-
}
|
|
7062
|
+
layout: orientationLabelLayout()
|
|
6436
7063
|
};
|
|
6437
|
-
case "LNDARE":
|
|
7064
|
+
case "LNDARE": {
|
|
7065
|
+
const tierExpr = buildLandAreaTierExpression();
|
|
7066
|
+
const sizeAt = (t1, t2) => [
|
|
7067
|
+
"match",
|
|
7068
|
+
tierExpr,
|
|
7069
|
+
1,
|
|
7070
|
+
t1,
|
|
7071
|
+
2,
|
|
7072
|
+
t2,
|
|
7073
|
+
t2
|
|
7074
|
+
];
|
|
6438
7075
|
return {
|
|
6439
7076
|
type: "symbol",
|
|
6440
7077
|
textField: ["get", "OBJNAM"],
|
|
@@ -6442,28 +7079,41 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6442
7079
|
"interpolate",
|
|
6443
7080
|
["linear"],
|
|
6444
7081
|
["zoom"],
|
|
6445
|
-
|
|
7082
|
+
5,
|
|
7083
|
+
sizeAt(8, 0),
|
|
7084
|
+
7,
|
|
7085
|
+
sizeAt(10, 0),
|
|
6446
7086
|
9,
|
|
6447
|
-
|
|
7087
|
+
sizeAt(11, 0),
|
|
6448
7088
|
11,
|
|
6449
|
-
|
|
6450
|
-
13
|
|
7089
|
+
sizeAt(11, 9),
|
|
7090
|
+
13,
|
|
7091
|
+
sizeAt(10, 10),
|
|
7092
|
+
16,
|
|
7093
|
+
sizeAt(9, 10)
|
|
6451
7094
|
],
|
|
6452
7095
|
textColor: DARK_BG,
|
|
6453
7096
|
textHaloColor: COLOR.LAND_NATURAL,
|
|
6454
|
-
textHaloWidth:
|
|
7097
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6455
7098
|
textOffset: [0, 0],
|
|
6456
7099
|
textFont: ["Open Sans Regular"],
|
|
6457
|
-
minzoom:
|
|
6458
|
-
layout:
|
|
6459
|
-
"text-anchor": "center",
|
|
6460
|
-
"text-allow-overlap": false,
|
|
6461
|
-
"text-padding": 6,
|
|
6462
|
-
"text-optional": true,
|
|
6463
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6464
|
-
}
|
|
7100
|
+
minzoom: 5,
|
|
7101
|
+
layout: orientationLabelLayout()
|
|
6465
7102
|
};
|
|
6466
|
-
|
|
7103
|
+
}
|
|
7104
|
+
case "BUAARE": {
|
|
7105
|
+
const tierExpr = buildBuiltUpAreaTierExpression();
|
|
7106
|
+
const sizeAt = (t1, t2, t3) => [
|
|
7107
|
+
"match",
|
|
7108
|
+
tierExpr,
|
|
7109
|
+
1,
|
|
7110
|
+
t1,
|
|
7111
|
+
2,
|
|
7112
|
+
t2,
|
|
7113
|
+
3,
|
|
7114
|
+
t3,
|
|
7115
|
+
t3
|
|
7116
|
+
];
|
|
6467
7117
|
return {
|
|
6468
7118
|
type: "symbol",
|
|
6469
7119
|
textField: ["get", "OBJNAM"],
|
|
@@ -6471,28 +7121,32 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6471
7121
|
"interpolate",
|
|
6472
7122
|
["linear"],
|
|
6473
7123
|
["zoom"],
|
|
7124
|
+
3,
|
|
7125
|
+
sizeAt(11, 0, 0),
|
|
7126
|
+
5,
|
|
7127
|
+
sizeAt(13, 0, 0),
|
|
6474
7128
|
7,
|
|
7129
|
+
sizeAt(13, 9, 0),
|
|
7130
|
+
9,
|
|
7131
|
+
sizeAt(12, 12, 0),
|
|
6475
7132
|
11,
|
|
6476
|
-
10,
|
|
7133
|
+
sizeAt(11, 12, 10),
|
|
6477
7134
|
13,
|
|
6478
|
-
|
|
6479
|
-
|
|
7135
|
+
sizeAt(10, 11, 12),
|
|
7136
|
+
16,
|
|
7137
|
+
sizeAt(10, 10, 11)
|
|
6480
7138
|
],
|
|
6481
7139
|
textColor: DARK_BG,
|
|
6482
7140
|
textHaloColor: COLOR.CITY,
|
|
6483
|
-
textHaloWidth:
|
|
7141
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6484
7142
|
textOffset: [0, 0],
|
|
6485
7143
|
textFont: ["Open Sans Regular"],
|
|
6486
|
-
minzoom:
|
|
6487
|
-
layout: {
|
|
6488
|
-
"text-
|
|
6489
|
-
|
|
6490
|
-
"text-padding": 8,
|
|
6491
|
-
"text-optional": true,
|
|
6492
|
-
"text-letter-spacing": 0.05,
|
|
6493
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6494
|
-
}
|
|
7144
|
+
minzoom: 3,
|
|
7145
|
+
layout: orientationLabelLayout({
|
|
7146
|
+
"text-letter-spacing": 0.05
|
|
7147
|
+
})
|
|
6495
7148
|
};
|
|
7149
|
+
}
|
|
6496
7150
|
case "BRIDGE":
|
|
6497
7151
|
return {
|
|
6498
7152
|
type: "symbol",
|
|
@@ -6560,7 +7214,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6560
7214
|
"text-optional": true
|
|
6561
7215
|
}
|
|
6562
7216
|
};
|
|
6563
|
-
case "AIRARE":
|
|
7217
|
+
case "AIRARE": {
|
|
7218
|
+
const tierExpr = buildAirportTierExpression();
|
|
7219
|
+
const sizeAt = (t1, t2) => [
|
|
7220
|
+
"match",
|
|
7221
|
+
tierExpr,
|
|
7222
|
+
1,
|
|
7223
|
+
t1,
|
|
7224
|
+
2,
|
|
7225
|
+
t2,
|
|
7226
|
+
t2
|
|
7227
|
+
];
|
|
6564
7228
|
return {
|
|
6565
7229
|
type: "symbol",
|
|
6566
7230
|
textField: ["get", "OBJNAM"],
|
|
@@ -6568,25 +7232,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6568
7232
|
"interpolate",
|
|
6569
7233
|
["linear"],
|
|
6570
7234
|
["zoom"],
|
|
7235
|
+
7,
|
|
7236
|
+
sizeAt(9, 0),
|
|
6571
7237
|
9,
|
|
6572
|
-
|
|
7238
|
+
sizeAt(11, 0),
|
|
7239
|
+
11,
|
|
7240
|
+
sizeAt(11, 9),
|
|
6573
7241
|
13,
|
|
6574
|
-
|
|
7242
|
+
sizeAt(10, 10),
|
|
7243
|
+
16,
|
|
7244
|
+
sizeAt(9, 9)
|
|
6575
7245
|
],
|
|
6576
7246
|
textColor: DARK_BG,
|
|
6577
7247
|
textHaloColor: COLOR.AIRPORT,
|
|
6578
|
-
textHaloWidth:
|
|
7248
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6579
7249
|
textOffset: [0, 0],
|
|
6580
7250
|
textFont: ["Open Sans Regular"],
|
|
6581
|
-
minzoom:
|
|
6582
|
-
layout:
|
|
6583
|
-
"text-anchor": "center",
|
|
6584
|
-
"text-allow-overlap": false,
|
|
6585
|
-
"text-padding": 5,
|
|
6586
|
-
"text-optional": true,
|
|
6587
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6588
|
-
}
|
|
7251
|
+
minzoom: 7,
|
|
7252
|
+
layout: orientationLabelLayout()
|
|
6589
7253
|
};
|
|
7254
|
+
}
|
|
6590
7255
|
case "SBDARE":
|
|
6591
7256
|
return {
|
|
6592
7257
|
type: "symbol",
|
|
@@ -6659,26 +7324,20 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6659
7324
|
"interpolate",
|
|
6660
7325
|
["linear"],
|
|
6661
7326
|
["zoom"],
|
|
7327
|
+
11,
|
|
7328
|
+
9,
|
|
7329
|
+
13,
|
|
6662
7330
|
8,
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
12,
|
|
6666
|
-
15,
|
|
6667
|
-
14
|
|
7331
|
+
16,
|
|
7332
|
+
8
|
|
6668
7333
|
],
|
|
6669
7334
|
textColor: "#c545c3",
|
|
6670
7335
|
textHaloColor: DARK_BG,
|
|
6671
|
-
textHaloWidth:
|
|
7336
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6672
7337
|
textOffset: [0, 0],
|
|
6673
7338
|
textFont: ["Open Sans Italic"],
|
|
6674
7339
|
minzoom: 8,
|
|
6675
|
-
layout:
|
|
6676
|
-
"text-anchor": "center",
|
|
6677
|
-
"text-allow-overlap": false,
|
|
6678
|
-
"text-padding": 6,
|
|
6679
|
-
"text-optional": true,
|
|
6680
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6681
|
-
}
|
|
7340
|
+
layout: orientationLabelLayout()
|
|
6682
7341
|
};
|
|
6683
7342
|
case "WEDKLP":
|
|
6684
7343
|
return {
|
|
@@ -8785,7 +9444,21 @@ var LINE_FROM_POLYGON_LAYERS = /* @__PURE__ */ new Set([
|
|
|
8785
9444
|
"MIPARE",
|
|
8786
9445
|
"TESARE",
|
|
8787
9446
|
"MAGVAR",
|
|
8788
|
-
"PRDARE"
|
|
9447
|
+
"PRDARE",
|
|
9448
|
+
"TUNNEL",
|
|
9449
|
+
// Jurisdictional zones (INT1 N40–N47) and IMO routing measures
|
|
9450
|
+
// (INT1 M14, M27, M28) — magenta dashed boundary, no fill. Vast
|
|
9451
|
+
// offshore polygons would tint half the chart if flood-filled, so
|
|
9452
|
+
// every member here renders as boundary-only. DWRTCL is not listed
|
|
9453
|
+
// because it's a native LineString class, not a polygon-as-line.
|
|
9454
|
+
// Closes issue #575 rows 8–15.
|
|
9455
|
+
"ADMARE",
|
|
9456
|
+
"COSARE",
|
|
9457
|
+
"CONZNE",
|
|
9458
|
+
"EXEZNE",
|
|
9459
|
+
"TSEZNE",
|
|
9460
|
+
"DWRTPT",
|
|
9461
|
+
"TWRTPT"
|
|
8789
9462
|
]);
|
|
8790
9463
|
var ZOOM_SCALED_LINES2 = {
|
|
8791
9464
|
DEPCNT: [8, 0.3, 14, 0.8],
|
|
@@ -9773,6 +10446,87 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
9773
10446
|
metadata: { "s52:objectClass": "RECTRC", "s52:role": "polygon" }
|
|
9774
10447
|
});
|
|
9775
10448
|
}
|
|
10449
|
+
if (objectClass === "PONTON" && resolved.type === "fill") {
|
|
10450
|
+
layers.push({
|
|
10451
|
+
id: `s52-PONTON-line`,
|
|
10452
|
+
type: "line",
|
|
10453
|
+
source: sourceId,
|
|
10454
|
+
"source-layer": "PONTON",
|
|
10455
|
+
filter: GEOM_FILTERS.line,
|
|
10456
|
+
paint: {
|
|
10457
|
+
"line-color": resolveColor("CHGRF", ct),
|
|
10458
|
+
"line-width": 1.5
|
|
10459
|
+
},
|
|
10460
|
+
metadata: { "s52:objectClass": "PONTON", "s52:role": "line" }
|
|
10461
|
+
});
|
|
10462
|
+
}
|
|
10463
|
+
if (objectClass === "SILTNK" && resolved.type === "symbol") {
|
|
10464
|
+
layers.push({
|
|
10465
|
+
id: `s52-SILTNK-symbol-polygon`,
|
|
10466
|
+
type: "symbol",
|
|
10467
|
+
source: sourceId,
|
|
10468
|
+
"source-layer": "SILTNK",
|
|
10469
|
+
filter: GEOM_FILTERS.fill,
|
|
10470
|
+
layout: {
|
|
10471
|
+
"icon-image": "TNKCON02",
|
|
10472
|
+
"icon-size": 0.6,
|
|
10473
|
+
"icon-allow-overlap": true,
|
|
10474
|
+
"icon-ignore-placement": false,
|
|
10475
|
+
"symbol-placement": "point"
|
|
10476
|
+
},
|
|
10477
|
+
paint: {},
|
|
10478
|
+
metadata: { "s52:objectClass": "SILTNK", "s52:role": "symbol-polygon" }
|
|
10479
|
+
});
|
|
10480
|
+
}
|
|
10481
|
+
if (objectClass === "ACHBRT" && resolved.type === "symbol") {
|
|
10482
|
+
layers.push({
|
|
10483
|
+
id: `s52-ACHBRT-symbol-polygon`,
|
|
10484
|
+
type: "symbol",
|
|
10485
|
+
source: sourceId,
|
|
10486
|
+
"source-layer": "ACHBRT",
|
|
10487
|
+
filter: GEOM_FILTERS.fill,
|
|
10488
|
+
layout: {
|
|
10489
|
+
"icon-image": "ACHARE02",
|
|
10490
|
+
"icon-size": 0.5,
|
|
10491
|
+
"icon-allow-overlap": true,
|
|
10492
|
+
"icon-ignore-placement": false,
|
|
10493
|
+
"symbol-placement": "point"
|
|
10494
|
+
},
|
|
10495
|
+
paint: {},
|
|
10496
|
+
metadata: { "s52:objectClass": "ACHBRT", "s52:role": "symbol-polygon" }
|
|
10497
|
+
});
|
|
10498
|
+
}
|
|
10499
|
+
if (objectClass === "BERTHS" && resolved.type === "line") {
|
|
10500
|
+
layers.push({
|
|
10501
|
+
id: `s52-BERTHS-circle`,
|
|
10502
|
+
type: "circle",
|
|
10503
|
+
source: sourceId,
|
|
10504
|
+
"source-layer": "BERTHS",
|
|
10505
|
+
filter: GEOM_FILTERS.circle,
|
|
10506
|
+
paint: {
|
|
10507
|
+
"circle-color": resolveColor("CHBLK", ct),
|
|
10508
|
+
"circle-radius": ["interpolate", ["linear"], ["zoom"], 12, 1.5, 14, 2.2, 17, 3],
|
|
10509
|
+
"circle-stroke-color": resolveColor("CHBLK", ct),
|
|
10510
|
+
"circle-stroke-width": 0.5
|
|
10511
|
+
},
|
|
10512
|
+
metadata: { "s52:objectClass": "BERTHS", "s52:role": "point" }
|
|
10513
|
+
});
|
|
10514
|
+
}
|
|
10515
|
+
if (objectClass === "TUNNEL" && resolved.type === "line") {
|
|
10516
|
+
layers.push({
|
|
10517
|
+
id: `s52-TUNNEL-line`,
|
|
10518
|
+
type: "line",
|
|
10519
|
+
source: sourceId,
|
|
10520
|
+
"source-layer": "TUNNEL",
|
|
10521
|
+
filter: GEOM_FILTERS.line,
|
|
10522
|
+
paint: {
|
|
10523
|
+
"line-color": resolveColor("CHGRD", ct),
|
|
10524
|
+
"line-width": 1,
|
|
10525
|
+
"line-dasharray": [2, 2]
|
|
10526
|
+
},
|
|
10527
|
+
metadata: { "s52:objectClass": "TUNNEL", "s52:role": "line" }
|
|
10528
|
+
});
|
|
10529
|
+
}
|
|
9776
10530
|
}
|
|
9777
10531
|
return layers;
|
|
9778
10532
|
}
|
|
@@ -10008,9 +10762,21 @@ var META_LAYERS = /* @__PURE__ */ new Set([
|
|
|
10008
10762
|
"M_CSCL",
|
|
10009
10763
|
"TS_FEB",
|
|
10010
10764
|
"TS_TIS",
|
|
10011
|
-
"COSARE",
|
|
10012
|
-
"NEWOBJ",
|
|
10013
10765
|
"LOCMAG"
|
|
10766
|
+
// COSARE was previously suppressed here as meta. The weekly layer-
|
|
10767
|
+
// coverage audit (issue #575) classified it as a jurisdictional polygon
|
|
10768
|
+
// (S-52 INT1 N40, same family as ADMARE / TESARE). It now has an
|
|
10769
|
+
// S52_LOOKUP entry and renders as a magenta dashed boundary; suppressing
|
|
10770
|
+
// it as meta would defeat that wire-up.
|
|
10771
|
+
//
|
|
10772
|
+
// NEWOBJ was likewise previously suppressed here. That was the source
|
|
10773
|
+
// of audit gap row 22: NEWOBJ is the S-57 placeholder for features the
|
|
10774
|
+
// HO has identified but not yet classified. Skipping it silently hid
|
|
10775
|
+
// the HO's own "we don't know what this is, but it is here" signal —
|
|
10776
|
+
// the opposite of what mariners need. The class now renders via its
|
|
10777
|
+
// S52_LOOKUP entry as a vivid magenta circle, displayCategory STANDARD,
|
|
10778
|
+
// scamin 0. Do not put it back here — see the lookup entry for the
|
|
10779
|
+
// safety contract.
|
|
10014
10780
|
]);
|
|
10015
10781
|
var PALETTE_NAMES = {
|
|
10016
10782
|
DAY: "DAY_BRIGHT",
|
|
@@ -10101,21 +10867,45 @@ function makeBandVariants(layer, B) {
|
|
|
10101
10867
|
}
|
|
10102
10868
|
return variants;
|
|
10103
10869
|
}
|
|
10104
|
-
|
|
10870
|
+
var CELL_BAND_OPACITY_CURVE = {
|
|
10871
|
+
"1": [[3, 0.5], [5, 0.3], [16, 0.15]],
|
|
10872
|
+
"2": [[5, 0.5], [7, 0.3], [16, 0.15]],
|
|
10873
|
+
"3": [[7, 0.55], [9, 0.35], [16, 0.18]],
|
|
10874
|
+
"4": [[9, 0.55], [11, 0.35], [16, 0.2]],
|
|
10875
|
+
"5": [[11, 0.6], [13, 0.35], [18, 0.25]],
|
|
10876
|
+
"6": [[13, 0.75], [16, 0.55], [22, 0.45]]
|
|
10877
|
+
};
|
|
10878
|
+
function fanOrientationLabelByCellBand(label) {
|
|
10879
|
+
const cellBandExpr = [
|
|
10880
|
+
"slice",
|
|
10881
|
+
["coalesce", ["get", "_cell_id"], "??9???"],
|
|
10882
|
+
2,
|
|
10883
|
+
3
|
|
10884
|
+
];
|
|
10105
10885
|
const variants = [];
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
if (D === "1") continue;
|
|
10113
|
-
variants.push({
|
|
10886
|
+
for (const code of BAND_DRAW_ORDER) {
|
|
10887
|
+
const range = BAND_PRIORITY_RANGES[code];
|
|
10888
|
+
const curve = CELL_BAND_OPACITY_CURVE[code];
|
|
10889
|
+
const opacityExpr = ["interpolate", ["linear"], ["zoom"]];
|
|
10890
|
+
for (const [z, o] of curve) opacityExpr.push(z, o);
|
|
10891
|
+
const variant = {
|
|
10114
10892
|
...label,
|
|
10115
|
-
id: `${label.id}-
|
|
10116
|
-
filter: combineWithBandFilter(
|
|
10117
|
-
|
|
10118
|
-
|
|
10893
|
+
id: `${label.id}-cell${code}`,
|
|
10894
|
+
filter: combineWithBandFilter(
|
|
10895
|
+
label.filter,
|
|
10896
|
+
["==", cellBandExpr, code]
|
|
10897
|
+
),
|
|
10898
|
+
minzoom: Math.max(
|
|
10899
|
+
label.minzoom ?? range.minzoom,
|
|
10900
|
+
range.minzoom
|
|
10901
|
+
),
|
|
10902
|
+
paint: {
|
|
10903
|
+
...label.paint ?? {},
|
|
10904
|
+
"text-opacity": opacityExpr
|
|
10905
|
+
}
|
|
10906
|
+
};
|
|
10907
|
+
delete variant.maxzoom;
|
|
10908
|
+
variants.push(variant);
|
|
10119
10909
|
}
|
|
10120
10910
|
return variants;
|
|
10121
10911
|
}
|
|
@@ -10239,7 +11029,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
10239
11029
|
for (const { objectClass, label } of bundles) {
|
|
10240
11030
|
if (!label) continue;
|
|
10241
11031
|
if (getLabelBehavior(objectClass) === "orientation-cross-band") {
|
|
10242
|
-
labelLayers.push(...
|
|
11032
|
+
labelLayers.push(...fanOrientationLabelByCellBand(label));
|
|
10243
11033
|
}
|
|
10244
11034
|
}
|
|
10245
11035
|
for (const code of BAND_DRAW_ORDER) {
|