autumnplot-gl 3.1.0 → 4.0.0-beta

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.
Files changed (56) hide show
  1. package/README.md +6 -11
  2. package/dist/110.autumnplot-gl.js +1 -1
  3. package/dist/110.autumnplot-gl.js.map +1 -1
  4. package/dist/autumnplot-gl.js +1 -1
  5. package/dist/autumnplot-gl.js.map +1 -1
  6. package/dist/marchingsquares.wasm +0 -0
  7. package/lib/AutumnTypes.d.ts +53 -5
  8. package/lib/AutumnTypes.js +25 -1
  9. package/lib/Barbs.d.ts +23 -6
  10. package/lib/Barbs.js +20 -18
  11. package/lib/BillboardCollection.d.ts +16 -8
  12. package/lib/BillboardCollection.js +107 -59
  13. package/lib/Color.d.ts +57 -0
  14. package/lib/Color.js +163 -0
  15. package/lib/ColorBar.d.ts +12 -1
  16. package/lib/ColorBar.js +9 -7
  17. package/lib/Colormap.d.ts +19 -18
  18. package/lib/Colormap.js +84 -23
  19. package/lib/Contour.d.ts +42 -11
  20. package/lib/Contour.js +67 -58
  21. package/lib/ContourCreator.d.ts +4 -0
  22. package/lib/ContourCreator.js +2 -1
  23. package/lib/Fill.d.ts +27 -16
  24. package/lib/Fill.js +105 -83
  25. package/lib/Grid.d.ts +125 -29
  26. package/lib/Grid.js +303 -95
  27. package/lib/Hodographs.d.ts +24 -6
  28. package/lib/Hodographs.js +28 -24
  29. package/lib/Map.js +1 -1
  30. package/lib/Paintball.d.ts +6 -5
  31. package/lib/Paintball.js +38 -32
  32. package/lib/ParticleTracer.d.ts +19 -0
  33. package/lib/ParticleTracer.js +37 -0
  34. package/lib/PlotComponent.d.ts +6 -7
  35. package/lib/PlotComponent.js +17 -7
  36. package/lib/PlotLayer.d.ts +4 -4
  37. package/lib/PlotLayer.worker.d.ts +1 -2
  38. package/lib/PlotLayer.worker.js +22 -57
  39. package/lib/PolylineCollection.d.ts +18 -9
  40. package/lib/PolylineCollection.js +124 -89
  41. package/lib/RawField.d.ts +76 -23
  42. package/lib/RawField.js +138 -29
  43. package/lib/ShaderManager.d.ts +12 -0
  44. package/lib/ShaderManager.js +58 -0
  45. package/lib/StationPlot.d.ts +145 -0
  46. package/lib/StationPlot.js +205 -0
  47. package/lib/TextCollection.d.ts +12 -8
  48. package/lib/TextCollection.js +113 -71
  49. package/lib/cpp/marchingsquares.js +483 -585
  50. package/lib/cpp/marchingsquares.wasm +0 -0
  51. package/lib/cpp/marchingsquares_embind.d.ts +23 -3
  52. package/lib/index.d.ts +7 -4
  53. package/lib/index.js +5 -3
  54. package/lib/utils.d.ts +5 -8
  55. package/lib/utils.js +12 -83
  56. package/package.json +2 -2
package/lib/Hodographs.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { PlotComponent } from "./PlotComponent";
2
2
  import { PolylineCollection } from "./PolylineCollection";
3
3
  import { BillboardCollection } from "./BillboardCollection";
4
- import { getMinZoom, hex2rgb, normalizeOptions } from './utils';
4
+ import { getMinZoom, normalizeOptions } from './utils';
5
5
  import { ColorMap } from "./Colormap";
6
- const LINE_WIDTH = 4;
6
+ import { Color } from "./Color";
7
+ const LINE_WIDTH_MULTIPLIER = 2.5;
7
8
  const BG_MAX_RING_MAG = 40;
8
9
  const HODO_BG_DIMS = {
9
10
  BB_WIDTH: 256,
@@ -14,7 +15,7 @@ const HODO_BG_DIMS = {
14
15
  BB_MAG_WRAP: 1000,
15
16
  BB_MAG_BIN_SIZE: 1000,
16
17
  };
17
- function _createHodoBackgroundTexture() {
18
+ function _createHodoBackgroundTexture(line_width) {
18
19
  let canvas = document.createElement('canvas');
19
20
  canvas.width = HODO_BG_DIMS.BB_TEX_WIDTH;
20
21
  canvas.height = HODO_BG_DIMS.BB_TEX_HEIGHT;
@@ -22,10 +23,10 @@ function _createHodoBackgroundTexture() {
22
23
  if (ctx === null) {
23
24
  throw "Could not get rendering context for the hodograph background canvas";
24
25
  }
25
- ctx.lineWidth = LINE_WIDTH;
26
+ ctx.lineWidth = line_width;
26
27
  for (let irng = HODO_BG_DIMS.BB_TEX_WIDTH / 4; irng <= HODO_BG_DIMS.BB_TEX_WIDTH / 2; irng += HODO_BG_DIMS.BB_TEX_WIDTH / 4) {
27
28
  ctx.beginPath();
28
- ctx.arc(HODO_BG_DIMS.BB_TEX_WIDTH / 2, HODO_BG_DIMS.BB_TEX_WIDTH / 2, irng - LINE_WIDTH / 2, 0, 2 * Math.PI);
29
+ ctx.arc(HODO_BG_DIMS.BB_TEX_WIDTH / 2, HODO_BG_DIMS.BB_TEX_WIDTH / 2, irng - line_width / 2, 0, 2 * Math.PI);
29
30
  ctx.stroke();
30
31
  }
31
32
  const ctr_x = HODO_BG_DIMS.BB_TEX_WIDTH / 2, ctr_y = HODO_BG_DIMS.BB_TEX_WIDTH / 2;
@@ -39,13 +40,15 @@ function _createHodoBackgroundTexture() {
39
40
  return canvas;
40
41
  }
41
42
  ;
42
- let HODO_BG_TEXTURE = null;
43
43
  const HODO_CMAP = new ColorMap([0, 1, 3, 6, 9], ['#ffffcc', '#a1dab4', '#41b6c4', '#225ea8']);
44
44
  const hodograph_opt_defaults = {
45
45
  bgcolor: '#000000',
46
- thin_fac: 1
46
+ thin_fac: 1,
47
+ hodo_line_width: 2.5,
48
+ background_line_width: 1.5,
49
+ height_cmap: HODO_CMAP
47
50
  };
48
- /** A class representing a a field of hodograph plots */
51
+ /** A class representing a field of hodograph plots */
49
52
  class Hodographs extends PlotComponent {
50
53
  /**
51
54
  * Create a field of hodographs
@@ -56,7 +59,8 @@ class Hodographs extends PlotComponent {
56
59
  super();
57
60
  this.profile_field = profile_field;
58
61
  this.opts = normalizeOptions(opts, hodograph_opt_defaults);
59
- this.hodo_scale = (HODO_BG_DIMS.BB_TEX_WIDTH - LINE_WIDTH / 2) / (HODO_BG_DIMS.BB_TEX_WIDTH * BG_MAX_RING_MAG);
62
+ this.hodo_bg_texture = _createHodoBackgroundTexture(this.opts.background_line_width * LINE_WIDTH_MULTIPLIER);
63
+ this.hodo_scale = (HODO_BG_DIMS.BB_TEX_WIDTH - this.opts.background_line_width / 2) / (HODO_BG_DIMS.BB_TEX_WIDTH * BG_MAX_RING_MAG);
60
64
  this.bg_size = 140;
61
65
  this.gl_elems = null;
62
66
  this.line_elems = null;
@@ -73,17 +77,19 @@ class Hodographs extends PlotComponent {
73
77
  const gl = this.gl_elems.gl;
74
78
  this.gl_elems.bg_billboard.updateField(field.getStormMotionGrid());
75
79
  const profiles = this.profile_field.profiles;
76
- const hodo_polyline = profiles.map(prof => {
80
+ const { lats, lons } = this.profile_field.getProfileCoords();
81
+ const hodo_polyline = profiles.map((prof, iprof) => {
77
82
  const zoom = getMinZoom(prof['jlat'], prof['ilon'], this.opts.thin_fac);
78
83
  return {
79
84
  'offsets': [...prof['u']].map((u, ipt) => [u - prof['smu'], prof['v'][ipt] - prof['smv']]),
80
- 'vertices': [...prof['u']].map(u => [prof['lon'], prof['lat']]),
85
+ 'vertices': [...prof['u']].map(u => [lons[iprof], lats[iprof]]),
81
86
  'zoom': zoom,
82
87
  'data': [...prof['z']],
83
88
  };
84
89
  });
85
- const hodo_line = await PolylineCollection.make(gl, hodo_polyline, { line_width: 2.5, cmap: HODO_CMAP, offset_scale: this.hodo_scale * this.bg_size });
86
- const sm_polyline = profiles.map(prof => {
90
+ const hodo_line = await PolylineCollection.make(gl, hodo_polyline, { line_width: this.opts.hodo_line_width, cmap: this.opts.height_cmap,
91
+ offset_scale: this.hodo_scale * this.bg_size, offset_rotates_with_map: false });
92
+ const sm_polyline = profiles.map((prof, iprof) => {
87
93
  const zoom = getMinZoom(prof['jlat'], prof['ilon'], this.opts.thin_fac);
88
94
  const sm_mag = Math.hypot(prof['smu'], prof['smv']);
89
95
  const sm_ang = Math.PI / 2 - Math.atan2(-prof['smv'], -prof['smu']);
@@ -91,11 +97,12 @@ class Hodographs extends PlotComponent {
91
97
  return {
92
98
  'offsets': [[buffer * Math.sin(sm_ang), buffer * Math.cos(sm_ang)],
93
99
  [sm_mag * Math.sin(sm_ang), sm_mag * Math.cos(sm_ang)]],
94
- 'vertices': [[prof['lon'], prof['lat']], [prof['lon'], prof['lat']]],
100
+ 'vertices': [[lons[iprof], lats[iprof]], [lons[iprof], lats[iprof]]],
95
101
  'zoom': zoom
96
102
  };
97
103
  });
98
- const sm_line = await PolylineCollection.make(gl, sm_polyline, { line_width: 1.5, color: this.opts.bgcolor, offset_scale: this.hodo_scale * this.bg_size });
104
+ const sm_line = await PolylineCollection.make(gl, sm_polyline, { line_width: this.opts.background_line_width, color: this.opts.bgcolor,
105
+ offset_scale: this.hodo_scale * this.bg_size, offset_rotates_with_map: false });
99
106
  this.line_elems = {
100
107
  hodo_line: hodo_line, sm_line: sm_line
101
108
  };
@@ -105,12 +112,9 @@ class Hodographs extends PlotComponent {
105
112
  * Add the hodographs to a map
106
113
  */
107
114
  async onAdd(map, gl) {
108
- if (HODO_BG_TEXTURE === null) {
109
- HODO_BG_TEXTURE = _createHodoBackgroundTexture();
110
- }
111
- const bg_image = { 'format': gl.RGBA, 'type': gl.UNSIGNED_BYTE, 'image': HODO_BG_TEXTURE, 'mag_filter': gl.NEAREST };
115
+ const bg_image = { 'format': gl.RGBA, 'type': gl.UNSIGNED_BYTE, 'image': this.hodo_bg_texture, 'mag_filter': gl.NEAREST };
112
116
  const max_zoom = map.getMaxZoom();
113
- const bg_billboard = new BillboardCollection(this.profile_field.getStormMotionGrid(), this.opts.thin_fac, max_zoom, bg_image, HODO_BG_DIMS, hex2rgb(this.opts.bgcolor), this.bg_size * 0.004);
117
+ const bg_billboard = new BillboardCollection(this.profile_field.getStormMotionGrid(), this.opts.thin_fac, max_zoom, bg_image, HODO_BG_DIMS, this.bg_size * 0.004, { color: Color.fromHex(this.opts.bgcolor), rotate_with_map: false });
114
118
  await bg_billboard.setup(gl);
115
119
  this.gl_elems = {
116
120
  gl: gl, map: map, bg_billboard: bg_billboard
@@ -121,7 +125,7 @@ class Hodographs extends PlotComponent {
121
125
  * @internal
122
126
  * Render the hodographs
123
127
  */
124
- render(gl, matrix) {
128
+ render(gl, arg) {
125
129
  if (this.gl_elems === null || this.line_elems === null)
126
130
  return;
127
131
  const gl_elems = this.gl_elems;
@@ -131,9 +135,9 @@ class Hodographs extends PlotComponent {
131
135
  const map_height = gl_elems.map.getCanvas().height;
132
136
  const bearing = gl_elems.map.getBearing();
133
137
  const pitch = gl_elems.map.getPitch();
134
- line_elems.hodo_line.render(gl, matrix, [map_width, map_height], zoom, bearing, pitch);
135
- line_elems.sm_line.render(gl, matrix, [map_width, map_height], zoom, bearing, bearing);
136
- gl_elems.bg_billboard.render(gl, matrix, [map_width, map_height], zoom, bearing, pitch);
138
+ line_elems.hodo_line.render(gl, arg, [map_width, map_height], zoom, bearing, pitch);
139
+ line_elems.sm_line.render(gl, arg, [map_width, map_height], zoom, bearing, bearing);
140
+ gl_elems.bg_billboard.render(gl, arg, [map_width, map_height], zoom, bearing, pitch);
137
141
  }
138
142
  }
139
143
  export default Hodographs;
package/lib/Map.js CHANGED
@@ -130,7 +130,7 @@ function lngFromMercatorX(x) {
130
130
  function mercatorYfromLat(lat) {
131
131
  const sin_lat = Math.sin(lat * Math.PI / 180);
132
132
  const y = (180 - (90 / Math.PI * Math.log((1 + sin_lat) / (1 - sin_lat)))) / 360;
133
- return Math.min(2, Math.max(-2, y));
133
+ return Math.min(1.5, Math.max(-0.5, y));
134
134
  }
135
135
  function latFromMercatorY(y) {
136
136
  return Math.atan(Math.sinh((180 - y * 360) * Math.PI / 180)) * 180 / Math.PI;
@@ -1,4 +1,5 @@
1
- import { TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
1
+ import { RenderMethodArg, TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
2
+ import { StructuredGrid } from "./Grid";
2
3
  import { MapLikeType } from "./Map";
3
4
  import { PlotComponent } from "./PlotComponent";
4
5
  import { RawScalarField } from "./RawField";
@@ -20,7 +21,7 @@ interface PaintballOptions {
20
21
  * of single-precision floats, this works for up to 24 members. (Technically speaking, I don't need the quotes around "bits", as they're bits of the
21
22
  * significand of an IEEE 754 float.)
22
23
  */
23
- declare class Paintball<ArrayType extends TypedArray, MapType extends MapLikeType> extends PlotComponent<MapType> {
24
+ declare class Paintball<ArrayType extends TypedArray, GridType extends StructuredGrid, MapType extends MapLikeType> extends PlotComponent<MapType> {
24
25
  private field;
25
26
  readonly opts: Required<PaintballOptions>;
26
27
  private readonly color_components;
@@ -33,12 +34,12 @@ declare class Paintball<ArrayType extends TypedArray, MapType extends MapLikeTyp
33
34
  * `M2` is the same thing for member 2, and `M3` and `M4` and up to `Mn` are the same thing for the rest of the members.
34
35
  * @param opts - Options for creating the paintball plot
35
36
  */
36
- constructor(field: RawScalarField<ArrayType>, opts?: PaintballOptions);
37
+ constructor(field: RawScalarField<ArrayType, GridType>, opts?: PaintballOptions);
37
38
  /**
38
39
  * Update the field displayed as a paintball plot
39
40
  * @param field - The new field to display as a paintball plot
40
41
  */
41
- updateField(field: RawScalarField<ArrayType>): Promise<void>;
42
+ updateField(field: RawScalarField<ArrayType, GridType>): Promise<void>;
42
43
  /**
43
44
  * @internal
44
45
  * Add the paintball plot to a map.
@@ -48,7 +49,7 @@ declare class Paintball<ArrayType extends TypedArray, MapType extends MapLikeTyp
48
49
  * @internal
49
50
  * Render the paintball plot
50
51
  */
51
- render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
52
+ render(gl: WebGLAnyRenderingContext, arg: RenderMethodArg): void;
52
53
  }
53
54
  export default Paintball;
54
55
  export type { PaintballOptions };
package/lib/Paintball.js CHANGED
@@ -1,32 +1,40 @@
1
- import { PlotComponent, getGLFormatTypeAlignment } from "./PlotComponent";
2
- import { hex2rgba, normalizeOptions } from "./utils";
3
- import { WGLProgram, WGLTexture } from "autumn-wgl";
4
- const paintball_vertex_shader_src = `uniform mat4 u_matrix;
1
+ import { getRendererData } from "./AutumnTypes";
2
+ import { Color } from "./Color";
3
+ import { PlotComponent } from "./PlotComponent";
4
+ import { ShaderProgramManager } from "./ShaderManager";
5
+ import { normalizeOptions } from "./utils";
6
+ import { WGLTexture } from "autumn-wgl";
7
+ const paintball_vertex_shader_src = `#version 300 es
8
+
5
9
  uniform int u_offset;
6
10
 
7
- attribute vec2 a_pos;
8
- attribute vec2 a_tex_coord;
11
+ in vec2 a_pos;
12
+ in vec2 a_tex_coord;
9
13
 
10
- varying highp vec2 v_tex_coord;
14
+ out highp vec2 v_tex_coord;
11
15
 
12
16
  void main() {
13
17
  float globe_width = 1.;
14
18
  vec2 globe_offset = vec2(globe_width * float(u_offset), 0.);
15
19
 
16
- gl_Position = u_matrix * vec4(a_pos + globe_offset, 0.0, 1.0);
20
+ gl_Position = projectTile(a_pos.xy + globe_offset);
17
21
  v_tex_coord = a_tex_coord;
18
22
  }`
19
- const paintball_fragment_shader_src = `#define MAX_N_COLORS 24
23
+ const paintball_fragment_shader_src = `#version 300 es
24
+
25
+ #define MAX_N_COLORS 24
20
26
 
21
- varying highp vec2 v_tex_coord;
27
+ in highp vec2 v_tex_coord;
22
28
 
23
29
  uniform sampler2D u_fill_sampler;
24
30
  uniform lowp vec4 u_colors[MAX_N_COLORS];
25
31
  uniform int u_num_colors;
26
32
  uniform highp float u_opacity;
27
33
 
34
+ out highp vec4 fragColor;
35
+
28
36
  void main() {
29
- highp float fill_val = texture2D(u_fill_sampler, v_tex_coord).r;
37
+ highp float fill_val = texture(u_fill_sampler, v_tex_coord).r;
30
38
 
31
39
  if (fill_val < 0.5) {
32
40
  discard;
@@ -43,7 +51,7 @@ void main() {
43
51
  }
44
52
 
45
53
  color.a = color.a * u_opacity;
46
- gl_FragColor = color;
54
+ fragColor = color;
47
55
  }`
48
56
  const paintball_opt_defaults = {
49
57
  colors: ['#000000'],
@@ -68,7 +76,7 @@ class Paintball extends PlotComponent {
68
76
  super();
69
77
  this.field = field;
70
78
  this.opts = normalizeOptions(opts, paintball_opt_defaults);
71
- this.color_components = [...this.opts.colors].reverse().map(color => hex2rgba(color)).flat();
79
+ this.color_components = [...this.opts.colors].reverse().map(color => Color.fromHex(color).toRGBATuple()).flat();
72
80
  this.gl_elems = null;
73
81
  this.fill_texture = null;
74
82
  }
@@ -82,12 +90,7 @@ class Paintball extends PlotComponent {
82
90
  return;
83
91
  const gl = this.gl_elems.gl;
84
92
  gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
85
- const tex_data = this.field.getTextureData();
86
- const { format, type, row_alignment } = getGLFormatTypeAlignment(gl, !(tex_data instanceof Float32Array));
87
- const fill_image = { 'format': format, 'type': type,
88
- 'width': this.field.grid.ni, 'height': this.field.grid.nj, 'image': tex_data,
89
- 'mag_filter': gl.NEAREST, 'row_alignment': row_alignment,
90
- };
93
+ const fill_image = this.field.getWGLTextureSpec(gl, gl.NEAREST);
91
94
  if (this.fill_texture === null) {
92
95
  this.fill_texture = new WGLTexture(gl, fill_image);
93
96
  }
@@ -101,12 +104,12 @@ class Paintball extends PlotComponent {
101
104
  */
102
105
  async onAdd(map, gl) {
103
106
  gl.getExtension('OES_texture_float');
104
- const program = new WGLProgram(gl, paintball_vertex_shader_src, paintball_fragment_shader_src);
105
107
  const { vertices: verts_buf, texcoords: tex_coords_buf } = await this.field.grid.getWGLBuffers(gl);
106
108
  const vertices = verts_buf;
107
109
  const texcoords = tex_coords_buf;
110
+ const shader_manager = new ShaderProgramManager(paintball_vertex_shader_src, paintball_fragment_shader_src, []);
108
111
  this.gl_elems = {
109
- gl: gl, program: program, vertices: vertices, texcoords: texcoords,
112
+ gl: gl, shader_manager: shader_manager, vertices: vertices, texcoords: texcoords,
110
113
  };
111
114
  this.updateField(this.field);
112
115
  }
@@ -114,23 +117,26 @@ class Paintball extends PlotComponent {
114
117
  * @internal
115
118
  * Render the paintball plot
116
119
  */
117
- render(gl, matrix) {
120
+ render(gl, arg) {
118
121
  if (this.gl_elems === null || this.fill_texture === null)
119
122
  return;
120
123
  const gl_elems = this.gl_elems;
121
- if (matrix instanceof Float32Array)
122
- matrix = [...matrix];
124
+ const render_data = getRendererData(arg);
125
+ const program = this.gl_elems.shader_manager.getShaderProgram(gl, render_data.shaderData);
123
126
  // Render to framebuffer
124
- gl_elems.program.use({ 'a_pos': gl_elems.vertices, 'a_tex_coord': gl_elems.texcoords }, { 'u_matrix': matrix, 'u_opacity': this.opts.opacity, 'u_colors': this.color_components, 'u_num_colors': this.opts.colors.length, 'u_offset': 0 }, { 'u_fill_sampler': this.fill_texture });
127
+ program.use({ 'a_pos': gl_elems.vertices, 'a_tex_coord': gl_elems.texcoords }, { 'u_opacity': this.opts.opacity, 'u_colors': this.color_components, 'u_num_colors': this.opts.colors.length, 'u_offset': 0,
128
+ ...this.gl_elems.shader_manager.getShaderUniforms(render_data) }, { 'u_fill_sampler': this.fill_texture });
125
129
  gl.enable(gl.BLEND);
126
130
  gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
127
- gl_elems.program.draw();
128
- gl_elems.program.setUniforms({ 'u_offset': -2 });
129
- gl_elems.program.draw();
130
- gl_elems.program.setUniforms({ 'u_offset': -1 });
131
- gl_elems.program.draw();
132
- gl_elems.program.setUniforms({ 'u_offset': 1 });
133
- gl_elems.program.draw();
131
+ program.draw();
132
+ if (render_data.type != 'maplibre' || !render_data.shaderData.define.includes('GLOBE')) {
133
+ program.setUniforms({ 'u_offset': -2 });
134
+ program.draw();
135
+ program.setUniforms({ 'u_offset': -1 });
136
+ program.draw();
137
+ program.setUniforms({ 'u_offset': 1 });
138
+ program.draw();
139
+ }
134
140
  }
135
141
  }
136
142
  export default Paintball;
@@ -0,0 +1,19 @@
1
+ import { RenderMethodArg, TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
2
+ import { Grid } from "./Grid";
3
+ import { MapLikeType } from "./Map";
4
+ import { PlotComponent } from "./PlotComponent";
5
+ import { RawVectorField } from "./RawField";
6
+ interface ParticleTracerOptions {
7
+ }
8
+ declare class ParticleTracer<ArrayType extends TypedArray, GridType extends Grid, MapType extends MapLikeType> extends PlotComponent<MapType> {
9
+ field: RawVectorField<ArrayType, GridType>;
10
+ readonly opts: Required<ParticleTracerOptions>;
11
+ private gl_elems;
12
+ private wind_textures;
13
+ constructor(fields: RawVectorField<ArrayType, GridType>, opts?: ParticleTracerOptions);
14
+ updateField(field: RawVectorField<ArrayType, GridType>): void;
15
+ onAdd(map: MapType, gl: WebGLAnyRenderingContext): Promise<void>;
16
+ onRemove(map: MapType, gl: WebGLAnyRenderingContext): void;
17
+ render(gl: WebGLAnyRenderingContext, args: RenderMethodArg): void;
18
+ }
19
+ export { ParticleTracer };
@@ -0,0 +1,37 @@
1
+ import { WGLTexture } from "autumn-wgl";
2
+ import { PlotComponent } from "./PlotComponent";
3
+ import { normalizeOptions } from "./utils";
4
+ const particle_tracer_opt_defaults = {};
5
+ class ParticleTracer extends PlotComponent {
6
+ constructor(fields, opts) {
7
+ super();
8
+ this.field = fields;
9
+ this.opts = normalizeOptions(opts, particle_tracer_opt_defaults);
10
+ this.gl_elems = null;
11
+ this.wind_textures = null;
12
+ }
13
+ updateField(field) {
14
+ this.field = field;
15
+ if (this.gl_elems === null)
16
+ return;
17
+ const gl = this.gl_elems.gl;
18
+ const { u: u_image, v: v_image } = this.field.getWGLTextureSpecs(gl, gl.NEAREST);
19
+ if (this.wind_textures === null) {
20
+ this.wind_textures = { u: new WGLTexture(gl, u_image), v: new WGLTexture(gl, v_image) };
21
+ }
22
+ else {
23
+ this.wind_textures.u.setImageData(u_image);
24
+ this.wind_textures.v.setImageData(v_image);
25
+ }
26
+ }
27
+ async onAdd(map, gl) {
28
+ const { rotation: proj_rotation_tex } = this.field.grid.getVectorRotationTexture(gl, this.field.relative_to == 'earth');
29
+ this.gl_elems = { gl: gl, proj_rot_texture: proj_rotation_tex };
30
+ this.updateField(this.field);
31
+ }
32
+ onRemove(map, gl) {
33
+ }
34
+ render(gl, args) {
35
+ }
36
+ }
37
+ export { ParticleTracer };
@@ -1,25 +1,24 @@
1
1
  import * as Comlink from 'comlink';
2
2
  import { MapLikeType } from './Map';
3
- import { WebGLAnyRenderingContext } from './AutumnTypes';
3
+ import { RenderMethodArg, TypedArrayStr, WebGLAnyRenderingContext } from './AutumnTypes';
4
4
  declare const layer_worker: Comlink.Remote<{
5
- makeBBElements: (field_lats: Float32Array, field_lons: Float32Array, field_ni: number, field_nj: number, thin_fac_base: number, max_zoom: number) => {
5
+ makeBBElements: (field_lats: Float32Array, field_lons: Float32Array, min_zoom: Uint8Array, field_ni: number, field_nj: number, map_max_zoom: number) => {
6
6
  pts: Float32Array;
7
7
  tex_coords: Float32Array;
8
8
  };
9
9
  makeDomainVerticesAndTexCoords: (field_lats: Float32Array, field_lons: Float32Array, field_ni: number, field_nj: number, texcoord_margin_r: number, texcoord_margin_s: number) => {
10
10
  vertices: Float32Array;
11
11
  tex_coords: Float32Array;
12
- grid_cell_size: Float32Array;
13
12
  };
14
13
  makePolyLines: (lines: import("./AutumnTypes").LineData[]) => import("./AutumnTypes").Polyline;
15
14
  }>;
16
15
  declare abstract class PlotComponent<MapType extends MapLikeType> {
17
16
  abstract onAdd(map: MapType, gl: WebGLAnyRenderingContext): Promise<void>;
18
- abstract render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
17
+ abstract render(gl: WebGLAnyRenderingContext, arg: RenderMethodArg): void;
19
18
  }
20
- declare function getGLFormatTypeAlignment(gl: WebGLAnyRenderingContext, is_float16: boolean): {
21
- format: 33325 | 33326 | 6409;
22
- type: 36193 | 5131 | 5126;
19
+ declare function getGLFormatTypeAlignment(gl: WebGLAnyRenderingContext, array_dtype: TypedArrayStr): {
20
+ format: 33321 | 33325 | 33326 | 6409;
21
+ type: 36193 | 5131 | 5121 | 5126;
23
22
  row_alignment: number;
24
23
  };
25
24
  export { PlotComponent, layer_worker, getGLFormatTypeAlignment };
@@ -5,20 +5,25 @@ const worker = new Worker(new URL('./PlotLayer.worker', import.meta.url));
5
5
  const layer_worker = Comlink.wrap(worker);
6
6
  class PlotComponent {
7
7
  }
8
- function getGLFormatTypeAlignment(gl, is_float16) {
8
+ function getGLFormatTypeAlignment(gl, array_dtype) {
9
9
  let format, type, row_alignment;
10
10
  const is_webgl2 = isWebGL2Ctx(gl);
11
- if (is_float16) {
11
+ if (array_dtype == 'float16') {
12
12
  const ext = gl.getExtension('OES_texture_half_float');
13
13
  const ext_lin = gl.getExtension('OES_texture_half_float_linear');
14
- if ((!is_webgl2 && ext === null) || (!is_webgl2 && ext_lin === null)) {
15
- throw "Float16 data are not supported on this hardware. Try Float32 data instead.";
14
+ if (is_webgl2) {
15
+ format = gl.R16F;
16
+ type = gl.HALF_FLOAT;
17
+ }
18
+ else {
19
+ if (ext === null || ext_lin === null)
20
+ throw "Float16 data are not supported on this hardware. Try Float32 data instead.";
21
+ format = gl.LUMINANCE;
22
+ type = ext.HALF_FLOAT_OES;
16
23
  }
17
- format = is_webgl2 ? gl.R16F : gl.LUMINANCE;
18
- type = is_webgl2 ? gl.HALF_FLOAT : ext.HALF_FLOAT_OES;
19
24
  row_alignment = 2;
20
25
  }
21
- else {
26
+ else if (array_dtype == 'float32') {
22
27
  const ext = gl.getExtension('OES_texture_float');
23
28
  const ext_lin = gl.getExtension('OES_texture_float_linear');
24
29
  // As of 11/3/2023, Safari/WebKit on iOS reports as supporting float textures,
@@ -34,6 +39,11 @@ function getGLFormatTypeAlignment(gl, is_float16) {
34
39
  type = gl.FLOAT;
35
40
  row_alignment = 4;
36
41
  }
42
+ else {
43
+ format = is_webgl2 ? gl.R8 : gl.LUMINANCE;
44
+ type = gl.UNSIGNED_BYTE;
45
+ row_alignment = 1;
46
+ }
37
47
  return { format: format, type: type, row_alignment: row_alignment };
38
48
  }
39
49
  export { PlotComponent, layer_worker, getGLFormatTypeAlignment };
@@ -1,10 +1,10 @@
1
- import { WebGLAnyRenderingContext } from './AutumnTypes';
1
+ import { RenderMethodArg, WebGLAnyRenderingContext } from './AutumnTypes';
2
2
  import { MapLikeType } from './Map';
3
3
  import { PlotComponent } from './PlotComponent';
4
4
  declare abstract class PlotLayerBase<MapType extends MapLikeType> {
5
5
  readonly type: 'custom';
6
6
  readonly id: string;
7
- protected map: MapType;
7
+ protected map: MapType | null;
8
8
  constructor(id: string);
9
9
  abstract onAdd(map: MapType, gl: WebGLAnyRenderingContext): void;
10
10
  abstract render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
@@ -36,7 +36,7 @@ declare class PlotLayer<MapType extends MapLikeType> extends PlotLayerBase<MapTy
36
36
  * @internal
37
37
  * Render this layer
38
38
  */
39
- render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
39
+ render(gl: WebGLAnyRenderingContext, matrix: RenderMethodArg): void;
40
40
  }
41
41
  /**
42
42
  * A varying map layer. If the data don't have a varying component, such as over time, it might be easier to use an {@link PlotLayer} instead.
@@ -70,7 +70,7 @@ declare class MultiPlotLayer<MapType extends MapLikeType> extends PlotLayerBase<
70
70
  * @internal
71
71
  * Render this layer
72
72
  */
73
- render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
73
+ render(gl: WebGLAnyRenderingContext, matrix: RenderMethodArg): void;
74
74
  /**
75
75
  * Set the active key
76
76
  * @param key - The new key. The field with that key is plotted immediately.
@@ -1,12 +1,11 @@
1
1
  import { LineData, Polyline } from "./AutumnTypes";
2
- declare function makeBBElements(field_lats: Float32Array, field_lons: Float32Array, field_ni: number, field_nj: number, thin_fac_base: number, max_zoom: number): {
2
+ declare function makeBBElements(field_lats: Float32Array, field_lons: Float32Array, min_zoom: Uint8Array, field_ni: number, field_nj: number, map_max_zoom: number): {
3
3
  pts: Float32Array;
4
4
  tex_coords: Float32Array;
5
5
  };
6
6
  declare function makeDomainVerticesAndTexCoords(field_lats: Float32Array, field_lons: Float32Array, field_ni: number, field_nj: number, texcoord_margin_r: number, texcoord_margin_s: number): {
7
7
  vertices: Float32Array;
8
8
  tex_coords: Float32Array;
9
- grid_cell_size: Float32Array;
10
9
  };
11
10
  declare function makePolylines(lines: LineData[]): Polyline;
12
11
  declare const ep_interface: {