autumnplot-gl 4.0.0-beta → 4.1.0
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/README.md +13 -207
- package/dist/812.autumnplot-gl.js +2 -0
- package/dist/812.autumnplot-gl.js.map +1 -0
- package/dist/983.autumnplot-gl.js +2 -0
- package/dist/983.autumnplot-gl.js.map +1 -0
- package/dist/autumnplot-gl.js +1 -1
- package/dist/autumnplot-gl.js.map +1 -1
- package/dist/marchingsquares.wasm +0 -0
- package/lib/AutumnTypes.d.ts +38 -5
- package/lib/AutumnTypes.js +7 -1
- package/lib/Barbs.d.ts +12 -2
- package/lib/Barbs.js +9 -0
- package/lib/BillboardCollection.d.ts +2 -2
- package/lib/BillboardCollection.js +14 -14
- package/lib/Color.d.ts +1 -0
- package/lib/Color.js +1 -0
- package/lib/ColorBar.d.ts +14 -0
- package/lib/ColorBar.js +15 -8
- package/lib/Colormap.d.ts +9 -1
- package/lib/Colormap.js +24 -1
- package/lib/Contour.d.ts +26 -1
- package/lib/Contour.js +24 -2
- package/lib/ContourCreator.worker.d.ts +25 -0
- package/lib/{ContourCreator.js → ContourCreator.worker.js} +15 -14
- package/lib/Fill.d.ts +31 -11
- package/lib/Fill.js +38 -18
- package/lib/Hodographs.d.ts +19 -3
- package/lib/Hodographs.js +45 -20
- package/lib/Map.d.ts +13 -1
- package/lib/Map.js +62 -8
- package/lib/Paintball.d.ts +14 -5
- package/lib/Paintball.js +96 -46
- package/lib/PlotComponent.d.ts +9 -3
- package/lib/PlotComponent.js +36 -1
- package/lib/PlotLayer.d.ts +2 -2
- package/lib/PlotLayer.js +2 -2
- package/lib/PlotLayer.worker.js +9 -3
- package/lib/RawField.d.ts +223 -27
- package/lib/RawField.js +413 -59
- package/lib/StationPlot.d.ts +78 -11
- package/lib/StationPlot.js +113 -30
- package/lib/TextCollection.d.ts +5 -0
- package/lib/TextCollection.js +82 -9
- package/lib/WasmInterface.d.ts +7 -0
- package/lib/WasmInterface.js +11 -0
- package/lib/WorkerPool.d.ts +8 -0
- package/lib/WorkerPool.js +77 -0
- package/lib/cpp/marchingsquares.js +127 -13
- package/lib/cpp/marchingsquares.wasm +0 -0
- package/lib/cpp/marchingsquares_embind.d.ts +16 -3
- package/lib/grids/AutoZoom.d.ts +21 -0
- package/lib/grids/AutoZoom.js +63 -0
- package/lib/grids/DomainBuffer.d.ts +14 -0
- package/lib/grids/DomainBuffer.js +16 -0
- package/lib/grids/Geostationary.d.ts +35 -0
- package/lib/grids/Geostationary.js +47 -0
- package/lib/grids/Grid.d.ts +36 -0
- package/lib/grids/Grid.js +12 -0
- package/lib/grids/GridCoordinates.d.ts +10 -0
- package/lib/grids/GridCoordinates.js +64 -0
- package/lib/grids/LambertGrid.d.ts +73 -0
- package/lib/grids/LambertGrid.js +92 -0
- package/lib/grids/PlateCarreeGrid.d.ts +46 -0
- package/lib/grids/PlateCarreeGrid.js +55 -0
- package/lib/grids/PlateCarreeRotatedGrid.d.ts +53 -0
- package/lib/grids/PlateCarreeRotatedGrid.js +65 -0
- package/lib/grids/RadarSweepGrid.d.ts +46 -0
- package/lib/grids/RadarSweepGrid.js +74 -0
- package/lib/grids/StructuredGrid.d.ts +49 -0
- package/lib/grids/StructuredGrid.js +103 -0
- package/lib/grids/UnstructuredGrid.d.ts +56 -0
- package/lib/grids/UnstructuredGrid.js +102 -0
- package/lib/index.d.ts +23 -6
- package/lib/index.js +18 -8
- package/lib/utils.d.ts +11 -2
- package/lib/utils.js +63 -1
- package/package.json +4 -3
- package/dist/110.autumnplot-gl.js +0 -2
- package/dist/110.autumnplot-gl.js.map +0 -1
- package/lib/ContourCreator.d.ts +0 -22
- package/lib/Grid.d.ts +0 -263
- package/lib/Grid.js +0 -547
- package/lib/ParticleTracer.d.ts +0 -19
- package/lib/ParticleTracer.js +0 -37
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
class WorkerPool_ {
|
|
3
|
+
constructor(workers, init) {
|
|
4
|
+
this.workers = workers.map(wkr => ({ worker: Comlink.wrap(wkr), is_busy: false }));
|
|
5
|
+
if (init) {
|
|
6
|
+
this.workers.forEach(wkr => init(wkr.worker));
|
|
7
|
+
}
|
|
8
|
+
this.queue = new Map();
|
|
9
|
+
}
|
|
10
|
+
call(path, args, callback) {
|
|
11
|
+
const worker_idx = this.workers.map(((w, iw) => [w, iw])).filter(([w, iw]) => !w.is_busy)[0];
|
|
12
|
+
if (worker_idx === undefined) {
|
|
13
|
+
this.enqueue(path, args, callback);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const [worker, iw] = worker_idx;
|
|
17
|
+
const dequeueAndStart = () => {
|
|
18
|
+
if (this.queueSize(path) > 0) {
|
|
19
|
+
const queue_data = this.dequeue(path);
|
|
20
|
+
if (queue_data === undefined)
|
|
21
|
+
return;
|
|
22
|
+
this.startRun(worker, path, queue_data.args).then(queue_data.callback).then(dequeueAndStart);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
this.startRun(worker, path, args).then(callback).then(dequeueAndStart);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
enqueue(path, args, callback) {
|
|
29
|
+
const path_str = path.join(".");
|
|
30
|
+
const old_queue = this.queue.get(path_str);
|
|
31
|
+
const new_queue = old_queue ? old_queue : [];
|
|
32
|
+
new_queue.push({ args: args, callback: callback });
|
|
33
|
+
this.queue.set(path_str, new_queue);
|
|
34
|
+
}
|
|
35
|
+
dequeue(path) {
|
|
36
|
+
const path_str = path.join(".");
|
|
37
|
+
const queue = this.queue.get(path_str);
|
|
38
|
+
if (!queue) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const elem = queue.shift();
|
|
42
|
+
this.queue.set(path_str, queue);
|
|
43
|
+
return elem;
|
|
44
|
+
}
|
|
45
|
+
queueSize(path) {
|
|
46
|
+
const path_str = path.join(".");
|
|
47
|
+
const queue = this.queue.get(path_str);
|
|
48
|
+
if (!queue) {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
return queue.length;
|
|
52
|
+
}
|
|
53
|
+
async startRun(worker, path, args) {
|
|
54
|
+
let rem = worker.worker;
|
|
55
|
+
path.forEach(p => rem = rem[p]);
|
|
56
|
+
worker.is_busy = true;
|
|
57
|
+
const ret = await rem(...args);
|
|
58
|
+
worker.is_busy = false;
|
|
59
|
+
return ret;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function createProxy(pool, path, target) {
|
|
63
|
+
const proxy = new Proxy(target, {
|
|
64
|
+
get(tgt, prop) {
|
|
65
|
+
return createProxy(pool, [...path, prop], () => { });
|
|
66
|
+
},
|
|
67
|
+
apply(tgt, this_arg, func_args) {
|
|
68
|
+
return new Promise((resolve, reject) => pool.call(path, func_args, resolve));
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return proxy;
|
|
72
|
+
}
|
|
73
|
+
function createWorkerPool(workers, init) {
|
|
74
|
+
const pool = new WorkerPool_(workers, init);
|
|
75
|
+
return createProxy(pool, [], () => { });
|
|
76
|
+
}
|
|
77
|
+
export { createWorkerPool };
|
|
@@ -40,10 +40,13 @@ var readyPromise = new Promise((resolve, reject) => {
|
|
|
40
40
|
// Determine the runtime environment we are in. You can customize this by
|
|
41
41
|
// setting the ENVIRONMENT setting at compile time (see settings.js).
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
var
|
|
45
|
-
var
|
|
46
|
-
|
|
43
|
+
// Attempt to auto-detect the environment
|
|
44
|
+
var ENVIRONMENT_IS_WEB = typeof window == 'object';
|
|
45
|
+
var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function';
|
|
46
|
+
// N.b. Electron.js environment is simultaneously a NODE-environment, but
|
|
47
|
+
// also a web environment.
|
|
48
|
+
var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
|
|
49
|
+
var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
|
|
47
50
|
|
|
48
51
|
if (Module['ENVIRONMENT']) {
|
|
49
52
|
throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
|
|
@@ -114,7 +117,17 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
|
|
|
114
117
|
|
|
115
118
|
{
|
|
116
119
|
// include: web_or_worker_shell_read.js
|
|
117
|
-
|
|
120
|
+
if (ENVIRONMENT_IS_WORKER) {
|
|
121
|
+
readBinary = (url) => {
|
|
122
|
+
var xhr = new XMLHttpRequest();
|
|
123
|
+
xhr.open('GET', url, false);
|
|
124
|
+
xhr.responseType = 'arraybuffer';
|
|
125
|
+
xhr.send(null);
|
|
126
|
+
return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
readAsync = (url) => {
|
|
118
131
|
assert(!isFileURI(url), "readAsync does not work with file:// URLs");
|
|
119
132
|
return fetch(url, { credentials: 'same-origin' })
|
|
120
133
|
.then((response) => {
|
|
@@ -177,8 +190,6 @@ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
|
|
|
177
190
|
|
|
178
191
|
var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
|
|
179
192
|
|
|
180
|
-
assert(!ENVIRONMENT_IS_WORKER, 'worker environment detected but not enabled at build time. Add `worker` to `-sENVIRONMENT` to enable.');
|
|
181
|
-
|
|
182
193
|
assert(!ENVIRONMENT_IS_NODE, 'node environment detected but not enabled at build time. Add `node` to `-sENVIRONMENT` to enable.');
|
|
183
194
|
|
|
184
195
|
assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
|
|
@@ -2386,6 +2397,14 @@ function dbg(...args) {
|
|
|
2386
2397
|
|
|
2387
2398
|
var __emval_new_array = () => Emval.toHandle([]);
|
|
2388
2399
|
|
|
2400
|
+
var __emval_new_array_from_memory_view = (view) => {
|
|
2401
|
+
view = Emval.toValue(view);
|
|
2402
|
+
// using for..loop is faster than Array.from
|
|
2403
|
+
var a = new Array(view.length);
|
|
2404
|
+
for (var i = 0; i < view.length; i++) a[i] = view[i];
|
|
2405
|
+
return Emval.toHandle(a);
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2389
2408
|
|
|
2390
2409
|
var __emval_new_cstring = (v) => Emval.toHandle(getStringOrSymbol(v));
|
|
2391
2410
|
|
|
@@ -2560,6 +2579,100 @@ function dbg(...args) {
|
|
|
2560
2579
|
};
|
|
2561
2580
|
|
|
2562
2581
|
|
|
2582
|
+
var getCFunc = (ident) => {
|
|
2583
|
+
var func = Module['_' + ident]; // closure exported function
|
|
2584
|
+
assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
|
|
2585
|
+
return func;
|
|
2586
|
+
};
|
|
2587
|
+
|
|
2588
|
+
var writeArrayToMemory = (array, buffer) => {
|
|
2589
|
+
assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
|
|
2590
|
+
HEAP8.set(array, buffer);
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
|
|
2596
|
+
var stringToUTF8OnStack = (str) => {
|
|
2597
|
+
var size = lengthBytesUTF8(str) + 1;
|
|
2598
|
+
var ret = stackAlloc(size);
|
|
2599
|
+
stringToUTF8(str, ret, size);
|
|
2600
|
+
return ret;
|
|
2601
|
+
};
|
|
2602
|
+
|
|
2603
|
+
|
|
2604
|
+
|
|
2605
|
+
|
|
2606
|
+
|
|
2607
|
+
/**
|
|
2608
|
+
* @param {string|null=} returnType
|
|
2609
|
+
* @param {Array=} argTypes
|
|
2610
|
+
* @param {Arguments|Array=} args
|
|
2611
|
+
* @param {Object=} opts
|
|
2612
|
+
*/
|
|
2613
|
+
var ccall = (ident, returnType, argTypes, args, opts) => {
|
|
2614
|
+
// For fast lookup of conversion functions
|
|
2615
|
+
var toC = {
|
|
2616
|
+
'string': (str) => {
|
|
2617
|
+
var ret = 0;
|
|
2618
|
+
if (str !== null && str !== undefined && str !== 0) { // null string
|
|
2619
|
+
// at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
|
|
2620
|
+
ret = stringToUTF8OnStack(str);
|
|
2621
|
+
}
|
|
2622
|
+
return ret;
|
|
2623
|
+
},
|
|
2624
|
+
'array': (arr) => {
|
|
2625
|
+
var ret = stackAlloc(arr.length);
|
|
2626
|
+
writeArrayToMemory(arr, ret);
|
|
2627
|
+
return ret;
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
|
|
2631
|
+
function convertReturnValue(ret) {
|
|
2632
|
+
if (returnType === 'string') {
|
|
2633
|
+
|
|
2634
|
+
return UTF8ToString(ret);
|
|
2635
|
+
}
|
|
2636
|
+
if (returnType === 'boolean') return Boolean(ret);
|
|
2637
|
+
return ret;
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
var func = getCFunc(ident);
|
|
2641
|
+
var cArgs = [];
|
|
2642
|
+
var stack = 0;
|
|
2643
|
+
assert(returnType !== 'array', 'Return type should not be "array".');
|
|
2644
|
+
if (args) {
|
|
2645
|
+
for (var i = 0; i < args.length; i++) {
|
|
2646
|
+
var converter = toC[argTypes[i]];
|
|
2647
|
+
if (converter) {
|
|
2648
|
+
if (stack === 0) stack = stackSave();
|
|
2649
|
+
cArgs[i] = converter(args[i]);
|
|
2650
|
+
} else {
|
|
2651
|
+
cArgs[i] = args[i];
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
var ret = func(...cArgs);
|
|
2656
|
+
function onDone(ret) {
|
|
2657
|
+
if (stack !== 0) stackRestore(stack);
|
|
2658
|
+
return convertReturnValue(ret);
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
ret = onDone(ret);
|
|
2662
|
+
return ret;
|
|
2663
|
+
};
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
/**
|
|
2668
|
+
* @param {string=} returnType
|
|
2669
|
+
* @param {Array=} argTypes
|
|
2670
|
+
* @param {Object=} opts
|
|
2671
|
+
*/
|
|
2672
|
+
var cwrap = (ident, returnType, argTypes, opts) => {
|
|
2673
|
+
return (...args) => ccall(ident, returnType, argTypes, args, opts);
|
|
2674
|
+
};
|
|
2675
|
+
|
|
2563
2676
|
var incrementExceptionRefcount = (ptr) => ___cxa_increment_exception_refcount(ptr);
|
|
2564
2677
|
Module['incrementExceptionRefcount'] = incrementExceptionRefcount;
|
|
2565
2678
|
|
|
@@ -2570,7 +2683,6 @@ function dbg(...args) {
|
|
|
2570
2683
|
|
|
2571
2684
|
|
|
2572
2685
|
|
|
2573
|
-
var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
|
|
2574
2686
|
|
|
2575
2687
|
var getExceptionMessageCommon = (ptr) => {
|
|
2576
2688
|
var sp = stackSave();
|
|
@@ -2657,6 +2769,8 @@ var wasmImports = {
|
|
|
2657
2769
|
/** @export */
|
|
2658
2770
|
_emval_new_array: __emval_new_array,
|
|
2659
2771
|
/** @export */
|
|
2772
|
+
_emval_new_array_from_memory_view: __emval_new_array_from_memory_view,
|
|
2773
|
+
/** @export */
|
|
2660
2774
|
_emval_new_cstring: __emval_new_cstring,
|
|
2661
2775
|
/** @export */
|
|
2662
2776
|
_emval_new_object: __emval_new_object,
|
|
@@ -2825,6 +2939,8 @@ function invoke_j(index) {
|
|
|
2825
2939
|
// include: postamble.js
|
|
2826
2940
|
// === Auto-generated postamble setup entry stuff ===
|
|
2827
2941
|
|
|
2942
|
+
Module['ccall'] = ccall;
|
|
2943
|
+
Module['cwrap'] = cwrap;
|
|
2828
2944
|
var missingLibrarySymbols = [
|
|
2829
2945
|
'writeI53ToI64',
|
|
2830
2946
|
'writeI53ToI64Clamped',
|
|
@@ -2873,9 +2989,6 @@ var missingLibrarySymbols = [
|
|
|
2873
2989
|
'STACK_ALIGN',
|
|
2874
2990
|
'POINTER_SIZE',
|
|
2875
2991
|
'ASSERTIONS',
|
|
2876
|
-
'getCFunc',
|
|
2877
|
-
'ccall',
|
|
2878
|
-
'cwrap',
|
|
2879
2992
|
'uleb128Encode',
|
|
2880
2993
|
'sigToWasmTypes',
|
|
2881
2994
|
'generateFuncType',
|
|
@@ -2895,8 +3008,6 @@ var missingLibrarySymbols = [
|
|
|
2895
3008
|
'AsciiToString',
|
|
2896
3009
|
'stringToAscii',
|
|
2897
3010
|
'stringToNewUTF8',
|
|
2898
|
-
'stringToUTF8OnStack',
|
|
2899
|
-
'writeArrayToMemory',
|
|
2900
3011
|
'registerKeyEventCallback',
|
|
2901
3012
|
'maybeCStringToJsString',
|
|
2902
3013
|
'findEventTarget',
|
|
@@ -3074,6 +3185,7 @@ var unexportedSymbols = [
|
|
|
3074
3185
|
'dynCall',
|
|
3075
3186
|
'wasmTable',
|
|
3076
3187
|
'noExitRuntime',
|
|
3188
|
+
'getCFunc',
|
|
3077
3189
|
'freeTableIndexes',
|
|
3078
3190
|
'functionsInTableMap',
|
|
3079
3191
|
'setValue',
|
|
@@ -3093,6 +3205,8 @@ var unexportedSymbols = [
|
|
|
3093
3205
|
'UTF32ToString',
|
|
3094
3206
|
'stringToUTF32',
|
|
3095
3207
|
'lengthBytesUTF32',
|
|
3208
|
+
'stringToUTF8OnStack',
|
|
3209
|
+
'writeArrayToMemory',
|
|
3096
3210
|
'JSEvents',
|
|
3097
3211
|
'specialHTMLTargets',
|
|
3098
3212
|
'findCanvasEventTarget',
|
|
Binary file
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
// TypeScript bindings for emscripten-generated code. Automatically generated at compile time.
|
|
2
2
|
declare namespace RuntimeExports {
|
|
3
|
+
let HEAPU8: any;
|
|
3
4
|
let HEAPF32: any;
|
|
4
5
|
let HEAPF64: any;
|
|
6
|
+
/**
|
|
7
|
+
* @param {string|null=} returnType
|
|
8
|
+
* @param {Array=} argTypes
|
|
9
|
+
* @param {Arguments|Array=} args
|
|
10
|
+
* @param {Object=} opts
|
|
11
|
+
*/
|
|
12
|
+
function ccall(ident: any, returnType?: (string | null) | undefined, argTypes?: any[] | undefined, args?: (IArguments | any[]) | undefined, opts?: any | undefined): any;
|
|
13
|
+
/**
|
|
14
|
+
* @param {string=} returnType
|
|
15
|
+
* @param {Array=} argTypes
|
|
16
|
+
* @param {Object=} opts
|
|
17
|
+
*/
|
|
18
|
+
function cwrap(ident: any, returnType?: string | undefined, argTypes?: any[] | undefined, opts?: any | undefined): (...args: any[]) => any;
|
|
5
19
|
let HEAP_DATA_VIEW: any;
|
|
6
20
|
let HEAP8: any;
|
|
7
|
-
let HEAPU8: any;
|
|
8
21
|
let HEAP16: any;
|
|
9
22
|
let HEAPU16: any;
|
|
10
23
|
let HEAP32: any;
|
|
@@ -16,8 +29,8 @@ interface WasmModule {
|
|
|
16
29
|
}
|
|
17
30
|
|
|
18
31
|
interface EmbindModule {
|
|
19
|
-
makeContoursFloat32(_0: any, _1: any, _2: any, _3: any, _4: any
|
|
20
|
-
makeContoursFloat16(_0: any, _1: any, _2: any, _3: any, _4: any
|
|
32
|
+
makeContoursFloat32(_0: any, _1: any, _2: any, _3: any, _4: any): any;
|
|
33
|
+
makeContoursFloat16(_0: any, _1: any, _2: any, _3: any, _4: any): any;
|
|
21
34
|
getContourLevelsFloat32(_0: any, _1: number, _2: number, _3: number): any;
|
|
22
35
|
getContourLevelsFloat16(_0: any, _1: number, _2: number, _3: number): any;
|
|
23
36
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WGLBuffer, WGLTexture } from "autumn-wgl";
|
|
2
|
+
import { WebGLAnyRenderingContext } from "../AutumnTypes";
|
|
3
|
+
import { AbstractConstructor, Grid } from "./Grid";
|
|
4
|
+
interface AutoZoomGridIntf {
|
|
5
|
+
getWGLBillboardBuffers(gl: WebGLAnyRenderingContext, thin_fac: number, max_zoom: number): Promise<{
|
|
6
|
+
'vertices': WGLBuffer;
|
|
7
|
+
'texcoords': WGLBuffer;
|
|
8
|
+
}>;
|
|
9
|
+
getVectorRotationTexture(gl: WebGLAnyRenderingContext, data_are_earth_relative: boolean): {
|
|
10
|
+
'rotation': WGLTexture;
|
|
11
|
+
};
|
|
12
|
+
getVectorRotationAtPoint(lon: number, lat: number): number;
|
|
13
|
+
getMinVisibleZoom(thin_fac: number): Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
declare function autoZoomGridMixin<G extends AbstractConstructor<Grid>>(base: G): AbstractConstructor<AutoZoomGridIntf> & G;
|
|
16
|
+
/**
|
|
17
|
+
* Grids of this type can be used with wind barbs, observations, and anything that needs automatic thinning.
|
|
18
|
+
*/
|
|
19
|
+
type AutoZoomGrid<T extends Grid = Grid> = InstanceType<ReturnType<typeof autoZoomGridMixin<AbstractConstructor<T>>>>;
|
|
20
|
+
export { autoZoomGridMixin };
|
|
21
|
+
export type { AutoZoomGrid, AutoZoomGridIntf };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { WGLBuffer, WGLTexture } from "autumn-wgl";
|
|
2
|
+
import { Cache } from "../utils";
|
|
3
|
+
import { getGLFormatTypeAlignment, layer_worker } from "../PlotComponent";
|
|
4
|
+
import { Float16Array } from "@petamoriken/float16";
|
|
5
|
+
async function makeWGLBillboardBuffers(gl, grid, thin_fac, map_max_zoom) {
|
|
6
|
+
const { lats: field_lats, lons: field_lons } = grid.getEarthCoords();
|
|
7
|
+
const min_zoom = grid.getMinVisibleZoom(thin_fac);
|
|
8
|
+
const bb_elements = await layer_worker.makeBBElements(field_lats, field_lons, min_zoom, grid.ni, grid.nj, map_max_zoom);
|
|
9
|
+
const vertices = new WGLBuffer(gl, bb_elements['pts'], 2, gl.POINTS, { per_instance: true });
|
|
10
|
+
const texcoords = new WGLBuffer(gl, bb_elements['tex_coords'], 2, gl.POINTS, { per_instance: true });
|
|
11
|
+
return { 'vertices': vertices, 'texcoords': texcoords };
|
|
12
|
+
}
|
|
13
|
+
function makeVectorRotationTexture(gl, grid, data_are_earth_relative) {
|
|
14
|
+
const coords = grid.getEarthCoords();
|
|
15
|
+
const rot_vals = new Float16Array(grid.ni * grid.nj).fill(parseFloat('nan'));
|
|
16
|
+
if (data_are_earth_relative) {
|
|
17
|
+
rot_vals.fill(0);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
if (!grid.is_conformal) {
|
|
21
|
+
// If the grid is non-conformal, we need a fully general change of basis from grid coordinates to earth coordinates. This is not supported for now, so warn about it.
|
|
22
|
+
console.warn('Vector rotations for non-conformal projections are not supported. The output may look incorrect.');
|
|
23
|
+
}
|
|
24
|
+
for (let icd = 0; icd < coords.lats.length; icd++) {
|
|
25
|
+
const lon = coords.lons[icd];
|
|
26
|
+
const lat = coords.lats[icd];
|
|
27
|
+
rot_vals[icd] = grid.getVectorRotationAtPoint(lon, lat);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const { format, type, row_alignment } = getGLFormatTypeAlignment(gl, 'float16');
|
|
31
|
+
const rot_img = {
|
|
32
|
+
format: format, type: type, row_alignment: row_alignment, image: new Uint16Array(rot_vals.buffer),
|
|
33
|
+
width: grid.ni, height: grid.nj, mag_filter: gl.LINEAR
|
|
34
|
+
};
|
|
35
|
+
const rot_tex = new WGLTexture(gl, rot_img);
|
|
36
|
+
return { 'rotation': rot_tex };
|
|
37
|
+
}
|
|
38
|
+
function autoZoomGridMixin(base) {
|
|
39
|
+
class AutoZoomGrid extends base {
|
|
40
|
+
constructor(...args) {
|
|
41
|
+
super(...args);
|
|
42
|
+
this.billboard_buffer_cache = new Cache((gl, thin_fac, max_zoom) => {
|
|
43
|
+
return makeWGLBillboardBuffers(gl, this, thin_fac, max_zoom);
|
|
44
|
+
});
|
|
45
|
+
this.vector_rotation_cache = new Cache((gl, data_are_earth_relative) => {
|
|
46
|
+
return makeVectorRotationTexture(gl, this, data_are_earth_relative);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async getWGLBillboardBuffers(gl, thin_fac, max_zoom) {
|
|
50
|
+
return await this.billboard_buffer_cache.getValue(gl, thin_fac, max_zoom);
|
|
51
|
+
}
|
|
52
|
+
getVectorRotationTexture(gl, data_are_earth_relative) {
|
|
53
|
+
return this.vector_rotation_cache.getValue(gl, data_are_earth_relative);
|
|
54
|
+
}
|
|
55
|
+
getVectorRotationAtPoint(lon, lat) {
|
|
56
|
+
const [x, y] = this.transform(lon, lat);
|
|
57
|
+
const [x_pertlon, y_pertlon] = this.transform(lon + 0.01, lat);
|
|
58
|
+
return Math.atan2(y_pertlon - y, x_pertlon - x);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return AutoZoomGrid;
|
|
62
|
+
}
|
|
63
|
+
export { autoZoomGridMixin };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WGLBuffer } from "autumn-wgl";
|
|
2
|
+
import { WebGLAnyRenderingContext } from "../AutumnTypes";
|
|
3
|
+
import { AbstractConstructor, Grid } from "./Grid";
|
|
4
|
+
type DomainBuffers = {
|
|
5
|
+
vertices: WGLBuffer;
|
|
6
|
+
texcoords: WGLBuffer;
|
|
7
|
+
};
|
|
8
|
+
interface DomainBufferIntf {
|
|
9
|
+
getDomainBuffers(gl: WebGLAnyRenderingContext): Promise<DomainBuffers>;
|
|
10
|
+
}
|
|
11
|
+
declare function domainBufferMixin<G extends AbstractConstructor<Grid>>(base: G): AbstractConstructor<DomainBufferIntf> & G;
|
|
12
|
+
type DomainBufferGrid<T extends Grid = Grid> = InstanceType<ReturnType<typeof domainBufferMixin<AbstractConstructor<T>>>>;
|
|
13
|
+
export { domainBufferMixin };
|
|
14
|
+
export type { DomainBuffers, DomainBufferGrid, DomainBufferIntf };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Cache } from "../utils";
|
|
2
|
+
function domainBufferMixin(base) {
|
|
3
|
+
class DomainBufferMixin extends base {
|
|
4
|
+
constructor(...args) {
|
|
5
|
+
super(...args);
|
|
6
|
+
this.buffer_cache = new Cache((gl) => {
|
|
7
|
+
return this.makeDomainBuffers(gl);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
async getDomainBuffers(gl) {
|
|
11
|
+
return await this.buffer_cache.getValue(gl);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return DomainBufferMixin;
|
|
15
|
+
}
|
|
16
|
+
export { domainBufferMixin };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { WebGLAnyRenderingContext } from "../AutumnTypes";
|
|
2
|
+
import { StructuredGrid } from "./StructuredGrid";
|
|
3
|
+
declare const GeostationaryImage_base: import("./Grid").AbstractConstructor<import("./GridCoordinates").GridCoordinateIntf> & typeof StructuredGrid;
|
|
4
|
+
/**
|
|
5
|
+
* Grid for geostationary satellite images
|
|
6
|
+
*
|
|
7
|
+
* ## Plot Component Compatibility
|
|
8
|
+
* - :white_check_mark: `Fill`
|
|
9
|
+
* - :white_check_mark: `Raster`
|
|
10
|
+
* - :white_check_mark: `Contour`
|
|
11
|
+
* - :white_check_mark: `Paintball`
|
|
12
|
+
* - :x: `Barbs`
|
|
13
|
+
* - :x: `Hodographs`
|
|
14
|
+
* - :x: `StationPlot`
|
|
15
|
+
*/
|
|
16
|
+
declare class GeostationaryImage extends GeostationaryImage_base {
|
|
17
|
+
readonly satellite_lon: number;
|
|
18
|
+
readonly ll_x: number;
|
|
19
|
+
readonly ll_y: number;
|
|
20
|
+
readonly ur_x: number;
|
|
21
|
+
readonly ur_y: number;
|
|
22
|
+
private readonly vpp;
|
|
23
|
+
constructor(ni: number, nj: number, ll_x: number, ll_y: number, ur_x: number, ur_y: number, satellite_lon: number, thin_x?: number, thin_y?: number);
|
|
24
|
+
protected makeDomainBuffers(gl: WebGLAnyRenderingContext): Promise<{
|
|
25
|
+
vertices: import("autumn-wgl").WGLBuffer;
|
|
26
|
+
texcoords: import("autumn-wgl").WGLBuffer;
|
|
27
|
+
}>;
|
|
28
|
+
transform(x: number, y: number, opts?: {
|
|
29
|
+
inverse?: boolean;
|
|
30
|
+
}): [number, number];
|
|
31
|
+
copy(): GeostationaryImage;
|
|
32
|
+
/** @internal */
|
|
33
|
+
getThinnedGrid(thin_fac: number, map_max_zoom: number): this;
|
|
34
|
+
}
|
|
35
|
+
export { GeostationaryImage };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { geostationaryProjection } from "../Map";
|
|
2
|
+
import { gridCoordinateMixin } from "./GridCoordinates";
|
|
3
|
+
import { StructuredGrid, makeCartesianDomainBuffers } from "./StructuredGrid";
|
|
4
|
+
/**
|
|
5
|
+
* Grid for geostationary satellite images
|
|
6
|
+
*
|
|
7
|
+
* ## Plot Component Compatibility
|
|
8
|
+
* - :white_check_mark: `Fill`
|
|
9
|
+
* - :white_check_mark: `Raster`
|
|
10
|
+
* - :white_check_mark: `Contour`
|
|
11
|
+
* - :white_check_mark: `Paintball`
|
|
12
|
+
* - :x: `Barbs`
|
|
13
|
+
* - :x: `Hodographs`
|
|
14
|
+
* - :x: `StationPlot`
|
|
15
|
+
*/
|
|
16
|
+
class GeostationaryImage extends gridCoordinateMixin(StructuredGrid) {
|
|
17
|
+
constructor(ni, nj, ll_x, ll_y, ur_x, ur_y, satellite_lon, thin_x, thin_y) {
|
|
18
|
+
super('geostationary', false, ni, nj, thin_x, thin_y);
|
|
19
|
+
this.satellite_lon = satellite_lon;
|
|
20
|
+
this.ll_x = ll_x;
|
|
21
|
+
this.ll_y = ll_y;
|
|
22
|
+
this.ur_x = ur_x;
|
|
23
|
+
this.ur_y = ur_y;
|
|
24
|
+
//this.vpp = verticalPerspective({lon_0: satellite_lon, lat_0: 0, alt: 35786023.0, a: 6378137.0, b: 6356752.31414});
|
|
25
|
+
this.vpp = geostationaryProjection({ lon_0: satellite_lon, alt: 35786023.0 + 6378137.0, a: 6378137.0, b: 6356752.31414 });
|
|
26
|
+
this.setupCoordinateCaches(ll_x, ur_x, ll_y, ur_y);
|
|
27
|
+
}
|
|
28
|
+
async makeDomainBuffers(gl) {
|
|
29
|
+
const simplify_ni = Math.max(Math.floor(this.ni / 20), 20);
|
|
30
|
+
const simplify_nj = Math.max(Math.floor(this.nj / 20), 20);
|
|
31
|
+
return await makeCartesianDomainBuffers(gl, this, simplify_ni, simplify_nj, { margin_r: false, margin_s: false });
|
|
32
|
+
}
|
|
33
|
+
transform(x, y, opts) {
|
|
34
|
+
opts = opts === undefined ? {} : opts;
|
|
35
|
+
const inverse = opts.inverse === undefined ? false : opts.inverse;
|
|
36
|
+
return this.vpp(x, y, { inverse: inverse });
|
|
37
|
+
}
|
|
38
|
+
copy() {
|
|
39
|
+
return new GeostationaryImage(this.ni, this.nj, this.ll_x, this.ll_y, this.ur_x, this.ur_y, this.satellite_lon);
|
|
40
|
+
}
|
|
41
|
+
/** @internal */
|
|
42
|
+
getThinnedGrid(thin_fac, map_max_zoom) {
|
|
43
|
+
const { ni, nj, thin_x, thin_y, ll_x, ll_y, ur_x, ur_y } = this.thinnedGridParameters(thin_fac, map_max_zoom, this.ll_x, this.ll_y, this.ur_x, this.ur_y);
|
|
44
|
+
return new GeostationaryImage(ni, nj, ll_x, ll_y, ur_x, ur_y, this.satellite_lon, this.thin_x * thin_x, this.thin_y * thin_y);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export { GeostationaryImage };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TypedArray } from "../AutumnTypes";
|
|
2
|
+
interface EarthCoords {
|
|
3
|
+
lons: Float32Array;
|
|
4
|
+
lats: Float32Array;
|
|
5
|
+
}
|
|
6
|
+
interface GridCoords {
|
|
7
|
+
x: Float32Array;
|
|
8
|
+
y: Float32Array;
|
|
9
|
+
}
|
|
10
|
+
type GridType = 'latlon' | 'latlonrot' | 'lcc' | 'unstructured' | 'radar' | 'geostationary';
|
|
11
|
+
declare const WGS84_SEMIMAJOR = 6378137;
|
|
12
|
+
declare const WGS84_SEMIMINOR = 6356752.314245;
|
|
13
|
+
/** The base class for grid types */
|
|
14
|
+
declare abstract class Grid {
|
|
15
|
+
readonly type: GridType;
|
|
16
|
+
readonly ni: number;
|
|
17
|
+
readonly nj: number;
|
|
18
|
+
readonly is_conformal: boolean;
|
|
19
|
+
constructor(type: GridType, is_conformal: boolean, ni: number, nj: number);
|
|
20
|
+
abstract getEarthCoords(): EarthCoords;
|
|
21
|
+
abstract getGridCoords(): GridCoords;
|
|
22
|
+
abstract transform(x: number, y: number, opts?: {
|
|
23
|
+
inverse?: boolean;
|
|
24
|
+
}): [number, number];
|
|
25
|
+
abstract sampleNearestGridPoint(lon: number, lat: number, ary: TypedArray): {
|
|
26
|
+
sample: number;
|
|
27
|
+
sample_lon: number;
|
|
28
|
+
sample_lat: number;
|
|
29
|
+
};
|
|
30
|
+
abstract getThinnedGrid(thin_fac: number, map_max_zoom: number): this;
|
|
31
|
+
abstract thinDataArray<ArrayType extends TypedArray>(original_grid: Grid, ary: ArrayType): ArrayType;
|
|
32
|
+
abstract copy(): Grid;
|
|
33
|
+
}
|
|
34
|
+
type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
|
35
|
+
export { Grid, WGS84_SEMIMAJOR, WGS84_SEMIMINOR };
|
|
36
|
+
export type { AbstractConstructor, EarthCoords, GridCoords, GridType };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const WGS84_SEMIMAJOR = 6378137.0;
|
|
2
|
+
const WGS84_SEMIMINOR = 6356752.314245;
|
|
3
|
+
/** The base class for grid types */
|
|
4
|
+
class Grid {
|
|
5
|
+
constructor(type, is_conformal, ni, nj) {
|
|
6
|
+
this.type = type;
|
|
7
|
+
this.is_conformal = is_conformal;
|
|
8
|
+
this.ni = ni;
|
|
9
|
+
this.nj = nj;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export { Grid, WGS84_SEMIMAJOR, WGS84_SEMIMINOR };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AbstractConstructor, EarthCoords, Grid, GridCoords } from "./Grid";
|
|
2
|
+
type GridElement = 'center' | 'edge';
|
|
3
|
+
interface GridCoordinateIntf {
|
|
4
|
+
setupCoordinateCaches(start_i: number, end_i: number, start_j: number, end_j: number): void;
|
|
5
|
+
getEarthCoords(ni?: number, nj?: number, which_i?: GridElement, which_j?: GridElement): EarthCoords;
|
|
6
|
+
getGridCoords(): GridCoords;
|
|
7
|
+
}
|
|
8
|
+
declare function gridCoordinateMixin<G extends AbstractConstructor<Grid>>(base: G): AbstractConstructor<GridCoordinateIntf> & G;
|
|
9
|
+
export { gridCoordinateMixin };
|
|
10
|
+
export type { GridElement, GridCoordinateIntf };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Cache } from "../utils";
|
|
2
|
+
function gridCoordinateMixin(base) {
|
|
3
|
+
class GridCoordinates extends base {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.ll_cache = null;
|
|
7
|
+
this.gc_cache = null;
|
|
8
|
+
}
|
|
9
|
+
setupCoordinateCaches(start_i, end_i, start_j, end_j) {
|
|
10
|
+
const di = (end_i - start_i) / (this.ni - 1);
|
|
11
|
+
const dj = (end_j - start_j) / (this.nj - 1);
|
|
12
|
+
this.ll_cache = new Cache((ni, nj, which_i, which_j) => {
|
|
13
|
+
const ni_grid = which_i == 'center' ? ni : ni + 1;
|
|
14
|
+
const nj_grid = which_j == 'center' ? nj : nj + 1;
|
|
15
|
+
const ni_grid_full = which_i == 'center' ? this.ni : this.ni + 1;
|
|
16
|
+
const nj_grid_full = which_j == 'center' ? this.nj : this.nj + 1;
|
|
17
|
+
const ni_offset = which_i == 'center' ? 0 : -di / 2;
|
|
18
|
+
const nj_offset = which_j == 'center' ? 0 : -dj / 2;
|
|
19
|
+
const lons = new Float32Array(ni_grid * nj_grid);
|
|
20
|
+
const lats = new Float32Array(ni_grid * nj_grid);
|
|
21
|
+
const di_req = (ni_grid_full - 1) / (ni_grid - 1) * di;
|
|
22
|
+
const dj_req = (nj_grid_full - 1) / (nj_grid - 1) * dj;
|
|
23
|
+
for (let i = 0; i < ni_grid; i++) {
|
|
24
|
+
const x = start_i + i * di_req + ni_offset;
|
|
25
|
+
for (let j = 0; j < nj_grid; j++) {
|
|
26
|
+
const y = start_j + j * dj_req + nj_offset;
|
|
27
|
+
const [lon, lat] = this.transform(x, y, { inverse: true });
|
|
28
|
+
const idx = i + j * ni_grid;
|
|
29
|
+
lons[idx] = lon;
|
|
30
|
+
lats[idx] = lat;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { lons: lons, lats: lats };
|
|
34
|
+
});
|
|
35
|
+
this.gc_cache = new Cache(() => {
|
|
36
|
+
const x = new Float32Array(this.ni);
|
|
37
|
+
const y = new Float32Array(this.nj);
|
|
38
|
+
for (let i = 0; i < this.ni; i++) {
|
|
39
|
+
x[i] = start_i + i * di;
|
|
40
|
+
}
|
|
41
|
+
for (let j = 0; j < this.nj; j++) {
|
|
42
|
+
y[j] = start_j + j * dj;
|
|
43
|
+
}
|
|
44
|
+
return { x: x, y: y };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
getEarthCoords(ni, nj, which_i, which_j) {
|
|
48
|
+
if (this.ll_cache === null)
|
|
49
|
+
throw "Need to set up coordinate caches first";
|
|
50
|
+
ni = ni === undefined ? this.ni : ni;
|
|
51
|
+
nj = nj === undefined ? this.nj : nj;
|
|
52
|
+
which_i = which_i === undefined ? 'center' : which_i;
|
|
53
|
+
which_j = which_j === undefined ? 'center' : which_j;
|
|
54
|
+
return this.ll_cache.getValue(ni, nj, which_i, which_j);
|
|
55
|
+
}
|
|
56
|
+
getGridCoords() {
|
|
57
|
+
if (this.gc_cache === null)
|
|
58
|
+
throw "Need to set up coordinate caches first";
|
|
59
|
+
return this.gc_cache.getValue();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return GridCoordinates;
|
|
63
|
+
}
|
|
64
|
+
export { gridCoordinateMixin };
|