autumnplot-gl 2.0.0 → 2.2.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/lib/RawField.d.ts CHANGED
@@ -1,30 +1,18 @@
1
- import { WebGLAnyRenderingContext, WindProfile } from "./AutumnTypes";
1
+ import { Float16Array } from "@petamoriken/float16";
2
+ import { TypedArray, WebGLAnyRenderingContext, WindProfile } from "./AutumnTypes";
2
3
  import { WGLBuffer } from "autumn-wgl";
3
- declare class Cache<A extends unknown[], R> {
4
- cached_value: R | null;
5
- compute_value: (...args: A) => R;
6
- constructor(compute_value: (...args: A) => R);
7
- getValue(...args: A): R;
8
- }
9
4
  interface Coords {
10
5
  lons: Float32Array;
11
6
  lats: Float32Array;
12
7
  }
13
- type GridType = 'latlon' | 'lcc';
8
+ type GridType = 'latlon' | 'latlonrot' | 'lcc';
14
9
  declare abstract class Grid {
15
10
  readonly type: GridType;
16
11
  readonly ni: number;
17
12
  readonly nj: number;
18
13
  readonly is_conformal: boolean;
19
- readonly _buffer_cache: Cache<[WebGLAnyRenderingContext], Promise<{
20
- 'vertices': WGLBuffer;
21
- 'texcoords': WGLBuffer;
22
- 'cellsize': WGLBuffer;
23
- }>>;
24
- readonly _billboard_buffer_cache: Cache<[WebGLAnyRenderingContext, number, number], Promise<{
25
- 'vertices': WGLBuffer;
26
- 'texcoords': WGLBuffer;
27
- }>>;
14
+ private readonly buffer_cache;
15
+ private readonly billboard_buffer_cache;
28
16
  constructor(type: GridType, is_conformal: boolean, ni: number, nj: number);
29
17
  abstract copy(opts?: {
30
18
  ni?: number;
@@ -51,8 +39,7 @@ declare class PlateCarreeGrid extends Grid {
51
39
  readonly ll_lat: number;
52
40
  readonly ur_lon: number;
53
41
  readonly ur_lat: number;
54
- /** @private */
55
- readonly _ll_cache: Cache<[], Coords>;
42
+ private readonly ll_cache;
56
43
  /**
57
44
  * Create a plate carree grid
58
45
  * @param ni - The number of grid points in the i (longitude) direction
@@ -80,6 +67,47 @@ declare class PlateCarreeGrid extends Grid {
80
67
  }): [number, number];
81
68
  getThinnedGrid(thin_x: number, thin_y: number): PlateCarreeGrid;
82
69
  }
70
+ /** A rotated lat-lon (plate carree) grid with uniform grid spacing */
71
+ declare class PlateCarreeRotatedGrid extends Grid {
72
+ readonly np_lon: number;
73
+ readonly np_lat: number;
74
+ readonly lon_shift: number;
75
+ readonly ll_lon: number;
76
+ readonly ll_lat: number;
77
+ readonly ur_lon: number;
78
+ readonly ur_lat: number;
79
+ private readonly llrot;
80
+ private readonly ll_cache;
81
+ /**
82
+ * Create a Lambert conformal conic grid
83
+ * @param ni - The number of grid points in the i (longitude) direction
84
+ * @param nj - The number of grid points in the j (latitude) direction
85
+ * @param np_lon - The longitude of the north pole for the rotated grid
86
+ * @param np_lat - The latitude of the north pole for the rotated grid
87
+ * @param lon_shift - The angle around the rotated north pole to shift the central meridian
88
+ * @param ll_lon - The longitude of the lower left corner of the grid (on the rotated earth)
89
+ * @param ll_lat - The latitude of the lower left corner of the grid (on the rotated earth)
90
+ * @param ur_lon - The longitude of the upper right corner of the grid (on the rotated earth)
91
+ * @param ur_lat - The latitude of the upper right corner of the grid (on the rotated earth)
92
+ */
93
+ constructor(ni: number, nj: number, np_lon: number, np_lat: number, lon_shift: number, ll_lon: number, ll_lat: number, ur_lon: number, ur_lat: number);
94
+ copy(opts?: {
95
+ ni?: number;
96
+ nj?: number;
97
+ ll_lon?: number;
98
+ ll_lat?: number;
99
+ ur_lon?: number;
100
+ ur_lat?: number;
101
+ }): PlateCarreeRotatedGrid;
102
+ /**
103
+ * Get a list of longitudes and latitudes on the grid (internal method)
104
+ */
105
+ getCoords(): Coords;
106
+ transform(x: number, y: number, opts?: {
107
+ inverse?: boolean;
108
+ }): [number, number];
109
+ getThinnedGrid(thin_x: number, thin_y: number): PlateCarreeRotatedGrid;
110
+ }
83
111
  /** A Lambert conformal conic grid with uniform grid spacing */
84
112
  declare class LambertGrid extends Grid {
85
113
  readonly lon_0: number;
@@ -89,12 +117,8 @@ declare class LambertGrid extends Grid {
89
117
  readonly ll_y: number;
90
118
  readonly ur_x: number;
91
119
  readonly ur_y: number;
92
- /** @private */
93
- readonly lcc: (a: number, b: number, opts?: {
94
- inverse: boolean;
95
- }) => [number, number];
96
- /** @private */
97
- readonly _ll_cache: Cache<[], Coords>;
120
+ private readonly lcc;
121
+ private readonly ll_cache;
98
122
  /**
99
123
  * Create a Lambert conformal conic grid
100
124
  * @param ni - The number of grid points in the i (longitude) direction
@@ -125,17 +149,21 @@ declare class LambertGrid extends Grid {
125
149
  }): [number, number];
126
150
  getThinnedGrid(thin_x: number, thin_y: number): LambertGrid;
127
151
  }
152
+ type TextureDataType<ArrayType> = ArrayType extends Float32Array ? Float32Array : Uint16Array;
128
153
  /** A class representing a raw 2D field of gridded data, such as height or u wind. */
129
- declare class RawScalarField {
154
+ declare class RawScalarField<ArrayType extends TypedArray> {
130
155
  readonly grid: Grid;
131
- readonly data: Float32Array;
156
+ readonly data: ArrayType;
132
157
  /**
133
158
  * Create a data field.
134
159
  * @param grid - The grid on which the data are defined
135
160
  * @param data - The data, which should be given as a 1D array in row-major order, with the first element being at the lower-left corner of the grid.
136
161
  */
137
- constructor(grid: Grid, data: Float32Array);
138
- getThinnedField(thin_x: number, thin_y: number): RawScalarField;
162
+ constructor(grid: Grid, data: ArrayType);
163
+ /** @internal */
164
+ getTextureData(): TextureDataType<ArrayType>;
165
+ isFloat16(): boolean;
166
+ getThinnedField(thin_x: number, thin_y: number): RawScalarField<ArrayType>;
139
167
  /**
140
168
  * Create a new field by aggregating a number of fields using a specific function
141
169
  * @param func - A function that will be applied each element of the field. It should take the same number of arguments as fields you have and return a single number.
@@ -145,7 +173,7 @@ declare class RawScalarField {
145
173
  * // Compute wind speed from u and v
146
174
  * wind_speed_field = RawScalarField.aggreateFields(Math.hypot, u_field, v_field);
147
175
  */
148
- static aggregateFields(func: (...args: number[]) => number, ...args: RawScalarField[]): RawScalarField;
176
+ static aggregateFields<ArrayType extends TypedArray>(func: (...args: number[]) => number, ...args: RawScalarField<ArrayType>[]): RawScalarField<ArrayType>;
149
177
  }
150
178
  type VectorRelativeTo = 'earth' | 'grid';
151
179
  interface RawVectorFieldOptions {
@@ -156,15 +184,11 @@ interface RawVectorFieldOptions {
156
184
  relative_to?: VectorRelativeTo;
157
185
  }
158
186
  /** A class representing a 2D gridded field of vectors */
159
- declare class RawVectorField {
160
- readonly u: RawScalarField;
161
- readonly v: RawScalarField;
187
+ declare class RawVectorField<ArrayType extends TypedArray> {
188
+ readonly u: RawScalarField<ArrayType>;
189
+ readonly v: RawScalarField<ArrayType>;
162
190
  readonly relative_to: VectorRelativeTo;
163
- /** @private */
164
- readonly _rotate_cache: Cache<[], {
165
- u: RawScalarField;
166
- v: RawScalarField;
167
- }>;
191
+ private readonly rotate_cache;
168
192
  /**
169
193
  * Create a vector field.
170
194
  * @param grid - The grid on which the vector components are defined
@@ -172,10 +196,10 @@ declare class RawVectorField {
172
196
  * @param v - The v (north/south) component of the vectors, which should be given as a 1D array in row-major order, with the first element being at the lower-left corner of the grid
173
197
  * @param opts - Options for creating the vector field.
174
198
  */
175
- constructor(grid: Grid, u: Float32Array, v: Float32Array, opts?: RawVectorFieldOptions);
176
- getThinnedField(thin_x: number, thin_y: number): RawVectorField;
199
+ constructor(grid: Grid, u: ArrayType, v: ArrayType, opts?: RawVectorFieldOptions);
200
+ getThinnedField(thin_x: number, thin_y: number): RawVectorField<ArrayType>;
177
201
  get grid(): Grid;
178
- toEarthRelative(): RawVectorField;
202
+ toEarthRelative(): RawVectorField<ArrayType>;
179
203
  }
180
204
  /** A class grid of wind profiles */
181
205
  declare class RawProfileField {
@@ -188,7 +212,7 @@ declare class RawProfileField {
188
212
  */
189
213
  constructor(grid: Grid, profiles: WindProfile[]);
190
214
  /** Get the gridded storm motion vector field (internal method) */
191
- getStormMotionGrid(): RawVectorField;
215
+ getStormMotionGrid(): RawVectorField<Float16Array>;
192
216
  }
193
- export { RawScalarField, RawVectorField, RawProfileField, PlateCarreeGrid, LambertGrid, Grid };
194
- export type { GridType, RawVectorFieldOptions, VectorRelativeTo };
217
+ export { RawScalarField, RawVectorField, RawProfileField, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid, Grid };
218
+ export type { GridType, RawVectorFieldOptions, VectorRelativeTo, TextureDataType };
package/lib/RawField.js CHANGED
@@ -1,19 +1,8 @@
1
- import { lambertConformalConic } from "./Map";
1
+ import { Float16Array } from "@petamoriken/float16";
2
+ import { lambertConformalConic, rotateSphere } from "./Map";
2
3
  import { layer_worker } from "./PlotComponent";
3
- import { zip } from "./utils";
4
+ import { Cache, zip } from "./utils";
4
5
  import { WGLBuffer } from "autumn-wgl";
5
- class Cache {
6
- constructor(compute_value) {
7
- this.cached_value = null;
8
- this.compute_value = compute_value;
9
- }
10
- getValue(...args) {
11
- if (this.cached_value === null) {
12
- this.cached_value = this.compute_value(...args);
13
- }
14
- return this.cached_value;
15
- }
16
- }
17
6
  async function makeWGLDomainBuffers(gl, grid, native_grid) {
18
7
  native_grid = native_grid !== undefined ? native_grid : grid;
19
8
  const texcoord_margin_r = 1 / (2 * native_grid.ni);
@@ -42,20 +31,20 @@ class Grid {
42
31
  this.is_conformal = is_conformal;
43
32
  this.ni = ni;
44
33
  this.nj = nj;
45
- this._buffer_cache = new Cache((gl) => {
34
+ this.buffer_cache = new Cache((gl) => {
46
35
  const new_ni = Math.max(Math.floor(this.ni / 50), 20);
47
36
  const new_nj = Math.max(Math.floor(this.nj / 50), 20);
48
37
  return makeWGLDomainBuffers(gl, this.copy({ ni: new_ni, nj: new_nj }), this);
49
38
  });
50
- this._billboard_buffer_cache = new Cache((gl, thin_fac, max_zoom) => {
39
+ this.billboard_buffer_cache = new Cache((gl, thin_fac, max_zoom) => {
51
40
  return makeWGLBillboardBuffers(gl, this, thin_fac, max_zoom);
52
41
  });
53
42
  }
54
43
  async getWGLBuffers(gl) {
55
- return await this._buffer_cache.getValue(gl);
44
+ return await this.buffer_cache.getValue(gl);
56
45
  }
57
46
  async getWGLBillboardBuffers(gl, thin_fac, max_zoom) {
58
- return await this._billboard_buffer_cache.getValue(gl, thin_fac, max_zoom);
47
+ return await this.billboard_buffer_cache.getValue(gl, thin_fac, max_zoom);
59
48
  }
60
49
  }
61
50
  /** A plate carree (a.k.a. lat/lon) grid with uniform grid spacing */
@@ -75,7 +64,7 @@ class PlateCarreeGrid extends Grid {
75
64
  this.ll_lat = ll_lat;
76
65
  this.ur_lon = ur_lon;
77
66
  this.ur_lat = ur_lat;
78
- this._ll_cache = new Cache(() => {
67
+ this.ll_cache = new Cache(() => {
79
68
  const dlon = (this.ur_lon - this.ll_lon) / (this.ni - 1);
80
69
  const dlat = (this.ur_lat - this.ll_lat) / (this.nj - 1);
81
70
  const lons = new Float32Array(this.ni * this.nj);
@@ -104,7 +93,7 @@ class PlateCarreeGrid extends Grid {
104
93
  * Get a list of longitudes and latitudes on the grid (internal method)
105
94
  */
106
95
  getCoords() {
107
- return this._ll_cache.getValue();
96
+ return this.ll_cache.getValue();
108
97
  }
109
98
  transform(x, y, opts) {
110
99
  return [x, y];
@@ -123,6 +112,81 @@ class PlateCarreeGrid extends Grid {
123
112
  return new PlateCarreeGrid(ni, nj, ll_lon, ll_lat, ur_lon, ur_lat);
124
113
  }
125
114
  }
115
+ /** A rotated lat-lon (plate carree) grid with uniform grid spacing */
116
+ class PlateCarreeRotatedGrid extends Grid {
117
+ /**
118
+ * Create a Lambert conformal conic grid
119
+ * @param ni - The number of grid points in the i (longitude) direction
120
+ * @param nj - The number of grid points in the j (latitude) direction
121
+ * @param np_lon - The longitude of the north pole for the rotated grid
122
+ * @param np_lat - The latitude of the north pole for the rotated grid
123
+ * @param lon_shift - The angle around the rotated north pole to shift the central meridian
124
+ * @param ll_lon - The longitude of the lower left corner of the grid (on the rotated earth)
125
+ * @param ll_lat - The latitude of the lower left corner of the grid (on the rotated earth)
126
+ * @param ur_lon - The longitude of the upper right corner of the grid (on the rotated earth)
127
+ * @param ur_lat - The latitude of the upper right corner of the grid (on the rotated earth)
128
+ */
129
+ constructor(ni, nj, np_lon, np_lat, lon_shift, ll_lon, ll_lat, ur_lon, ur_lat) {
130
+ super('latlonrot', true, ni, nj);
131
+ this.np_lon = np_lon;
132
+ this.np_lat = np_lat;
133
+ this.lon_shift = lon_shift;
134
+ this.ll_lon = ll_lon;
135
+ this.ll_lat = ll_lat;
136
+ this.ur_lon = ur_lon;
137
+ this.ur_lat = ur_lat;
138
+ this.llrot = rotateSphere({ np_lon: np_lon, np_lat: np_lat, lon_shift: lon_shift });
139
+ this.ll_cache = new Cache(() => {
140
+ const lons = new Float32Array(this.ni * this.nj);
141
+ const lats = new Float32Array(this.ni * this.nj);
142
+ for (let i = 0; i < this.ni; i++) {
143
+ const lon_p = this.ll_lon + (this.ur_lon - this.ll_lon) * i / (this.ni - 1);
144
+ for (let j = 0; j < this.nj; j++) {
145
+ const lat_p = this.ll_lat + (this.ur_lat - this.ll_lat) * j / (this.nj - 1);
146
+ const [lon, lat] = this.llrot(lon_p, lat_p);
147
+ const idx = i + j * this.ni;
148
+ lons[idx] = lon;
149
+ lats[idx] = lat;
150
+ }
151
+ }
152
+ return { lons: lons, lats: lats };
153
+ });
154
+ }
155
+ copy(opts) {
156
+ opts = opts !== undefined ? opts : {};
157
+ const ni = opts.ni !== undefined ? opts.ni : this.ni;
158
+ const nj = opts.nj !== undefined ? opts.nj : this.nj;
159
+ const ll_lon = opts.ll_lon !== undefined ? opts.ll_lon : this.ll_lon;
160
+ const ll_lat = opts.ll_lat !== undefined ? opts.ll_lat : this.ll_lat;
161
+ const ur_lon = opts.ur_lon !== undefined ? opts.ur_lon : this.ur_lon;
162
+ const ur_lat = opts.ur_lat !== undefined ? opts.ur_lat : this.ur_lat;
163
+ return new PlateCarreeRotatedGrid(ni, nj, this.np_lon, this.np_lat, this.lon_shift, ll_lon, ll_lat, ur_lon, ur_lat);
164
+ }
165
+ /**
166
+ * Get a list of longitudes and latitudes on the grid (internal method)
167
+ */
168
+ getCoords() {
169
+ return this.ll_cache.getValue();
170
+ }
171
+ transform(x, y, opts) {
172
+ opts = opts === undefined ? {} : opts;
173
+ const inverse = 'inverse' in opts ? opts.inverse : false;
174
+ return this.llrot(x, y, { inverse: !inverse });
175
+ }
176
+ getThinnedGrid(thin_x, thin_y) {
177
+ const dlon = (this.ur_lon - this.ll_lon) / this.ni;
178
+ const dlat = (this.ur_lat - this.ll_lat) / this.nj;
179
+ const ni = Math.ceil(this.ni / thin_x);
180
+ const nj = Math.ceil(this.nj / thin_y);
181
+ const ni_remove = (this.ni - 1) % thin_x;
182
+ const nj_remove = (this.nj - 1) % thin_y;
183
+ const ll_lon = this.ll_lon;
184
+ const ll_lat = this.ll_lat;
185
+ const ur_lon = this.ur_lon - ni_remove * dlon;
186
+ const ur_lat = this.ur_lat - nj_remove * dlat;
187
+ return new PlateCarreeRotatedGrid(ni, nj, this.np_lon, this.np_lat, this.lon_shift, ll_lon, ll_lat, ur_lon, ur_lat);
188
+ }
189
+ }
126
190
  /** A Lambert conformal conic grid with uniform grid spacing */
127
191
  class LambertGrid extends Grid {
128
192
  /**
@@ -147,7 +211,7 @@ class LambertGrid extends Grid {
147
211
  this.ur_x = ur_x;
148
212
  this.ur_y = ur_y;
149
213
  this.lcc = lambertConformalConic({ lon_0: lon_0, lat_0: lat_0, lat_std: lat_std });
150
- this._ll_cache = new Cache(() => {
214
+ this.ll_cache = new Cache(() => {
151
215
  const lons = new Float32Array(this.ni * this.nj);
152
216
  const lats = new Float32Array(this.ni * this.nj);
153
217
  for (let i = 0; i < this.ni; i++) {
@@ -177,7 +241,7 @@ class LambertGrid extends Grid {
177
241
  * Get a list of longitudes and latitudes on the grid (internal method)
178
242
  */
179
243
  getCoords() {
180
- return this._ll_cache.getValue();
244
+ return this.ll_cache.getValue();
181
245
  }
182
246
  transform(x, y, opts) {
183
247
  opts = opts === undefined ? {} : opts;
@@ -198,6 +262,9 @@ class LambertGrid extends Grid {
198
262
  return new LambertGrid(ni, nj, this.lon_0, this.lat_0, this.lat_std, ll_x, ll_y, ur_x, ur_y);
199
263
  }
200
264
  }
265
+ function getArrayConstructor(ary) {
266
+ return ary.constructor;
267
+ }
201
268
  /** A class representing a raw 2D field of gridded data, such as height or u wind. */
202
269
  class RawScalarField {
203
270
  /**
@@ -212,9 +279,25 @@ class RawScalarField {
212
279
  throw `Data size (${data.length}) doesn't match the grid dimensions (${grid.ni} x ${grid.nj}; expected ${grid.ni * grid.nj} points)`;
213
280
  }
214
281
  }
282
+ /** @internal */
283
+ getTextureData() {
284
+ // Need to give float16 data as uint16s to make WebGL happy: https://github.com/petamoriken/float16/issues/105
285
+ let data;
286
+ if (this.data instanceof Float32Array) {
287
+ data = this.data;
288
+ }
289
+ else {
290
+ data = new Uint16Array(this.data.buffer);
291
+ }
292
+ return data;
293
+ }
294
+ isFloat16() {
295
+ return !(this.data instanceof Float32Array);
296
+ }
215
297
  getThinnedField(thin_x, thin_y) {
298
+ const arrayType = getArrayConstructor(this.data);
216
299
  const new_grid = this.grid.getThinnedGrid(thin_x, thin_y);
217
- const new_data = new Float32Array(new_grid.ni * new_grid.nj);
300
+ const new_data = new arrayType(new_grid.ni * new_grid.nj);
218
301
  for (let i = 0; i < new_grid.ni; i++) {
219
302
  for (let j = 0; j < new_grid.nj; j++) {
220
303
  const idx_old = i * thin_x + this.grid.ni * j * thin_y;
@@ -239,8 +322,9 @@ class RawScalarField {
239
322
  yield func(elem);
240
323
  }
241
324
  }
325
+ const arrayType = getArrayConstructor(args[0].data);
242
326
  const zipped_args = zip(...args.map(a => a.data));
243
- const agg_data = new Float32Array(mapGenerator(zipped_args, (a) => func(...a)));
327
+ const agg_data = new arrayType(mapGenerator(zipped_args, (a) => func(...a)));
244
328
  return new RawScalarField(args[0].grid, agg_data);
245
329
  }
246
330
  }
@@ -255,14 +339,15 @@ class RawVectorField {
255
339
  */
256
340
  constructor(grid, u, v, opts) {
257
341
  opts = opts === undefined ? {} : opts;
342
+ const arrayType = getArrayConstructor(u);
258
343
  this.u = new RawScalarField(grid, u);
259
344
  this.v = new RawScalarField(grid, v);
260
345
  this.relative_to = opts.relative_to === undefined ? 'grid' : opts.relative_to;
261
- this._rotate_cache = new Cache(() => {
346
+ this.rotate_cache = new Cache(() => {
262
347
  const grid = this.u.grid;
263
348
  const coords = grid.getCoords();
264
- const u_rot = new Float32Array(coords.lats.length);
265
- const v_rot = new Float32Array(coords.lats.length);
349
+ const u_rot = new arrayType(coords.lats.length);
350
+ const v_rot = new arrayType(coords.lats.length);
266
351
  for (let icd = 0; icd < coords.lats.length; icd++) {
267
352
  const lon = coords.lons[icd];
268
353
  const lat = coords.lats[icd];
@@ -307,7 +392,7 @@ class RawVectorField {
307
392
  v = this.v;
308
393
  }
309
394
  else {
310
- const { u: u_, v: v_ } = this._rotate_cache.getValue();
395
+ const { u: u_, v: v_ } = this.rotate_cache.getValue();
311
396
  u = u_;
312
397
  v = v_;
313
398
  }
@@ -327,8 +412,8 @@ class RawProfileField {
327
412
  }
328
413
  /** Get the gridded storm motion vector field (internal method) */
329
414
  getStormMotionGrid() {
330
- const u = new Float32Array(this.grid.ni * this.grid.nj);
331
- const v = new Float32Array(this.grid.ni * this.grid.nj);
415
+ const u = new Float16Array(this.grid.ni * this.grid.nj);
416
+ const v = new Float16Array(this.grid.ni * this.grid.nj);
332
417
  this.profiles.forEach(prof => {
333
418
  const idx = prof.ilon + this.grid.ni * prof.jlat;
334
419
  u[idx] = prof.smu;
@@ -337,4 +422,4 @@ class RawProfileField {
337
422
  return new RawVectorField(this.grid, u, v, { relative_to: 'grid' });
338
423
  }
339
424
  }
340
- export { RawScalarField, RawVectorField, RawProfileField, PlateCarreeGrid, LambertGrid, Grid };
425
+ export { RawScalarField, RawVectorField, RawProfileField, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid, Grid };
package/lib/index.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { PlotComponent } from "./PlotComponent";
2
2
  import Contour, { ContourOptions } from "./Contour";
3
- import ContourFill, { ContourFillOptions } from "./ContourFill";
3
+ import { ContourFill, Raster, ContourFillOptions, RasterOptions } from "./Fill";
4
4
  import Barbs, { BarbsOptions } from "./Barbs";
5
5
  import Paintball, { PaintballOptions } from "./Paintball";
6
6
  import Hodographs, { HodographOptions } from './Hodographs';
7
7
  import { PlotLayer, MultiPlotLayer } from './PlotLayer';
8
- import { WindProfile, WebGLAnyRenderingContext } from "./AutumnTypes";
8
+ import { WindProfile, WebGLAnyRenderingContext, TypedArray } from "./AutumnTypes";
9
9
  import { MapType } from "./Map";
10
10
  import { ColorMap, Color } from './Colormap';
11
11
  import { makeColorBar, makePaintballKey, ColorbarOrientation, ColorbarTickDirection, ColorBarOptions, PaintballKeyOptions } from "./ColorBar";
12
- import { RawScalarField, RawVectorField, RawProfileField, Grid, GridType, VectorRelativeTo, RawVectorFieldOptions, PlateCarreeGrid, LambertGrid } from "./RawField";
12
+ import { RawScalarField, RawVectorField, RawProfileField, Grid, GridType, VectorRelativeTo, RawVectorFieldOptions, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid } from "./RawField";
13
13
  declare const colormaps: {
14
14
  bluered: (level_min: number, level_max: number, n_colors: number) => ColorMap;
15
15
  redblue: (level_min: number, level_max: number, n_colors: number) => ColorMap;
@@ -18,5 +18,6 @@ declare const colormaps: {
18
18
  pw_cape: ColorMap;
19
19
  pw_t2m: ColorMap;
20
20
  pw_td2m: ColorMap;
21
+ nws_storm_clear_refl: ColorMap;
21
22
  };
22
- export { PlotComponent, Barbs, BarbsOptions, Contour, ContourOptions, ContourFill, ContourFillOptions, Paintball, PaintballOptions, Hodographs, HodographOptions, WindProfile, PlotLayer, MultiPlotLayer, MapType, ColorMap, colormaps, makeColorBar, makePaintballKey, Color, ColorbarOrientation, ColorbarTickDirection, ColorBarOptions, PaintballKeyOptions, RawScalarField, RawVectorField, RawProfileField, Grid, GridType, VectorRelativeTo, RawVectorFieldOptions, PlateCarreeGrid, LambertGrid, WebGLAnyRenderingContext };
23
+ export { PlotComponent, Barbs, BarbsOptions, Contour, ContourOptions, ContourFill, Raster, ContourFillOptions, RasterOptions, Paintball, PaintballOptions, Hodographs, HodographOptions, WindProfile, PlotLayer, MultiPlotLayer, MapType, ColorMap, colormaps, makeColorBar, makePaintballKey, Color, ColorbarOrientation, ColorbarTickDirection, ColorBarOptions, PaintballKeyOptions, RawScalarField, RawVectorField, RawProfileField, Grid, GridType, VectorRelativeTo, RawVectorFieldOptions, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid, WebGLAnyRenderingContext, TypedArray };
package/lib/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { PlotComponent } from "./PlotComponent";
2
2
  import Contour from "./Contour";
3
- import ContourFill from "./ContourFill";
3
+ import { ContourFill, Raster } from "./Fill";
4
4
  import Barbs from "./Barbs";
5
5
  import Paintball from "./Paintball";
6
6
  import Hodographs from './Hodographs';
7
7
  import { PlotLayer, MultiPlotLayer } from './PlotLayer';
8
- import { ColorMap, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m } from './Colormap';
8
+ import { ColorMap, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m, nws_storm_clear_refl } from './Colormap';
9
9
  import { makeColorBar, makePaintballKey } from "./ColorBar";
10
- import { RawScalarField, RawVectorField, RawProfileField, Grid, PlateCarreeGrid, LambertGrid } from "./RawField";
10
+ import { RawScalarField, RawVectorField, RawProfileField, Grid, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid } from "./RawField";
11
11
  const colormaps = {
12
12
  bluered: bluered,
13
13
  redblue: redblue,
@@ -15,6 +15,7 @@ const colormaps = {
15
15
  pw_speed850mb: pw_speed850mb,
16
16
  pw_cape: pw_cape,
17
17
  pw_t2m: pw_t2m,
18
- pw_td2m: pw_td2m
18
+ pw_td2m: pw_td2m,
19
+ nws_storm_clear_refl: nws_storm_clear_refl,
19
20
  };
20
- export { PlotComponent, Barbs, Contour, ContourFill, Paintball, Hodographs, PlotLayer, MultiPlotLayer, ColorMap, colormaps, makeColorBar, makePaintballKey, RawScalarField, RawVectorField, RawProfileField, Grid, PlateCarreeGrid, LambertGrid };
21
+ export { PlotComponent, Barbs, Contour, ContourFill, Raster, Paintball, Hodographs, PlotLayer, MultiPlotLayer, ColorMap, colormaps, makeColorBar, makePaintballKey, RawScalarField, RawVectorField, RawProfileField, Grid, PlateCarreeGrid, PlateCarreeRotatedGrid, LambertGrid };
package/lib/utils.d.ts CHANGED
@@ -6,4 +6,11 @@ declare const rgb2hsv: (rgb: [number, number, number]) => [number, number, numbe
6
6
  declare const hsv2rgb: (hsv: [number, number, number]) => [number, number, number];
7
7
  declare function getMinZoom(jlat: number, ilon: number, thin_fac_base: number): number;
8
8
  declare function zip(...args: any[]): Generator<any[], void, unknown>;
9
- export { hex2rgba, rgba2hex, hex2rgb, rgb2hex, rgb2hsv, hsv2rgb, zip, getMinZoom };
9
+ declare function getOS(): string;
10
+ declare class Cache<A extends unknown[], R> {
11
+ private cached_value;
12
+ private readonly compute_value;
13
+ constructor(compute_value: (...args: A) => R);
14
+ getValue(...args: A): R;
15
+ }
16
+ export { hex2rgba, rgba2hex, hex2rgb, rgb2hex, rgb2hsv, hsv2rgb, zip, getMinZoom, getOS, Cache };
package/lib/utils.js CHANGED
@@ -100,4 +100,36 @@ function* zip(...args) {
100
100
  yield current.map(x => x.value);
101
101
  }
102
102
  }
103
- export { hex2rgba, rgba2hex, hex2rgb, rgb2hex, rgb2hsv, hsv2rgb, zip, getMinZoom };
103
+ function getOS() {
104
+ const userAgent = window.navigator.userAgent, platform = window.navigator.platform, macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'], iosPlatforms = ['iPhone', 'iPad', 'iPod'];
105
+ let os = null;
106
+ if (macosPlatforms.indexOf(platform) !== -1 && navigator.maxTouchPoints <= 1) {
107
+ os = 'Mac OS';
108
+ }
109
+ else if (iosPlatforms.indexOf(platform) !== -1 || (macosPlatforms.indexOf(platform) !== -1 && navigator.maxTouchPoints > 1)) {
110
+ os = 'iOS';
111
+ }
112
+ else if (windowsPlatforms.indexOf(platform) !== -1) {
113
+ os = 'Windows';
114
+ }
115
+ else if (/Android/.test(userAgent)) {
116
+ os = 'Android';
117
+ }
118
+ else if (/Linux/.test(platform)) {
119
+ os = 'Linux';
120
+ }
121
+ return os;
122
+ }
123
+ class Cache {
124
+ constructor(compute_value) {
125
+ this.cached_value = null;
126
+ this.compute_value = compute_value;
127
+ }
128
+ getValue(...args) {
129
+ if (this.cached_value === null) {
130
+ this.cached_value = this.compute_value(...args);
131
+ }
132
+ return this.cached_value;
133
+ }
134
+ }
135
+ export { hex2rgba, rgba2hex, hex2rgb, rgb2hex, rgb2hsv, hsv2rgb, zip, getMinZoom, getOS, Cache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autumnplot-gl",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -31,7 +31,8 @@
31
31
  "webpack-glsl-loader": "^1.0.1"
32
32
  },
33
33
  "dependencies": {
34
- "autumn-wgl": "^1.1.0",
34
+ "@petamoriken/float16": "^3.8.4",
35
+ "autumn-wgl": "^1.2.0",
35
36
  "comlink": "^4.3.1"
36
37
  }
37
38
  }
@@ -1,58 +0,0 @@
1
- import { PlotComponent } from './PlotComponent';
2
- import { ColorMap } from './Colormap';
3
- import { WGLBuffer, WGLProgram, WGLTexture } from 'autumn-wgl';
4
- import { RawScalarField } from './RawField';
5
- import { MapType } from './Map';
6
- import { WebGLAnyRenderingContext } from './AutumnTypes';
7
- interface ContourFillOptions {
8
- /** The color map to use when creating the fills */
9
- cmap: ColorMap;
10
- /**
11
- * The opacity for the filled contours
12
- * @default 1
13
- */
14
- opacity?: number;
15
- }
16
- interface ContourFillGLElems {
17
- program: WGLProgram;
18
- vertices: WGLBuffer;
19
- fill_texture: WGLTexture;
20
- texcoords: WGLBuffer;
21
- cmap_texture: WGLTexture;
22
- cmap_nonlin_texture: WGLTexture;
23
- }
24
- /**
25
- * A filled contoured field
26
- * @example
27
- * // Create a field of filled contours with the provided color map
28
- * const fill = new ContourFill(wind_speed_field, {cmap: color_map});
29
- */
30
- declare class ContourFill extends PlotComponent {
31
- readonly field: RawScalarField;
32
- readonly cmap: ColorMap;
33
- readonly opacity: number;
34
- /** @private */
35
- readonly cmap_image: HTMLCanvasElement;
36
- /** @private */
37
- readonly index_map: Float32Array;
38
- /** @private */
39
- gl_elems: ContourFillGLElems | null;
40
- /**
41
- * Create a filled contoured field
42
- * @param field - The field to create filled contours from
43
- * @param opts - Options for creating the filled contours
44
- */
45
- constructor(field: RawScalarField, opts: ContourFillOptions);
46
- /**
47
- * @internal
48
- * Add the filled contours to a map
49
- */
50
- onAdd(map: MapType, gl: WebGLAnyRenderingContext): Promise<void>;
51
- /**
52
- * @internal
53
- * Render the filled contours
54
- */
55
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
56
- }
57
- export default ContourFill;
58
- export type { ContourFillOptions };