@chrtco/sdk 0.7.4 → 0.7.6
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 +21 -21
- package/dist/atlas/browser.cjs.map +1 -1
- package/dist/atlas/browser.js +21 -21
- package/dist/atlas/browser.js.map +1 -1
- package/dist/index.cjs +370 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +370 -291
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3248,18 +3248,37 @@ function depareFillExpression(ct = "DAY") {
|
|
|
3248
3248
|
resolveColor("DEPDW", ct)
|
|
3249
3249
|
];
|
|
3250
3250
|
}
|
|
3251
|
-
function
|
|
3252
|
-
|
|
3251
|
+
function listAttrString(attr) {
|
|
3252
|
+
return ["to-string", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], ""]];
|
|
3253
|
+
}
|
|
3254
|
+
function listAttrCase(attr, cases, fallback) {
|
|
3255
|
+
const attrStr = listAttrString(attr);
|
|
3253
3256
|
const expr = ["case"];
|
|
3254
3257
|
for (const [code, value] of cases) {
|
|
3255
|
-
expr.push([">=", ["index-of", `"${code}"`,
|
|
3258
|
+
expr.push([">=", ["index-of", `"${code}"`, attrStr], 0], value);
|
|
3259
|
+
}
|
|
3260
|
+
for (const [code, value] of cases) {
|
|
3261
|
+
expr.push(["==", attrStr, code], value);
|
|
3256
3262
|
}
|
|
3257
3263
|
for (const [code, value] of cases) {
|
|
3258
|
-
expr.push(["==",
|
|
3264
|
+
expr.push(["==", attrStr, `[${code}]`], value);
|
|
3259
3265
|
}
|
|
3260
3266
|
expr.push(fallback);
|
|
3261
3267
|
return expr;
|
|
3262
3268
|
}
|
|
3269
|
+
function listAttrHas(attr, codes) {
|
|
3270
|
+
const attrStr = listAttrString(attr);
|
|
3271
|
+
const clauses = [];
|
|
3272
|
+
for (const code of codes) {
|
|
3273
|
+
clauses.push([">=", ["index-of", `"${code}"`, attrStr], 0]);
|
|
3274
|
+
clauses.push(["==", attrStr, code]);
|
|
3275
|
+
clauses.push(["==", attrStr, `[${code}]`]);
|
|
3276
|
+
}
|
|
3277
|
+
return ["any", ...clauses];
|
|
3278
|
+
}
|
|
3279
|
+
function colourCodeCase(cases, fallback) {
|
|
3280
|
+
return listAttrCase("COLOUR", cases, fallback);
|
|
3281
|
+
}
|
|
3263
3282
|
function lightColor(props, ct = "DAY") {
|
|
3264
3283
|
const raw = props.COLOUR ?? props.colour;
|
|
3265
3284
|
const code = Array.isArray(raw) ? Number(raw[0]) : typeof raw === "string" && raw.startsWith("[") ? Number(JSON.parse(raw)[0]) : Number(raw ?? 0);
|
|
@@ -5298,7 +5317,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5298
5317
|
description: "Church spire or steeple, conspicuous from seaward. Useful for visual fixing.",
|
|
5299
5318
|
s52PlRef: "LNDMRK17",
|
|
5300
5319
|
attributeKey: "CATLMK",
|
|
5301
|
-
attributeValue:
|
|
5320
|
+
attributeValue: 20,
|
|
5302
5321
|
renderSize: "32x32",
|
|
5303
5322
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Spire, building, position circle" }],
|
|
5304
5323
|
lineStyles: [{ element: "Building outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5315,7 +5334,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5315
5334
|
description: "Tower conspicuous from seaward. General-purpose landmark symbol.",
|
|
5316
5335
|
s52PlRef: "LNDMRK20",
|
|
5317
5336
|
attributeKey: "CATLMK",
|
|
5318
|
-
attributeValue:
|
|
5337
|
+
attributeValue: 17,
|
|
5319
5338
|
renderSize: "32x32",
|
|
5320
5339
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower body, cap, position circle" }],
|
|
5321
5340
|
lineStyles: [{ element: "Tower outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5332,7 +5351,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5332
5351
|
description: "Industrial chimney or smokestack visible from the sea.",
|
|
5333
5352
|
s52PlRef: "LNDMRK01",
|
|
5334
5353
|
attributeKey: "CATLMK",
|
|
5335
|
-
attributeValue:
|
|
5354
|
+
attributeValue: 3,
|
|
5336
5355
|
renderSize: "32x32",
|
|
5337
5356
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Chimney body, smoke, position circle" }],
|
|
5338
5357
|
lineStyles: [{ element: "Body outline", width: 0.8, color: "#000000" }, { element: "Smoke plume", width: 1, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5349,7 +5368,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5349
5368
|
description: "Flagstaff or flagpole conspicuous from seaward.",
|
|
5350
5369
|
s52PlRef: "LNDMRK03",
|
|
5351
5370
|
attributeKey: "CATLMK",
|
|
5352
|
-
attributeValue:
|
|
5371
|
+
attributeValue: 5,
|
|
5353
5372
|
renderSize: "32x32",
|
|
5354
5373
|
colors: [
|
|
5355
5374
|
{ token: "CHBLK", hex: "#000000", usage: "Pole and position circle" },
|
|
@@ -5369,7 +5388,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5369
5388
|
description: "Monument or memorial conspicuous from the sea.",
|
|
5370
5389
|
s52PlRef: "LNDMRK05",
|
|
5371
5390
|
attributeKey: "CATLMK",
|
|
5372
|
-
attributeValue:
|
|
5391
|
+
attributeValue: 9,
|
|
5373
5392
|
renderSize: "32x32",
|
|
5374
5393
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Monument body, base, position circle" }],
|
|
5375
5394
|
lineStyles: [{ element: "Body outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5384,9 +5403,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5384
5403
|
getSvg: landmarkWindmill,
|
|
5385
5404
|
group: "landmarks",
|
|
5386
5405
|
description: "Traditional windmill with rotating vanes. Conspicuous landmark.",
|
|
5387
|
-
s52PlRef: "
|
|
5406
|
+
s52PlRef: "WNDMIL12",
|
|
5388
5407
|
attributeKey: "CATLMK",
|
|
5389
|
-
attributeValue:
|
|
5408
|
+
attributeValue: 18,
|
|
5390
5409
|
renderSize: "32x32",
|
|
5391
5410
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, vanes, hub, position circle" }],
|
|
5392
5411
|
lineStyles: [{ element: "Tower", width: 1.5, color: "#000000" }, { element: "Vane arms", width: 1.2, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5401,9 +5420,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5401
5420
|
getSvg: landmarkWindTurbine,
|
|
5402
5421
|
group: "landmarks",
|
|
5403
5422
|
description: "Modern 3-blade wind turbine. Increasingly common offshore landmark.",
|
|
5404
|
-
s52PlRef: "
|
|
5423
|
+
s52PlRef: "WIMCON11",
|
|
5405
5424
|
attributeKey: "CATLMK",
|
|
5406
|
-
attributeValue:
|
|
5425
|
+
attributeValue: 19,
|
|
5407
5426
|
renderSize: "32x32",
|
|
5408
5427
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, blades, hub, position circle" }],
|
|
5409
5428
|
lineStyles: [{ element: "Tower", width: 1.5, color: "#000000" }, { element: "Blades", width: 1.2, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5420,7 +5439,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5420
5439
|
description: "Dome or cupola (e.g., observatory, mosque) visible from the sea.",
|
|
5421
5440
|
s52PlRef: "LNDMRK03",
|
|
5422
5441
|
attributeKey: "CATLMK",
|
|
5423
|
-
attributeValue:
|
|
5442
|
+
attributeValue: 15,
|
|
5424
5443
|
renderSize: "32x32",
|
|
5425
5444
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Dome, base, position circle" }],
|
|
5426
5445
|
lineStyles: [{ element: "Base outline", width: 0.8, color: "#000000" }, { element: "Dome curve", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5437,7 +5456,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5437
5456
|
description: "Radar scanner antenna conspicuous from seaward.",
|
|
5438
5457
|
s52PlRef: "LNDMRK12",
|
|
5439
5458
|
attributeKey: "CATLMK",
|
|
5440
|
-
attributeValue:
|
|
5459
|
+
attributeValue: 16,
|
|
5441
5460
|
renderSize: "32x32",
|
|
5442
5461
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, scanner dish, position circle" }],
|
|
5443
5462
|
lineStyles: [{ element: "Tower", width: 1.5, color: "#000000" }, { element: "Scanner frame", width: 1.5, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5454,7 +5473,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5454
5473
|
description: "Satellite dish or parabolic antenna visible from the sea.",
|
|
5455
5474
|
s52PlRef: "LNDMRK12",
|
|
5456
5475
|
attributeKey: "CATLMK",
|
|
5457
|
-
attributeValue:
|
|
5476
|
+
attributeValue: 4,
|
|
5458
5477
|
renderSize: "32x32",
|
|
5459
5478
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, dish, position circle" }],
|
|
5460
5479
|
lineStyles: [{ element: "Tower", width: 1.5, color: "#000000" }, { element: "Dish curve", width: 1.5, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5469,9 +5488,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5469
5488
|
getSvg: landmarkWaterTower,
|
|
5470
5489
|
group: "landmarks",
|
|
5471
5490
|
description: "Water tower. Elevated tank on supporting structure, conspicuous landmark.",
|
|
5472
|
-
s52PlRef: "
|
|
5473
|
-
attributeKey: "
|
|
5474
|
-
attributeValue:
|
|
5491
|
+
s52PlRef: "TOWERS12",
|
|
5492
|
+
attributeKey: "CATSIL",
|
|
5493
|
+
attributeValue: 4,
|
|
5475
5494
|
renderSize: "32x32",
|
|
5476
5495
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tank, legs, position circle" }],
|
|
5477
5496
|
lineStyles: [{ element: "Leg outlines", width: 1.2, color: "#000000" }, { element: "Tank outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5488,7 +5507,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5488
5507
|
description: "Radio or television transmission mast with horizontal cross-arms.",
|
|
5489
5508
|
s52PlRef: "LNDMRK10",
|
|
5490
5509
|
attributeKey: "CATLMK",
|
|
5491
|
-
attributeValue:
|
|
5510
|
+
attributeValue: 7,
|
|
5492
5511
|
renderSize: "32x32",
|
|
5493
5512
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Mast, cross-arms, top, position circle" }],
|
|
5494
5513
|
lineStyles: [{ element: "Main mast", width: 1.5, color: "#000000" }, { element: "Cross-arms", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5505,7 +5524,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5505
5524
|
description: "Religious cross or calvary conspicuous from seaward.",
|
|
5506
5525
|
s52PlRef: "LNDMRK05",
|
|
5507
5526
|
attributeKey: "CATLMK",
|
|
5508
|
-
attributeValue:
|
|
5527
|
+
attributeValue: 14,
|
|
5509
5528
|
renderSize: "32x32",
|
|
5510
5529
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Cross arms and position circle" }],
|
|
5511
5530
|
lineStyles: [{ element: "Vertical arm", width: 2, color: "#000000" }, { element: "Horizontal arm", width: 2, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5522,7 +5541,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5522
5541
|
description: "General mast (not radio/TV). Pole with spherical top.",
|
|
5523
5542
|
s52PlRef: "LNDMRK10",
|
|
5524
5543
|
attributeKey: "CATLMK",
|
|
5525
|
-
attributeValue:
|
|
5544
|
+
attributeValue: 7,
|
|
5526
5545
|
renderSize: "32x32",
|
|
5527
5546
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Mast pole, top ball, position circle" }],
|
|
5528
5547
|
lineStyles: [{ element: "Mast pole", width: 2, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5537,9 +5556,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5537
5556
|
getSvg: landmarkSilo,
|
|
5538
5557
|
group: "landmarks",
|
|
5539
5558
|
description: "Silo, grain elevator, or storage tank conspicuous from the sea.",
|
|
5540
|
-
s52PlRef: "
|
|
5541
|
-
attributeKey: "
|
|
5542
|
-
attributeValue:
|
|
5559
|
+
s52PlRef: "SILBUI01",
|
|
5560
|
+
attributeKey: "CATSIL",
|
|
5561
|
+
attributeValue: 1,
|
|
5543
5562
|
renderSize: "32x32",
|
|
5544
5563
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Body, dome top, position circle" }],
|
|
5545
5564
|
lineStyles: [{ element: "Body outline", width: 0.8, color: "#000000" }, { element: "Dome curve", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5941,27 +5960,18 @@ function getIconExpression(layerName) {
|
|
|
5941
5960
|
];
|
|
5942
5961
|
}
|
|
5943
5962
|
if (layerName === "LNDMRK") {
|
|
5944
|
-
return [
|
|
5945
|
-
"
|
|
5946
|
-
["coalesce", ["get", "CATLMK"], ["get", "catlmk"], 0],
|
|
5947
|
-
1,
|
|
5948
|
-
"CAIRNS11",
|
|
5949
|
-
// Cairn
|
|
5950
|
-
17,
|
|
5951
|
-
"BCNTOW01",
|
|
5952
|
-
// Tower
|
|
5953
|
-
18,
|
|
5954
|
-
"LNDMRK18",
|
|
5963
|
+
return listAttrCase("CATLMK", [
|
|
5964
|
+
["18", "LNDMRK18"],
|
|
5955
5965
|
// Windmill (4-vane)
|
|
5956
|
-
19,
|
|
5957
|
-
"LNDMRK19",
|
|
5966
|
+
["19", "LNDMRK19"],
|
|
5958
5967
|
// Wind motor / turbine (3-blade)
|
|
5959
|
-
|
|
5960
|
-
|
|
5968
|
+
["1", "CAIRNS11"],
|
|
5969
|
+
// Cairn
|
|
5970
|
+
["17", "BCNTOW01"],
|
|
5971
|
+
// Tower
|
|
5972
|
+
["20", "BCNTOW01"]
|
|
5961
5973
|
// Spire → tower
|
|
5962
|
-
|
|
5963
|
-
// Default: tower
|
|
5964
|
-
];
|
|
5974
|
+
], "BCNTOW01");
|
|
5965
5975
|
}
|
|
5966
5976
|
if (layerName === "DAYMAR") {
|
|
5967
5977
|
return [
|
|
@@ -6101,18 +6111,12 @@ function getIconExpression(layerName) {
|
|
|
6101
6111
|
];
|
|
6102
6112
|
}
|
|
6103
6113
|
if (layerName === "LIGHTS") {
|
|
6104
|
-
return [
|
|
6105
|
-
"
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
9,
|
|
6111
|
-
"LIGHTS82",
|
|
6112
|
-
// Air obstruction light
|
|
6113
|
-
"LIGHTS11"
|
|
6114
|
-
// Default: major light
|
|
6115
|
-
];
|
|
6114
|
+
return listAttrCase("CATLIT", [
|
|
6115
|
+
["8", "LIGHTS82"],
|
|
6116
|
+
// Floodlight
|
|
6117
|
+
["9", "LIGHTS82"]
|
|
6118
|
+
// Strip light
|
|
6119
|
+
], "LIGHTS11");
|
|
6116
6120
|
}
|
|
6117
6121
|
return SYMBOL_MAP[layerName] ?? "";
|
|
6118
6122
|
}
|
|
@@ -6463,30 +6467,141 @@ function buildSeabedLabelExpression() {
|
|
|
6463
6467
|
const natsurJoined = ["slice", natsurParts, 1];
|
|
6464
6468
|
return ["concat", natquaPrefix, natsurJoined];
|
|
6465
6469
|
}
|
|
6470
|
+
function underseaFeatureNameMatch(objnam) {
|
|
6471
|
+
const terms = [
|
|
6472
|
+
"Canyon",
|
|
6473
|
+
"Seamount",
|
|
6474
|
+
"Ridge",
|
|
6475
|
+
"Basin",
|
|
6476
|
+
"Swell",
|
|
6477
|
+
"Knoll",
|
|
6478
|
+
"Shoal",
|
|
6479
|
+
"Ledge",
|
|
6480
|
+
"Bank",
|
|
6481
|
+
"Valley",
|
|
6482
|
+
"Spur",
|
|
6483
|
+
"Escarpment"
|
|
6484
|
+
];
|
|
6485
|
+
return ["any", ...terms.map((t) => [">=", ["index-of", t, objnam], 0])];
|
|
6486
|
+
}
|
|
6487
|
+
var CATSEA_RELIEF_CODES = [
|
|
6488
|
+
2,
|
|
6489
|
+
// gat
|
|
6490
|
+
3,
|
|
6491
|
+
// bank
|
|
6492
|
+
4,
|
|
6493
|
+
// deep
|
|
6494
|
+
6,
|
|
6495
|
+
// trench
|
|
6496
|
+
7,
|
|
6497
|
+
// basin
|
|
6498
|
+
8,
|
|
6499
|
+
// mud flats
|
|
6500
|
+
9,
|
|
6501
|
+
// reef
|
|
6502
|
+
10,
|
|
6503
|
+
// ledge
|
|
6504
|
+
11,
|
|
6505
|
+
// canyon
|
|
6506
|
+
13,
|
|
6507
|
+
// shoal
|
|
6508
|
+
14,
|
|
6509
|
+
// knoll
|
|
6510
|
+
15,
|
|
6511
|
+
// ridge
|
|
6512
|
+
16,
|
|
6513
|
+
// seamount
|
|
6514
|
+
17,
|
|
6515
|
+
// pinnacle
|
|
6516
|
+
18,
|
|
6517
|
+
// abyssal plain
|
|
6518
|
+
19,
|
|
6519
|
+
// plateau
|
|
6520
|
+
20,
|
|
6521
|
+
// spur
|
|
6522
|
+
21,
|
|
6523
|
+
// shelf
|
|
6524
|
+
22,
|
|
6525
|
+
// trough
|
|
6526
|
+
23,
|
|
6527
|
+
// saddle
|
|
6528
|
+
24,
|
|
6529
|
+
// abyssal hills
|
|
6530
|
+
25,
|
|
6531
|
+
// apron
|
|
6532
|
+
26,
|
|
6533
|
+
// archipelagic apron
|
|
6534
|
+
27,
|
|
6535
|
+
// borderland
|
|
6536
|
+
28,
|
|
6537
|
+
// continental margin
|
|
6538
|
+
29,
|
|
6539
|
+
// continental rise
|
|
6540
|
+
30,
|
|
6541
|
+
// escarpment
|
|
6542
|
+
31,
|
|
6543
|
+
// fan
|
|
6544
|
+
32,
|
|
6545
|
+
// fracture zone
|
|
6546
|
+
33,
|
|
6547
|
+
// gap
|
|
6548
|
+
34,
|
|
6549
|
+
// guyot
|
|
6550
|
+
35,
|
|
6551
|
+
// hill
|
|
6552
|
+
36,
|
|
6553
|
+
// hole
|
|
6554
|
+
37,
|
|
6555
|
+
// hollow
|
|
6556
|
+
39,
|
|
6557
|
+
// levee
|
|
6558
|
+
40,
|
|
6559
|
+
// median valley
|
|
6560
|
+
41,
|
|
6561
|
+
// moat
|
|
6562
|
+
42,
|
|
6563
|
+
// mountains
|
|
6564
|
+
43,
|
|
6565
|
+
// peak
|
|
6566
|
+
44,
|
|
6567
|
+
// province
|
|
6568
|
+
45,
|
|
6569
|
+
// rise
|
|
6570
|
+
47,
|
|
6571
|
+
// seamount chain
|
|
6572
|
+
48,
|
|
6573
|
+
// shelf-edge
|
|
6574
|
+
49,
|
|
6575
|
+
// sill
|
|
6576
|
+
50,
|
|
6577
|
+
// slope
|
|
6578
|
+
51,
|
|
6579
|
+
// terrace
|
|
6580
|
+
52
|
|
6581
|
+
// valley
|
|
6582
|
+
];
|
|
6466
6583
|
function buildSeaAreaTierExpression() {
|
|
6467
|
-
const catsea = ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0];
|
|
6584
|
+
const catsea = ["to-number", ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0]];
|
|
6468
6585
|
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6469
6586
|
return [
|
|
6470
6587
|
"case",
|
|
6471
|
-
// Tier
|
|
6472
|
-
// anchorage
|
|
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).
|
|
6588
|
+
// Tier 4 — Anchorage detail (before all promotions so "Boston Harbor,
|
|
6589
|
+
// MA …" anchorage compound names don't bubble up).
|
|
6487
6590
|
[">=", ["index-of", "Anchorage Area", objnam], 0],
|
|
6488
6591
|
4,
|
|
6489
|
-
//
|
|
6592
|
+
// Tier 5 — undersea relief, by authoritative CATSEA code first
|
|
6593
|
+
// (Georges Bank=3, Georges Shoal=13, …), then by name for
|
|
6594
|
+
// uncategorised features. Before promotion shims; see
|
|
6595
|
+
// underseaFeatureNameMatch.
|
|
6596
|
+
["match", catsea, CATSEA_RELIEF_CODES, true, false],
|
|
6597
|
+
5,
|
|
6598
|
+
underseaFeatureNameMatch(objnam),
|
|
6599
|
+
5,
|
|
6600
|
+
// Tier 3 by authoritative CATSEA: bay / narrows.
|
|
6601
|
+
["match", catsea, [5, 12], true, false],
|
|
6602
|
+
3,
|
|
6603
|
+
// OBJNAM promotion shims (CATSEA has no ocean/sea/gulf/sound/strait
|
|
6604
|
+
// codes, so names are the only signal for the headline tiers):
|
|
6490
6605
|
[">=", ["index-of", "Atlantic Ocean", objnam], 0],
|
|
6491
6606
|
1,
|
|
6492
6607
|
[">=", ["index-of", "Pacific Ocean", objnam], 0],
|
|
@@ -6495,9 +6610,6 @@ function buildSeaAreaTierExpression() {
|
|
|
6495
6610
|
1,
|
|
6496
6611
|
[">=", ["index-of", "Gulf of", objnam], 0],
|
|
6497
6612
|
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
6613
|
[">=", ["index-of", " Bay", objnam], 0],
|
|
6502
6614
|
3,
|
|
6503
6615
|
[">=", ["index-of", " Sound", objnam], 0],
|
|
@@ -6531,6 +6643,11 @@ function buildLandRegionTierExpression() {
|
|
|
6531
6643
|
const nameLen = ["length", objnam];
|
|
6532
6644
|
return [
|
|
6533
6645
|
"case",
|
|
6646
|
+
// NOAA also encodes undersea relief names (e.g. "Block Canyon", 12
|
|
6647
|
+
// chars, no comma) as LNDRGN — without this demotion they'd qualify
|
|
6648
|
+
// as tier-1 "major region" and paint at overview zoom.
|
|
6649
|
+
underseaFeatureNameMatch(objnam),
|
|
6650
|
+
2,
|
|
6534
6651
|
["all", ["<=", nameLen, 12], ["==", ["index-of", ",", objnam], -1]],
|
|
6535
6652
|
1,
|
|
6536
6653
|
2
|
|
@@ -6612,6 +6729,36 @@ function orientationLabelLayout(extras = {}) {
|
|
|
6612
6729
|
...extras
|
|
6613
6730
|
};
|
|
6614
6731
|
}
|
|
6732
|
+
function tieredSizeCurve(tierExpr, stops) {
|
|
6733
|
+
const withHolds = [];
|
|
6734
|
+
for (let i = 0; i < stops.length; i++) {
|
|
6735
|
+
if (i > 0) {
|
|
6736
|
+
const [pz, pv] = stops[i - 1];
|
|
6737
|
+
const [nz, nv] = stops[i];
|
|
6738
|
+
if (pv.some((v, t) => v === 0 && nv[t] > 0)) {
|
|
6739
|
+
const hz = Math.round((nz - 0.2) * 10) / 10;
|
|
6740
|
+
if (hz > pz) {
|
|
6741
|
+
const f = (hz - pz) / (nz - pz);
|
|
6742
|
+
withHolds.push([
|
|
6743
|
+
hz,
|
|
6744
|
+
pv.map(
|
|
6745
|
+
(v, t) => v === 0 && nv[t] > 0 ? 0 : Math.round((v + (nv[t] - v) * f) * 10) / 10
|
|
6746
|
+
)
|
|
6747
|
+
]);
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
}
|
|
6751
|
+
withHolds.push(stops[i]);
|
|
6752
|
+
}
|
|
6753
|
+
const expr = ["interpolate", ["linear"], ["zoom"]];
|
|
6754
|
+
for (const [z, vals] of withHolds) {
|
|
6755
|
+
const m = ["match", tierExpr];
|
|
6756
|
+
for (let t = 0; t < vals.length - 1; t++) m.push(t + 1, vals[t]);
|
|
6757
|
+
m.push(vals[vals.length - 1]);
|
|
6758
|
+
expr.push(z, m);
|
|
6759
|
+
}
|
|
6760
|
+
return expr;
|
|
6761
|
+
}
|
|
6615
6762
|
var ORIENTATION_HALO_WIDTH = [
|
|
6616
6763
|
"interpolate",
|
|
6617
6764
|
["linear"],
|
|
@@ -6661,6 +6808,11 @@ var LABEL_BEHAVIOR = {
|
|
|
6661
6808
|
function getLabelBehavior(layerName) {
|
|
6662
6809
|
return LABEL_BEHAVIOR[layerName] ?? "feature-band-gated";
|
|
6663
6810
|
}
|
|
6811
|
+
var LABEL_ANCHOR_FILTER = [
|
|
6812
|
+
"!=",
|
|
6813
|
+
["get", "_label_anchor"],
|
|
6814
|
+
false
|
|
6815
|
+
];
|
|
6664
6816
|
function getLabelConfig(layerName, opts = {}) {
|
|
6665
6817
|
const ct = opts.colorTable ?? "DAY";
|
|
6666
6818
|
switch (layerName) {
|
|
@@ -6741,35 +6893,23 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6741
6893
|
}
|
|
6742
6894
|
case "LNDRGN": {
|
|
6743
6895
|
const tierExpr = buildLandRegionTierExpression();
|
|
6744
|
-
const sizeAt = (t1, t2) => [
|
|
6745
|
-
"match",
|
|
6746
|
-
tierExpr,
|
|
6747
|
-
1,
|
|
6748
|
-
t1,
|
|
6749
|
-
2,
|
|
6750
|
-
t2,
|
|
6751
|
-
t2
|
|
6752
|
-
];
|
|
6753
6896
|
return {
|
|
6754
6897
|
type: "symbol",
|
|
6755
6898
|
textField: ["get", "OBJNAM"],
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
11,
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
16,
|
|
6771
|
-
sizeAt(10, 10)
|
|
6772
|
-
],
|
|
6899
|
+
// Tier-1 entry moved from z5 to z7: undersea-relief names without a
|
|
6900
|
+
// generic keyword ("Three Dory", "Outer Fall") can't be demoted by
|
|
6901
|
+
// pattern, so the overview/general bands stay clean by holding ALL
|
|
6902
|
+
// LNDRGN labels until coastal zoom. The Carto basemap already labels
|
|
6903
|
+
// major land regions at z5-z6. Columns: t1 major region, t2 local
|
|
6904
|
+
// point (also the default).
|
|
6905
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
6906
|
+
[5, [0, 0]],
|
|
6907
|
+
[7, [11, 0]],
|
|
6908
|
+
[9, [12, 0]],
|
|
6909
|
+
[11, [12, 9]],
|
|
6910
|
+
[13, [11, 11]],
|
|
6911
|
+
[16, [10, 10]]
|
|
6912
|
+
]),
|
|
6773
6913
|
textColor: DARK_BG,
|
|
6774
6914
|
textHaloColor: COLOR.LAND_REGION,
|
|
6775
6915
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6909,19 +7049,6 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6909
7049
|
}
|
|
6910
7050
|
case "SEAARE": {
|
|
6911
7051
|
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
|
-
];
|
|
6925
7052
|
return {
|
|
6926
7053
|
type: "symbol",
|
|
6927
7054
|
textField: ["get", "OBJNAM"],
|
|
@@ -6930,26 +7057,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6930
7057
|
// it floods the overview with hundreds of small italic labels that
|
|
6931
7058
|
// crowd out the headline Ocean/Sea/Gulf names. It becomes visible only
|
|
6932
7059
|
// at approach scale (z9) when the user has zoomed in enough that
|
|
6933
|
-
// individual banks are useful context.
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
[
|
|
6937
|
-
[
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
9,
|
|
6945
|
-
sizeAt(12, 13, 14, 0, 9),
|
|
6946
|
-
11,
|
|
6947
|
-
sizeAt(10, 12, 13, 0, 11),
|
|
6948
|
-
13,
|
|
6949
|
-
sizeAt(9, 11, 12, 10, 11),
|
|
6950
|
-
16,
|
|
6951
|
-
sizeAt(9, 10, 11, 11, 10)
|
|
6952
|
-
],
|
|
7060
|
+
// individual banks are useful context. Columns: t1 ocean, t2 sea/gulf,
|
|
7061
|
+
// t3 bay/sound, t4 anchorage, default.
|
|
7062
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7063
|
+
[3, [14, 8, 0, 0, 0]],
|
|
7064
|
+
[5, [16, 13, 9, 0, 0]],
|
|
7065
|
+
[7, [14, 14, 12, 0, 0]],
|
|
7066
|
+
[9, [12, 13, 14, 0, 9]],
|
|
7067
|
+
[11, [10, 12, 13, 0, 11]],
|
|
7068
|
+
[13, [9, 11, 12, 10, 11]],
|
|
7069
|
+
[16, [9, 10, 11, 11, 10]]
|
|
7070
|
+
]),
|
|
6953
7071
|
textColor: DARK_BG,
|
|
6954
7072
|
textHaloColor: COLOR.WATER_DEEP,
|
|
6955
7073
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6958,39 +7076,38 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6958
7076
|
minzoom: 5,
|
|
6959
7077
|
layout: orientationLabelLayout({
|
|
6960
7078
|
"text-letter-spacing": 0.15,
|
|
6961
|
-
"text-max-width": 9
|
|
7079
|
+
"text-max-width": 9,
|
|
7080
|
+
// SEAARE is always-paint, unlike the other orientation classes.
|
|
7081
|
+
// MapLibre places symbols topmost-layer-first, so with
|
|
7082
|
+
// allow-overlap:false the dense sounding field (drawn above)
|
|
7083
|
+
// collision-starves big-water names — observed on staging at z8:
|
|
7084
|
+
// only 2 SEAARE labels survived viewport-wide, with Cape Cod Bay
|
|
7085
|
+
// and Gulf of Maine dropped entirely. Always-paint is safe for
|
|
7086
|
+
// this class because (a) the dominance composition in
|
|
7087
|
+
// fanOrientationLabelByCellBand suppresses cross-band duplicate
|
|
7088
|
+
// copies, and (b) tier sizing zeroes relief/anchorage names at
|
|
7089
|
+
// the zooms where density is a problem. Rivers/lakes/land keep
|
|
7090
|
+
// collision-dedup — their within-band multi-polygon stacking was
|
|
7091
|
+
// the original complaint, and they lack big-water headline value.
|
|
7092
|
+
"text-allow-overlap": true,
|
|
7093
|
+
"text-ignore-placement": true,
|
|
7094
|
+
"text-optional": false,
|
|
7095
|
+
"text-padding": 2
|
|
6962
7096
|
})
|
|
6963
7097
|
};
|
|
6964
7098
|
}
|
|
6965
7099
|
case "LAKARE": {
|
|
6966
7100
|
const tierExpr = buildLakeTierExpression();
|
|
6967
|
-
const sizeAt = (t1, t2) => [
|
|
6968
|
-
"match",
|
|
6969
|
-
tierExpr,
|
|
6970
|
-
1,
|
|
6971
|
-
t1,
|
|
6972
|
-
2,
|
|
6973
|
-
t2,
|
|
6974
|
-
t2
|
|
6975
|
-
];
|
|
6976
7101
|
return {
|
|
6977
7102
|
type: "symbol",
|
|
6978
7103
|
textField: ["get", "OBJNAM"],
|
|
6979
|
-
textSize: [
|
|
6980
|
-
|
|
6981
|
-
[
|
|
6982
|
-
[
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
sizeAt(11, 0),
|
|
6987
|
-
11,
|
|
6988
|
-
sizeAt(11, 9),
|
|
6989
|
-
13,
|
|
6990
|
-
sizeAt(10, 11),
|
|
6991
|
-
16,
|
|
6992
|
-
sizeAt(9, 10)
|
|
6993
|
-
],
|
|
7104
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7105
|
+
[7, [9, 0]],
|
|
7106
|
+
[9, [11, 0]],
|
|
7107
|
+
[11, [11, 9]],
|
|
7108
|
+
[13, [10, 11]],
|
|
7109
|
+
[16, [9, 10]]
|
|
7110
|
+
]),
|
|
6994
7111
|
textColor: DARK_BG,
|
|
6995
7112
|
textHaloColor: COLOR.WATER,
|
|
6996
7113
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7002,33 +7119,16 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
7002
7119
|
}
|
|
7003
7120
|
case "RIVERS": {
|
|
7004
7121
|
const tierExpr = buildRiverTierExpression();
|
|
7005
|
-
const sizeAt = (t1, t2) => [
|
|
7006
|
-
"match",
|
|
7007
|
-
tierExpr,
|
|
7008
|
-
1,
|
|
7009
|
-
t1,
|
|
7010
|
-
2,
|
|
7011
|
-
t2,
|
|
7012
|
-
t2
|
|
7013
|
-
];
|
|
7014
7122
|
return {
|
|
7015
7123
|
type: "symbol",
|
|
7016
7124
|
textField: ["get", "OBJNAM"],
|
|
7017
|
-
textSize: [
|
|
7018
|
-
|
|
7019
|
-
[
|
|
7020
|
-
[
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
sizeAt(11, 0),
|
|
7025
|
-
11,
|
|
7026
|
-
sizeAt(11, 9),
|
|
7027
|
-
13,
|
|
7028
|
-
sizeAt(10, 10),
|
|
7029
|
-
16,
|
|
7030
|
-
sizeAt(9, 10)
|
|
7031
|
-
],
|
|
7125
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7126
|
+
[7, [9, 0]],
|
|
7127
|
+
[9, [11, 0]],
|
|
7128
|
+
[11, [11, 9]],
|
|
7129
|
+
[13, [10, 10]],
|
|
7130
|
+
[16, [9, 10]]
|
|
7131
|
+
]),
|
|
7032
7132
|
textColor: DARK_BG,
|
|
7033
7133
|
textHaloColor: COLOR.WATER,
|
|
7034
7134
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7063,35 +7163,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
7063
7163
|
};
|
|
7064
7164
|
case "LNDARE": {
|
|
7065
7165
|
const tierExpr = buildLandAreaTierExpression();
|
|
7066
|
-
const sizeAt = (t1, t2) => [
|
|
7067
|
-
"match",
|
|
7068
|
-
tierExpr,
|
|
7069
|
-
1,
|
|
7070
|
-
t1,
|
|
7071
|
-
2,
|
|
7072
|
-
t2,
|
|
7073
|
-
t2
|
|
7074
|
-
];
|
|
7075
7166
|
return {
|
|
7076
7167
|
type: "symbol",
|
|
7077
7168
|
textField: ["get", "OBJNAM"],
|
|
7078
|
-
textSize: [
|
|
7079
|
-
|
|
7080
|
-
[
|
|
7081
|
-
[
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
9,
|
|
7087
|
-
sizeAt(11, 0),
|
|
7088
|
-
11,
|
|
7089
|
-
sizeAt(11, 9),
|
|
7090
|
-
13,
|
|
7091
|
-
sizeAt(10, 10),
|
|
7092
|
-
16,
|
|
7093
|
-
sizeAt(9, 10)
|
|
7094
|
-
],
|
|
7169
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7170
|
+
[5, [8, 0]],
|
|
7171
|
+
[7, [10, 0]],
|
|
7172
|
+
[9, [11, 0]],
|
|
7173
|
+
[11, [11, 9]],
|
|
7174
|
+
[13, [10, 10]],
|
|
7175
|
+
[16, [9, 10]]
|
|
7176
|
+
]),
|
|
7095
7177
|
textColor: DARK_BG,
|
|
7096
7178
|
textHaloColor: COLOR.LAND_NATURAL,
|
|
7097
7179
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7103,39 +7185,18 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
7103
7185
|
}
|
|
7104
7186
|
case "BUAARE": {
|
|
7105
7187
|
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
|
-
];
|
|
7117
7188
|
return {
|
|
7118
7189
|
type: "symbol",
|
|
7119
7190
|
textField: ["get", "OBJNAM"],
|
|
7120
|
-
textSize: [
|
|
7121
|
-
|
|
7122
|
-
[
|
|
7123
|
-
[
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
sizeAt(13, 9, 0),
|
|
7130
|
-
9,
|
|
7131
|
-
sizeAt(12, 12, 0),
|
|
7132
|
-
11,
|
|
7133
|
-
sizeAt(11, 12, 10),
|
|
7134
|
-
13,
|
|
7135
|
-
sizeAt(10, 11, 12),
|
|
7136
|
-
16,
|
|
7137
|
-
sizeAt(10, 10, 11)
|
|
7138
|
-
],
|
|
7191
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7192
|
+
[3, [11, 0, 0]],
|
|
7193
|
+
[5, [13, 0, 0]],
|
|
7194
|
+
[7, [13, 9, 0]],
|
|
7195
|
+
[9, [12, 12, 0]],
|
|
7196
|
+
[11, [11, 12, 10]],
|
|
7197
|
+
[13, [10, 11, 12]],
|
|
7198
|
+
[16, [10, 10, 11]]
|
|
7199
|
+
]),
|
|
7139
7200
|
textColor: DARK_BG,
|
|
7140
7201
|
textHaloColor: COLOR.CITY,
|
|
7141
7202
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7216,33 +7277,16 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
7216
7277
|
};
|
|
7217
7278
|
case "AIRARE": {
|
|
7218
7279
|
const tierExpr = buildAirportTierExpression();
|
|
7219
|
-
const sizeAt = (t1, t2) => [
|
|
7220
|
-
"match",
|
|
7221
|
-
tierExpr,
|
|
7222
|
-
1,
|
|
7223
|
-
t1,
|
|
7224
|
-
2,
|
|
7225
|
-
t2,
|
|
7226
|
-
t2
|
|
7227
|
-
];
|
|
7228
7280
|
return {
|
|
7229
7281
|
type: "symbol",
|
|
7230
7282
|
textField: ["get", "OBJNAM"],
|
|
7231
|
-
textSize: [
|
|
7232
|
-
|
|
7233
|
-
[
|
|
7234
|
-
[
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
sizeAt(11, 0),
|
|
7239
|
-
11,
|
|
7240
|
-
sizeAt(11, 9),
|
|
7241
|
-
13,
|
|
7242
|
-
sizeAt(10, 10),
|
|
7243
|
-
16,
|
|
7244
|
-
sizeAt(9, 9)
|
|
7245
|
-
],
|
|
7283
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7284
|
+
[7, [9, 0]],
|
|
7285
|
+
[9, [11, 0]],
|
|
7286
|
+
[11, [11, 9]],
|
|
7287
|
+
[13, [10, 10]],
|
|
7288
|
+
[16, [9, 9]]
|
|
7289
|
+
]),
|
|
7246
7290
|
textColor: DARK_BG,
|
|
7247
7291
|
textHaloColor: COLOR.AIRPORT,
|
|
7248
7292
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7560,6 +7604,18 @@ function preprocessSoundings(fc) {
|
|
|
7560
7604
|
}
|
|
7561
7605
|
return { type: "FeatureCollection", features };
|
|
7562
7606
|
}
|
|
7607
|
+
function firstListCode(raw) {
|
|
7608
|
+
if (raw == null) return NaN;
|
|
7609
|
+
if (Array.isArray(raw)) return Number(raw[0]);
|
|
7610
|
+
if (typeof raw === "string" && raw.startsWith("[")) {
|
|
7611
|
+
try {
|
|
7612
|
+
const arr = JSON.parse(raw);
|
|
7613
|
+
if (Array.isArray(arr)) return Number(arr[0]);
|
|
7614
|
+
} catch {
|
|
7615
|
+
}
|
|
7616
|
+
}
|
|
7617
|
+
return Number(raw);
|
|
7618
|
+
}
|
|
7563
7619
|
function preprocessLights(fc) {
|
|
7564
7620
|
return {
|
|
7565
7621
|
type: "FeatureCollection",
|
|
@@ -7568,7 +7624,7 @@ function preprocessLights(fc) {
|
|
|
7568
7624
|
const parts = [];
|
|
7569
7625
|
const litchr = Number(props.LITCHR);
|
|
7570
7626
|
if (litchr && LITCHR_ABBR[litchr]) parts.push(LITCHR_ABBR[litchr]);
|
|
7571
|
-
const colour =
|
|
7627
|
+
const colour = firstListCode(props.COLOUR);
|
|
7572
7628
|
if (colour && COLOUR_ABBR[colour]) parts.push(COLOUR_ABBR[colour]);
|
|
7573
7629
|
const sigper = Number(props.SIGPER);
|
|
7574
7630
|
if (sigper && sigper > 0) parts.push(sigper + "s");
|
|
@@ -7642,7 +7698,7 @@ function preprocessNavAids(fc) {
|
|
|
7642
7698
|
const match = objnam.match(/(\d+[A-Z]?)\s*$/);
|
|
7643
7699
|
if (!match) return f;
|
|
7644
7700
|
const designation = match[1];
|
|
7645
|
-
const colourCode =
|
|
7701
|
+
const colourCode = firstListCode(props.COLOUR);
|
|
7646
7702
|
const prefix = NAV_COLOUR_PREFIX[colourCode];
|
|
7647
7703
|
const label = prefix ? `${prefix} "${designation}"` : `"${designation}"`;
|
|
7648
7704
|
return {
|
|
@@ -9721,23 +9777,30 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
9721
9777
|
}
|
|
9722
9778
|
if (objectClass === "LNDMRK" && resolved.type === "symbol") {
|
|
9723
9779
|
const baseFilterParts = layer.filter && layer.filter[0] === "all" ? layer.filter.slice(1) : layer.filter ? [layer.filter] : [];
|
|
9724
|
-
const
|
|
9725
|
-
const
|
|
9726
|
-
const isLighthouse = ["==", catlmk, 17];
|
|
9780
|
+
const isWind = listAttrHas("CATLMK", ["18", "19"]);
|
|
9781
|
+
const isLighthouse = listAttrHas("CATLMK", ["17"]);
|
|
9727
9782
|
const scaminFloor = scaminToMinZoom(entry?.scamin);
|
|
9728
9783
|
const windLayer = {
|
|
9729
9784
|
...layer,
|
|
9730
9785
|
id: `s52-${objectClass}-wind-symbol`,
|
|
9731
|
-
filter: ["all", ...baseFilterParts, isWind]
|
|
9786
|
+
filter: ["all", ...baseFilterParts, isWind],
|
|
9787
|
+
// Explicit, not inherited: turbines share exact coordinates with
|
|
9788
|
+
// their aviation-light LIGHTS feature; without allow-overlap the
|
|
9789
|
+
// turbine icon loses collision to the LIGHTS flare and vanishes.
|
|
9790
|
+
// (The value currently also arrives via the entry-layout
|
|
9791
|
+
// spread-last chain, but that chain is fragile — see s52-lookup
|
|
9792
|
+
// LNDMRK entry — so the intent is pinned here.)
|
|
9793
|
+
layout: { ...layer.layout ?? {}, "icon-allow-overlap": true }
|
|
9732
9794
|
};
|
|
9733
9795
|
delete windLayer.minzoom;
|
|
9734
9796
|
const lighthouseLayer = {
|
|
9735
9797
|
...layer,
|
|
9736
9798
|
id: `s52-${objectClass}-lighthouse-symbol`,
|
|
9737
|
-
filter: ["all", ...baseFilterParts, isLighthouse],
|
|
9799
|
+
filter: ["all", ...baseFilterParts, isLighthouse, ["!", isWind]],
|
|
9738
9800
|
layout: {
|
|
9739
9801
|
...layer.layout ?? {},
|
|
9740
|
-
"icon-image": "LIGHTHOUSE01"
|
|
9802
|
+
"icon-image": "LIGHTHOUSE01",
|
|
9803
|
+
"icon-allow-overlap": true
|
|
9741
9804
|
}
|
|
9742
9805
|
};
|
|
9743
9806
|
delete lighthouseLayer.minzoom;
|
|
@@ -10514,7 +10577,10 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
10514
10577
|
}
|
|
10515
10578
|
if (objectClass === "TUNNEL" && resolved.type === "line") {
|
|
10516
10579
|
layers.push({
|
|
10517
|
-
|
|
10580
|
+
// NOT `s52-TUNNEL-line` — that id is already taken by the main layer
|
|
10581
|
+
// (`s52-${objectClass}-${resolved.type}`), and duplicate layer ids
|
|
10582
|
+
// are a Mapbox style-spec violation (caught by style-integrity.test).
|
|
10583
|
+
id: `s52-TUNNEL-linestring`,
|
|
10518
10584
|
type: "line",
|
|
10519
10585
|
source: sourceId,
|
|
10520
10586
|
"source-layer": "TUNNEL",
|
|
@@ -10615,7 +10681,7 @@ function buildLabelLayer2(objectClass, ct, sourceId = DEFAULT_REGION, depthUnits
|
|
|
10615
10681
|
delete layer.filter;
|
|
10616
10682
|
}
|
|
10617
10683
|
if (getLabelBehavior(objectClass) === "orientation-cross-band") {
|
|
10618
|
-
|
|
10684
|
+
layer.filter = LABEL_ANCHOR_FILTER;
|
|
10619
10685
|
}
|
|
10620
10686
|
return layer;
|
|
10621
10687
|
}
|
|
@@ -10888,24 +10954,37 @@ function fanOrientationLabelByCellBand(label) {
|
|
|
10888
10954
|
const curve = CELL_BAND_OPACITY_CURVE[code];
|
|
10889
10955
|
const opacityExpr = ["interpolate", ["linear"], ["zoom"]];
|
|
10890
10956
|
for (const [z, o] of curve) opacityExpr.push(z, o);
|
|
10891
|
-
const
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
paint: {
|
|
10903
|
-
...label.paint ?? {},
|
|
10904
|
-
"text-opacity": opacityExpr
|
|
10905
|
-
}
|
|
10957
|
+
const cellFiltered = combineWithBandFilter(
|
|
10958
|
+
label.filter,
|
|
10959
|
+
["==", cellBandExpr, code]
|
|
10960
|
+
);
|
|
10961
|
+
const minzoom = Math.max(
|
|
10962
|
+
label.minzoom ?? range.minzoom,
|
|
10963
|
+
range.minzoom
|
|
10964
|
+
);
|
|
10965
|
+
const paint = {
|
|
10966
|
+
...label.paint ?? {},
|
|
10967
|
+
"text-opacity": opacityExpr
|
|
10906
10968
|
};
|
|
10907
|
-
|
|
10908
|
-
|
|
10969
|
+
variants.push({
|
|
10970
|
+
...label,
|
|
10971
|
+
id: `${label.id}-cell${code}-notdom`,
|
|
10972
|
+
filter: combineWithBandFilter(cellFiltered, NOT_DOMINATED_FILTER),
|
|
10973
|
+
minzoom,
|
|
10974
|
+
paint
|
|
10975
|
+
});
|
|
10976
|
+
for (const D of BAND_DRAW_ORDER) {
|
|
10977
|
+
const dom = BAND_PRIORITY_RANGES[D];
|
|
10978
|
+
if (dom.minzoom <= minzoom) continue;
|
|
10979
|
+
variants.push({
|
|
10980
|
+
...label,
|
|
10981
|
+
id: `${label.id}-cell${code}-domBy${D}`,
|
|
10982
|
+
filter: combineWithBandFilter(cellFiltered, dominatedByMinFilter(D)),
|
|
10983
|
+
minzoom,
|
|
10984
|
+
maxzoom: dom.minzoom,
|
|
10985
|
+
paint
|
|
10986
|
+
});
|
|
10987
|
+
}
|
|
10909
10988
|
}
|
|
10910
10989
|
return variants;
|
|
10911
10990
|
}
|