@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.js
CHANGED
|
@@ -3143,18 +3143,37 @@ function depareFillExpression(ct = "DAY") {
|
|
|
3143
3143
|
resolveColor("DEPDW", ct)
|
|
3144
3144
|
];
|
|
3145
3145
|
}
|
|
3146
|
-
function
|
|
3147
|
-
|
|
3146
|
+
function listAttrString(attr) {
|
|
3147
|
+
return ["to-string", ["coalesce", ["get", attr], ["get", attr.toLowerCase()], ""]];
|
|
3148
|
+
}
|
|
3149
|
+
function listAttrCase(attr, cases, fallback) {
|
|
3150
|
+
const attrStr = listAttrString(attr);
|
|
3148
3151
|
const expr = ["case"];
|
|
3149
3152
|
for (const [code, value] of cases) {
|
|
3150
|
-
expr.push([">=", ["index-of", `"${code}"`,
|
|
3153
|
+
expr.push([">=", ["index-of", `"${code}"`, attrStr], 0], value);
|
|
3154
|
+
}
|
|
3155
|
+
for (const [code, value] of cases) {
|
|
3156
|
+
expr.push(["==", attrStr, code], value);
|
|
3151
3157
|
}
|
|
3152
3158
|
for (const [code, value] of cases) {
|
|
3153
|
-
expr.push(["==",
|
|
3159
|
+
expr.push(["==", attrStr, `[${code}]`], value);
|
|
3154
3160
|
}
|
|
3155
3161
|
expr.push(fallback);
|
|
3156
3162
|
return expr;
|
|
3157
3163
|
}
|
|
3164
|
+
function listAttrHas(attr, codes) {
|
|
3165
|
+
const attrStr = listAttrString(attr);
|
|
3166
|
+
const clauses = [];
|
|
3167
|
+
for (const code of codes) {
|
|
3168
|
+
clauses.push([">=", ["index-of", `"${code}"`, attrStr], 0]);
|
|
3169
|
+
clauses.push(["==", attrStr, code]);
|
|
3170
|
+
clauses.push(["==", attrStr, `[${code}]`]);
|
|
3171
|
+
}
|
|
3172
|
+
return ["any", ...clauses];
|
|
3173
|
+
}
|
|
3174
|
+
function colourCodeCase(cases, fallback) {
|
|
3175
|
+
return listAttrCase("COLOUR", cases, fallback);
|
|
3176
|
+
}
|
|
3158
3177
|
function lightColor(props, ct = "DAY") {
|
|
3159
3178
|
const raw = props.COLOUR ?? props.colour;
|
|
3160
3179
|
const code = Array.isArray(raw) ? Number(raw[0]) : typeof raw === "string" && raw.startsWith("[") ? Number(JSON.parse(raw)[0]) : Number(raw ?? 0);
|
|
@@ -5193,7 +5212,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5193
5212
|
description: "Church spire or steeple, conspicuous from seaward. Useful for visual fixing.",
|
|
5194
5213
|
s52PlRef: "LNDMRK17",
|
|
5195
5214
|
attributeKey: "CATLMK",
|
|
5196
|
-
attributeValue:
|
|
5215
|
+
attributeValue: 20,
|
|
5197
5216
|
renderSize: "32x32",
|
|
5198
5217
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Spire, building, position circle" }],
|
|
5199
5218
|
lineStyles: [{ element: "Building outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5210,7 +5229,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5210
5229
|
description: "Tower conspicuous from seaward. General-purpose landmark symbol.",
|
|
5211
5230
|
s52PlRef: "LNDMRK20",
|
|
5212
5231
|
attributeKey: "CATLMK",
|
|
5213
|
-
attributeValue:
|
|
5232
|
+
attributeValue: 17,
|
|
5214
5233
|
renderSize: "32x32",
|
|
5215
5234
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower body, cap, position circle" }],
|
|
5216
5235
|
lineStyles: [{ element: "Tower outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5227,7 +5246,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5227
5246
|
description: "Industrial chimney or smokestack visible from the sea.",
|
|
5228
5247
|
s52PlRef: "LNDMRK01",
|
|
5229
5248
|
attributeKey: "CATLMK",
|
|
5230
|
-
attributeValue:
|
|
5249
|
+
attributeValue: 3,
|
|
5231
5250
|
renderSize: "32x32",
|
|
5232
5251
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Chimney body, smoke, position circle" }],
|
|
5233
5252
|
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" }],
|
|
@@ -5244,7 +5263,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5244
5263
|
description: "Flagstaff or flagpole conspicuous from seaward.",
|
|
5245
5264
|
s52PlRef: "LNDMRK03",
|
|
5246
5265
|
attributeKey: "CATLMK",
|
|
5247
|
-
attributeValue:
|
|
5266
|
+
attributeValue: 5,
|
|
5248
5267
|
renderSize: "32x32",
|
|
5249
5268
|
colors: [
|
|
5250
5269
|
{ token: "CHBLK", hex: "#000000", usage: "Pole and position circle" },
|
|
@@ -5264,7 +5283,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5264
5283
|
description: "Monument or memorial conspicuous from the sea.",
|
|
5265
5284
|
s52PlRef: "LNDMRK05",
|
|
5266
5285
|
attributeKey: "CATLMK",
|
|
5267
|
-
attributeValue:
|
|
5286
|
+
attributeValue: 9,
|
|
5268
5287
|
renderSize: "32x32",
|
|
5269
5288
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Monument body, base, position circle" }],
|
|
5270
5289
|
lineStyles: [{ element: "Body outline", width: 0.8, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5279,9 +5298,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5279
5298
|
getSvg: landmarkWindmill,
|
|
5280
5299
|
group: "landmarks",
|
|
5281
5300
|
description: "Traditional windmill with rotating vanes. Conspicuous landmark.",
|
|
5282
|
-
s52PlRef: "
|
|
5301
|
+
s52PlRef: "WNDMIL12",
|
|
5283
5302
|
attributeKey: "CATLMK",
|
|
5284
|
-
attributeValue:
|
|
5303
|
+
attributeValue: 18,
|
|
5285
5304
|
renderSize: "32x32",
|
|
5286
5305
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, vanes, hub, position circle" }],
|
|
5287
5306
|
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" }],
|
|
@@ -5296,9 +5315,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5296
5315
|
getSvg: landmarkWindTurbine,
|
|
5297
5316
|
group: "landmarks",
|
|
5298
5317
|
description: "Modern 3-blade wind turbine. Increasingly common offshore landmark.",
|
|
5299
|
-
s52PlRef: "
|
|
5318
|
+
s52PlRef: "WIMCON11",
|
|
5300
5319
|
attributeKey: "CATLMK",
|
|
5301
|
-
attributeValue:
|
|
5320
|
+
attributeValue: 19,
|
|
5302
5321
|
renderSize: "32x32",
|
|
5303
5322
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, blades, hub, position circle" }],
|
|
5304
5323
|
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" }],
|
|
@@ -5315,7 +5334,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5315
5334
|
description: "Dome or cupola (e.g., observatory, mosque) visible from the sea.",
|
|
5316
5335
|
s52PlRef: "LNDMRK03",
|
|
5317
5336
|
attributeKey: "CATLMK",
|
|
5318
|
-
attributeValue:
|
|
5337
|
+
attributeValue: 15,
|
|
5319
5338
|
renderSize: "32x32",
|
|
5320
5339
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Dome, base, position circle" }],
|
|
5321
5340
|
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" }],
|
|
@@ -5332,7 +5351,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5332
5351
|
description: "Radar scanner antenna conspicuous from seaward.",
|
|
5333
5352
|
s52PlRef: "LNDMRK12",
|
|
5334
5353
|
attributeKey: "CATLMK",
|
|
5335
|
-
attributeValue:
|
|
5354
|
+
attributeValue: 16,
|
|
5336
5355
|
renderSize: "32x32",
|
|
5337
5356
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, scanner dish, position circle" }],
|
|
5338
5357
|
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" }],
|
|
@@ -5349,7 +5368,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5349
5368
|
description: "Satellite dish or parabolic antenna visible from the sea.",
|
|
5350
5369
|
s52PlRef: "LNDMRK12",
|
|
5351
5370
|
attributeKey: "CATLMK",
|
|
5352
|
-
attributeValue:
|
|
5371
|
+
attributeValue: 4,
|
|
5353
5372
|
renderSize: "32x32",
|
|
5354
5373
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tower, dish, position circle" }],
|
|
5355
5374
|
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" }],
|
|
@@ -5364,9 +5383,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5364
5383
|
getSvg: landmarkWaterTower,
|
|
5365
5384
|
group: "landmarks",
|
|
5366
5385
|
description: "Water tower. Elevated tank on supporting structure, conspicuous landmark.",
|
|
5367
|
-
s52PlRef: "
|
|
5368
|
-
attributeKey: "
|
|
5369
|
-
attributeValue:
|
|
5386
|
+
s52PlRef: "TOWERS12",
|
|
5387
|
+
attributeKey: "CATSIL",
|
|
5388
|
+
attributeValue: 4,
|
|
5370
5389
|
renderSize: "32x32",
|
|
5371
5390
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Tank, legs, position circle" }],
|
|
5372
5391
|
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" }],
|
|
@@ -5383,7 +5402,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5383
5402
|
description: "Radio or television transmission mast with horizontal cross-arms.",
|
|
5384
5403
|
s52PlRef: "LNDMRK10",
|
|
5385
5404
|
attributeKey: "CATLMK",
|
|
5386
|
-
attributeValue:
|
|
5405
|
+
attributeValue: 7,
|
|
5387
5406
|
renderSize: "32x32",
|
|
5388
5407
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Mast, cross-arms, top, position circle" }],
|
|
5389
5408
|
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" }],
|
|
@@ -5400,7 +5419,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5400
5419
|
description: "Religious cross or calvary conspicuous from seaward.",
|
|
5401
5420
|
s52PlRef: "LNDMRK05",
|
|
5402
5421
|
attributeKey: "CATLMK",
|
|
5403
|
-
attributeValue:
|
|
5422
|
+
attributeValue: 14,
|
|
5404
5423
|
renderSize: "32x32",
|
|
5405
5424
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Cross arms and position circle" }],
|
|
5406
5425
|
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" }],
|
|
@@ -5417,7 +5436,7 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5417
5436
|
description: "General mast (not radio/TV). Pole with spherical top.",
|
|
5418
5437
|
s52PlRef: "LNDMRK10",
|
|
5419
5438
|
attributeKey: "CATLMK",
|
|
5420
|
-
attributeValue:
|
|
5439
|
+
attributeValue: 7,
|
|
5421
5440
|
renderSize: "32x32",
|
|
5422
5441
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Mast pole, top ball, position circle" }],
|
|
5423
5442
|
lineStyles: [{ element: "Mast pole", width: 2, color: "#000000" }, { element: "Position circle", width: 0.6, pattern: "2, 2", color: "#000000" }],
|
|
@@ -5432,9 +5451,9 @@ var NAUTICAL_SYMBOLS = [
|
|
|
5432
5451
|
getSvg: landmarkSilo,
|
|
5433
5452
|
group: "landmarks",
|
|
5434
5453
|
description: "Silo, grain elevator, or storage tank conspicuous from the sea.",
|
|
5435
|
-
s52PlRef: "
|
|
5436
|
-
attributeKey: "
|
|
5437
|
-
attributeValue:
|
|
5454
|
+
s52PlRef: "SILBUI01",
|
|
5455
|
+
attributeKey: "CATSIL",
|
|
5456
|
+
attributeValue: 1,
|
|
5438
5457
|
renderSize: "32x32",
|
|
5439
5458
|
colors: [{ token: "CHBLK", hex: "#000000", usage: "Body, dome top, position circle" }],
|
|
5440
5459
|
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" }],
|
|
@@ -5836,27 +5855,18 @@ function getIconExpression(layerName) {
|
|
|
5836
5855
|
];
|
|
5837
5856
|
}
|
|
5838
5857
|
if (layerName === "LNDMRK") {
|
|
5839
|
-
return [
|
|
5840
|
-
"
|
|
5841
|
-
["coalesce", ["get", "CATLMK"], ["get", "catlmk"], 0],
|
|
5842
|
-
1,
|
|
5843
|
-
"CAIRNS11",
|
|
5844
|
-
// Cairn
|
|
5845
|
-
17,
|
|
5846
|
-
"BCNTOW01",
|
|
5847
|
-
// Tower
|
|
5848
|
-
18,
|
|
5849
|
-
"LNDMRK18",
|
|
5858
|
+
return listAttrCase("CATLMK", [
|
|
5859
|
+
["18", "LNDMRK18"],
|
|
5850
5860
|
// Windmill (4-vane)
|
|
5851
|
-
19,
|
|
5852
|
-
"LNDMRK19",
|
|
5861
|
+
["19", "LNDMRK19"],
|
|
5853
5862
|
// Wind motor / turbine (3-blade)
|
|
5854
|
-
|
|
5855
|
-
|
|
5863
|
+
["1", "CAIRNS11"],
|
|
5864
|
+
// Cairn
|
|
5865
|
+
["17", "BCNTOW01"],
|
|
5866
|
+
// Tower
|
|
5867
|
+
["20", "BCNTOW01"]
|
|
5856
5868
|
// Spire → tower
|
|
5857
|
-
|
|
5858
|
-
// Default: tower
|
|
5859
|
-
];
|
|
5869
|
+
], "BCNTOW01");
|
|
5860
5870
|
}
|
|
5861
5871
|
if (layerName === "DAYMAR") {
|
|
5862
5872
|
return [
|
|
@@ -5996,18 +6006,12 @@ function getIconExpression(layerName) {
|
|
|
5996
6006
|
];
|
|
5997
6007
|
}
|
|
5998
6008
|
if (layerName === "LIGHTS") {
|
|
5999
|
-
return [
|
|
6000
|
-
"
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
9,
|
|
6006
|
-
"LIGHTS82",
|
|
6007
|
-
// Air obstruction light
|
|
6008
|
-
"LIGHTS11"
|
|
6009
|
-
// Default: major light
|
|
6010
|
-
];
|
|
6009
|
+
return listAttrCase("CATLIT", [
|
|
6010
|
+
["8", "LIGHTS82"],
|
|
6011
|
+
// Floodlight
|
|
6012
|
+
["9", "LIGHTS82"]
|
|
6013
|
+
// Strip light
|
|
6014
|
+
], "LIGHTS11");
|
|
6011
6015
|
}
|
|
6012
6016
|
return SYMBOL_MAP[layerName] ?? "";
|
|
6013
6017
|
}
|
|
@@ -6358,30 +6362,141 @@ function buildSeabedLabelExpression() {
|
|
|
6358
6362
|
const natsurJoined = ["slice", natsurParts, 1];
|
|
6359
6363
|
return ["concat", natquaPrefix, natsurJoined];
|
|
6360
6364
|
}
|
|
6365
|
+
function underseaFeatureNameMatch(objnam) {
|
|
6366
|
+
const terms = [
|
|
6367
|
+
"Canyon",
|
|
6368
|
+
"Seamount",
|
|
6369
|
+
"Ridge",
|
|
6370
|
+
"Basin",
|
|
6371
|
+
"Swell",
|
|
6372
|
+
"Knoll",
|
|
6373
|
+
"Shoal",
|
|
6374
|
+
"Ledge",
|
|
6375
|
+
"Bank",
|
|
6376
|
+
"Valley",
|
|
6377
|
+
"Spur",
|
|
6378
|
+
"Escarpment"
|
|
6379
|
+
];
|
|
6380
|
+
return ["any", ...terms.map((t) => [">=", ["index-of", t, objnam], 0])];
|
|
6381
|
+
}
|
|
6382
|
+
var CATSEA_RELIEF_CODES = [
|
|
6383
|
+
2,
|
|
6384
|
+
// gat
|
|
6385
|
+
3,
|
|
6386
|
+
// bank
|
|
6387
|
+
4,
|
|
6388
|
+
// deep
|
|
6389
|
+
6,
|
|
6390
|
+
// trench
|
|
6391
|
+
7,
|
|
6392
|
+
// basin
|
|
6393
|
+
8,
|
|
6394
|
+
// mud flats
|
|
6395
|
+
9,
|
|
6396
|
+
// reef
|
|
6397
|
+
10,
|
|
6398
|
+
// ledge
|
|
6399
|
+
11,
|
|
6400
|
+
// canyon
|
|
6401
|
+
13,
|
|
6402
|
+
// shoal
|
|
6403
|
+
14,
|
|
6404
|
+
// knoll
|
|
6405
|
+
15,
|
|
6406
|
+
// ridge
|
|
6407
|
+
16,
|
|
6408
|
+
// seamount
|
|
6409
|
+
17,
|
|
6410
|
+
// pinnacle
|
|
6411
|
+
18,
|
|
6412
|
+
// abyssal plain
|
|
6413
|
+
19,
|
|
6414
|
+
// plateau
|
|
6415
|
+
20,
|
|
6416
|
+
// spur
|
|
6417
|
+
21,
|
|
6418
|
+
// shelf
|
|
6419
|
+
22,
|
|
6420
|
+
// trough
|
|
6421
|
+
23,
|
|
6422
|
+
// saddle
|
|
6423
|
+
24,
|
|
6424
|
+
// abyssal hills
|
|
6425
|
+
25,
|
|
6426
|
+
// apron
|
|
6427
|
+
26,
|
|
6428
|
+
// archipelagic apron
|
|
6429
|
+
27,
|
|
6430
|
+
// borderland
|
|
6431
|
+
28,
|
|
6432
|
+
// continental margin
|
|
6433
|
+
29,
|
|
6434
|
+
// continental rise
|
|
6435
|
+
30,
|
|
6436
|
+
// escarpment
|
|
6437
|
+
31,
|
|
6438
|
+
// fan
|
|
6439
|
+
32,
|
|
6440
|
+
// fracture zone
|
|
6441
|
+
33,
|
|
6442
|
+
// gap
|
|
6443
|
+
34,
|
|
6444
|
+
// guyot
|
|
6445
|
+
35,
|
|
6446
|
+
// hill
|
|
6447
|
+
36,
|
|
6448
|
+
// hole
|
|
6449
|
+
37,
|
|
6450
|
+
// hollow
|
|
6451
|
+
39,
|
|
6452
|
+
// levee
|
|
6453
|
+
40,
|
|
6454
|
+
// median valley
|
|
6455
|
+
41,
|
|
6456
|
+
// moat
|
|
6457
|
+
42,
|
|
6458
|
+
// mountains
|
|
6459
|
+
43,
|
|
6460
|
+
// peak
|
|
6461
|
+
44,
|
|
6462
|
+
// province
|
|
6463
|
+
45,
|
|
6464
|
+
// rise
|
|
6465
|
+
47,
|
|
6466
|
+
// seamount chain
|
|
6467
|
+
48,
|
|
6468
|
+
// shelf-edge
|
|
6469
|
+
49,
|
|
6470
|
+
// sill
|
|
6471
|
+
50,
|
|
6472
|
+
// slope
|
|
6473
|
+
51,
|
|
6474
|
+
// terrace
|
|
6475
|
+
52
|
|
6476
|
+
// valley
|
|
6477
|
+
];
|
|
6361
6478
|
function buildSeaAreaTierExpression() {
|
|
6362
|
-
const catsea = ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0];
|
|
6479
|
+
const catsea = ["to-number", ["coalesce", ["get", "CATSEA"], ["get", "catsea"], 0]];
|
|
6363
6480
|
const objnam = ["coalesce", ["get", "OBJNAM"], ""];
|
|
6364
6481
|
return [
|
|
6365
6482
|
"case",
|
|
6366
|
-
// Tier
|
|
6367
|
-
// anchorage
|
|
6368
|
-
["==", ["to-number", catsea], 31],
|
|
6369
|
-
1,
|
|
6370
|
-
["any", ["==", ["to-number", catsea], 29], ["==", ["to-number", catsea], 30]],
|
|
6371
|
-
2,
|
|
6372
|
-
[
|
|
6373
|
-
"any",
|
|
6374
|
-
["==", ["to-number", catsea], 4],
|
|
6375
|
-
["==", ["to-number", catsea], 11],
|
|
6376
|
-
["==", ["to-number", catsea], 27],
|
|
6377
|
-
["==", ["to-number", catsea], 28]
|
|
6378
|
-
],
|
|
6379
|
-
3,
|
|
6380
|
-
// Tier 4 — Anchorage detail (must be checked before OBJNAM-substring
|
|
6381
|
-
// promotion so "Boston Harbor, MA …" anchorages don't bubble up).
|
|
6483
|
+
// Tier 4 — Anchorage detail (before all promotions so "Boston Harbor,
|
|
6484
|
+
// MA …" anchorage compound names don't bubble up).
|
|
6382
6485
|
[">=", ["index-of", "Anchorage Area", objnam], 0],
|
|
6383
6486
|
4,
|
|
6384
|
-
//
|
|
6487
|
+
// Tier 5 — undersea relief, by authoritative CATSEA code first
|
|
6488
|
+
// (Georges Bank=3, Georges Shoal=13, …), then by name for
|
|
6489
|
+
// uncategorised features. Before promotion shims; see
|
|
6490
|
+
// underseaFeatureNameMatch.
|
|
6491
|
+
["match", catsea, CATSEA_RELIEF_CODES, true, false],
|
|
6492
|
+
5,
|
|
6493
|
+
underseaFeatureNameMatch(objnam),
|
|
6494
|
+
5,
|
|
6495
|
+
// Tier 3 by authoritative CATSEA: bay / narrows.
|
|
6496
|
+
["match", catsea, [5, 12], true, false],
|
|
6497
|
+
3,
|
|
6498
|
+
// OBJNAM promotion shims (CATSEA has no ocean/sea/gulf/sound/strait
|
|
6499
|
+
// codes, so names are the only signal for the headline tiers):
|
|
6385
6500
|
[">=", ["index-of", "Atlantic Ocean", objnam], 0],
|
|
6386
6501
|
1,
|
|
6387
6502
|
[">=", ["index-of", "Pacific Ocean", objnam], 0],
|
|
@@ -6390,9 +6505,6 @@ function buildSeaAreaTierExpression() {
|
|
|
6390
6505
|
1,
|
|
6391
6506
|
[">=", ["index-of", "Gulf of", objnam], 0],
|
|
6392
6507
|
2,
|
|
6393
|
-
// Bay/Sound/Sea/Strait/Channel as a tier-3 shim (matches "Massachusetts
|
|
6394
|
-
// Bay", "Buzzards Bay", "Long Island Sound", "Block Island Sound",
|
|
6395
|
-
// "Vineyard Sound", "Cape Cod Bay", etc. without needing CATSEA).
|
|
6396
6508
|
[">=", ["index-of", " Bay", objnam], 0],
|
|
6397
6509
|
3,
|
|
6398
6510
|
[">=", ["index-of", " Sound", objnam], 0],
|
|
@@ -6426,6 +6538,11 @@ function buildLandRegionTierExpression() {
|
|
|
6426
6538
|
const nameLen = ["length", objnam];
|
|
6427
6539
|
return [
|
|
6428
6540
|
"case",
|
|
6541
|
+
// NOAA also encodes undersea relief names (e.g. "Block Canyon", 12
|
|
6542
|
+
// chars, no comma) as LNDRGN — without this demotion they'd qualify
|
|
6543
|
+
// as tier-1 "major region" and paint at overview zoom.
|
|
6544
|
+
underseaFeatureNameMatch(objnam),
|
|
6545
|
+
2,
|
|
6429
6546
|
["all", ["<=", nameLen, 12], ["==", ["index-of", ",", objnam], -1]],
|
|
6430
6547
|
1,
|
|
6431
6548
|
2
|
|
@@ -6507,6 +6624,36 @@ function orientationLabelLayout(extras = {}) {
|
|
|
6507
6624
|
...extras
|
|
6508
6625
|
};
|
|
6509
6626
|
}
|
|
6627
|
+
function tieredSizeCurve(tierExpr, stops) {
|
|
6628
|
+
const withHolds = [];
|
|
6629
|
+
for (let i = 0; i < stops.length; i++) {
|
|
6630
|
+
if (i > 0) {
|
|
6631
|
+
const [pz, pv] = stops[i - 1];
|
|
6632
|
+
const [nz, nv] = stops[i];
|
|
6633
|
+
if (pv.some((v, t) => v === 0 && nv[t] > 0)) {
|
|
6634
|
+
const hz = Math.round((nz - 0.2) * 10) / 10;
|
|
6635
|
+
if (hz > pz) {
|
|
6636
|
+
const f = (hz - pz) / (nz - pz);
|
|
6637
|
+
withHolds.push([
|
|
6638
|
+
hz,
|
|
6639
|
+
pv.map(
|
|
6640
|
+
(v, t) => v === 0 && nv[t] > 0 ? 0 : Math.round((v + (nv[t] - v) * f) * 10) / 10
|
|
6641
|
+
)
|
|
6642
|
+
]);
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
}
|
|
6646
|
+
withHolds.push(stops[i]);
|
|
6647
|
+
}
|
|
6648
|
+
const expr = ["interpolate", ["linear"], ["zoom"]];
|
|
6649
|
+
for (const [z, vals] of withHolds) {
|
|
6650
|
+
const m = ["match", tierExpr];
|
|
6651
|
+
for (let t = 0; t < vals.length - 1; t++) m.push(t + 1, vals[t]);
|
|
6652
|
+
m.push(vals[vals.length - 1]);
|
|
6653
|
+
expr.push(z, m);
|
|
6654
|
+
}
|
|
6655
|
+
return expr;
|
|
6656
|
+
}
|
|
6510
6657
|
var ORIENTATION_HALO_WIDTH = [
|
|
6511
6658
|
"interpolate",
|
|
6512
6659
|
["linear"],
|
|
@@ -6556,6 +6703,11 @@ var LABEL_BEHAVIOR = {
|
|
|
6556
6703
|
function getLabelBehavior(layerName) {
|
|
6557
6704
|
return LABEL_BEHAVIOR[layerName] ?? "feature-band-gated";
|
|
6558
6705
|
}
|
|
6706
|
+
var LABEL_ANCHOR_FILTER = [
|
|
6707
|
+
"!=",
|
|
6708
|
+
["get", "_label_anchor"],
|
|
6709
|
+
false
|
|
6710
|
+
];
|
|
6559
6711
|
function getLabelConfig(layerName, opts = {}) {
|
|
6560
6712
|
const ct = opts.colorTable ?? "DAY";
|
|
6561
6713
|
switch (layerName) {
|
|
@@ -6636,35 +6788,23 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6636
6788
|
}
|
|
6637
6789
|
case "LNDRGN": {
|
|
6638
6790
|
const tierExpr = buildLandRegionTierExpression();
|
|
6639
|
-
const sizeAt = (t1, t2) => [
|
|
6640
|
-
"match",
|
|
6641
|
-
tierExpr,
|
|
6642
|
-
1,
|
|
6643
|
-
t1,
|
|
6644
|
-
2,
|
|
6645
|
-
t2,
|
|
6646
|
-
t2
|
|
6647
|
-
];
|
|
6648
6791
|
return {
|
|
6649
6792
|
type: "symbol",
|
|
6650
6793
|
textField: ["get", "OBJNAM"],
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
11,
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
16,
|
|
6666
|
-
sizeAt(10, 10)
|
|
6667
|
-
],
|
|
6794
|
+
// Tier-1 entry moved from z5 to z7: undersea-relief names without a
|
|
6795
|
+
// generic keyword ("Three Dory", "Outer Fall") can't be demoted by
|
|
6796
|
+
// pattern, so the overview/general bands stay clean by holding ALL
|
|
6797
|
+
// LNDRGN labels until coastal zoom. The Carto basemap already labels
|
|
6798
|
+
// major land regions at z5-z6. Columns: t1 major region, t2 local
|
|
6799
|
+
// point (also the default).
|
|
6800
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
6801
|
+
[5, [0, 0]],
|
|
6802
|
+
[7, [11, 0]],
|
|
6803
|
+
[9, [12, 0]],
|
|
6804
|
+
[11, [12, 9]],
|
|
6805
|
+
[13, [11, 11]],
|
|
6806
|
+
[16, [10, 10]]
|
|
6807
|
+
]),
|
|
6668
6808
|
textColor: DARK_BG,
|
|
6669
6809
|
textHaloColor: COLOR.LAND_REGION,
|
|
6670
6810
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6804,19 +6944,6 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6804
6944
|
}
|
|
6805
6945
|
case "SEAARE": {
|
|
6806
6946
|
const tierExpr = buildSeaAreaTierExpression();
|
|
6807
|
-
const sizeAt = (t1, t2, t3, t4, def) => [
|
|
6808
|
-
"match",
|
|
6809
|
-
tierExpr,
|
|
6810
|
-
1,
|
|
6811
|
-
t1,
|
|
6812
|
-
2,
|
|
6813
|
-
t2,
|
|
6814
|
-
3,
|
|
6815
|
-
t3,
|
|
6816
|
-
4,
|
|
6817
|
-
t4,
|
|
6818
|
-
def
|
|
6819
|
-
];
|
|
6820
6947
|
return {
|
|
6821
6948
|
type: "symbol",
|
|
6822
6949
|
textField: ["get", "OBJNAM"],
|
|
@@ -6825,26 +6952,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6825
6952
|
// it floods the overview with hundreds of small italic labels that
|
|
6826
6953
|
// crowd out the headline Ocean/Sea/Gulf names. It becomes visible only
|
|
6827
6954
|
// at approach scale (z9) when the user has zoomed in enough that
|
|
6828
|
-
// individual banks are useful context.
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
[
|
|
6832
|
-
[
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
9,
|
|
6840
|
-
sizeAt(12, 13, 14, 0, 9),
|
|
6841
|
-
11,
|
|
6842
|
-
sizeAt(10, 12, 13, 0, 11),
|
|
6843
|
-
13,
|
|
6844
|
-
sizeAt(9, 11, 12, 10, 11),
|
|
6845
|
-
16,
|
|
6846
|
-
sizeAt(9, 10, 11, 11, 10)
|
|
6847
|
-
],
|
|
6955
|
+
// individual banks are useful context. Columns: t1 ocean, t2 sea/gulf,
|
|
6956
|
+
// t3 bay/sound, t4 anchorage, default.
|
|
6957
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
6958
|
+
[3, [14, 8, 0, 0, 0]],
|
|
6959
|
+
[5, [16, 13, 9, 0, 0]],
|
|
6960
|
+
[7, [14, 14, 12, 0, 0]],
|
|
6961
|
+
[9, [12, 13, 14, 0, 9]],
|
|
6962
|
+
[11, [10, 12, 13, 0, 11]],
|
|
6963
|
+
[13, [9, 11, 12, 10, 11]],
|
|
6964
|
+
[16, [9, 10, 11, 11, 10]]
|
|
6965
|
+
]),
|
|
6848
6966
|
textColor: DARK_BG,
|
|
6849
6967
|
textHaloColor: COLOR.WATER_DEEP,
|
|
6850
6968
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6853,39 +6971,38 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6853
6971
|
minzoom: 5,
|
|
6854
6972
|
layout: orientationLabelLayout({
|
|
6855
6973
|
"text-letter-spacing": 0.15,
|
|
6856
|
-
"text-max-width": 9
|
|
6974
|
+
"text-max-width": 9,
|
|
6975
|
+
// SEAARE is always-paint, unlike the other orientation classes.
|
|
6976
|
+
// MapLibre places symbols topmost-layer-first, so with
|
|
6977
|
+
// allow-overlap:false the dense sounding field (drawn above)
|
|
6978
|
+
// collision-starves big-water names — observed on staging at z8:
|
|
6979
|
+
// only 2 SEAARE labels survived viewport-wide, with Cape Cod Bay
|
|
6980
|
+
// and Gulf of Maine dropped entirely. Always-paint is safe for
|
|
6981
|
+
// this class because (a) the dominance composition in
|
|
6982
|
+
// fanOrientationLabelByCellBand suppresses cross-band duplicate
|
|
6983
|
+
// copies, and (b) tier sizing zeroes relief/anchorage names at
|
|
6984
|
+
// the zooms where density is a problem. Rivers/lakes/land keep
|
|
6985
|
+
// collision-dedup — their within-band multi-polygon stacking was
|
|
6986
|
+
// the original complaint, and they lack big-water headline value.
|
|
6987
|
+
"text-allow-overlap": true,
|
|
6988
|
+
"text-ignore-placement": true,
|
|
6989
|
+
"text-optional": false,
|
|
6990
|
+
"text-padding": 2
|
|
6857
6991
|
})
|
|
6858
6992
|
};
|
|
6859
6993
|
}
|
|
6860
6994
|
case "LAKARE": {
|
|
6861
6995
|
const tierExpr = buildLakeTierExpression();
|
|
6862
|
-
const sizeAt = (t1, t2) => [
|
|
6863
|
-
"match",
|
|
6864
|
-
tierExpr,
|
|
6865
|
-
1,
|
|
6866
|
-
t1,
|
|
6867
|
-
2,
|
|
6868
|
-
t2,
|
|
6869
|
-
t2
|
|
6870
|
-
];
|
|
6871
6996
|
return {
|
|
6872
6997
|
type: "symbol",
|
|
6873
6998
|
textField: ["get", "OBJNAM"],
|
|
6874
|
-
textSize: [
|
|
6875
|
-
|
|
6876
|
-
[
|
|
6877
|
-
[
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
sizeAt(11, 0),
|
|
6882
|
-
11,
|
|
6883
|
-
sizeAt(11, 9),
|
|
6884
|
-
13,
|
|
6885
|
-
sizeAt(10, 11),
|
|
6886
|
-
16,
|
|
6887
|
-
sizeAt(9, 10)
|
|
6888
|
-
],
|
|
6999
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7000
|
+
[7, [9, 0]],
|
|
7001
|
+
[9, [11, 0]],
|
|
7002
|
+
[11, [11, 9]],
|
|
7003
|
+
[13, [10, 11]],
|
|
7004
|
+
[16, [9, 10]]
|
|
7005
|
+
]),
|
|
6889
7006
|
textColor: DARK_BG,
|
|
6890
7007
|
textHaloColor: COLOR.WATER,
|
|
6891
7008
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6897,33 +7014,16 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6897
7014
|
}
|
|
6898
7015
|
case "RIVERS": {
|
|
6899
7016
|
const tierExpr = buildRiverTierExpression();
|
|
6900
|
-
const sizeAt = (t1, t2) => [
|
|
6901
|
-
"match",
|
|
6902
|
-
tierExpr,
|
|
6903
|
-
1,
|
|
6904
|
-
t1,
|
|
6905
|
-
2,
|
|
6906
|
-
t2,
|
|
6907
|
-
t2
|
|
6908
|
-
];
|
|
6909
7017
|
return {
|
|
6910
7018
|
type: "symbol",
|
|
6911
7019
|
textField: ["get", "OBJNAM"],
|
|
6912
|
-
textSize: [
|
|
6913
|
-
|
|
6914
|
-
[
|
|
6915
|
-
[
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
sizeAt(11, 0),
|
|
6920
|
-
11,
|
|
6921
|
-
sizeAt(11, 9),
|
|
6922
|
-
13,
|
|
6923
|
-
sizeAt(10, 10),
|
|
6924
|
-
16,
|
|
6925
|
-
sizeAt(9, 10)
|
|
6926
|
-
],
|
|
7020
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7021
|
+
[7, [9, 0]],
|
|
7022
|
+
[9, [11, 0]],
|
|
7023
|
+
[11, [11, 9]],
|
|
7024
|
+
[13, [10, 10]],
|
|
7025
|
+
[16, [9, 10]]
|
|
7026
|
+
]),
|
|
6927
7027
|
textColor: DARK_BG,
|
|
6928
7028
|
textHaloColor: COLOR.WATER,
|
|
6929
7029
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6958,35 +7058,17 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6958
7058
|
};
|
|
6959
7059
|
case "LNDARE": {
|
|
6960
7060
|
const tierExpr = buildLandAreaTierExpression();
|
|
6961
|
-
const sizeAt = (t1, t2) => [
|
|
6962
|
-
"match",
|
|
6963
|
-
tierExpr,
|
|
6964
|
-
1,
|
|
6965
|
-
t1,
|
|
6966
|
-
2,
|
|
6967
|
-
t2,
|
|
6968
|
-
t2
|
|
6969
|
-
];
|
|
6970
7061
|
return {
|
|
6971
7062
|
type: "symbol",
|
|
6972
7063
|
textField: ["get", "OBJNAM"],
|
|
6973
|
-
textSize: [
|
|
6974
|
-
|
|
6975
|
-
[
|
|
6976
|
-
[
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
9,
|
|
6982
|
-
sizeAt(11, 0),
|
|
6983
|
-
11,
|
|
6984
|
-
sizeAt(11, 9),
|
|
6985
|
-
13,
|
|
6986
|
-
sizeAt(10, 10),
|
|
6987
|
-
16,
|
|
6988
|
-
sizeAt(9, 10)
|
|
6989
|
-
],
|
|
7064
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7065
|
+
[5, [8, 0]],
|
|
7066
|
+
[7, [10, 0]],
|
|
7067
|
+
[9, [11, 0]],
|
|
7068
|
+
[11, [11, 9]],
|
|
7069
|
+
[13, [10, 10]],
|
|
7070
|
+
[16, [9, 10]]
|
|
7071
|
+
]),
|
|
6990
7072
|
textColor: DARK_BG,
|
|
6991
7073
|
textHaloColor: COLOR.LAND_NATURAL,
|
|
6992
7074
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -6998,39 +7080,18 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
6998
7080
|
}
|
|
6999
7081
|
case "BUAARE": {
|
|
7000
7082
|
const tierExpr = buildBuiltUpAreaTierExpression();
|
|
7001
|
-
const sizeAt = (t1, t2, t3) => [
|
|
7002
|
-
"match",
|
|
7003
|
-
tierExpr,
|
|
7004
|
-
1,
|
|
7005
|
-
t1,
|
|
7006
|
-
2,
|
|
7007
|
-
t2,
|
|
7008
|
-
3,
|
|
7009
|
-
t3,
|
|
7010
|
-
t3
|
|
7011
|
-
];
|
|
7012
7083
|
return {
|
|
7013
7084
|
type: "symbol",
|
|
7014
7085
|
textField: ["get", "OBJNAM"],
|
|
7015
|
-
textSize: [
|
|
7016
|
-
|
|
7017
|
-
[
|
|
7018
|
-
[
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
sizeAt(13, 9, 0),
|
|
7025
|
-
9,
|
|
7026
|
-
sizeAt(12, 12, 0),
|
|
7027
|
-
11,
|
|
7028
|
-
sizeAt(11, 12, 10),
|
|
7029
|
-
13,
|
|
7030
|
-
sizeAt(10, 11, 12),
|
|
7031
|
-
16,
|
|
7032
|
-
sizeAt(10, 10, 11)
|
|
7033
|
-
],
|
|
7086
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7087
|
+
[3, [11, 0, 0]],
|
|
7088
|
+
[5, [13, 0, 0]],
|
|
7089
|
+
[7, [13, 9, 0]],
|
|
7090
|
+
[9, [12, 12, 0]],
|
|
7091
|
+
[11, [11, 12, 10]],
|
|
7092
|
+
[13, [10, 11, 12]],
|
|
7093
|
+
[16, [10, 10, 11]]
|
|
7094
|
+
]),
|
|
7034
7095
|
textColor: DARK_BG,
|
|
7035
7096
|
textHaloColor: COLOR.CITY,
|
|
7036
7097
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7111,33 +7172,16 @@ function getLabelConfig(layerName, opts = {}) {
|
|
|
7111
7172
|
};
|
|
7112
7173
|
case "AIRARE": {
|
|
7113
7174
|
const tierExpr = buildAirportTierExpression();
|
|
7114
|
-
const sizeAt = (t1, t2) => [
|
|
7115
|
-
"match",
|
|
7116
|
-
tierExpr,
|
|
7117
|
-
1,
|
|
7118
|
-
t1,
|
|
7119
|
-
2,
|
|
7120
|
-
t2,
|
|
7121
|
-
t2
|
|
7122
|
-
];
|
|
7123
7175
|
return {
|
|
7124
7176
|
type: "symbol",
|
|
7125
7177
|
textField: ["get", "OBJNAM"],
|
|
7126
|
-
textSize: [
|
|
7127
|
-
|
|
7128
|
-
[
|
|
7129
|
-
[
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
sizeAt(11, 0),
|
|
7134
|
-
11,
|
|
7135
|
-
sizeAt(11, 9),
|
|
7136
|
-
13,
|
|
7137
|
-
sizeAt(10, 10),
|
|
7138
|
-
16,
|
|
7139
|
-
sizeAt(9, 9)
|
|
7140
|
-
],
|
|
7178
|
+
textSize: tieredSizeCurve(tierExpr, [
|
|
7179
|
+
[7, [9, 0]],
|
|
7180
|
+
[9, [11, 0]],
|
|
7181
|
+
[11, [11, 9]],
|
|
7182
|
+
[13, [10, 10]],
|
|
7183
|
+
[16, [9, 9]]
|
|
7184
|
+
]),
|
|
7141
7185
|
textColor: DARK_BG,
|
|
7142
7186
|
textHaloColor: COLOR.AIRPORT,
|
|
7143
7187
|
textHaloWidth: ORIENTATION_HALO_WIDTH,
|
|
@@ -7455,6 +7499,18 @@ function preprocessSoundings(fc) {
|
|
|
7455
7499
|
}
|
|
7456
7500
|
return { type: "FeatureCollection", features };
|
|
7457
7501
|
}
|
|
7502
|
+
function firstListCode(raw) {
|
|
7503
|
+
if (raw == null) return NaN;
|
|
7504
|
+
if (Array.isArray(raw)) return Number(raw[0]);
|
|
7505
|
+
if (typeof raw === "string" && raw.startsWith("[")) {
|
|
7506
|
+
try {
|
|
7507
|
+
const arr = JSON.parse(raw);
|
|
7508
|
+
if (Array.isArray(arr)) return Number(arr[0]);
|
|
7509
|
+
} catch {
|
|
7510
|
+
}
|
|
7511
|
+
}
|
|
7512
|
+
return Number(raw);
|
|
7513
|
+
}
|
|
7458
7514
|
function preprocessLights(fc) {
|
|
7459
7515
|
return {
|
|
7460
7516
|
type: "FeatureCollection",
|
|
@@ -7463,7 +7519,7 @@ function preprocessLights(fc) {
|
|
|
7463
7519
|
const parts = [];
|
|
7464
7520
|
const litchr = Number(props.LITCHR);
|
|
7465
7521
|
if (litchr && LITCHR_ABBR[litchr]) parts.push(LITCHR_ABBR[litchr]);
|
|
7466
|
-
const colour =
|
|
7522
|
+
const colour = firstListCode(props.COLOUR);
|
|
7467
7523
|
if (colour && COLOUR_ABBR[colour]) parts.push(COLOUR_ABBR[colour]);
|
|
7468
7524
|
const sigper = Number(props.SIGPER);
|
|
7469
7525
|
if (sigper && sigper > 0) parts.push(sigper + "s");
|
|
@@ -7537,7 +7593,7 @@ function preprocessNavAids(fc) {
|
|
|
7537
7593
|
const match = objnam.match(/(\d+[A-Z]?)\s*$/);
|
|
7538
7594
|
if (!match) return f;
|
|
7539
7595
|
const designation = match[1];
|
|
7540
|
-
const colourCode =
|
|
7596
|
+
const colourCode = firstListCode(props.COLOUR);
|
|
7541
7597
|
const prefix = NAV_COLOUR_PREFIX[colourCode];
|
|
7542
7598
|
const label = prefix ? `${prefix} "${designation}"` : `"${designation}"`;
|
|
7543
7599
|
return {
|
|
@@ -9616,23 +9672,30 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
9616
9672
|
}
|
|
9617
9673
|
if (objectClass === "LNDMRK" && resolved.type === "symbol") {
|
|
9618
9674
|
const baseFilterParts = layer.filter && layer.filter[0] === "all" ? layer.filter.slice(1) : layer.filter ? [layer.filter] : [];
|
|
9619
|
-
const
|
|
9620
|
-
const
|
|
9621
|
-
const isLighthouse = ["==", catlmk, 17];
|
|
9675
|
+
const isWind = listAttrHas("CATLMK", ["18", "19"]);
|
|
9676
|
+
const isLighthouse = listAttrHas("CATLMK", ["17"]);
|
|
9622
9677
|
const scaminFloor = scaminToMinZoom(entry?.scamin);
|
|
9623
9678
|
const windLayer = {
|
|
9624
9679
|
...layer,
|
|
9625
9680
|
id: `s52-${objectClass}-wind-symbol`,
|
|
9626
|
-
filter: ["all", ...baseFilterParts, isWind]
|
|
9681
|
+
filter: ["all", ...baseFilterParts, isWind],
|
|
9682
|
+
// Explicit, not inherited: turbines share exact coordinates with
|
|
9683
|
+
// their aviation-light LIGHTS feature; without allow-overlap the
|
|
9684
|
+
// turbine icon loses collision to the LIGHTS flare and vanishes.
|
|
9685
|
+
// (The value currently also arrives via the entry-layout
|
|
9686
|
+
// spread-last chain, but that chain is fragile — see s52-lookup
|
|
9687
|
+
// LNDMRK entry — so the intent is pinned here.)
|
|
9688
|
+
layout: { ...layer.layout ?? {}, "icon-allow-overlap": true }
|
|
9627
9689
|
};
|
|
9628
9690
|
delete windLayer.minzoom;
|
|
9629
9691
|
const lighthouseLayer = {
|
|
9630
9692
|
...layer,
|
|
9631
9693
|
id: `s52-${objectClass}-lighthouse-symbol`,
|
|
9632
|
-
filter: ["all", ...baseFilterParts, isLighthouse],
|
|
9694
|
+
filter: ["all", ...baseFilterParts, isLighthouse, ["!", isWind]],
|
|
9633
9695
|
layout: {
|
|
9634
9696
|
...layer.layout ?? {},
|
|
9635
|
-
"icon-image": "LIGHTHOUSE01"
|
|
9697
|
+
"icon-image": "LIGHTHOUSE01",
|
|
9698
|
+
"icon-allow-overlap": true
|
|
9636
9699
|
}
|
|
9637
9700
|
};
|
|
9638
9701
|
delete lighthouseLayer.minzoom;
|
|
@@ -10409,7 +10472,10 @@ function buildLayersForClass(objectClass, ct, sourceId = DEFAULT_REGION) {
|
|
|
10409
10472
|
}
|
|
10410
10473
|
if (objectClass === "TUNNEL" && resolved.type === "line") {
|
|
10411
10474
|
layers.push({
|
|
10412
|
-
|
|
10475
|
+
// NOT `s52-TUNNEL-line` — that id is already taken by the main layer
|
|
10476
|
+
// (`s52-${objectClass}-${resolved.type}`), and duplicate layer ids
|
|
10477
|
+
// are a Mapbox style-spec violation (caught by style-integrity.test).
|
|
10478
|
+
id: `s52-TUNNEL-linestring`,
|
|
10413
10479
|
type: "line",
|
|
10414
10480
|
source: sourceId,
|
|
10415
10481
|
"source-layer": "TUNNEL",
|
|
@@ -10510,7 +10576,7 @@ function buildLabelLayer2(objectClass, ct, sourceId = DEFAULT_REGION, depthUnits
|
|
|
10510
10576
|
delete layer.filter;
|
|
10511
10577
|
}
|
|
10512
10578
|
if (getLabelBehavior(objectClass) === "orientation-cross-band") {
|
|
10513
|
-
|
|
10579
|
+
layer.filter = LABEL_ANCHOR_FILTER;
|
|
10514
10580
|
}
|
|
10515
10581
|
return layer;
|
|
10516
10582
|
}
|
|
@@ -10783,24 +10849,37 @@ function fanOrientationLabelByCellBand(label) {
|
|
|
10783
10849
|
const curve = CELL_BAND_OPACITY_CURVE[code];
|
|
10784
10850
|
const opacityExpr = ["interpolate", ["linear"], ["zoom"]];
|
|
10785
10851
|
for (const [z, o] of curve) opacityExpr.push(z, o);
|
|
10786
|
-
const
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
paint: {
|
|
10798
|
-
...label.paint ?? {},
|
|
10799
|
-
"text-opacity": opacityExpr
|
|
10800
|
-
}
|
|
10852
|
+
const cellFiltered = combineWithBandFilter(
|
|
10853
|
+
label.filter,
|
|
10854
|
+
["==", cellBandExpr, code]
|
|
10855
|
+
);
|
|
10856
|
+
const minzoom = Math.max(
|
|
10857
|
+
label.minzoom ?? range.minzoom,
|
|
10858
|
+
range.minzoom
|
|
10859
|
+
);
|
|
10860
|
+
const paint = {
|
|
10861
|
+
...label.paint ?? {},
|
|
10862
|
+
"text-opacity": opacityExpr
|
|
10801
10863
|
};
|
|
10802
|
-
|
|
10803
|
-
|
|
10864
|
+
variants.push({
|
|
10865
|
+
...label,
|
|
10866
|
+
id: `${label.id}-cell${code}-notdom`,
|
|
10867
|
+
filter: combineWithBandFilter(cellFiltered, NOT_DOMINATED_FILTER),
|
|
10868
|
+
minzoom,
|
|
10869
|
+
paint
|
|
10870
|
+
});
|
|
10871
|
+
for (const D of BAND_DRAW_ORDER) {
|
|
10872
|
+
const dom = BAND_PRIORITY_RANGES[D];
|
|
10873
|
+
if (dom.minzoom <= minzoom) continue;
|
|
10874
|
+
variants.push({
|
|
10875
|
+
...label,
|
|
10876
|
+
id: `${label.id}-cell${code}-domBy${D}`,
|
|
10877
|
+
filter: combineWithBandFilter(cellFiltered, dominatedByMinFilter(D)),
|
|
10878
|
+
minzoom,
|
|
10879
|
+
maxzoom: dom.minzoom,
|
|
10880
|
+
paint
|
|
10881
|
+
});
|
|
10882
|
+
}
|
|
10804
10883
|
}
|
|
10805
10884
|
return variants;
|
|
10806
10885
|
}
|