@chrtco/sdk 0.7.2 → 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 +954 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +954 -155
- 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",
|
|
@@ -5967,6 +6405,15 @@ var NATQUA_ABBR = [
|
|
|
5967
6405
|
// hard
|
|
5968
6406
|
];
|
|
5969
6407
|
var DARK_BG = "#1a1d23";
|
|
6408
|
+
var NAV_HALO = {
|
|
6409
|
+
WHITE: { bright: "#ffffff", night: "#b8b0a0" },
|
|
6410
|
+
CREAM: { bright: "#fdf0b0", night: "#a89868" },
|
|
6411
|
+
YELLOW: { bright: "#eab308", night: "#806020" },
|
|
6412
|
+
BLUE: { bright: "#b0c8e8", night: "#7088a0" }
|
|
6413
|
+
};
|
|
6414
|
+
function navHalo(palette, ct) {
|
|
6415
|
+
return ct === "NIGHT" ? NAV_HALO[palette].night : NAV_HALO[palette].bright;
|
|
6416
|
+
}
|
|
5970
6417
|
var NAV_AID_LABEL_TEXT_SIZE = [
|
|
5971
6418
|
"interpolate",
|
|
5972
6419
|
["linear"],
|
|
@@ -6016,6 +6463,124 @@ function buildSeabedLabelExpression() {
|
|
|
6016
6463
|
const natsurJoined = ["slice", natsurParts, 1];
|
|
6017
6464
|
return ["concat", natquaPrefix, natsurJoined];
|
|
6018
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
|
+
}
|
|
6019
6584
|
var COLOR = {
|
|
6020
6585
|
WATER: "#9ec1d8",
|
|
6021
6586
|
WATER_DEEP: "#8fb8d0",
|
|
@@ -6036,6 +6601,30 @@ var ORIENTATION_BAND_SORT_KEY = [
|
|
|
6036
6601
|
["slice", ["coalesce", ["get", "_cell_id"], "??9???"], 2, 3],
|
|
6037
6602
|
9
|
|
6038
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
|
+
];
|
|
6039
6628
|
var LABEL_BEHAVIOR = {
|
|
6040
6629
|
// Orientation labels — render once across all bands.
|
|
6041
6630
|
SEAARE: "orientation-cross-band",
|
|
@@ -6073,9 +6662,9 @@ function getLabelBehavior(layerName) {
|
|
|
6073
6662
|
return LABEL_BEHAVIOR[layerName] ?? "feature-band-gated";
|
|
6074
6663
|
}
|
|
6075
6664
|
function getLabelConfig(layerName, opts = {}) {
|
|
6665
|
+
const ct = opts.colorTable ?? "DAY";
|
|
6076
6666
|
switch (layerName) {
|
|
6077
6667
|
case "SOUNDG": {
|
|
6078
|
-
const ct = opts.colorTable ?? "DAY";
|
|
6079
6668
|
const safetyContour = opts.safetyContour ?? 10;
|
|
6080
6669
|
const twoShade = opts.twoShadeSoundings ?? true;
|
|
6081
6670
|
const weight = opts.soundingFontWeight ?? "semibold";
|
|
@@ -6150,7 +6739,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6150
6739
|
}
|
|
6151
6740
|
};
|
|
6152
6741
|
}
|
|
6153
|
-
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
|
+
];
|
|
6154
6753
|
return {
|
|
6155
6754
|
type: "symbol",
|
|
6156
6755
|
textField: ["get", "OBJNAM"],
|
|
@@ -6158,27 +6757,28 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6158
6757
|
"interpolate",
|
|
6159
6758
|
["linear"],
|
|
6160
6759
|
["zoom"],
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
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)
|
|
6167
6772
|
],
|
|
6168
6773
|
textColor: DARK_BG,
|
|
6169
6774
|
textHaloColor: COLOR.LAND_REGION,
|
|
6170
|
-
textHaloWidth:
|
|
6775
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6171
6776
|
textOffset: [0, 0],
|
|
6172
6777
|
textFont: ["Open Sans Regular"],
|
|
6173
|
-
minzoom:
|
|
6174
|
-
layout:
|
|
6175
|
-
"text-anchor": "center",
|
|
6176
|
-
"text-allow-overlap": false,
|
|
6177
|
-
"text-padding": 6,
|
|
6178
|
-
"text-optional": true,
|
|
6179
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6180
|
-
}
|
|
6778
|
+
minzoom: 5,
|
|
6779
|
+
layout: orientationLabelLayout()
|
|
6181
6780
|
};
|
|
6781
|
+
}
|
|
6182
6782
|
case "LNDMRK":
|
|
6183
6783
|
return {
|
|
6184
6784
|
type: "symbol",
|
|
@@ -6197,7 +6797,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6197
6797
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6198
6798
|
textFont: NAV_AID_LABEL_FONT,
|
|
6199
6799
|
textColor: DARK_BG,
|
|
6200
|
-
textHaloColor: "
|
|
6800
|
+
textHaloColor: navHalo("WHITE", ct),
|
|
6201
6801
|
textHaloWidth: 1.5,
|
|
6202
6802
|
textOffset: [0, 1.5],
|
|
6203
6803
|
minzoom: 10
|
|
@@ -6209,7 +6809,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6209
6809
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6210
6810
|
textFont: NAV_AID_LABEL_FONT,
|
|
6211
6811
|
textColor: DARK_BG,
|
|
6212
|
-
textHaloColor: "
|
|
6812
|
+
textHaloColor: navHalo("WHITE", ct),
|
|
6213
6813
|
textHaloWidth: 1.5,
|
|
6214
6814
|
textOffset: [0, 1.5],
|
|
6215
6815
|
minzoom: 10
|
|
@@ -6222,7 +6822,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6222
6822
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6223
6823
|
textFont: NAV_AID_LABEL_FONT,
|
|
6224
6824
|
textColor: DARK_BG,
|
|
6225
|
-
textHaloColor: "
|
|
6825
|
+
textHaloColor: navHalo("CREAM", ct),
|
|
6226
6826
|
textHaloWidth: 1.5,
|
|
6227
6827
|
textOffset: [0, 1.5],
|
|
6228
6828
|
minzoom: 10
|
|
@@ -6235,7 +6835,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6235
6835
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6236
6836
|
textFont: NAV_AID_LABEL_FONT,
|
|
6237
6837
|
textColor: DARK_BG,
|
|
6238
|
-
textHaloColor: "
|
|
6838
|
+
textHaloColor: navHalo("YELLOW", ct),
|
|
6239
6839
|
textHaloWidth: 1.5,
|
|
6240
6840
|
textOffset: [0, 1.5],
|
|
6241
6841
|
minzoom: 10
|
|
@@ -6248,7 +6848,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6248
6848
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6249
6849
|
textFont: NAV_AID_LABEL_FONT,
|
|
6250
6850
|
textColor: DARK_BG,
|
|
6251
|
-
textHaloColor: "
|
|
6851
|
+
textHaloColor: navHalo("WHITE", ct),
|
|
6252
6852
|
textHaloWidth: 1.5,
|
|
6253
6853
|
textOffset: [0, 1.5],
|
|
6254
6854
|
minzoom: 10
|
|
@@ -6260,7 +6860,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6260
6860
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6261
6861
|
textFont: NAV_AID_LABEL_FONT,
|
|
6262
6862
|
textColor: DARK_BG,
|
|
6263
|
-
textHaloColor: "
|
|
6863
|
+
textHaloColor: navHalo("CREAM", ct),
|
|
6264
6864
|
textHaloWidth: 1.5,
|
|
6265
6865
|
textOffset: [2, 0],
|
|
6266
6866
|
minzoom: 9,
|
|
@@ -6296,7 +6896,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6296
6896
|
textSize: NAV_AID_LABEL_TEXT_SIZE,
|
|
6297
6897
|
textFont: NAV_AID_LABEL_FONT,
|
|
6298
6898
|
textColor: DARK_BG,
|
|
6299
|
-
textHaloColor: "
|
|
6899
|
+
textHaloColor: navHalo("BLUE", ct),
|
|
6300
6900
|
textHaloWidth: 1.5,
|
|
6301
6901
|
textOffset: [2, 1.2],
|
|
6302
6902
|
minzoom: 11,
|
|
@@ -6307,40 +6907,72 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6307
6907
|
}
|
|
6308
6908
|
};
|
|
6309
6909
|
}
|
|
6310
|
-
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
|
+
];
|
|
6311
6925
|
return {
|
|
6312
6926
|
type: "symbol",
|
|
6313
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.
|
|
6314
6934
|
textSize: [
|
|
6315
6935
|
"interpolate",
|
|
6316
6936
|
["linear"],
|
|
6317
6937
|
["zoom"],
|
|
6938
|
+
3,
|
|
6939
|
+
sizeAt(14, 8, 0, 0, 0),
|
|
6318
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),
|
|
6319
6946
|
11,
|
|
6320
|
-
|
|
6947
|
+
sizeAt(10, 12, 13, 0, 11),
|
|
6321
6948
|
13,
|
|
6322
|
-
11,
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
17
|
|
6949
|
+
sizeAt(9, 11, 12, 10, 11),
|
|
6950
|
+
16,
|
|
6951
|
+
sizeAt(9, 10, 11, 11, 10)
|
|
6326
6952
|
],
|
|
6327
6953
|
textColor: DARK_BG,
|
|
6328
6954
|
textHaloColor: COLOR.WATER_DEEP,
|
|
6329
|
-
textHaloWidth:
|
|
6955
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6330
6956
|
textOffset: [0, 0],
|
|
6331
6957
|
textFont: ["Open Sans Italic"],
|
|
6332
6958
|
minzoom: 5,
|
|
6333
|
-
layout: {
|
|
6334
|
-
"text-anchor": "center",
|
|
6335
|
-
"text-allow-overlap": false,
|
|
6336
|
-
"text-padding": 10,
|
|
6337
|
-
"text-optional": true,
|
|
6959
|
+
layout: orientationLabelLayout({
|
|
6338
6960
|
"text-letter-spacing": 0.15,
|
|
6339
|
-
"text-max-width": 9
|
|
6340
|
-
|
|
6341
|
-
}
|
|
6961
|
+
"text-max-width": 9
|
|
6962
|
+
})
|
|
6342
6963
|
};
|
|
6343
|
-
|
|
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
|
+
];
|
|
6344
6976
|
return {
|
|
6345
6977
|
type: "symbol",
|
|
6346
6978
|
textField: ["get", "OBJNAM"],
|
|
@@ -6348,28 +6980,37 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6348
6980
|
"interpolate",
|
|
6349
6981
|
["linear"],
|
|
6350
6982
|
["zoom"],
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
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)
|
|
6357
6993
|
],
|
|
6358
6994
|
textColor: DARK_BG,
|
|
6359
6995
|
textHaloColor: COLOR.WATER,
|
|
6360
|
-
textHaloWidth:
|
|
6996
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6361
6997
|
textOffset: [0, 0],
|
|
6362
6998
|
textFont: ["Open Sans Italic"],
|
|
6363
|
-
minzoom:
|
|
6364
|
-
layout:
|
|
6365
|
-
"text-anchor": "center",
|
|
6366
|
-
"text-allow-overlap": false,
|
|
6367
|
-
"text-padding": 6,
|
|
6368
|
-
"text-optional": true,
|
|
6369
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6370
|
-
}
|
|
6999
|
+
minzoom: 7,
|
|
7000
|
+
layout: orientationLabelLayout()
|
|
6371
7001
|
};
|
|
6372
|
-
|
|
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
|
+
];
|
|
6373
7014
|
return {
|
|
6374
7015
|
type: "symbol",
|
|
6375
7016
|
textField: ["get", "OBJNAM"],
|
|
@@ -6377,27 +7018,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6377
7018
|
"interpolate",
|
|
6378
7019
|
["linear"],
|
|
6379
7020
|
["zoom"],
|
|
7021
|
+
7,
|
|
7022
|
+
sizeAt(9, 0),
|
|
6380
7023
|
9,
|
|
6381
|
-
|
|
6382
|
-
12,
|
|
7024
|
+
sizeAt(11, 0),
|
|
6383
7025
|
11,
|
|
6384
|
-
|
|
6385
|
-
13
|
|
7026
|
+
sizeAt(11, 9),
|
|
7027
|
+
13,
|
|
7028
|
+
sizeAt(10, 10),
|
|
7029
|
+
16,
|
|
7030
|
+
sizeAt(9, 10)
|
|
6386
7031
|
],
|
|
6387
7032
|
textColor: DARK_BG,
|
|
6388
7033
|
textHaloColor: COLOR.WATER,
|
|
6389
|
-
textHaloWidth:
|
|
7034
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6390
7035
|
textOffset: [0, 0],
|
|
6391
7036
|
textFont: ["Open Sans Italic"],
|
|
6392
|
-
minzoom:
|
|
6393
|
-
layout:
|
|
6394
|
-
"text-anchor": "center",
|
|
6395
|
-
"text-allow-overlap": false,
|
|
6396
|
-
"text-padding": 4,
|
|
6397
|
-
"text-optional": true,
|
|
6398
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6399
|
-
}
|
|
7037
|
+
minzoom: 7,
|
|
7038
|
+
layout: orientationLabelLayout()
|
|
6400
7039
|
};
|
|
7040
|
+
}
|
|
6401
7041
|
case "CANALS":
|
|
6402
7042
|
return {
|
|
6403
7043
|
type: "symbol",
|
|
@@ -6407,25 +7047,31 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6407
7047
|
["linear"],
|
|
6408
7048
|
["zoom"],
|
|
6409
7049
|
11,
|
|
7050
|
+
10,
|
|
7051
|
+
13,
|
|
6410
7052
|
9,
|
|
6411
|
-
|
|
6412
|
-
|
|
7053
|
+
16,
|
|
7054
|
+
9
|
|
6413
7055
|
],
|
|
6414
7056
|
textColor: DARK_BG,
|
|
6415
7057
|
textHaloColor: COLOR.WATER,
|
|
6416
|
-
textHaloWidth:
|
|
7058
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6417
7059
|
textOffset: [0, 0],
|
|
6418
7060
|
textFont: ["Open Sans Italic"],
|
|
6419
7061
|
minzoom: 11,
|
|
6420
|
-
layout:
|
|
6421
|
-
"text-anchor": "center",
|
|
6422
|
-
"text-allow-overlap": false,
|
|
6423
|
-
"text-padding": 4,
|
|
6424
|
-
"text-optional": true,
|
|
6425
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6426
|
-
}
|
|
7062
|
+
layout: orientationLabelLayout()
|
|
6427
7063
|
};
|
|
6428
|
-
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
|
+
];
|
|
6429
7075
|
return {
|
|
6430
7076
|
type: "symbol",
|
|
6431
7077
|
textField: ["get", "OBJNAM"],
|
|
@@ -6433,28 +7079,41 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6433
7079
|
"interpolate",
|
|
6434
7080
|
["linear"],
|
|
6435
7081
|
["zoom"],
|
|
6436
|
-
|
|
7082
|
+
5,
|
|
7083
|
+
sizeAt(8, 0),
|
|
7084
|
+
7,
|
|
7085
|
+
sizeAt(10, 0),
|
|
6437
7086
|
9,
|
|
6438
|
-
|
|
7087
|
+
sizeAt(11, 0),
|
|
6439
7088
|
11,
|
|
6440
|
-
|
|
6441
|
-
13
|
|
7089
|
+
sizeAt(11, 9),
|
|
7090
|
+
13,
|
|
7091
|
+
sizeAt(10, 10),
|
|
7092
|
+
16,
|
|
7093
|
+
sizeAt(9, 10)
|
|
6442
7094
|
],
|
|
6443
7095
|
textColor: DARK_BG,
|
|
6444
7096
|
textHaloColor: COLOR.LAND_NATURAL,
|
|
6445
|
-
textHaloWidth:
|
|
7097
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6446
7098
|
textOffset: [0, 0],
|
|
6447
7099
|
textFont: ["Open Sans Regular"],
|
|
6448
|
-
minzoom:
|
|
6449
|
-
layout:
|
|
6450
|
-
"text-anchor": "center",
|
|
6451
|
-
"text-allow-overlap": false,
|
|
6452
|
-
"text-padding": 6,
|
|
6453
|
-
"text-optional": true,
|
|
6454
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6455
|
-
}
|
|
7100
|
+
minzoom: 5,
|
|
7101
|
+
layout: orientationLabelLayout()
|
|
6456
7102
|
};
|
|
6457
|
-
|
|
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
|
+
];
|
|
6458
7117
|
return {
|
|
6459
7118
|
type: "symbol",
|
|
6460
7119
|
textField: ["get", "OBJNAM"],
|
|
@@ -6462,28 +7121,32 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6462
7121
|
"interpolate",
|
|
6463
7122
|
["linear"],
|
|
6464
7123
|
["zoom"],
|
|
7124
|
+
3,
|
|
7125
|
+
sizeAt(11, 0, 0),
|
|
7126
|
+
5,
|
|
7127
|
+
sizeAt(13, 0, 0),
|
|
6465
7128
|
7,
|
|
7129
|
+
sizeAt(13, 9, 0),
|
|
7130
|
+
9,
|
|
7131
|
+
sizeAt(12, 12, 0),
|
|
6466
7132
|
11,
|
|
6467
|
-
10,
|
|
6468
|
-
13,
|
|
7133
|
+
sizeAt(11, 12, 10),
|
|
6469
7134
|
13,
|
|
6470
|
-
|
|
7135
|
+
sizeAt(10, 11, 12),
|
|
7136
|
+
16,
|
|
7137
|
+
sizeAt(10, 10, 11)
|
|
6471
7138
|
],
|
|
6472
7139
|
textColor: DARK_BG,
|
|
6473
7140
|
textHaloColor: COLOR.CITY,
|
|
6474
|
-
textHaloWidth:
|
|
7141
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6475
7142
|
textOffset: [0, 0],
|
|
6476
7143
|
textFont: ["Open Sans Regular"],
|
|
6477
|
-
minzoom:
|
|
6478
|
-
layout: {
|
|
6479
|
-
"text-
|
|
6480
|
-
|
|
6481
|
-
"text-padding": 8,
|
|
6482
|
-
"text-optional": true,
|
|
6483
|
-
"text-letter-spacing": 0.05,
|
|
6484
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6485
|
-
}
|
|
7144
|
+
minzoom: 3,
|
|
7145
|
+
layout: orientationLabelLayout({
|
|
7146
|
+
"text-letter-spacing": 0.05
|
|
7147
|
+
})
|
|
6486
7148
|
};
|
|
7149
|
+
}
|
|
6487
7150
|
case "BRIDGE":
|
|
6488
7151
|
return {
|
|
6489
7152
|
type: "symbol",
|
|
@@ -6551,7 +7214,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6551
7214
|
"text-optional": true
|
|
6552
7215
|
}
|
|
6553
7216
|
};
|
|
6554
|
-
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
|
+
];
|
|
6555
7228
|
return {
|
|
6556
7229
|
type: "symbol",
|
|
6557
7230
|
textField: ["get", "OBJNAM"],
|
|
@@ -6559,25 +7232,26 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6559
7232
|
"interpolate",
|
|
6560
7233
|
["linear"],
|
|
6561
7234
|
["zoom"],
|
|
7235
|
+
7,
|
|
7236
|
+
sizeAt(9, 0),
|
|
6562
7237
|
9,
|
|
6563
|
-
|
|
7238
|
+
sizeAt(11, 0),
|
|
7239
|
+
11,
|
|
7240
|
+
sizeAt(11, 9),
|
|
6564
7241
|
13,
|
|
6565
|
-
|
|
7242
|
+
sizeAt(10, 10),
|
|
7243
|
+
16,
|
|
7244
|
+
sizeAt(9, 9)
|
|
6566
7245
|
],
|
|
6567
7246
|
textColor: DARK_BG,
|
|
6568
7247
|
textHaloColor: COLOR.AIRPORT,
|
|
6569
|
-
textHaloWidth:
|
|
7248
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6570
7249
|
textOffset: [0, 0],
|
|
6571
7250
|
textFont: ["Open Sans Regular"],
|
|
6572
|
-
minzoom:
|
|
6573
|
-
layout:
|
|
6574
|
-
"text-anchor": "center",
|
|
6575
|
-
"text-allow-overlap": false,
|
|
6576
|
-
"text-padding": 5,
|
|
6577
|
-
"text-optional": true,
|
|
6578
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6579
|
-
}
|
|
7251
|
+
minzoom: 7,
|
|
7252
|
+
layout: orientationLabelLayout()
|
|
6580
7253
|
};
|
|
7254
|
+
}
|
|
6581
7255
|
case "SBDARE":
|
|
6582
7256
|
return {
|
|
6583
7257
|
type: "symbol",
|
|
@@ -6650,26 +7324,20 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6650
7324
|
"interpolate",
|
|
6651
7325
|
["linear"],
|
|
6652
7326
|
["zoom"],
|
|
7327
|
+
11,
|
|
7328
|
+
9,
|
|
7329
|
+
13,
|
|
6653
7330
|
8,
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
12,
|
|
6657
|
-
15,
|
|
6658
|
-
14
|
|
7331
|
+
16,
|
|
7332
|
+
8
|
|
6659
7333
|
],
|
|
6660
7334
|
textColor: "#c545c3",
|
|
6661
7335
|
textHaloColor: DARK_BG,
|
|
6662
|
-
textHaloWidth:
|
|
7336
|
+
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
6663
7337
|
textOffset: [0, 0],
|
|
6664
7338
|
textFont: ["Open Sans Italic"],
|
|
6665
7339
|
minzoom: 8,
|
|
6666
|
-
layout:
|
|
6667
|
-
"text-anchor": "center",
|
|
6668
|
-
"text-allow-overlap": false,
|
|
6669
|
-
"text-padding": 6,
|
|
6670
|
-
"text-optional": true,
|
|
6671
|
-
"symbol-sort-key": ORIENTATION_BAND_SORT_KEY
|
|
6672
|
-
}
|
|
7340
|
+
layout: orientationLabelLayout()
|
|
6673
7341
|
};
|
|
6674
7342
|
case "WEDKLP":
|
|
6675
7343
|
return {
|
|
@@ -6702,7 +7370,7 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6702
7370
|
case "UWTROC":
|
|
6703
7371
|
case "OBSTRN":
|
|
6704
7372
|
case "WRECKS": {
|
|
6705
|
-
const
|
|
7373
|
+
const ct2 = opts.colorTable ?? "DAY";
|
|
6706
7374
|
const valsou = [
|
|
6707
7375
|
"to-number",
|
|
6708
7376
|
["coalesce", ["get", "VALSOU"], ["get", "valsou"], 0],
|
|
@@ -6729,8 +7397,8 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6729
7397
|
16,
|
|
6730
7398
|
11
|
|
6731
7399
|
],
|
|
6732
|
-
textColor: resolveColor("CHBLK",
|
|
6733
|
-
textHaloColor: resolveColor("CHWHT",
|
|
7400
|
+
textColor: resolveColor("CHBLK", ct2),
|
|
7401
|
+
textHaloColor: resolveColor("CHWHT", ct2),
|
|
6734
7402
|
textHaloWidth: 1.2,
|
|
6735
7403
|
// Place to the upper-right of the symbol so it doesn't sit on top
|
|
6736
7404
|
// of the asterisk / cross. Anchor top-left so the offset grows
|
|
@@ -8776,7 +9444,21 @@ var LINE_FROM_POLYGON_LAYERS = /* @__PURE__ */ new Set([
|
|
|
8776
9444
|
"MIPARE",
|
|
8777
9445
|
"TESARE",
|
|
8778
9446
|
"MAGVAR",
|
|
8779
|
-
"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"
|
|
8780
9462
|
]);
|
|
8781
9463
|
var ZOOM_SCALED_LINES2 = {
|
|
8782
9464
|
DEPCNT: [8, 0.3, 14, 0.8],
|
|
@@ -9764,6 +10446,87 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
9764
10446
|
metadata: { "s52:objectClass": "RECTRC", "s52:role": "polygon" }
|
|
9765
10447
|
});
|
|
9766
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
|
+
}
|
|
9767
10530
|
}
|
|
9768
10531
|
return layers;
|
|
9769
10532
|
}
|
|
@@ -9999,9 +10762,21 @@ var META_LAYERS = /* @__PURE__ */ new Set([
|
|
|
9999
10762
|
"M_CSCL",
|
|
10000
10763
|
"TS_FEB",
|
|
10001
10764
|
"TS_TIS",
|
|
10002
|
-
"COSARE",
|
|
10003
|
-
"NEWOBJ",
|
|
10004
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.
|
|
10005
10780
|
]);
|
|
10006
10781
|
var PALETTE_NAMES = {
|
|
10007
10782
|
DAY: "DAY_BRIGHT",
|
|
@@ -10092,21 +10867,45 @@ function makeBandVariants(layer, B) {
|
|
|
10092
10867
|
}
|
|
10093
10868
|
return variants;
|
|
10094
10869
|
}
|
|
10095
|
-
|
|
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
|
+
];
|
|
10096
10885
|
const variants = [];
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
if (D === "1") continue;
|
|
10104
|
-
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 = {
|
|
10105
10892
|
...label,
|
|
10106
|
-
id: `${label.id}-
|
|
10107
|
-
filter: combineWithBandFilter(
|
|
10108
|
-
|
|
10109
|
-
|
|
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);
|
|
10110
10909
|
}
|
|
10111
10910
|
return variants;
|
|
10112
10911
|
}
|
|
@@ -10230,7 +11029,7 @@ function generateStyle(palette = "DAY", opts = {}) {
|
|
|
10230
11029
|
for (const { objectClass, label } of bundles) {
|
|
10231
11030
|
if (!label) continue;
|
|
10232
11031
|
if (getLabelBehavior(objectClass) === "orientation-cross-band") {
|
|
10233
|
-
labelLayers.push(...
|
|
11032
|
+
labelLayers.push(...fanOrientationLabelByCellBand(label));
|
|
10234
11033
|
}
|
|
10235
11034
|
}
|
|
10236
11035
|
for (const code of BAND_DRAW_ORDER) {
|