@aguacerowx/react-native 0.0.35 → 0.0.37
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/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/.transforms/8f329a9571a96a1c1c0869d49784e448/results.bin +1 -0
- package/android/build/.transforms/8f329a9571a96a1c1c0869d49784e448/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/f95abdfc98a7a06fc247f75cdd74def9/results.bin +1 -0
- package/android/build/.transforms/f95abdfc98a7a06fc247f75cdd74def9/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +7 -15
- package/android/src/main/res/raw/fragment_shader.glsl +7 -15
- package/ios/GridRenderLayer.swift +191 -58
- package/ios/GridRenderLayerBridge.swift +8 -0
- package/ios/GridRenderLayerView.m +1 -17
- package/ios/Shaders.metal +7 -15
- package/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +7 -15
- package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +7 -15
- package/lib/commonjs/ios/GridRenderLayer.swift +191 -58
- package/lib/commonjs/ios/GridRenderLayerBridge.swift +8 -0
- package/lib/commonjs/ios/GridRenderLayerView.m +1 -17
- package/lib/commonjs/ios/Shaders.metal +7 -15
- package/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/commonjs/package.json +1 -1
- package/lib/commonjs/src/WeatherLayerManager.js +34 -12
- package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +7 -15
- package/lib/module/android/src/main/res/raw/fragment_shader.glsl +7 -15
- package/lib/module/ios/GridRenderLayer.swift +191 -58
- package/lib/module/ios/GridRenderLayerBridge.swift +8 -0
- package/lib/module/ios/GridRenderLayerView.m +1 -17
- package/lib/module/ios/Shaders.metal +7 -15
- package/lib/module/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/module/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +191 -58
- package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +8 -0
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +1 -17
- package/lib/module/lib/commonjs/ios/Shaders.metal +7 -15
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec.h +0 -0
- package/lib/module/lib/commonjs/package.json +1 -1
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js +34 -12
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/package.json +1 -1
- package/lib/module/src/WeatherLayerManager.js +35 -13
- package/lib/module/src/WeatherLayerManager.js.map +1 -1
- package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/WeatherLayerManager.js +151 -121
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// packages/react-native/src/WeatherLayerManager.js
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import { AguaceroCore, DICTIONARIES, getUnitConversionFunction } from '@aguacerowx/javascript-sdk';
|
|
4
|
+
import { fromByteArray } from 'base64-js';
|
|
5
|
+
import React, { forwardRef, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { NativeModules, Platform } from 'react-native';
|
|
5
7
|
import { AguaceroContext } from './AguaceroContext';
|
|
6
8
|
import { GridRenderLayer } from './GridRenderLayer';
|
|
7
|
-
import { fromByteArray } from 'base64-js';
|
|
8
|
-
import { Platform, NativeModules } from 'react-native';
|
|
9
9
|
import { mapRegistry } from './MapRegistry';
|
|
10
10
|
|
|
11
11
|
function findLatestModelRun(modelsData, modelName) {
|
|
@@ -67,27 +67,27 @@ const _generateColormapBytes = (colormap) => {
|
|
|
67
67
|
return data;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
AguaceroCore.prototype.setMapCenter = function(center) {
|
|
70
|
+
AguaceroCore.prototype.setMapCenter = function (center) {
|
|
71
71
|
this.emit('map:move', center);
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
75
|
-
const {
|
|
76
|
-
inspectorEnabled,
|
|
77
|
-
onInspect,
|
|
78
|
-
apiKey,
|
|
79
|
-
customColormaps,
|
|
80
|
-
initialMode,
|
|
75
|
+
const {
|
|
76
|
+
inspectorEnabled,
|
|
77
|
+
onInspect,
|
|
78
|
+
apiKey,
|
|
79
|
+
customColormaps,
|
|
80
|
+
initialMode,
|
|
81
81
|
initialVariable,
|
|
82
|
-
autoRefresh,
|
|
83
|
-
autoRefreshInterval,
|
|
82
|
+
autoRefresh,
|
|
83
|
+
autoRefreshInterval,
|
|
84
84
|
initialModel,
|
|
85
|
-
...restProps
|
|
85
|
+
...restProps
|
|
86
86
|
} = props;
|
|
87
87
|
const context = useContext(AguaceroContext);
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
// Create the core here instead of getting it from context
|
|
90
|
-
const core = useMemo(() => new AguaceroCore({
|
|
90
|
+
const core = useMemo(() => new AguaceroCore({
|
|
91
91
|
apiKey: apiKey,
|
|
92
92
|
customColormaps: customColormaps,
|
|
93
93
|
// ADD: Pass layerOptions to the core's constructor
|
|
@@ -97,27 +97,27 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
97
97
|
model: initialModel
|
|
98
98
|
}
|
|
99
99
|
}), [apiKey]);
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
const gridLayerRef = useRef(null);
|
|
102
102
|
const currentGridDataRef = useRef(null);
|
|
103
103
|
const autoRefreshIntervalId = useRef(null);
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
// Cache for preloaded grid data - stores the processed data ready for GPU upload
|
|
106
106
|
const preloadedDataCache = useRef(new Map());
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
// Store geometry and colormap that don't change with forecast hour
|
|
109
109
|
const cachedGeometry = useRef(null);
|
|
110
110
|
const cachedColormap = useRef(null);
|
|
111
111
|
const cachedDataRange = useRef([0, 1]);
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
// Track if we've done the initial load
|
|
114
114
|
const hasInitialLoad = useRef(false);
|
|
115
115
|
const hasPreloadedRef = useRef(false);
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
// Track the last state we processed to avoid redundant updates
|
|
118
118
|
const lastProcessedState = useRef(null);
|
|
119
119
|
const previousStateRef = useRef(null);
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
const [renderProps, setRenderProps] = useState({
|
|
122
122
|
opacity: 1,
|
|
123
123
|
dataRange: [0, 1]
|
|
@@ -223,11 +223,11 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
223
223
|
}
|
|
224
224
|
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
225
225
|
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
228
228
|
cachedColormap.current = { key: `${variable}-${units}` };
|
|
229
229
|
cachedDataRange.current = dataRange;
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
setRenderProps({ opacity: state.opacity, dataRange: dataRange });
|
|
232
232
|
hasInitialLoad.current = true;
|
|
233
233
|
}
|
|
@@ -259,7 +259,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
259
259
|
|
|
260
260
|
// Load the current frame FIRST and WAIT for it before continuing
|
|
261
261
|
const currentCacheKey = isMRMS ? `mrms-${currentFrame}-${variable}` : `${model}-${date}-${run}-${currentFrame}-${variable}`;
|
|
262
|
-
|
|
262
|
+
|
|
263
263
|
if (!preloadedDataCache.current.has(currentCacheKey)) {
|
|
264
264
|
let resourcePath;
|
|
265
265
|
if (isMRMS) {
|
|
@@ -277,13 +277,13 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
277
277
|
|
|
278
278
|
try {
|
|
279
279
|
const result = await WeatherFrameProcessorModule.processFrame(options);
|
|
280
|
-
|
|
280
|
+
|
|
281
281
|
if (!result || !result.filePath) {
|
|
282
282
|
return;
|
|
283
283
|
}
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
const { baseUnit } = core._getColormapForVariable(variable);
|
|
286
|
-
|
|
286
|
+
|
|
287
287
|
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
288
288
|
|
|
289
289
|
const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
|
|
@@ -315,7 +315,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
315
315
|
dataOffset = convertedOffset;
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
if (baseUnit !== toUnit) {
|
|
320
320
|
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
321
321
|
if (conversionFunc) {
|
|
@@ -333,21 +333,21 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
333
333
|
convertedScale = convertedOffsetPlusScale - convertedOffset;
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
|
-
}
|
|
337
|
-
|
|
336
|
+
}
|
|
337
|
+
|
|
338
338
|
const frameData = {
|
|
339
339
|
filePath: result.filePath,
|
|
340
340
|
nx, ny,
|
|
341
341
|
scale: convertedScale,
|
|
342
342
|
offset: convertedOffset,
|
|
343
343
|
missing: result.missing,
|
|
344
|
-
corners,
|
|
344
|
+
corners,
|
|
345
345
|
gridDef,
|
|
346
346
|
scaleType: result.scaleType,
|
|
347
347
|
originalScale: result.scale,
|
|
348
348
|
originalOffset: result.offset
|
|
349
349
|
};
|
|
350
|
-
|
|
350
|
+
|
|
351
351
|
preloadedDataCache.current.set(currentCacheKey, frameData);
|
|
352
352
|
|
|
353
353
|
// Update the GPU with the current frame
|
|
@@ -402,19 +402,19 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
402
402
|
console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}: No filePath`);
|
|
403
403
|
return;
|
|
404
404
|
}
|
|
405
|
-
|
|
405
|
+
|
|
406
406
|
// ADD: Same two-step conversion as the current frame
|
|
407
407
|
const { baseUnit } = core._getColormapForVariable(variable);
|
|
408
408
|
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
409
409
|
const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
|
|
410
410
|
const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
|
|
411
|
-
|
|
411
|
+
|
|
412
412
|
let dataScale = result.scale;
|
|
413
413
|
let dataOffset = result.offset;
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
let convertedScale = dataScale;
|
|
416
416
|
let convertedOffset = dataOffset;
|
|
417
|
-
|
|
417
|
+
|
|
418
418
|
// Step 1: Convert from server unit to colormap base unit
|
|
419
419
|
if (serverDataUnit !== baseUnit) {
|
|
420
420
|
const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
|
|
@@ -436,7 +436,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
436
436
|
dataOffset = convertedOffset;
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
-
|
|
439
|
+
|
|
440
440
|
// Step 2: Convert from colormap base unit to target display unit
|
|
441
441
|
if (baseUnit !== toUnit) {
|
|
442
442
|
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
@@ -456,27 +456,27 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
|
-
|
|
459
|
+
|
|
460
460
|
const frameData = {
|
|
461
461
|
filePath: result.filePath,
|
|
462
462
|
nx, ny,
|
|
463
463
|
scale: convertedScale,
|
|
464
464
|
offset: convertedOffset,
|
|
465
465
|
missing: result.missing,
|
|
466
|
-
corners,
|
|
466
|
+
corners,
|
|
467
467
|
gridDef,
|
|
468
468
|
scaleType: result.scaleType,
|
|
469
469
|
originalScale: result.scale,
|
|
470
470
|
originalOffset: result.offset
|
|
471
471
|
};
|
|
472
|
-
|
|
472
|
+
|
|
473
473
|
preloadedDataCache.current.set(cacheKey, frameData);
|
|
474
474
|
|
|
475
475
|
if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
|
|
476
476
|
const frameInfoForGpu = {
|
|
477
477
|
[cacheKey]: {
|
|
478
|
-
filePath: frameData.filePath,
|
|
479
|
-
nx: frameData.nx,
|
|
478
|
+
filePath: frameData.filePath,
|
|
479
|
+
nx: frameData.nx,
|
|
480
480
|
ny: frameData.ny,
|
|
481
481
|
scale: frameData.scale,
|
|
482
482
|
offset: frameData.offset,
|
|
@@ -514,7 +514,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
514
514
|
|
|
515
515
|
const updateGPUWithCachedData = (state) => {
|
|
516
516
|
const { model, date, run, forecastHour, variable, units, isMRMS, mrmsTimestamp } = state;
|
|
517
|
-
|
|
517
|
+
|
|
518
518
|
const cacheKey = isMRMS
|
|
519
519
|
? `mrms-${mrmsTimestamp}-${variable}`
|
|
520
520
|
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
@@ -522,7 +522,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
522
522
|
if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
|
|
523
523
|
// Get the cached data BEFORE calling setActiveFrame
|
|
524
524
|
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
525
|
-
|
|
525
|
+
|
|
526
526
|
if (cachedData) {
|
|
527
527
|
currentGridDataRef.current = {
|
|
528
528
|
nx: cachedData.nx,
|
|
@@ -536,28 +536,30 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
536
536
|
scaleType: cachedData.scaleType
|
|
537
537
|
};
|
|
538
538
|
}
|
|
539
|
-
|
|
540
|
-
|
|
539
|
+
|
|
540
|
+
if (__DEV__) {
|
|
541
|
+
console.log(`[WeatherLayerManager] setActiveFrame: ${cacheKey}`);
|
|
542
|
+
}
|
|
541
543
|
gridLayerRef.current.setActiveFrame(cacheKey);
|
|
542
544
|
return true;
|
|
543
545
|
}
|
|
544
546
|
|
|
545
547
|
const cachedData = preloadedDataCache.current.get(cacheKey);
|
|
546
|
-
|
|
548
|
+
|
|
547
549
|
if (!cachedData) {
|
|
548
550
|
return false;
|
|
549
551
|
}
|
|
550
|
-
|
|
552
|
+
|
|
551
553
|
if (!gridLayerRef.current) {
|
|
552
554
|
console.warn(`⚠️ [updateGPUWithCachedData] GridLayer ref not available`); // CHANGED
|
|
553
555
|
return false;
|
|
554
556
|
}
|
|
555
|
-
|
|
557
|
+
|
|
556
558
|
if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
|
|
557
559
|
gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
|
|
558
560
|
cachedGeometry.current = { model: (isMRMS ? 'mrms' : model), variable };
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
+
}
|
|
562
|
+
|
|
561
563
|
const colormapKey = `${variable}-${units}`;
|
|
562
564
|
if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
|
|
563
565
|
const { colormap, baseUnit } = core._getColormapForVariable(variable);
|
|
@@ -575,14 +577,14 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
575
577
|
}
|
|
576
578
|
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
577
579
|
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
578
|
-
|
|
580
|
+
|
|
579
581
|
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
580
582
|
cachedColormap.current = { key: colormapKey };
|
|
581
583
|
cachedDataRange.current = dataRange;
|
|
582
|
-
|
|
584
|
+
|
|
583
585
|
setRenderProps(prev => ({ ...prev, dataRange }));
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
+
}
|
|
587
|
+
|
|
586
588
|
if (cachedData.filePath) {
|
|
587
589
|
gridLayerRef.current.updateDataTextureFromFile(
|
|
588
590
|
cachedData.filePath,
|
|
@@ -590,7 +592,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
590
592
|
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
591
593
|
cachedData.scaleType
|
|
592
594
|
);
|
|
593
|
-
|
|
595
|
+
|
|
594
596
|
// ADD THIS: Update inspector cache for file-based data too
|
|
595
597
|
currentGridDataRef.current = {
|
|
596
598
|
nx: cachedData.nx,
|
|
@@ -609,15 +611,15 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
609
611
|
cachedData.scale, cachedData.offset, cachedData.missing,
|
|
610
612
|
cachedData.scaleType
|
|
611
613
|
);
|
|
612
|
-
|
|
614
|
+
|
|
613
615
|
// Update the inspector cache when using dataAsBase64
|
|
614
616
|
const binaryString = atob(cachedData.dataAsBase64);
|
|
615
617
|
const uint8Array = new Uint8Array(binaryString.length);
|
|
616
|
-
|
|
618
|
+
|
|
617
619
|
for (let i = 0; i < binaryString.length; i++) {
|
|
618
620
|
uint8Array[i] = binaryString.charCodeAt(i);
|
|
619
621
|
}
|
|
620
|
-
|
|
622
|
+
|
|
621
623
|
currentGridDataRef.current = {
|
|
622
624
|
data: uint8Array,
|
|
623
625
|
nx: cachedData.nx,
|
|
@@ -634,11 +636,11 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
634
636
|
console.error('❌ [updateGPUWithCachedData] Cached data keys:', Object.keys(cachedData));
|
|
635
637
|
return false;
|
|
636
638
|
}
|
|
637
|
-
|
|
639
|
+
|
|
638
640
|
// Update inspector parameters for file-based data too
|
|
639
641
|
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
640
642
|
gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
|
|
641
|
-
}
|
|
643
|
+
}
|
|
642
644
|
return true;
|
|
643
645
|
};
|
|
644
646
|
|
|
@@ -660,16 +662,16 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
660
662
|
console.warn('🔍 [Inspector] Core not available');
|
|
661
663
|
return null;
|
|
662
664
|
}
|
|
663
|
-
|
|
665
|
+
|
|
664
666
|
// ADD THIS: Check if we have valid data before attempting inspection
|
|
665
667
|
if (!currentGridDataRef.current) {
|
|
666
668
|
return null;
|
|
667
669
|
}
|
|
668
|
-
|
|
670
|
+
|
|
669
671
|
try {
|
|
670
672
|
const gridIndices = core._getGridIndexFromLngLat(lng, lat);
|
|
671
673
|
if (!gridIndices) return null;
|
|
672
|
-
|
|
674
|
+
|
|
673
675
|
const { i, j } = gridIndices;
|
|
674
676
|
|
|
675
677
|
const value = await InspectorModule.getValueAtGridIndex(i, j);
|
|
@@ -677,12 +679,12 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
677
679
|
if (value === null) {
|
|
678
680
|
return null;
|
|
679
681
|
}
|
|
680
|
-
|
|
682
|
+
|
|
681
683
|
const { colormap, baseUnit } = core._getColormapForVariable(core.state.variable);
|
|
682
684
|
const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
|
|
683
685
|
const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
|
|
684
686
|
const minThreshold = finalColormap[0];
|
|
685
|
-
|
|
687
|
+
|
|
686
688
|
if (value < minThreshold) {
|
|
687
689
|
return null;
|
|
688
690
|
}
|
|
@@ -691,12 +693,12 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
691
693
|
if (value < minThreshold) {
|
|
692
694
|
return null;
|
|
693
695
|
}
|
|
694
|
-
|
|
696
|
+
|
|
695
697
|
// Also check if value is NaN or effectively missing
|
|
696
698
|
if (!isFinite(value)) {
|
|
697
699
|
return null;
|
|
698
700
|
}
|
|
699
|
-
|
|
701
|
+
|
|
700
702
|
return {
|
|
701
703
|
value: value,
|
|
702
704
|
unit: displayUnit,
|
|
@@ -736,7 +738,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
736
738
|
newTimestampsToPreload.forEach(frame => {
|
|
737
739
|
const cacheKey = `mrms-${frame}-${currentVariable}`;
|
|
738
740
|
if (preloadedDataCache.current.has(cacheKey)) return;
|
|
739
|
-
|
|
741
|
+
|
|
740
742
|
const frameDate = new Date(frame * 1000);
|
|
741
743
|
const y = frameDate.getUTCFullYear(), m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0'), d = frameDate.getUTCDate().toString().padStart(2, '0');
|
|
742
744
|
const resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${currentVariable}/0`;
|
|
@@ -752,7 +754,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
752
754
|
}
|
|
753
755
|
}).catch(error => console.warn(`[Auto-Refresh] Failed to preload frame ${frame}:`, error));
|
|
754
756
|
});
|
|
755
|
-
|
|
757
|
+
|
|
756
758
|
const newTimestampsSet = new Set(newTimestamps);
|
|
757
759
|
oldTimestamps.forEach(oldTs => {
|
|
758
760
|
if (!newTimestampsSet.has(oldTs)) {
|
|
@@ -776,31 +778,29 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
776
778
|
return;
|
|
777
779
|
}
|
|
778
780
|
|
|
779
|
-
const handleStateChange =
|
|
780
|
-
props.onStateChange?.(newState);
|
|
781
|
-
|
|
781
|
+
const handleStateChange = (newState) => {
|
|
782
782
|
if (!previousStateRef.current) {
|
|
783
783
|
previousStateRef.current = core.state;
|
|
784
|
-
}
|
|
784
|
+
}
|
|
785
785
|
|
|
786
786
|
const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
|
|
787
787
|
|
|
788
788
|
if (variableChanged && gridLayerRef.current?.setVariable) {
|
|
789
789
|
gridLayerRef.current.setVariable(newState.variable);
|
|
790
790
|
}
|
|
791
|
-
|
|
791
|
+
|
|
792
792
|
const stateKey = `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
|
|
793
793
|
|
|
794
|
-
const isOpacityOnlyChange =
|
|
794
|
+
const isOpacityOnlyChange =
|
|
795
795
|
hasInitialLoad.current &&
|
|
796
|
-
newState.opacity !== renderProps.opacity &&
|
|
796
|
+
newState.opacity !== renderProps.opacity &&
|
|
797
797
|
newState.variable === previousStateRef.current?.variable &&
|
|
798
798
|
newState.forecastHour === previousStateRef.current?.forecastHour &&
|
|
799
799
|
newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
|
|
800
800
|
newState.model === previousStateRef.current?.model &&
|
|
801
801
|
newState.units === previousStateRef.current?.units;
|
|
802
802
|
|
|
803
|
-
const isPlayStateOnlyChange =
|
|
803
|
+
const isPlayStateOnlyChange =
|
|
804
804
|
hasInitialLoad.current &&
|
|
805
805
|
newState.isPlaying !== previousStateRef.current?.isPlaying &&
|
|
806
806
|
newState.variable === previousStateRef.current?.variable &&
|
|
@@ -814,11 +814,11 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
814
814
|
previousStateRef.current = newState;
|
|
815
815
|
return;
|
|
816
816
|
}
|
|
817
|
-
|
|
817
|
+
|
|
818
818
|
if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
|
|
819
819
|
lastProcessedState.current = stateKey;
|
|
820
820
|
}
|
|
821
|
-
|
|
821
|
+
|
|
822
822
|
if (isOpacityOnlyChange) {
|
|
823
823
|
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
824
824
|
previousStateRef.current = newState;
|
|
@@ -830,7 +830,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
830
830
|
return;
|
|
831
831
|
}
|
|
832
832
|
|
|
833
|
-
const isUnitsOnlyChange =
|
|
833
|
+
const isUnitsOnlyChange =
|
|
834
834
|
hasInitialLoad.current &&
|
|
835
835
|
newState.model === previousStateRef.current.model &&
|
|
836
836
|
newState.isMRMS === previousStateRef.current.isMRMS &&
|
|
@@ -843,21 +843,21 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
843
843
|
|
|
844
844
|
if (isUnitsOnlyChange) {
|
|
845
845
|
const { variable, units, isMRMS, mrmsTimestamp, model, date, run, forecastHour } = newState;
|
|
846
|
-
const oldCacheKey = isMRMS
|
|
846
|
+
const oldCacheKey = isMRMS
|
|
847
847
|
? `mrms-${mrmsTimestamp}-${variable}`
|
|
848
848
|
: `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
849
|
-
|
|
849
|
+
|
|
850
850
|
const cachedData = preloadedDataCache.current.get(oldCacheKey);
|
|
851
|
-
|
|
851
|
+
|
|
852
852
|
if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
|
|
853
853
|
const { baseUnit } = core._getColormapForVariable(variable);
|
|
854
854
|
const toUnit = core._getTargetUnit(baseUnit, units);
|
|
855
855
|
const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
|
|
856
856
|
const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
|
|
857
|
-
|
|
857
|
+
|
|
858
858
|
let dataScale = cachedData.originalScale;
|
|
859
859
|
let dataOffset = cachedData.originalOffset;
|
|
860
|
-
|
|
860
|
+
|
|
861
861
|
if (serverDataUnit !== baseUnit) {
|
|
862
862
|
const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
|
|
863
863
|
if (conversionFunc) {
|
|
@@ -878,7 +878,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
878
878
|
}
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
|
-
|
|
881
|
+
|
|
882
882
|
if (baseUnit !== toUnit) {
|
|
883
883
|
const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
|
|
884
884
|
if (conversionFunc) {
|
|
@@ -898,19 +898,19 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
898
898
|
dataOffset = convertedOffset;
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
|
-
}
|
|
902
|
-
|
|
901
|
+
}
|
|
902
|
+
|
|
903
903
|
const { colormap } = core._getColormapForVariable(variable);
|
|
904
904
|
const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
|
|
905
905
|
let dataRange = (variable === 'ptypeRefl' || variable === 'ptypeRate') ? [5, 380] : [finalColormap[0], finalColormap[finalColormap.length - 2]];
|
|
906
906
|
const colormapBytes = _generateColormapBytes(finalColormap);
|
|
907
907
|
const colormapAsBase64 = fromByteArray(colormapBytes);
|
|
908
|
-
|
|
908
|
+
|
|
909
909
|
gridLayerRef.current.updateColormapTexture(colormapAsBase64);
|
|
910
910
|
cachedColormap.current = { key: `${variable}-${units}` };
|
|
911
911
|
cachedDataRange.current = dataRange;
|
|
912
912
|
setRenderProps(prev => ({ ...prev, dataRange, opacity: newState.opacity }));
|
|
913
|
-
|
|
913
|
+
|
|
914
914
|
if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
|
|
915
915
|
const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0;
|
|
916
916
|
gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue);
|
|
@@ -919,11 +919,11 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
919
919
|
const newCacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
|
|
920
920
|
preloadedDataCache.current.set(newCacheKey, { ...cachedData, scale: dataScale, offset: dataOffset });
|
|
921
921
|
}
|
|
922
|
-
|
|
922
|
+
|
|
923
923
|
previousStateRef.current = newState;
|
|
924
924
|
return;
|
|
925
925
|
}
|
|
926
|
-
|
|
926
|
+
|
|
927
927
|
const needsFullLoad =
|
|
928
928
|
!hasInitialLoad.current ||
|
|
929
929
|
newState.model !== previousStateRef.current.model ||
|
|
@@ -958,42 +958,72 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
958
958
|
setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
|
|
959
959
|
}
|
|
960
960
|
}
|
|
961
|
-
|
|
961
|
+
|
|
962
962
|
previousStateRef.current = newState;
|
|
963
963
|
};
|
|
964
|
-
// --- END REPLACEMENT ---
|
|
965
964
|
|
|
966
965
|
handleStateChangeRef.current = handleStateChange;
|
|
967
|
-
|
|
966
|
+
|
|
968
967
|
const stableHandler = (newState) => {
|
|
969
|
-
|
|
968
|
+
// OPTIMIZATION: If playing (high speed), prioritize MAP update and skip debounce
|
|
969
|
+
if (newState.isPlaying) {
|
|
970
|
+
// 1. Update Map FIRST (Native Enqueue)
|
|
971
|
+
if (handleStateChangeRef.current) {
|
|
972
|
+
handleStateChangeRef.current(newState);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// 2. Update UI Slider SECOND
|
|
976
|
+
// This ensures the heavy map frame is processing while React reconciles the slider
|
|
977
|
+
props.onStateChange?.(newState);
|
|
978
|
+
|
|
979
|
+
if (debounceTimeoutRef.current) {
|
|
980
|
+
clearTimeout(debounceTimeoutRef.current);
|
|
981
|
+
debounceTimeoutRef.current = null;
|
|
982
|
+
}
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// --- Existing Logic for scrubbing/paused ---
|
|
987
|
+
|
|
988
|
+
// 1. Immediate Slider Update for responsiveness
|
|
989
|
+
props.onStateChange?.(newState);
|
|
990
|
+
|
|
991
|
+
if (debounceTimeoutRef.current) {
|
|
992
|
+
clearTimeout(debounceTimeoutRef.current);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// Opacity and Play state changes should be immediate for the native layer too
|
|
996
|
+
const isOpacityOnlyChange =
|
|
970
997
|
previousStateRef.current &&
|
|
971
998
|
newState.opacity !== previousStateRef.current.opacity &&
|
|
972
999
|
newState.variable === previousStateRef.current.variable &&
|
|
973
1000
|
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
974
1001
|
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
975
1002
|
newState.model === previousStateRef.current.model &&
|
|
976
|
-
newState.units === previousStateRef.current.units
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1003
|
+
newState.units === previousStateRef.current.units;
|
|
1004
|
+
|
|
1005
|
+
const isPlayStateOnlyChange =
|
|
1006
|
+
previousStateRef.current &&
|
|
1007
|
+
newState.isPlaying !== previousStateRef.current.isPlaying &&
|
|
1008
|
+
newState.variable === previousStateRef.current.variable &&
|
|
1009
|
+
newState.forecastHour === previousStateRef.current.forecastHour &&
|
|
1010
|
+
newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
|
|
1011
|
+
newState.model === previousStateRef.current.model &&
|
|
1012
|
+
newState.units === previousStateRef.current.units;
|
|
1013
|
+
|
|
1014
|
+
if (isOpacityOnlyChange || isPlayStateOnlyChange || !previousStateRef.current) {
|
|
981
1015
|
if (handleStateChangeRef.current) {
|
|
982
1016
|
handleStateChangeRef.current(newState);
|
|
983
1017
|
}
|
|
984
1018
|
return;
|
|
985
1019
|
}
|
|
986
|
-
|
|
987
|
-
if (debounceTimeoutRef.current) {
|
|
988
|
-
clearTimeout(debounceTimeoutRef.current);
|
|
989
|
-
}
|
|
990
1020
|
|
|
991
1021
|
debounceTimeoutRef.current = setTimeout(() => {
|
|
992
1022
|
if (handleStateChangeRef.current) {
|
|
993
1023
|
handleStateChangeRef.current(newState);
|
|
994
1024
|
}
|
|
995
1025
|
debounceTimeoutRef.current = null;
|
|
996
|
-
},
|
|
1026
|
+
}, 16); // ~60fps map updates
|
|
997
1027
|
};
|
|
998
1028
|
|
|
999
1029
|
core.on('state:change', stableHandler);
|
|
@@ -1005,7 +1035,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1005
1035
|
}
|
|
1006
1036
|
};
|
|
1007
1037
|
}, [core]);
|
|
1008
|
-
|
|
1038
|
+
|
|
1009
1039
|
useEffect(() => {
|
|
1010
1040
|
return () => {
|
|
1011
1041
|
preloadedDataCache.current.clear();
|
|
@@ -1013,9 +1043,9 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1013
1043
|
lastProcessedState.current = null;
|
|
1014
1044
|
};
|
|
1015
1045
|
}, []);
|
|
1016
|
-
|
|
1046
|
+
|
|
1017
1047
|
const lastInspectorUpdateRef = useRef(0);
|
|
1018
|
-
const INSPECTOR_THROTTLE_MS = 50;
|
|
1048
|
+
const INSPECTOR_THROTTLE_MS = 50;
|
|
1019
1049
|
|
|
1020
1050
|
useEffect(() => {
|
|
1021
1051
|
if (!core || !inspectorEnabled) {
|
|
@@ -1026,16 +1056,16 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1026
1056
|
if (!center || !Array.isArray(center) || center.length !== 2) {
|
|
1027
1057
|
return;
|
|
1028
1058
|
}
|
|
1029
|
-
|
|
1059
|
+
|
|
1030
1060
|
// Throttle updates
|
|
1031
1061
|
const now = Date.now();
|
|
1032
1062
|
if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
|
|
1033
1063
|
return;
|
|
1034
1064
|
}
|
|
1035
1065
|
lastInspectorUpdateRef.current = now;
|
|
1036
|
-
|
|
1066
|
+
|
|
1037
1067
|
const [longitude, latitude] = center;
|
|
1038
|
-
|
|
1068
|
+
|
|
1039
1069
|
const payload = await getValueAtPoint(longitude, latitude);
|
|
1040
1070
|
onInspect?.(payload);
|
|
1041
1071
|
};
|
|
@@ -1062,10 +1092,10 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1062
1092
|
const triggerReinspection = () => {
|
|
1063
1093
|
const mapRef = mapRegistry.getMap();
|
|
1064
1094
|
const center = mapRef?._currentCenter;
|
|
1065
|
-
|
|
1095
|
+
|
|
1066
1096
|
if (center && Array.isArray(center) && center.length === 2) {
|
|
1067
1097
|
const [longitude, latitude] = center;
|
|
1068
|
-
|
|
1098
|
+
|
|
1069
1099
|
getValueAtPoint(longitude, latitude).then(payload => {
|
|
1070
1100
|
onInspect?.(payload);
|
|
1071
1101
|
});
|
|
@@ -1078,7 +1108,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1078
1108
|
return () => clearTimeout(timer);
|
|
1079
1109
|
}, [
|
|
1080
1110
|
core?.state?.variable,
|
|
1081
|
-
core?.state?.model,
|
|
1111
|
+
core?.state?.model,
|
|
1082
1112
|
core?.state?.forecastHour,
|
|
1083
1113
|
core?.state?.mrmsTimestamp,
|
|
1084
1114
|
core?.state?.units,
|
|
@@ -1090,22 +1120,22 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
|
|
|
1090
1120
|
if (!core) {
|
|
1091
1121
|
return;
|
|
1092
1122
|
}
|
|
1093
|
-
|
|
1123
|
+
|
|
1094
1124
|
const handleCameraChange = (center) => {
|
|
1095
1125
|
if (core && center) {
|
|
1096
1126
|
core.setMapCenter(center);
|
|
1097
1127
|
}
|
|
1098
1128
|
};
|
|
1099
|
-
|
|
1129
|
+
|
|
1100
1130
|
// Register with the global registry
|
|
1101
1131
|
mapRegistry.addCameraListener(handleCameraChange);
|
|
1102
|
-
|
|
1132
|
+
|
|
1103
1133
|
// Try to get initial center
|
|
1104
1134
|
const mapRef = mapRegistry.getMap();
|
|
1105
1135
|
if (mapRef?._currentCenter) {
|
|
1106
1136
|
handleCameraChange(mapRef._currentCenter);
|
|
1107
1137
|
}
|
|
1108
|
-
|
|
1138
|
+
|
|
1109
1139
|
return () => {
|
|
1110
1140
|
mapRegistry.removeCameraListener(handleCameraChange);
|
|
1111
1141
|
};
|