autumnplot-gl 2.1.0 → 2.2.1

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 CHANGED
@@ -19,7 +19,7 @@ npm i autumnplot-gl
19
19
  Additionally, pre-built autumnplot-gl javascript files area available [here](https://tsupinie.github.io/autumnplot-gl/dist/). Adding them to your page exposes the API via the `apgl` global variable (e.g., instead of `new PlateCarreeGrid(...)` in the examples, you'd call `new apgl.PlateCarreeGrid(...)`).
20
20
 
21
21
  ### A basic contour plot
22
- The first step in plotting data is to create a grid. Currently, the only supported grids are PlateCarree (a.k.a. Lat/Lon) and Lambert Conformal Conic.
22
+ The first step in plotting data is to create a grid. Currently, the only supported grids are PlateCarreeGrid (a.k.a. Lat/Lon), RotatedPlateCarreeGrid, and LambertGrid (a.k.a. Lambert Conformal Conic).
23
23
 
24
24
  ```javascript
25
25
  // Create a grid object that covers the continental United States
@@ -27,7 +27,7 @@ const nx = 121, ny = 61;
27
27
  const grid = new PlateCarreeGrid(nx, ny, -130, 20, -65, 55);
28
28
  ```
29
29
 
30
- Next, create a RawScalarField with the data. autumnplot-gl doesn't care about how data get to the browser, but it should end up in a Float32Array in row-major order with the first element being at the southwest corner of the grid. A future version might include support for reading from, say, a Zarr file. Once you have your data in that format, to create the raw data field:
30
+ Next, create a RawScalarField with the data. autumnplot-gl doesn't care about how data get to the browser, but it should end up in a `Float32Array` or `Float16Array` in row-major order with the first element being at the southwest corner of the grid. If you're using [zarr.js](https://github.com/gzuidhof/zarr.js/), you can use the `getRaw()` function on a `ZarrArray` to get data in the correct format. Also, `Float16Array`s are not in the Javascript standard library (for now), so for the time being, you'll need to use [this library](https://github.com/petamoriken/float16). However, the nice part about using a `Float16Array` is that your data will be stored as float16s in VRAM, so they'll take up half the space as the same data as float32s. Once you have your data in that format, to create the raw data field:
31
31
 
32
32
  ```javascript
33
33
  // Create the raw data field
@@ -81,7 +81,7 @@ map.on('load', () => {
81
81
 
82
82
  The wind barbs are automatically rotated based on the grid projection. Also, the density of the wind barbs is automatically varied based on the map zoom level. The `'thin_fac': 16` option means to plot every 16th wind barb in the i and j directions, and this is defined at zoom level 1. So at zoom level 2, it will plot every 8th wind barb, and at zoom level 3 every 4th wind barb, and so on. Because it divides in 2 for every deeper zoom level, `'thin_fac'` should be a power of 2.
83
83
 
84
- ### Filled contours
84
+ ### Filled contours or raster plots
85
85
 
86
86
  Plotting filled contours is also similar to plotting regular contours, but there's some additional steps for the color map. A couple color maps are available by default (see [here](#built-in-color-maps) for more details), but if you have the colors you want, creating your own is (relatively) painless (hopefully). First, set up the colormap. Here, we'll just use the bluered colormap included by default.
87
87
 
@@ -96,7 +96,13 @@ map.on('load', () => {
96
96
  });
97
97
  ```
98
98
 
99
- Normally, when you have color-filled contours, you have a color bar on the plot. To create an SVG color bar:
99
+ Making a raster plot is very similar (the two classes support the same options):
100
+
101
+ ```javascript
102
+ const raster = new Raster(height, {cmap: colormap});
103
+ ```
104
+
105
+ Normally, when you have a color fill, you have a color bar on the plot. To create an SVG color bar:
100
106
 
101
107
  ```javascript
102
108
  const colorbar_svg = makeColorBar(colormap, {label: "Height Perturbation (m)",
@@ -154,7 +160,7 @@ The above exmple uses map tiles from [Maptiler](https://www.maptiler.com/). Map
154
160
  So, I've created some [less-detailed map tiles](https://tsupinie.github.io/autumnplot-gl/tiles/) that are small enough that they can be hosted without dedicated hardware. However the tradeoff is that they're only useful down to zoom level 8 or 9 on the map, such that the viewport is somewhere between half a US state and a few counties in size. If that's good enough for you, then these tiles could be useful.
155
161
 
156
162
  ## Conspicuous absences
157
- A few capabilities are missing from this library as of v2.0.
163
+ A few capabilities are missing from this library as of v2.2.
158
164
  * Helper functions for reading from specific data formats. For instance, I'd like to add support for reading from a zarr file.
159
165
  * A whole bunch of little things that ought to be fairly straightforward like tweaking the size of the wind barbs and contour thicknesses.
160
166
  * Support for contour labeling. I'd like to add it, but I'm not really sure how I'd do it with the contours as I've implemented them. Any WebGL gurus, get in touch.
@@ -1,3 +1,4 @@
1
+ import { Float16Array } from "@petamoriken/float16";
1
2
  interface WindProfile {
2
3
  lat: number;
3
4
  lon: number;
@@ -33,5 +34,6 @@ interface LineSpec {
33
34
  }
34
35
  type WebGLAnyRenderingContext = WebGLRenderingContext | WebGL2RenderingContext;
35
36
  declare function isWebGL2Ctx(gl: WebGLAnyRenderingContext): gl is WebGL2RenderingContext;
37
+ type TypedArray = Float16Array | Float32Array;
36
38
  export { isWebGL2Ctx };
37
- export type { WindProfile, BillboardSpec, PolylineSpec, LineSpec, WebGLAnyRenderingContext };
39
+ export type { WindProfile, BillboardSpec, PolylineSpec, LineSpec, WebGLAnyRenderingContext, TypedArray };
package/lib/Barbs.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { PlotComponent } from "./PlotComponent";
2
- import { BillboardCollection } from './BillboardCollection';
3
2
  import { RawVectorField } from "./RawField";
4
3
  import { MapType } from "./Map";
5
- import { WebGLAnyRenderingContext } from "./AutumnTypes";
4
+ import { TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
6
5
  interface BarbsOptions {
7
6
  /**
8
7
  * The color to use for the barbs as a hex color string;.
@@ -16,10 +15,6 @@ interface BarbsOptions {
16
15
  */
17
16
  thin_fac?: number;
18
17
  }
19
- interface BarbsGLElems {
20
- map: MapType | null;
21
- barb_billboards: BillboardCollection | null;
22
- }
23
18
  /**
24
19
  * A class representing a field of wind barbs. The barbs are automatically thinned based on the zoom level on the map; the user only has to provide a
25
20
  * thinning factor at zoom level 1.
@@ -28,19 +23,18 @@ interface BarbsGLElems {
28
23
  * const vector_field = new RawVectorField(grid, u_data, v_data);
29
24
  * const barbs = new Barbs(vector_field, {color: '#000000', thin_fac: 16});
30
25
  */
31
- declare class Barbs extends PlotComponent {
26
+ declare class Barbs<ArrayType extends TypedArray> extends PlotComponent {
32
27
  /** The vector field */
33
- readonly fields: RawVectorField;
28
+ private readonly fields;
34
29
  readonly color: [number, number, number];
35
30
  readonly thin_fac: number;
36
- /** @private */
37
- gl_elems: BarbsGLElems | null;
31
+ private gl_elems;
38
32
  /**
39
33
  * Create a field of wind barbs
40
34
  * @param fields - The vector field to plot as barbs
41
35
  * @param opts - Options for creating the wind barbs
42
36
  */
43
- constructor(fields: RawVectorField, opts: BarbsOptions);
37
+ constructor(fields: RawVectorField<ArrayType>, opts: BarbsOptions);
44
38
  /**
45
39
  * @internal
46
40
  * Add the barb field to a map
@@ -50,7 +44,7 @@ declare class Barbs extends PlotComponent {
50
44
  * @internal
51
45
  * Render the barb field
52
46
  */
53
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
47
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
54
48
  }
55
49
  export default Barbs;
56
50
  export type { BarbsOptions };
@@ -1,17 +1,17 @@
1
- import { BillboardSpec, WebGLAnyRenderingContext } from "./AutumnTypes";
1
+ import { BillboardSpec, TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
2
2
  import { RawVectorField } from "./RawField";
3
- import { WGLBuffer, WGLProgram, WGLTexture, WGLTextureSpec } from "autumn-wgl";
4
- declare class BillboardCollection {
3
+ import { WGLTextureSpec } from "autumn-wgl";
4
+ declare class BillboardCollection<ArrayType extends TypedArray> {
5
5
  readonly spec: BillboardSpec;
6
6
  readonly color: [number, number, number];
7
7
  readonly size_multiplier: number;
8
- readonly program: WGLProgram;
9
- vertices: WGLBuffer | null;
10
- texcoords: WGLBuffer | null;
11
- readonly texture: WGLTexture;
12
- readonly u_texture: WGLTexture;
13
- readonly v_texture: WGLTexture;
14
- constructor(gl: WebGLAnyRenderingContext, field: RawVectorField, thin_fac: number, max_zoom: number, billboard_image: WGLTextureSpec, billboard_spec: BillboardSpec, billboard_color: [number, number, number], billboard_size_mult: number);
15
- render(gl: WebGLAnyRenderingContext, matrix: number[], [map_width, map_height]: [number, number], map_zoom: number, map_bearing: number, map_pitch: number): void;
8
+ private readonly program;
9
+ private vertices;
10
+ private texcoords;
11
+ private readonly texture;
12
+ private readonly u_texture;
13
+ private readonly v_texture;
14
+ constructor(gl: WebGLAnyRenderingContext, field: RawVectorField<ArrayType>, thin_fac: number, max_zoom: number, billboard_image: WGLTextureSpec, billboard_spec: BillboardSpec, billboard_color: [number, number, number], billboard_size_mult: number);
15
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array, [map_width, map_height]: [number, number], map_zoom: number, map_bearing: number, map_pitch: number): void;
16
16
  }
17
17
  export { BillboardCollection };
@@ -1,6 +1,7 @@
1
- import { isWebGL2Ctx } from "./AutumnTypes";
1
+ import { getGLFormatTypeAlignment } from "./PlotComponent";
2
2
  import { WGLProgram, WGLTexture } from "autumn-wgl";
3
3
  const billboard_vertex_shader_src = `uniform mat4 u_matrix;
4
+ uniform int u_offset;
4
5
 
5
6
  attribute vec3 a_pos;
6
7
  attribute vec2 a_tex_coord;
@@ -47,7 +48,10 @@ mat4 rotationXMatrix(float angle) {
47
48
  }
48
49
 
49
50
  void main() {
50
- vec4 pivot_pos = u_matrix * vec4(a_pos.xy, 0.0, 1.0);
51
+ float globe_width = 1.;
52
+ vec2 globe_offset = vec2(globe_width * float(u_offset), 0.);
53
+
54
+ vec4 pivot_pos = u_matrix * vec4(a_pos.xy + globe_offset, 0.0, 1.0);
51
55
  highp float zoom_corner = a_pos.z;
52
56
  lowp float min_zoom = floor(zoom_corner / 4.0);
53
57
  lowp float corner = mod(zoom_corner, 4.0);
@@ -56,7 +60,7 @@ void main() {
56
60
  highp float v = texture2D(u_v_sampler, a_tex_coord).r;
57
61
 
58
62
  lowp float bb_aspect = u_bb_width / u_bb_height;
59
- lowp float ang = atan(v, u) - 3.141592654 / 2.0;
63
+ lowp float ang = (abs(u) < 1e-6 && abs(v) < 1e-6) ? 0. : atan(v, u) - 3.141592654 / 2.0;
60
64
  highp float mag = length(vec2(u, v));
61
65
  mag = floor(mag / u_bb_mag_bin_size + 0.5) * u_bb_mag_bin_size;
62
66
 
@@ -119,14 +123,14 @@ class BillboardCollection {
119
123
  this.vertices = vertices;
120
124
  this.texcoords = texcoords;
121
125
  })();
122
- const format = isWebGL2Ctx(gl) ? gl.R32F : gl.LUMINANCE;
123
- const u_image = { 'format': format, 'type': gl.FLOAT,
124
- 'width': u_thin.grid.ni, 'height': u_thin.grid.nj, 'image': u_thin.data,
125
- 'mag_filter': gl.NEAREST,
126
+ const { format, type, row_alignment } = getGLFormatTypeAlignment(gl, u_thin.isFloat16());
127
+ const u_image = { 'format': format, 'type': type,
128
+ 'width': u_thin.grid.ni, 'height': u_thin.grid.nj, 'image': u_thin.getTextureData(),
129
+ 'mag_filter': gl.NEAREST, 'row_alignment': row_alignment,
126
130
  };
127
- const v_image = { 'format': format, 'type': gl.FLOAT,
128
- 'width': v_thin.grid.ni, 'height': v_thin.grid.nj, 'image': v_thin.data,
129
- 'mag_filter': gl.NEAREST,
131
+ const v_image = { 'format': format, 'type': type,
132
+ 'width': v_thin.grid.ni, 'height': v_thin.grid.nj, 'image': v_thin.getTextureData(),
133
+ 'mag_filter': gl.NEAREST, 'row_alignment': row_alignment,
130
134
  };
131
135
  this.texture = new WGLTexture(gl, billboard_image);
132
136
  this.u_texture = new WGLTexture(gl, u_image);
@@ -135,15 +139,23 @@ class BillboardCollection {
135
139
  render(gl, matrix, [map_width, map_height], map_zoom, map_bearing, map_pitch) {
136
140
  if (this.vertices === null || this.texcoords === null)
137
141
  return;
142
+ if (matrix instanceof Float32Array)
143
+ matrix = [...matrix];
138
144
  const bb_size = this.spec.BB_HEIGHT * (map_height / map_width) * this.size_multiplier;
139
145
  const bb_width = this.spec.BB_WIDTH / this.spec.BB_TEX_WIDTH;
140
146
  const bb_height = this.spec.BB_HEIGHT / this.spec.BB_TEX_HEIGHT;
141
147
  this.program.use({ 'a_pos': this.vertices, 'a_tex_coord': this.texcoords }, { 'u_bb_size': bb_size, 'u_bb_width': bb_width, 'u_bb_height': bb_height,
142
- 'u_bb_mag_bin_size': this.spec.BB_MAG_BIN_SIZE, 'u_bb_mag_wrap': this.spec.BB_MAG_WRAP,
148
+ 'u_bb_mag_bin_size': this.spec.BB_MAG_BIN_SIZE, 'u_bb_mag_wrap': this.spec.BB_MAG_WRAP, 'u_offset': 0,
143
149
  'u_bb_color': this.color, 'u_matrix': matrix, 'u_map_aspect': map_height / map_width, 'u_zoom': map_zoom, 'u_map_bearing': map_bearing }, { 'u_sampler': this.texture, 'u_u_sampler': this.u_texture, 'u_v_sampler': this.v_texture });
144
150
  gl.enable(gl.BLEND);
145
151
  gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
146
152
  this.program.draw();
153
+ this.program.setUniforms({ 'u_offset': -2 });
154
+ this.program.draw();
155
+ this.program.setUniforms({ 'u_offset': -1 });
156
+ this.program.draw();
157
+ this.program.setUniforms({ 'u_offset': 1 });
158
+ this.program.draw();
147
159
  }
148
160
  }
149
161
  export { BillboardCollection };
package/lib/Contour.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { WebGLAnyRenderingContext } from './AutumnTypes';
1
+ import { TypedArray, WebGLAnyRenderingContext } from './AutumnTypes';
2
2
  import { MapType } from './Map';
3
3
  import { PlotComponent } from './PlotComponent';
4
4
  import { RawScalarField } from './RawField';
5
- import { WGLBuffer, WGLProgram, WGLTexture } from 'autumn-wgl';
6
5
  interface ContourOptions {
7
6
  /**
8
7
  * The color of the contours as a hex color string
@@ -26,14 +25,6 @@ interface ContourOptions {
26
25
  */
27
26
  thinner?: (zoom: number) => number;
28
27
  }
29
- interface ContourGLElems {
30
- map: MapType;
31
- program: WGLProgram;
32
- vertices: WGLBuffer;
33
- grid_cell_size: WGLBuffer;
34
- fill_texture: WGLTexture;
35
- texcoords: WGLBuffer;
36
- }
37
28
  /**
38
29
  * A field of contoured data. The contours can optionally be thinned based on map zoom level.
39
30
  * @example
@@ -42,20 +33,19 @@ interface ContourGLElems {
42
33
  * const contours = new Contour(height_field, {color: '#000000', interval: 30,
43
34
  * thinner: zoom => zoom < 5 ? 2 : 1});
44
35
  */
45
- declare class Contour extends PlotComponent {
46
- readonly field: RawScalarField;
36
+ declare class Contour<ArrayType extends TypedArray> extends PlotComponent {
37
+ private readonly field;
47
38
  readonly color: [number, number, number];
48
39
  readonly interval: number;
49
40
  readonly levels: number[];
50
41
  readonly thinner: (zoom: number) => number;
51
- /** @private */
52
- gl_elems: ContourGLElems | null;
42
+ private gl_elems;
53
43
  /**
54
44
  * Create a contoured field
55
45
  * @param field - The field to contour
56
46
  * @param opts - Options for creating the contours
57
47
  */
58
- constructor(field: RawScalarField, opts: ContourOptions);
48
+ constructor(field: RawScalarField<ArrayType>, opts: ContourOptions);
59
49
  /**
60
50
  * @internal
61
51
  * Add the contours to a map
@@ -65,7 +55,7 @@ declare class Contour extends PlotComponent {
65
55
  * @internal
66
56
  * Render the contours
67
57
  */
68
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
58
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
69
59
  }
70
60
  export default Contour;
71
61
  export type { ContourOptions };
package/lib/Contour.js CHANGED
@@ -1,8 +1,8 @@
1
- import { isWebGL2Ctx } from './AutumnTypes';
2
- import { PlotComponent } from './PlotComponent';
1
+ import { PlotComponent, getGLFormatTypeAlignment } from './PlotComponent';
3
2
  import { hex2rgba } from './utils';
4
3
  import { WGLProgram, WGLTexture } from 'autumn-wgl';
5
4
  const contour_vertex_shader_src = `uniform mat4 u_matrix;
5
+ uniform int u_offset;
6
6
 
7
7
  attribute vec2 a_pos;
8
8
  attribute float a_grid_cell_size;
@@ -13,7 +13,10 @@ varying highp float v_grid_cell_size;
13
13
  varying highp float v_map_scale_fac;
14
14
 
15
15
  void main() {
16
- gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
16
+ float globe_width = 1.;
17
+ vec2 globe_offset = vec2(globe_width * float(u_offset), 0.);
18
+
19
+ gl_Position = u_matrix * vec4(a_pos + globe_offset, 0.0, 1.0);
17
20
  v_tex_coord = a_tex_coord;
18
21
  v_grid_cell_size = a_grid_cell_size;
19
22
 
@@ -40,16 +43,20 @@ uniform lowp float u_zoom_fac;
40
43
  void main() {
41
44
  highp float field_val = texture2D(u_fill_sampler, v_tex_coord).r;
42
45
 
43
-
46
+ lowp vec2 grid_point = fract(v_tex_coord / u_step_size + vec2(0.5, 0.5));
47
+ highp vec2 grid_sw = v_tex_coord - grid_point * u_step_size;
48
+
44
49
  lowp vec2 ihat = vec2(u_step_size.x, 0.0);
45
50
  lowp vec2 jhat = vec2(0.0, u_step_size.y);
46
- highp float fv_xp1 = texture2D(u_fill_sampler, v_tex_coord + ihat).r;
47
- highp float fv_xm1 = texture2D(u_fill_sampler, v_tex_coord - ihat).r;
48
- highp float fv_yp1 = texture2D(u_fill_sampler, v_tex_coord + jhat).r;
49
- highp float fv_ym1 = texture2D(u_fill_sampler, v_tex_coord - jhat).r;
50
- highp float fwidth_field = sqrt(((fv_xp1 - fv_xm1) * (fv_xp1 - fv_xm1) + (fv_yp1 - fv_ym1) * (fv_yp1 - fv_ym1)) / (5e5 * v_grid_cell_size));
51
+ highp float fv_sw = texture2D(u_fill_sampler, grid_sw).r;
52
+ highp float fv_se = texture2D(u_fill_sampler, grid_sw + ihat).r;
53
+ highp float fv_nw = texture2D(u_fill_sampler, grid_sw + jhat).r;
54
+ highp float fv_ne = texture2D(u_fill_sampler, grid_sw + ihat + jhat).r;
55
+
56
+ highp float dfdx = mix(fv_se, fv_ne, grid_point.y) - mix(fv_sw, fv_nw, grid_point.y);
57
+ highp float dfdy = mix(fv_nw, fv_ne, grid_point.x) - mix(fv_sw, fv_se, grid_point.x);
58
+ highp float fwidth_field = sqrt((dfdx * dfdx + dfdy * dfdy) / (5e5 * v_grid_cell_size));
51
59
 
52
-
53
60
  lowp float plot_val;
54
61
 
55
62
  if (u_num_contours > 0) {
@@ -99,7 +106,7 @@ void main() {
99
106
  }`
100
107
  /**
101
108
  * A field of contoured data. The contours can optionally be thinned based on map zoom level.
102
- * &example
109
+ * @example
103
110
  * // Create a contoured height field, with black contours every 30 m (assuming the height field is in
104
111
  * // meters) and only using every other contour when the map zoom level is less than 5.
105
112
  * const contours = new Contour(height_field, {color: '#000000', interval: 30,
@@ -108,8 +115,8 @@ void main() {
108
115
  class Contour extends PlotComponent {
109
116
  /**
110
117
  * Create a contoured field
111
- * &param field - The field to contour
112
- * &param opts - Options for creating the contours
118
+ * @param field - The field to contour
119
+ * @param opts - Options for creating the contours
113
120
  */
114
121
  constructor(field, opts) {
115
122
  super();
@@ -122,23 +129,21 @@ class Contour extends PlotComponent {
122
129
  this.gl_elems = null;
123
130
  }
124
131
  /**
125
- * &internal
132
+ * @internal
126
133
  * Add the contours to a map
127
134
  */
128
135
  async onAdd(map, gl) {
129
136
  // Basic procedure for these contours from https://www.shadertoy.com/view/lltBWM
130
- gl.getExtension('OES_texture_float');
131
- gl.getExtension('OES_texture_float_linear');
132
- gl.getExtension('OES_standard_derivatives');
137
+ gl.getExtension("OES_standard_derivatives");
133
138
  const program = new WGLProgram(gl, contour_vertex_shader_src, contour_fragment_shader_src);
134
139
  const { vertices: verts_buf, texcoords: tex_coords_buf, cellsize: cellsize_buf } = await this.field.grid.getWGLBuffers(gl);
135
140
  const vertices = verts_buf;
136
141
  const texcoords = tex_coords_buf;
137
142
  const grid_cell_size = cellsize_buf;
138
- const format = isWebGL2Ctx(gl) ? gl.R32F : gl.LUMINANCE;
139
- const fill_image = { 'format': format, 'type': gl.FLOAT,
140
- 'width': this.field.grid.ni, 'height': this.field.grid.nj, 'image': this.field.data,
141
- 'mag_filter': gl.LINEAR,
143
+ const { format, type, row_alignment } = getGLFormatTypeAlignment(gl, this.field.isFloat16());
144
+ const fill_image = { 'format': format, 'type': type,
145
+ 'width': this.field.grid.ni, 'height': this.field.grid.nj, 'image': this.field.getTextureData(),
146
+ 'mag_filter': gl.LINEAR, 'row_alignment': row_alignment,
142
147
  };
143
148
  const fill_texture = new WGLTexture(gl, fill_image);
144
149
  this.gl_elems = {
@@ -146,20 +151,22 @@ class Contour extends PlotComponent {
146
151
  };
147
152
  }
148
153
  /**
149
- * &internal
154
+ * @internal
150
155
  * Render the contours
151
156
  */
152
157
  render(gl, matrix) {
153
158
  if (this.gl_elems === null)
154
159
  return;
155
160
  const gl_elems = this.gl_elems;
161
+ if (matrix instanceof Float32Array)
162
+ matrix = [...matrix];
156
163
  const zoom = gl_elems.map.getZoom();
157
164
  const intv = this.thinner(zoom) * this.interval;
158
- const cutoff = 0.5 / intv;
159
- const step_size = [0.25 / this.field.grid.ni, 0.25 / this.field.grid.nj];
165
+ const cutoff = 0.3 / intv;
166
+ const step_size = [1 / this.field.grid.ni, 1 / this.field.grid.nj];
160
167
  const zoom_fac = Math.pow(2, zoom);
161
168
  let uniforms = { 'u_contour_interval': intv, 'u_line_cutoff': cutoff, 'u_color': this.color, 'u_step_size': step_size, 'u_zoom_fac': zoom_fac,
162
- 'u_matrix': matrix, 'u_num_contours': 0, 'u_contour_levels': [0] };
169
+ 'u_matrix': matrix, 'u_num_contours': 0, 'u_contour_levels': [0], 'u_offset': 0 };
163
170
  if (this.levels.length > 0) {
164
171
  uniforms = { ...uniforms, 'u_num_contours': this.levels.length, 'u_contour_levels': this.levels };
165
172
  }
@@ -167,6 +174,12 @@ class Contour extends PlotComponent {
167
174
  gl.enable(gl.BLEND);
168
175
  gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
169
176
  gl_elems.program.draw();
177
+ gl_elems.program.setUniforms({ 'u_offset': -2 });
178
+ gl_elems.program.draw();
179
+ gl_elems.program.setUniforms({ 'u_offset': -1 });
180
+ gl_elems.program.draw();
181
+ gl_elems.program.setUniforms({ 'u_offset': 1 });
182
+ gl_elems.program.draw();
170
183
  }
171
184
  }
172
185
  export default Contour;
package/lib/Fill.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { PlotComponent } from './PlotComponent';
2
2
  import { ColorMap } from './Colormap';
3
- import { WGLBuffer, WGLProgram, WGLTexture } from 'autumn-wgl';
4
3
  import { RawScalarField } from './RawField';
5
4
  import { MapType } from './Map';
6
- import { WebGLAnyRenderingContext } from './AutumnTypes';
5
+ import { TypedArray, WebGLAnyRenderingContext } from './AutumnTypes';
7
6
  interface ContourFillOptions {
8
7
  /** The color map to use when creating the fills */
9
8
  cmap: ColorMap;
@@ -22,29 +21,18 @@ interface RasterOptions {
22
21
  */
23
22
  opacity?: number;
24
23
  }
25
- interface PlotComponentFillGLElems {
26
- program: WGLProgram;
27
- vertices: WGLBuffer;
28
- fill_texture: WGLTexture;
29
- texcoords: WGLBuffer;
30
- cmap_texture: WGLTexture;
31
- cmap_nonlin_texture: WGLTexture;
32
- }
33
- declare class PlotComponentFill extends PlotComponent {
34
- readonly field: RawScalarField;
24
+ declare class PlotComponentFill<ArrayType extends TypedArray> extends PlotComponent {
25
+ private readonly field;
35
26
  readonly cmap: ColorMap;
36
27
  readonly opacity: number;
37
- /** @private */
38
- readonly cmap_image: HTMLCanvasElement;
39
- /** @private */
40
- readonly index_map: Float32Array;
41
- /** @private */
42
- gl_elems: PlotComponentFillGLElems | null;
43
- image_mag_filter: number | null;
44
- cmap_mag_filter: number | null;
45
- constructor(field: RawScalarField, opts: ContourFillOptions);
28
+ private readonly cmap_image;
29
+ private readonly index_map;
30
+ private gl_elems;
31
+ protected image_mag_filter: number | null;
32
+ protected cmap_mag_filter: number | null;
33
+ constructor(field: RawScalarField<ArrayType>, opts: ContourFillOptions);
46
34
  onAdd(map: MapType, gl: WebGLAnyRenderingContext): Promise<void>;
47
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
35
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
48
36
  }
49
37
  /**
50
38
  * A raster (i.e. pixel) plot
@@ -52,13 +40,13 @@ declare class PlotComponentFill extends PlotComponent {
52
40
  * // Create a raster plot with the provided color map
53
41
  * const raster = new Raster(wind_speed_field, {cmap: color_map});
54
42
  */
55
- declare class Raster extends PlotComponentFill {
43
+ declare class Raster<ArrayType extends TypedArray> extends PlotComponentFill<ArrayType> {
56
44
  /**
57
45
  * Create a raster plot
58
46
  * @param field - The field to create the raster plot from
59
47
  * @param opts - Options for creating the raster plot
60
48
  */
61
- constructor(field: RawScalarField, opts: RasterOptions);
49
+ constructor(field: RawScalarField<ArrayType>, opts: RasterOptions);
62
50
  /**
63
51
  * @internal
64
52
  * Add the raster plot to a map
@@ -68,7 +56,7 @@ declare class Raster extends PlotComponentFill {
68
56
  * @internal
69
57
  * Render the raster plot
70
58
  */
71
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
59
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
72
60
  }
73
61
  /**
74
62
  * A filled contoured field
@@ -76,13 +64,13 @@ declare class Raster extends PlotComponentFill {
76
64
  * // Create a field of filled contours with the provided color map
77
65
  * const fill = new ContourFill(wind_speed_field, {cmap: color_map});
78
66
  */
79
- declare class ContourFill extends PlotComponentFill {
67
+ declare class ContourFill<ArrayType extends TypedArray> extends PlotComponentFill<ArrayType> {
80
68
  /**
81
69
  * Create a filled contoured field
82
70
  * @param field - The field to create filled contours from
83
71
  * @param opts - Options for creating the filled contours
84
72
  */
85
- constructor(field: RawScalarField, opts: ContourFillOptions);
73
+ constructor(field: RawScalarField<ArrayType>, opts: ContourFillOptions);
86
74
  /**
87
75
  * @internal
88
76
  * Add the filled contours to a map
@@ -92,7 +80,7 @@ declare class ContourFill extends PlotComponentFill {
92
80
  * @internal
93
81
  * Render the filled contours
94
82
  */
95
- render(gl: WebGLAnyRenderingContext, matrix: number[]): void;
83
+ render(gl: WebGLAnyRenderingContext, matrix: number[] | Float32Array): void;
96
84
  }
97
85
  export { ContourFill, Raster };
98
86
  export type { ContourFillOptions, RasterOptions };