autumnplot-gl 3.2.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 (48) hide show
  1. package/lib/AutumnTypes.d.ts +53 -5
  2. package/lib/AutumnTypes.js +25 -1
  3. package/lib/Barbs.d.ts +6 -5
  4. package/lib/BillboardCollection.d.ts +8 -7
  5. package/lib/BillboardCollection.js +69 -58
  6. package/lib/Color.d.ts +1 -0
  7. package/lib/Color.js +3 -0
  8. package/lib/ColorBar.d.ts +10 -0
  9. package/lib/ColorBar.js +4 -2
  10. package/lib/Colormap.js +8 -8
  11. package/lib/Contour.d.ts +18 -8
  12. package/lib/Contour.js +17 -54
  13. package/lib/ContourCreator.d.ts +4 -0
  14. package/lib/ContourCreator.js +2 -1
  15. package/lib/Fill.d.ts +26 -14
  16. package/lib/Fill.js +97 -50
  17. package/lib/Grid.d.ts +124 -29
  18. package/lib/Grid.js +297 -94
  19. package/lib/Hodographs.d.ts +9 -8
  20. package/lib/Hodographs.js +14 -11
  21. package/lib/Map.js +1 -1
  22. package/lib/Paintball.d.ts +6 -5
  23. package/lib/Paintball.js +35 -30
  24. package/lib/ParticleTracer.d.ts +19 -0
  25. package/lib/ParticleTracer.js +37 -0
  26. package/lib/PlotComponent.d.ts +6 -7
  27. package/lib/PlotComponent.js +8 -3
  28. package/lib/PlotLayer.d.ts +3 -3
  29. package/lib/PlotLayer.worker.d.ts +1 -2
  30. package/lib/PlotLayer.worker.js +15 -50
  31. package/lib/PolylineCollection.d.ts +5 -3
  32. package/lib/PolylineCollection.js +60 -37
  33. package/lib/RawField.d.ts +76 -23
  34. package/lib/RawField.js +138 -29
  35. package/lib/ShaderManager.d.ts +12 -0
  36. package/lib/ShaderManager.js +58 -0
  37. package/lib/StationPlot.d.ts +136 -25
  38. package/lib/StationPlot.js +192 -60
  39. package/lib/TextCollection.d.ts +9 -6
  40. package/lib/TextCollection.js +94 -62
  41. package/lib/cpp/marchingsquares.js +483 -585
  42. package/lib/cpp/marchingsquares.wasm +0 -0
  43. package/lib/cpp/marchingsquares_embind.d.ts +23 -3
  44. package/lib/index.d.ts +4 -3
  45. package/lib/index.js +4 -3
  46. package/lib/utils.d.ts +4 -1
  47. package/lib/utils.js +12 -1
  48. package/package.json +2 -2
package/lib/Hodographs.js CHANGED
@@ -77,17 +77,19 @@ class Hodographs extends PlotComponent {
77
77
  const gl = this.gl_elems.gl;
78
78
  this.gl_elems.bg_billboard.updateField(field.getStormMotionGrid());
79
79
  const profiles = this.profile_field.profiles;
80
- const hodo_polyline = profiles.map(prof => {
80
+ const { lats, lons } = this.profile_field.getProfileCoords();
81
+ const hodo_polyline = profiles.map((prof, iprof) => {
81
82
  const zoom = getMinZoom(prof['jlat'], prof['ilon'], this.opts.thin_fac);
82
83
  return {
83
84
  'offsets': [...prof['u']].map((u, ipt) => [u - prof['smu'], prof['v'][ipt] - prof['smv']]),
84
- 'vertices': [...prof['u']].map(u => [prof['lon'], prof['lat']]),
85
+ 'vertices': [...prof['u']].map(u => [lons[iprof], lats[iprof]]),
85
86
  'zoom': zoom,
86
87
  'data': [...prof['z']],
87
88
  };
88
89
  });
89
- const hodo_line = await PolylineCollection.make(gl, hodo_polyline, { line_width: this.opts.hodo_line_width, cmap: this.opts.height_cmap, offset_scale: this.hodo_scale * this.bg_size });
90
- 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) => {
91
93
  const zoom = getMinZoom(prof['jlat'], prof['ilon'], this.opts.thin_fac);
92
94
  const sm_mag = Math.hypot(prof['smu'], prof['smv']);
93
95
  const sm_ang = Math.PI / 2 - Math.atan2(-prof['smv'], -prof['smu']);
@@ -95,11 +97,12 @@ class Hodographs extends PlotComponent {
95
97
  return {
96
98
  'offsets': [[buffer * Math.sin(sm_ang), buffer * Math.cos(sm_ang)],
97
99
  [sm_mag * Math.sin(sm_ang), sm_mag * Math.cos(sm_ang)]],
98
- 'vertices': [[prof['lon'], prof['lat']], [prof['lon'], prof['lat']]],
100
+ 'vertices': [[lons[iprof], lats[iprof]], [lons[iprof], lats[iprof]]],
99
101
  'zoom': zoom
100
102
  };
101
103
  });
102
- const sm_line = await PolylineCollection.make(gl, sm_polyline, { line_width: this.opts.background_line_width, 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 });
103
106
  this.line_elems = {
104
107
  hodo_line: hodo_line, sm_line: sm_line
105
108
  };
@@ -111,7 +114,7 @@ class Hodographs extends PlotComponent {
111
114
  async onAdd(map, gl) {
112
115
  const bg_image = { 'format': gl.RGBA, 'type': gl.UNSIGNED_BYTE, 'image': this.hodo_bg_texture, 'mag_filter': gl.NEAREST };
113
116
  const max_zoom = map.getMaxZoom();
114
- 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) });
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 });
115
118
  await bg_billboard.setup(gl);
116
119
  this.gl_elems = {
117
120
  gl: gl, map: map, bg_billboard: bg_billboard
@@ -122,7 +125,7 @@ class Hodographs extends PlotComponent {
122
125
  * @internal
123
126
  * Render the hodographs
124
127
  */
125
- render(gl, matrix) {
128
+ render(gl, arg) {
126
129
  if (this.gl_elems === null || this.line_elems === null)
127
130
  return;
128
131
  const gl_elems = this.gl_elems;
@@ -132,9 +135,9 @@ class Hodographs extends PlotComponent {
132
135
  const map_height = gl_elems.map.getCanvas().height;
133
136
  const bearing = gl_elems.map.getBearing();
134
137
  const pitch = gl_elems.map.getPitch();
135
- line_elems.hodo_line.render(gl, matrix, [map_width, map_height], zoom, bearing, pitch);
136
- line_elems.sm_line.render(gl, matrix, [map_width, map_height], zoom, bearing, bearing);
137
- 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);
138
141
  }
139
142
  }
140
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,33 +1,40 @@
1
+ import { getRendererData } from "./AutumnTypes";
1
2
  import { Color } from "./Color";
2
- import { PlotComponent, getGLFormatTypeAlignment } from "./PlotComponent";
3
+ import { PlotComponent } from "./PlotComponent";
4
+ import { ShaderProgramManager } from "./ShaderManager";
3
5
  import { normalizeOptions } from "./utils";
4
- import { WGLProgram, WGLTexture } from "autumn-wgl";
5
- const paintball_vertex_shader_src = `uniform mat4 u_matrix;
6
+ import { WGLTexture } from "autumn-wgl";
7
+ const paintball_vertex_shader_src = `#version 300 es
8
+
6
9
  uniform int u_offset;
7
10
 
8
- attribute vec2 a_pos;
9
- attribute vec2 a_tex_coord;
11
+ in vec2 a_pos;
12
+ in vec2 a_tex_coord;
10
13
 
11
- varying highp vec2 v_tex_coord;
14
+ out highp vec2 v_tex_coord;
12
15
 
13
16
  void main() {
14
17
  float globe_width = 1.;
15
18
  vec2 globe_offset = vec2(globe_width * float(u_offset), 0.);
16
19
 
17
- gl_Position = u_matrix * vec4(a_pos + globe_offset, 0.0, 1.0);
20
+ gl_Position = projectTile(a_pos.xy + globe_offset);
18
21
  v_tex_coord = a_tex_coord;
19
22
  }`
20
- 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
21
26
 
22
- varying highp vec2 v_tex_coord;
27
+ in highp vec2 v_tex_coord;
23
28
 
24
29
  uniform sampler2D u_fill_sampler;
25
30
  uniform lowp vec4 u_colors[MAX_N_COLORS];
26
31
  uniform int u_num_colors;
27
32
  uniform highp float u_opacity;
28
33
 
34
+ out highp vec4 fragColor;
35
+
29
36
  void main() {
30
- 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;
31
38
 
32
39
  if (fill_val < 0.5) {
33
40
  discard;
@@ -44,7 +51,7 @@ void main() {
44
51
  }
45
52
 
46
53
  color.a = color.a * u_opacity;
47
- gl_FragColor = color;
54
+ fragColor = color;
48
55
  }`
49
56
  const paintball_opt_defaults = {
50
57
  colors: ['#000000'],
@@ -83,12 +90,7 @@ class Paintball extends PlotComponent {
83
90
  return;
84
91
  const gl = this.gl_elems.gl;
85
92
  gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
86
- const tex_data = this.field.getTextureData();
87
- const { format, type, row_alignment } = getGLFormatTypeAlignment(gl, !(tex_data instanceof Float32Array));
88
- const fill_image = { 'format': format, 'type': type,
89
- 'width': this.field.grid.ni, 'height': this.field.grid.nj, 'image': tex_data,
90
- 'mag_filter': gl.NEAREST, 'row_alignment': row_alignment,
91
- };
93
+ const fill_image = this.field.getWGLTextureSpec(gl, gl.NEAREST);
92
94
  if (this.fill_texture === null) {
93
95
  this.fill_texture = new WGLTexture(gl, fill_image);
94
96
  }
@@ -102,12 +104,12 @@ class Paintball extends PlotComponent {
102
104
  */
103
105
  async onAdd(map, gl) {
104
106
  gl.getExtension('OES_texture_float');
105
- const program = new WGLProgram(gl, paintball_vertex_shader_src, paintball_fragment_shader_src);
106
107
  const { vertices: verts_buf, texcoords: tex_coords_buf } = await this.field.grid.getWGLBuffers(gl);
107
108
  const vertices = verts_buf;
108
109
  const texcoords = tex_coords_buf;
110
+ const shader_manager = new ShaderProgramManager(paintball_vertex_shader_src, paintball_fragment_shader_src, []);
109
111
  this.gl_elems = {
110
- gl: gl, program: program, vertices: vertices, texcoords: texcoords,
112
+ gl: gl, shader_manager: shader_manager, vertices: vertices, texcoords: texcoords,
111
113
  };
112
114
  this.updateField(this.field);
113
115
  }
@@ -115,23 +117,26 @@ class Paintball extends PlotComponent {
115
117
  * @internal
116
118
  * Render the paintball plot
117
119
  */
118
- render(gl, matrix) {
120
+ render(gl, arg) {
119
121
  if (this.gl_elems === null || this.fill_texture === null)
120
122
  return;
121
123
  const gl_elems = this.gl_elems;
122
- if (matrix instanceof Float32Array)
123
- matrix = [...matrix];
124
+ const render_data = getRendererData(arg);
125
+ const program = this.gl_elems.shader_manager.getShaderProgram(gl, render_data.shaderData);
124
126
  // Render to framebuffer
125
- 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 });
126
129
  gl.enable(gl.BLEND);
127
130
  gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
128
- gl_elems.program.draw();
129
- gl_elems.program.setUniforms({ 'u_offset': -2 });
130
- gl_elems.program.draw();
131
- gl_elems.program.setUniforms({ 'u_offset': -1 });
132
- gl_elems.program.draw();
133
- gl_elems.program.setUniforms({ 'u_offset': 1 });
134
- 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
+ }
135
140
  }
136
141
  }
137
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,10 +5,10 @@ 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
14
  if (is_webgl2) {
@@ -23,7 +23,7 @@ function getGLFormatTypeAlignment(gl, is_float16) {
23
23
  }
24
24
  row_alignment = 2;
25
25
  }
26
- else {
26
+ else if (array_dtype == 'float32') {
27
27
  const ext = gl.getExtension('OES_texture_float');
28
28
  const ext_lin = gl.getExtension('OES_texture_float_linear');
29
29
  // As of 11/3/2023, Safari/WebKit on iOS reports as supporting float textures,
@@ -39,6 +39,11 @@ function getGLFormatTypeAlignment(gl, is_float16) {
39
39
  type = gl.FLOAT;
40
40
  row_alignment = 4;
41
41
  }
42
+ else {
43
+ format = is_webgl2 ? gl.R8 : gl.LUMINANCE;
44
+ type = gl.UNSIGNED_BYTE;
45
+ row_alignment = 1;
46
+ }
42
47
  return { format: format, type: type, row_alignment: row_alignment };
43
48
  }
44
49
  export { PlotComponent, layer_worker, getGLFormatTypeAlignment };
@@ -1,4 +1,4 @@
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> {
@@ -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: {
@@ -1,17 +1,11 @@
1
- import { getMinZoom } from "./utils";
2
1
  import * as Comlink from 'comlink';
3
2
  import { LngLat } from "./Map";
4
- function makeBBElements(field_lats, field_lons, field_ni, field_nj, thin_fac_base, max_zoom) {
5
- const n_pts_per_poly = 6;
6
- const n_coords_per_pt_pts = 3;
3
+ function makeBBElements(field_lats, field_lons, min_zoom, field_ni, field_nj, map_max_zoom) {
4
+ const n_coords_per_pt_pts = 2;
7
5
  const n_coords_per_pt_tc = 2;
8
- const n_density_tiers = Math.log2(thin_fac_base);
9
- const n_inaccessible_tiers = Math.max(n_density_tiers + 1 - max_zoom, 0);
10
- const trim_inaccessible = Math.pow(2, n_inaccessible_tiers);
11
- const field_ni_access = Math.floor((field_ni - 1) / trim_inaccessible) + 1;
12
- const field_nj_access = Math.floor((field_nj - 1) / trim_inaccessible) + 1;
13
- const n_elems_pts = field_ni_access * field_nj_access * n_pts_per_poly * n_coords_per_pt_pts;
14
- const n_elems_tc = field_ni_access * field_nj_access * n_pts_per_poly * n_coords_per_pt_tc;
6
+ const field_n_access = min_zoom.filter(mz => mz <= map_max_zoom).length;
7
+ const n_elems_pts = field_n_access * n_coords_per_pt_pts;
8
+ const n_elems_tc = field_n_access * n_coords_per_pt_tc;
15
9
  let pts = new Float32Array(n_elems_pts);
16
10
  let tex_coords = new Float32Array(n_elems_tc);
17
11
  let istart_pts = 0;
@@ -21,22 +15,16 @@ function makeBBElements(field_lats, field_lons, field_ni, field_nj, thin_fac_bas
21
15
  const idx = ilat * field_ni + ilon;
22
16
  const lat = field_lats[idx];
23
17
  const lon = field_lons[idx];
24
- const zoom = getMinZoom(ilat, ilon, thin_fac_base);
25
- if (zoom > max_zoom)
26
- continue;
18
+ const zoom = min_zoom[idx];
19
+ if (zoom > map_max_zoom || lon === undefined || lat === undefined)
20
+ continue; // TAS: Adding the checks for lat/lon here may be a bug waiting to happen? Not sure.
27
21
  const pt_ll = new LngLat(lon, lat).toMercatorCoord();
28
- // These contain a degenerate triangle on either end to imitate primitive restarting
29
- // (see https://groups.google.com/g/webgl-dev-list/c/KLfiwj4jax0/m/cKiezrhRz8MJ?pli=1)
30
- for (let icrnr = 0; icrnr < n_pts_per_poly; icrnr++) {
31
- const actual_icrnr = Math.max(0, Math.min(icrnr - 1, 3));
32
- pts[istart_pts + icrnr * n_coords_per_pt_pts + 0] = pt_ll.x;
33
- pts[istart_pts + icrnr * n_coords_per_pt_pts + 1] = pt_ll.y;
34
- pts[istart_pts + icrnr * n_coords_per_pt_pts + 2] = zoom * 4 + actual_icrnr;
35
- tex_coords[istart_tc + icrnr * n_coords_per_pt_tc + 0] = ilon / (field_ni - 1);
36
- tex_coords[istart_tc + icrnr * n_coords_per_pt_tc + 1] = ilat / (field_nj - 1);
37
- }
38
- istart_pts += (n_pts_per_poly * n_coords_per_pt_pts);
39
- istart_tc += (n_pts_per_poly * n_coords_per_pt_tc);
22
+ pts[istart_pts + 0] = pt_ll.x;
23
+ pts[istart_pts + 1] = pt_ll.y;
24
+ tex_coords[istart_tc + 0] = ilon / (field_ni - 1) + zoom; // Pack the min zoom in with the texture coordinates; only works because the min zoom is always an integer
25
+ tex_coords[istart_tc + 1] = ilat / (field_nj - 1);
26
+ istart_pts += n_coords_per_pt_pts;
27
+ istart_tc += n_coords_per_pt_tc;
40
28
  }
41
29
  }
42
30
  return { 'pts': pts, 'tex_coords': tex_coords };
@@ -44,7 +32,6 @@ function makeBBElements(field_lats, field_lons, field_ni, field_nj, thin_fac_bas
44
32
  function makeDomainVerticesAndTexCoords(field_lats, field_lons, field_ni, field_nj, texcoord_margin_r, texcoord_margin_s) {
45
33
  const verts = new Float32Array(2 * 2 * (field_ni - 1) * (field_nj + 1)).fill(0);
46
34
  const tex_coords = new Float32Array(2 * 2 * (field_ni - 1) * (field_nj + 1)).fill(0);
47
- const grid_cell_size = new Float32Array(1 * 2 * (field_ni - 1) * (field_nj + 1)).fill(0);
48
35
  let ivert = 0;
49
36
  let itexcoord = 0;
50
37
  for (let i = 0; i < field_ni - 1; i++) {
@@ -83,29 +70,7 @@ function makeDomainVerticesAndTexCoords(field_lats, field_lons, field_ni, field_
83
70
  }
84
71
  }
85
72
  }
86
- let igcs = 0;
87
- for (let i = 0; i < field_ni - 1; i++) {
88
- for (let j = 0; j < field_nj - 1; j++) {
89
- const ivert = j == 0 ? 2 * (igcs + 1) : 2 * igcs;
90
- const x_ll = verts[ivert], y_ll = verts[ivert + 1], x_lr = verts[ivert + 2], y_lr = verts[ivert + 3], x_ul = verts[ivert + 4], y_ul = verts[ivert + 5], x_ur = verts[ivert + 6], y_ur = verts[ivert + 7];
91
- const area = 0.5 * Math.abs(x_ll * (y_lr - y_ul) + x_lr * (y_ul - y_ll) + x_ul * (y_ll - y_lr) +
92
- x_ur * (y_ul - y_lr) + x_ul * (y_lr - y_ur) + x_lr * (y_ur - y_ul));
93
- if (j == 0) {
94
- grid_cell_size[igcs] = area;
95
- igcs += 1;
96
- }
97
- grid_cell_size[igcs] = area;
98
- grid_cell_size[igcs + 1] = area;
99
- igcs += 2;
100
- if (j == field_nj - 2) {
101
- grid_cell_size[igcs] = area;
102
- grid_cell_size[igcs + 1] = area;
103
- grid_cell_size[igcs + 2] = area;
104
- igcs += 3;
105
- }
106
- }
107
- }
108
- return { 'vertices': verts, 'tex_coords': tex_coords, 'grid_cell_size': grid_cell_size };
73
+ return { 'vertices': verts, 'tex_coords': tex_coords };
109
74
  }
110
75
  /*
111
76
  function makePolylinesMiter(lines) {
@@ -1,4 +1,4 @@
1
- import { LineData, WebGLAnyRenderingContext } from "./AutumnTypes";
1
+ import { LineData, WebGLAnyRenderingContext, RenderMethodArg } from "./AutumnTypes";
2
2
  import { ColorMap } from "./Colormap";
3
3
  /**
4
4
  * A style to use to draw lines. The possible options are '-' for a solid line, '--' for a dashed line, ':' for a
@@ -9,6 +9,7 @@ type LineStyle = "-" | "--" | ":" | "-." | number[];
9
9
  declare function isLineStyle(obj: any): obj is LineStyle;
10
10
  interface PolylineCollectionOpts {
11
11
  offset_scale?: number;
12
+ offset_rotates_with_map?: boolean;
12
13
  color?: string;
13
14
  cmap?: ColorMap;
14
15
  line_width?: number;
@@ -17,7 +18,7 @@ interface PolylineCollectionOpts {
17
18
  declare class PolylineCollection {
18
19
  readonly width: number;
19
20
  readonly scale: number | null;
20
- private readonly program;
21
+ private readonly shader_manager;
21
22
  private readonly vertices;
22
23
  private readonly extrusion;
23
24
  private readonly offset;
@@ -25,11 +26,12 @@ declare class PolylineCollection {
25
26
  private readonly line_data;
26
27
  private readonly color;
27
28
  private readonly cmap_gpu;
29
+ private readonly offset_rotates_with_map;
28
30
  private readonly dash_texture;
29
31
  private readonly n_dash;
30
32
  private constructor();
31
33
  static make(gl: WebGLAnyRenderingContext, lines: LineData[], opts?: PolylineCollectionOpts): Promise<PolylineCollection>;
32
- render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array, [map_width, map_height]: [number, number], map_zoom: number, map_bearing: number, map_pitch: number): void;
34
+ render(gl: WebGLAnyRenderingContext, arg: RenderMethodArg, [map_width, map_height]: [number, number], map_zoom: number, map_bearing: number, map_pitch: number): void;
33
35
  }
34
36
  export { PolylineCollection, isLineStyle };
35
37
  export type { PolylineCollectionOpts, LineStyle };