@aguacerowx/mapsgl 0.0.57 → 0.0.58
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/index.js +45 -45
- package/package.json +1 -1
- package/src/GridRenderLayer.js +1387 -1387
- package/src/MapManager.js +197 -197
- package/src/NexradSitesOverlay.js +148 -148
- package/src/NexradWeatherController.js +3 -0
- package/src/SatelliteShaderManager.js +1000 -1000
- package/src/WorkerPool.js +340 -340
- package/src/defaultBasisBaseUrl.js +11 -11
- package/src/nexrad/MapboxRadarLayer.ts +783 -783
- package/src/nexrad/PreprocessedSweepParser.ts +225 -225
- package/src/nexrad/buildRadarRayGeometry.ts +97 -97
- package/src/nexrad/level3StormRelative.ts +116 -116
- package/src/nexrad/loadNexradSites.ts +119 -119
- package/src/nexrad/nexradArchiveDiag.ts +26 -26
- package/src/nexrad/nexradCrossSectionSampleAtLatLon.ts +121 -121
- package/src/nexrad/nexradMapboxFrameOpts.ts +126 -126
- package/src/nexrad/nexradSitesDefault.json +1699 -1699
- package/src/nexrad/radarArchiveCore.bundled.js +10 -0
- package/src/nexrad/radarArchiveCore.ts +11 -0
- package/src/nexrad/radarDecode.worker.ts +25 -25
- package/src/nexrad/radarDecodeSlot.ts +195 -195
- package/src/nexrad/radarFrameGpuMatch.ts +111 -111
- package/src/satelliteDefaultColormaps.js +37 -37
- package/src/satelliteKtxWorker.js +232 -232
- package/src/satelliteShader.js +17 -17
- package/src/style-applicator.js +112 -112
- package/src/style-layer-map.js +26 -26
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GeoJSON markers for all NEXRAD sites (picker mode). Aligned with aguacero-frontend NexradSitesLayer (simplified).
|
|
3
|
-
*/
|
|
4
|
-
const SOURCE_ID = 'aguacero-nexrad-sites-src';
|
|
5
|
-
const CIRCLE_LAYER_ID = 'aguacero-nexrad-sites-circles';
|
|
6
|
-
|
|
7
|
-
export class NexradSitesOverlay {
|
|
8
|
-
constructor(map, options = {}) {
|
|
9
|
-
this.map = map;
|
|
10
|
-
/** Same path as aguacero-frontend: serve `public/data/nexrad.json` (e.g. Vite → `/data/nexrad.json`). */
|
|
11
|
-
this.sitesUrl = options.nexradSitesUrl || '/data/nexrad.json';
|
|
12
|
-
this._onClick = null;
|
|
13
|
-
/** Coalesces overlapping `show()` calls (e.g. NEXRAD timestamp slider firing many state updates). */
|
|
14
|
-
this._showPromise = null;
|
|
15
|
-
this._destroyed = false;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
_layersPresent() {
|
|
19
|
-
try {
|
|
20
|
-
return Boolean(this.map.getSource(SOURCE_ID) && this.map.getLayer(CIRCLE_LAYER_ID));
|
|
21
|
-
} catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async show() {
|
|
27
|
-
if (this._layersPresent()) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if (this._showPromise) {
|
|
31
|
-
return this._showPromise;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
this._showPromise = this._loadAndMountSites();
|
|
35
|
-
try {
|
|
36
|
-
await this._showPromise;
|
|
37
|
-
} finally {
|
|
38
|
-
this._showPromise = null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async _loadAndMountSites() {
|
|
43
|
-
if (this._layersPresent()) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
await this.hide();
|
|
47
|
-
let res;
|
|
48
|
-
try {
|
|
49
|
-
res = await fetch(this.sitesUrl);
|
|
50
|
-
} catch (e) {
|
|
51
|
-
console.warn('[NexradSitesOverlay] Failed to load site list:', e);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (!res.ok) {
|
|
55
|
-
console.warn('[NexradSitesOverlay] HTTP', res.status, this.sitesUrl);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (this._destroyed) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const payload = await res.json();
|
|
62
|
-
const raw = Array.isArray(payload)
|
|
63
|
-
? payload
|
|
64
|
-
: payload?.features
|
|
65
|
-
? payload.features
|
|
66
|
-
: payload?.sites
|
|
67
|
-
? payload.sites
|
|
68
|
-
: [];
|
|
69
|
-
const features = [];
|
|
70
|
-
for (const item of raw) {
|
|
71
|
-
if (!item) continue;
|
|
72
|
-
const coords = item.geometry?.coordinates
|
|
73
|
-
? item.geometry.coordinates
|
|
74
|
-
: [item.lon ?? item.lng ?? item.longitude, item.lat ?? item.latitude];
|
|
75
|
-
const lon = Number(coords[0]);
|
|
76
|
-
const lat = Number(coords[1]);
|
|
77
|
-
const id = String(item.id ?? item.properties?.id ?? item.station ?? '').toUpperCase();
|
|
78
|
-
if (!id || !Number.isFinite(lat) || !Number.isFinite(lon)) continue;
|
|
79
|
-
features.push({
|
|
80
|
-
type: 'Feature',
|
|
81
|
-
geometry: { type: 'Point', coordinates: [lon, lat] },
|
|
82
|
-
properties: { name: id },
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
if (this._destroyed) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
this.map.addSource(SOURCE_ID, {
|
|
89
|
-
type: 'geojson',
|
|
90
|
-
data: { type: 'FeatureCollection', features },
|
|
91
|
-
});
|
|
92
|
-
this.map.addLayer({
|
|
93
|
-
id: CIRCLE_LAYER_ID,
|
|
94
|
-
type: 'circle',
|
|
95
|
-
source: SOURCE_ID,
|
|
96
|
-
paint: {
|
|
97
|
-
'circle-radius': 5,
|
|
98
|
-
'circle-color': '#3b82f6',
|
|
99
|
-
'circle-stroke-width': 1,
|
|
100
|
-
'circle-stroke-color': '#ffffff',
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
hide() {
|
|
106
|
-
try {
|
|
107
|
-
if (this.map.getLayer(CIRCLE_LAYER_ID)) this.map.removeLayer(CIRCLE_LAYER_ID);
|
|
108
|
-
if (this.map.getSource(SOURCE_ID)) this.map.removeSource(SOURCE_ID);
|
|
109
|
-
} catch {
|
|
110
|
-
/* ignore */
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @param {(siteId: string) => void} handler
|
|
116
|
-
*/
|
|
117
|
-
bindClick(handler) {
|
|
118
|
-
this.unbindClick();
|
|
119
|
-
this._onClick = (e) => {
|
|
120
|
-
const f = e.features?.[0];
|
|
121
|
-
const id = f?.properties?.name;
|
|
122
|
-
if (id) handler(String(id));
|
|
123
|
-
};
|
|
124
|
-
this.map.on('click', CIRCLE_LAYER_ID, this._onClick);
|
|
125
|
-
this.map.on('mouseenter', CIRCLE_LAYER_ID, () => {
|
|
126
|
-
this.map.getCanvas().style.cursor = 'pointer';
|
|
127
|
-
});
|
|
128
|
-
this.map.on('mouseleave', CIRCLE_LAYER_ID, () => {
|
|
129
|
-
this.map.getCanvas().style.cursor = '';
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
unbindClick() {
|
|
134
|
-
if (!this._onClick) return;
|
|
135
|
-
try {
|
|
136
|
-
this.map.off('click', CIRCLE_LAYER_ID, this._onClick);
|
|
137
|
-
} catch {
|
|
138
|
-
/* ignore */
|
|
139
|
-
}
|
|
140
|
-
this._onClick = null;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
destroy() {
|
|
144
|
-
this._destroyed = true;
|
|
145
|
-
this.unbindClick();
|
|
146
|
-
this.hide();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* GeoJSON markers for all NEXRAD sites (picker mode). Aligned with aguacero-frontend NexradSitesLayer (simplified).
|
|
3
|
+
*/
|
|
4
|
+
const SOURCE_ID = 'aguacero-nexrad-sites-src';
|
|
5
|
+
const CIRCLE_LAYER_ID = 'aguacero-nexrad-sites-circles';
|
|
6
|
+
|
|
7
|
+
export class NexradSitesOverlay {
|
|
8
|
+
constructor(map, options = {}) {
|
|
9
|
+
this.map = map;
|
|
10
|
+
/** Same path as aguacero-frontend: serve `public/data/nexrad.json` (e.g. Vite → `/data/nexrad.json`). */
|
|
11
|
+
this.sitesUrl = options.nexradSitesUrl || '/data/nexrad.json';
|
|
12
|
+
this._onClick = null;
|
|
13
|
+
/** Coalesces overlapping `show()` calls (e.g. NEXRAD timestamp slider firing many state updates). */
|
|
14
|
+
this._showPromise = null;
|
|
15
|
+
this._destroyed = false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
_layersPresent() {
|
|
19
|
+
try {
|
|
20
|
+
return Boolean(this.map.getSource(SOURCE_ID) && this.map.getLayer(CIRCLE_LAYER_ID));
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async show() {
|
|
27
|
+
if (this._layersPresent()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (this._showPromise) {
|
|
31
|
+
return this._showPromise;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this._showPromise = this._loadAndMountSites();
|
|
35
|
+
try {
|
|
36
|
+
await this._showPromise;
|
|
37
|
+
} finally {
|
|
38
|
+
this._showPromise = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async _loadAndMountSites() {
|
|
43
|
+
if (this._layersPresent()) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
await this.hide();
|
|
47
|
+
let res;
|
|
48
|
+
try {
|
|
49
|
+
res = await fetch(this.sitesUrl);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.warn('[NexradSitesOverlay] Failed to load site list:', e);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
console.warn('[NexradSitesOverlay] HTTP', res.status, this.sitesUrl);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (this._destroyed) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const payload = await res.json();
|
|
62
|
+
const raw = Array.isArray(payload)
|
|
63
|
+
? payload
|
|
64
|
+
: payload?.features
|
|
65
|
+
? payload.features
|
|
66
|
+
: payload?.sites
|
|
67
|
+
? payload.sites
|
|
68
|
+
: [];
|
|
69
|
+
const features = [];
|
|
70
|
+
for (const item of raw) {
|
|
71
|
+
if (!item) continue;
|
|
72
|
+
const coords = item.geometry?.coordinates
|
|
73
|
+
? item.geometry.coordinates
|
|
74
|
+
: [item.lon ?? item.lng ?? item.longitude, item.lat ?? item.latitude];
|
|
75
|
+
const lon = Number(coords[0]);
|
|
76
|
+
const lat = Number(coords[1]);
|
|
77
|
+
const id = String(item.id ?? item.properties?.id ?? item.station ?? '').toUpperCase();
|
|
78
|
+
if (!id || !Number.isFinite(lat) || !Number.isFinite(lon)) continue;
|
|
79
|
+
features.push({
|
|
80
|
+
type: 'Feature',
|
|
81
|
+
geometry: { type: 'Point', coordinates: [lon, lat] },
|
|
82
|
+
properties: { name: id },
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (this._destroyed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.map.addSource(SOURCE_ID, {
|
|
89
|
+
type: 'geojson',
|
|
90
|
+
data: { type: 'FeatureCollection', features },
|
|
91
|
+
});
|
|
92
|
+
this.map.addLayer({
|
|
93
|
+
id: CIRCLE_LAYER_ID,
|
|
94
|
+
type: 'circle',
|
|
95
|
+
source: SOURCE_ID,
|
|
96
|
+
paint: {
|
|
97
|
+
'circle-radius': 5,
|
|
98
|
+
'circle-color': '#3b82f6',
|
|
99
|
+
'circle-stroke-width': 1,
|
|
100
|
+
'circle-stroke-color': '#ffffff',
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
hide() {
|
|
106
|
+
try {
|
|
107
|
+
if (this.map.getLayer(CIRCLE_LAYER_ID)) this.map.removeLayer(CIRCLE_LAYER_ID);
|
|
108
|
+
if (this.map.getSource(SOURCE_ID)) this.map.removeSource(SOURCE_ID);
|
|
109
|
+
} catch {
|
|
110
|
+
/* ignore */
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @param {(siteId: string) => void} handler
|
|
116
|
+
*/
|
|
117
|
+
bindClick(handler) {
|
|
118
|
+
this.unbindClick();
|
|
119
|
+
this._onClick = (e) => {
|
|
120
|
+
const f = e.features?.[0];
|
|
121
|
+
const id = f?.properties?.name;
|
|
122
|
+
if (id) handler(String(id));
|
|
123
|
+
};
|
|
124
|
+
this.map.on('click', CIRCLE_LAYER_ID, this._onClick);
|
|
125
|
+
this.map.on('mouseenter', CIRCLE_LAYER_ID, () => {
|
|
126
|
+
this.map.getCanvas().style.cursor = 'pointer';
|
|
127
|
+
});
|
|
128
|
+
this.map.on('mouseleave', CIRCLE_LAYER_ID, () => {
|
|
129
|
+
this.map.getCanvas().style.cursor = '';
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
unbindClick() {
|
|
134
|
+
if (!this._onClick) return;
|
|
135
|
+
try {
|
|
136
|
+
this.map.off('click', CIRCLE_LAYER_ID, this._onClick);
|
|
137
|
+
} catch {
|
|
138
|
+
/* ignore */
|
|
139
|
+
}
|
|
140
|
+
this._onClick = null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
destroy() {
|
|
144
|
+
this._destroyed = true;
|
|
145
|
+
this.unbindClick();
|
|
146
|
+
this.hide();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
objectKeyToUrl,
|
|
9
9
|
setNexradArchiveApiKey,
|
|
10
10
|
setNexradArchiveBundleId,
|
|
11
|
+
setNexradArchiveSiteOrigin,
|
|
11
12
|
setNexradSitesFetchAuth,
|
|
12
13
|
} from './nexrad/radarArchiveCore.bundled.js';
|
|
13
14
|
import { MapboxRadarLayer } from './nexrad/MapboxRadarLayer.bundled.js';
|
|
@@ -275,6 +276,7 @@ export class NexradWeatherController {
|
|
|
275
276
|
|
|
276
277
|
setNexradArchiveApiKey(this.core.apiKey || '');
|
|
277
278
|
setNexradArchiveBundleId(this.core.bundleId || '');
|
|
279
|
+
setNexradArchiveSiteOrigin(this.core.gridRequestSiteOrigin || '');
|
|
278
280
|
setNexradSitesFetchAuth(this.core.apiKey || '', this.core.bundleId || '');
|
|
279
281
|
|
|
280
282
|
const times = [...(state.availableNexradTimestamps || [])]
|
|
@@ -362,6 +364,7 @@ export class NexradWeatherController {
|
|
|
362
364
|
|
|
363
365
|
setNexradArchiveApiKey(this.core.apiKey || '');
|
|
364
366
|
setNexradArchiveBundleId(this.core.bundleId || '');
|
|
367
|
+
setNexradArchiveSiteOrigin(this.core.gridRequestSiteOrigin || '');
|
|
365
368
|
setNexradSitesFetchAuth(this.core.apiKey || '', this.core.bundleId || '');
|
|
366
369
|
|
|
367
370
|
const unix = Number(state.nexradTimestamp);
|