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.
- package/README.md +6 -11
- package/dist/110.autumnplot-gl.js +1 -1
- package/dist/110.autumnplot-gl.js.map +1 -1
- package/dist/autumnplot-gl.js +1 -1
- package/dist/autumnplot-gl.js.map +1 -1
- package/dist/marchingsquares.wasm +0 -0
- package/lib/AutumnTypes.d.ts +53 -5
- package/lib/AutumnTypes.js +25 -1
- package/lib/Barbs.d.ts +23 -6
- package/lib/Barbs.js +20 -18
- package/lib/BillboardCollection.d.ts +16 -8
- package/lib/BillboardCollection.js +107 -59
- package/lib/Color.d.ts +57 -0
- package/lib/Color.js +163 -0
- package/lib/ColorBar.d.ts +12 -1
- package/lib/ColorBar.js +9 -7
- package/lib/Colormap.d.ts +19 -18
- package/lib/Colormap.js +84 -23
- package/lib/Contour.d.ts +42 -11
- package/lib/Contour.js +67 -58
- package/lib/ContourCreator.d.ts +4 -0
- package/lib/ContourCreator.js +2 -1
- package/lib/Fill.d.ts +27 -16
- package/lib/Fill.js +105 -83
- package/lib/Grid.d.ts +125 -29
- package/lib/Grid.js +303 -95
- package/lib/Hodographs.d.ts +24 -6
- package/lib/Hodographs.js +28 -24
- package/lib/Map.js +1 -1
- package/lib/Paintball.d.ts +6 -5
- package/lib/Paintball.js +38 -32
- package/lib/ParticleTracer.d.ts +19 -0
- package/lib/ParticleTracer.js +37 -0
- package/lib/PlotComponent.d.ts +6 -7
- package/lib/PlotComponent.js +17 -7
- package/lib/PlotLayer.d.ts +4 -4
- package/lib/PlotLayer.worker.d.ts +1 -2
- package/lib/PlotLayer.worker.js +22 -57
- package/lib/PolylineCollection.d.ts +18 -9
- package/lib/PolylineCollection.js +124 -89
- package/lib/RawField.d.ts +76 -23
- package/lib/RawField.js +138 -29
- package/lib/ShaderManager.d.ts +12 -0
- package/lib/ShaderManager.js +58 -0
- package/lib/StationPlot.d.ts +145 -0
- package/lib/StationPlot.js +205 -0
- package/lib/TextCollection.d.ts +12 -8
- package/lib/TextCollection.js +113 -71
- package/lib/cpp/marchingsquares.js +483 -585
- package/lib/cpp/marchingsquares.wasm +0 -0
- package/lib/cpp/marchingsquares_embind.d.ts +23 -3
- package/lib/index.d.ts +7 -4
- package/lib/index.js +5 -3
- package/lib/utils.d.ts +5 -8
- package/lib/utils.js +12 -83
- 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,
|
|
4
|
+
import { getMinZoom, normalizeOptions } from './utils';
|
|
5
5
|
import { ColorMap } from "./Colormap";
|
|
6
|
-
|
|
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 =
|
|
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 -
|
|
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
|
|
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.
|
|
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
|
|
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 => [
|
|
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:
|
|
86
|
-
|
|
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': [[
|
|
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:
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
135
|
-
line_elems.sm_line.render(gl,
|
|
136
|
-
gl_elems.bg_billboard.render(gl,
|
|
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(
|
|
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;
|
package/lib/Paintball.d.ts
CHANGED
|
@@ -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,
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
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
|
-
|
|
8
|
-
|
|
11
|
+
in vec2 a_pos;
|
|
12
|
+
in vec2 a_tex_coord;
|
|
9
13
|
|
|
10
|
-
|
|
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 =
|
|
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 = `#
|
|
23
|
+
const paintball_fragment_shader_src = `#version 300 es
|
|
24
|
+
|
|
25
|
+
#define MAX_N_COLORS 24
|
|
20
26
|
|
|
21
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =>
|
|
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
|
|
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,
|
|
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,
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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 };
|
package/lib/PlotComponent.d.ts
CHANGED
|
@@ -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,
|
|
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,
|
|
17
|
+
abstract render(gl: WebGLAnyRenderingContext, arg: RenderMethodArg): void;
|
|
19
18
|
}
|
|
20
|
-
declare function getGLFormatTypeAlignment(gl: WebGLAnyRenderingContext,
|
|
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 };
|
package/lib/PlotComponent.js
CHANGED
|
@@ -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,
|
|
8
|
+
function getGLFormatTypeAlignment(gl, array_dtype) {
|
|
9
9
|
let format, type, row_alignment;
|
|
10
10
|
const is_webgl2 = isWebGL2Ctx(gl);
|
|
11
|
-
if (
|
|
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 (
|
|
15
|
-
|
|
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 };
|
package/lib/PlotLayer.d.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
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,
|
|
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: {
|