autumnplot-gl 4.0.0-beta → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -207
- package/dist/812.autumnplot-gl.js +2 -0
- package/dist/812.autumnplot-gl.js.map +1 -0
- package/dist/983.autumnplot-gl.js +2 -0
- package/dist/983.autumnplot-gl.js.map +1 -0
- 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 +38 -5
- package/lib/AutumnTypes.js +7 -1
- package/lib/Barbs.d.ts +12 -2
- package/lib/Barbs.js +9 -0
- package/lib/BillboardCollection.d.ts +2 -2
- package/lib/BillboardCollection.js +14 -14
- package/lib/Color.d.ts +1 -0
- package/lib/Color.js +1 -0
- package/lib/ColorBar.d.ts +14 -0
- package/lib/ColorBar.js +15 -8
- package/lib/Colormap.d.ts +9 -1
- package/lib/Colormap.js +24 -1
- package/lib/Contour.d.ts +26 -1
- package/lib/Contour.js +24 -2
- package/lib/ContourCreator.worker.d.ts +25 -0
- package/lib/{ContourCreator.js → ContourCreator.worker.js} +15 -14
- package/lib/Fill.d.ts +31 -11
- package/lib/Fill.js +38 -18
- package/lib/Hodographs.d.ts +19 -3
- package/lib/Hodographs.js +45 -20
- package/lib/Map.d.ts +13 -1
- package/lib/Map.js +62 -8
- package/lib/Paintball.d.ts +14 -5
- package/lib/Paintball.js +96 -46
- package/lib/PlotComponent.d.ts +9 -3
- package/lib/PlotComponent.js +36 -1
- package/lib/PlotLayer.d.ts +2 -2
- package/lib/PlotLayer.js +2 -2
- package/lib/PlotLayer.worker.js +9 -3
- package/lib/RawField.d.ts +223 -27
- package/lib/RawField.js +413 -59
- package/lib/StationPlot.d.ts +78 -11
- package/lib/StationPlot.js +113 -30
- package/lib/TextCollection.d.ts +5 -0
- package/lib/TextCollection.js +82 -9
- package/lib/WasmInterface.d.ts +7 -0
- package/lib/WasmInterface.js +11 -0
- package/lib/WorkerPool.d.ts +8 -0
- package/lib/WorkerPool.js +77 -0
- package/lib/cpp/marchingsquares.js +127 -13
- package/lib/cpp/marchingsquares.wasm +0 -0
- package/lib/cpp/marchingsquares_embind.d.ts +16 -3
- package/lib/grids/AutoZoom.d.ts +21 -0
- package/lib/grids/AutoZoom.js +63 -0
- package/lib/grids/DomainBuffer.d.ts +14 -0
- package/lib/grids/DomainBuffer.js +16 -0
- package/lib/grids/Geostationary.d.ts +35 -0
- package/lib/grids/Geostationary.js +47 -0
- package/lib/grids/Grid.d.ts +36 -0
- package/lib/grids/Grid.js +12 -0
- package/lib/grids/GridCoordinates.d.ts +10 -0
- package/lib/grids/GridCoordinates.js +64 -0
- package/lib/grids/LambertGrid.d.ts +73 -0
- package/lib/grids/LambertGrid.js +92 -0
- package/lib/grids/PlateCarreeGrid.d.ts +46 -0
- package/lib/grids/PlateCarreeGrid.js +55 -0
- package/lib/grids/PlateCarreeRotatedGrid.d.ts +53 -0
- package/lib/grids/PlateCarreeRotatedGrid.js +65 -0
- package/lib/grids/RadarSweepGrid.d.ts +46 -0
- package/lib/grids/RadarSweepGrid.js +74 -0
- package/lib/grids/StructuredGrid.d.ts +49 -0
- package/lib/grids/StructuredGrid.js +103 -0
- package/lib/grids/UnstructuredGrid.d.ts +56 -0
- package/lib/grids/UnstructuredGrid.js +102 -0
- package/lib/index.d.ts +23 -6
- package/lib/index.js +18 -8
- package/lib/utils.d.ts +11 -2
- package/lib/utils.js +63 -1
- package/package.json +4 -3
- package/dist/110.autumnplot-gl.js +0 -2
- package/dist/110.autumnplot-gl.js.map +0 -1
- package/lib/ContourCreator.d.ts +0 -22
- package/lib/Grid.d.ts +0 -263
- package/lib/Grid.js +0 -547
- package/lib/ParticleTracer.d.ts +0 -19
- package/lib/ParticleTracer.js +0 -37
|
Binary file
|
package/lib/AutumnTypes.d.ts
CHANGED
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
import { Float16Array } from "@petamoriken/float16";
|
|
2
|
-
|
|
2
|
+
/** A wind profile with a storm-motion for plotting storm-relative hodographs */
|
|
3
|
+
interface StormRelativeWindProfile {
|
|
4
|
+
/** The grid index in the j direction (ignored for unstructured grids) */
|
|
3
5
|
jlat: number;
|
|
6
|
+
/** The grid index in the i direction */
|
|
4
7
|
ilon: number;
|
|
8
|
+
/** u component of storm motion in kts */
|
|
5
9
|
smu: number;
|
|
10
|
+
/** v component of storm motion in kts */
|
|
6
11
|
smv: number;
|
|
12
|
+
/** Ground-relative u winds in kts (will be converted to storm-relative during plotting) */
|
|
7
13
|
u: Float32Array;
|
|
14
|
+
/** Ground-relative v winds in kts (will be converted to storm-relative during plotting) */
|
|
8
15
|
v: Float32Array;
|
|
16
|
+
/** Height of each data point in km */
|
|
9
17
|
z: Float32Array;
|
|
10
18
|
}
|
|
19
|
+
/** A wind profile without a storm motion for plotting ground-relative hodographs */
|
|
20
|
+
interface GroundRelativeWindProfile {
|
|
21
|
+
/** The grid index in the j direction (ignored for unstructured grids) */
|
|
22
|
+
jlat: number;
|
|
23
|
+
/** The grid index in the i direction */
|
|
24
|
+
ilon: number;
|
|
25
|
+
/** Ground-relative u winds in kts */
|
|
26
|
+
u: Float32Array;
|
|
27
|
+
/** Ground-relative v winds in kts */
|
|
28
|
+
v: Float32Array;
|
|
29
|
+
/** Height of each data point in km */
|
|
30
|
+
z: Float32Array;
|
|
31
|
+
}
|
|
32
|
+
/** Different types of wind profiles for {@link Hodographs} components */
|
|
33
|
+
type WindProfile = StormRelativeWindProfile | GroundRelativeWindProfile;
|
|
34
|
+
declare function isStormRelativeWindProfile(obj: any): obj is StormRelativeWindProfile;
|
|
11
35
|
interface BillboardSpec {
|
|
12
36
|
BB_WIDTH: number;
|
|
13
37
|
BB_HEIGHT: number;
|
|
@@ -30,10 +54,19 @@ type Polyline = {
|
|
|
30
54
|
data?: Float32Array;
|
|
31
55
|
zoom?: Float32Array;
|
|
32
56
|
};
|
|
57
|
+
/** WebGL rendering contexts (either WebGL1 or WebGL2) */
|
|
33
58
|
type WebGLAnyRenderingContext = WebGLRenderingContext | WebGL2RenderingContext;
|
|
34
59
|
declare function isWebGL2Ctx(gl: WebGLAnyRenderingContext): gl is WebGL2RenderingContext;
|
|
35
|
-
|
|
36
|
-
type
|
|
60
|
+
/** Javascript typed arrays for use in raw fields */
|
|
61
|
+
type TypedArray = Float16Array | Float32Array | Uint8Array | Uint16Array | Uint32Array | Int16Array | Int32Array;
|
|
62
|
+
type TypedArrayStr = 'float16' | 'float32' | 'uint8' | 'uint16' | 'uint32' | 'int16' | 'int32';
|
|
63
|
+
type ContourableTypedArray = Float16Array | Float32Array;
|
|
64
|
+
declare function isContourable(ary: any): ary is ContourableTypedArray;
|
|
65
|
+
/**
|
|
66
|
+
* The result of contouring a field
|
|
67
|
+
*
|
|
68
|
+
* Each property is a different contour level giving an array of contours, and each contour is an array of [longitude, latitude].
|
|
69
|
+
*/
|
|
37
70
|
type ContourData = Record<number, [number, number][][]>;
|
|
38
71
|
type mat4 = number[] | Float32Array | Float64Array;
|
|
39
72
|
type RenderShaderData = {
|
|
@@ -84,5 +117,5 @@ type RendererDataAutumn = {
|
|
|
84
117
|
};
|
|
85
118
|
type RendererData = RendererDataMapLibre | RendererDataAutumn;
|
|
86
119
|
declare function getRendererData(arg: RenderMethodArg): RendererData;
|
|
87
|
-
export { isWebGL2Ctx, getRendererData };
|
|
88
|
-
export type { WindProfile, BillboardSpec, Polyline, LineData, WebGLAnyRenderingContext, TypedArray, TypedArrayStr, ContourData, RenderMethodArg, RendererData, RenderShaderData };
|
|
120
|
+
export { isWebGL2Ctx, isContourable, getRendererData, isStormRelativeWindProfile };
|
|
121
|
+
export type { WindProfile, StormRelativeWindProfile, GroundRelativeWindProfile, BillboardSpec, Polyline, LineData, WebGLAnyRenderingContext, TypedArray, TypedArrayStr, ContourableTypedArray, ContourData, RenderMethodArg, RendererData, RenderShaderData };
|
package/lib/AutumnTypes.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
function isStormRelativeWindProfile(obj) {
|
|
2
|
+
return 'smu' in obj && 'smv' in obj;
|
|
3
|
+
}
|
|
1
4
|
function isWebGL2Ctx(gl) {
|
|
2
5
|
return gl.getParameter(gl.VERSION).includes('WebGL 2.0');
|
|
3
6
|
}
|
|
7
|
+
function isContourable(ary) {
|
|
8
|
+
return ary instanceof Uint16Array || ary instanceof Float32Array;
|
|
9
|
+
}
|
|
4
10
|
function isMapLibreRenderArg(obj) {
|
|
5
11
|
return 'modelViewProjectionMatrix' in obj && 'defaultProjectionData' in obj && 'mainMatrix' in obj.defaultProjectionData;
|
|
6
12
|
}
|
|
@@ -25,4 +31,4 @@ function getRendererData(arg) {
|
|
|
25
31
|
}
|
|
26
32
|
return { type: 'autumn', mainMatrix: [...arg], shaderData: null };
|
|
27
33
|
}
|
|
28
|
-
export { isWebGL2Ctx, getRendererData };
|
|
34
|
+
export { isWebGL2Ctx, isContourable, getRendererData, isStormRelativeWindProfile };
|
package/lib/Barbs.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ import { RawVectorField } from "./RawField";
|
|
|
3
3
|
import { MapLikeType } from "./Map";
|
|
4
4
|
import { RenderMethodArg, TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
|
|
5
5
|
import { ColorMap } from "./Colormap";
|
|
6
|
-
import {
|
|
6
|
+
import { AutoZoomGrid } from "./grids/AutoZoom";
|
|
7
|
+
/** Options for {@link Barbs} components */
|
|
7
8
|
interface BarbsOptions {
|
|
8
9
|
/**
|
|
9
10
|
* The color to use for the barbs as a hex color string;.
|
|
@@ -34,12 +35,21 @@ interface BarbsOptions {
|
|
|
34
35
|
/**
|
|
35
36
|
* 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
|
|
36
37
|
* thinning factor at zoom level 1.
|
|
38
|
+
*
|
|
39
|
+
* ## Grid Compatibility
|
|
40
|
+
* - :white_check_mark: `PlateCarreeGrid`
|
|
41
|
+
* - :white_check_mark: `PlateCarreeRotatedGrid`
|
|
42
|
+
* - :white_check_mark: `LambertGrid`
|
|
43
|
+
* - :white_check_mark: `UnstructuredGrid`
|
|
44
|
+
* - :x: `RadarSweepGrid`
|
|
45
|
+
* - :x: `Geostationary`
|
|
46
|
+
*
|
|
37
47
|
* @example
|
|
38
48
|
* // Create a barb field with black barbs and plotting every 16th wind barb in both i and j at zoom level 1
|
|
39
49
|
* const vector_field = new RawVectorField(grid, u_data, v_data);
|
|
40
50
|
* const barbs = new Barbs(vector_field, {color: '#000000', thin_fac: 16});
|
|
41
51
|
*/
|
|
42
|
-
declare class Barbs<ArrayType extends TypedArray, GridType extends
|
|
52
|
+
declare class Barbs<ArrayType extends TypedArray, GridType extends AutoZoomGrid, MapType extends MapLikeType> extends PlotComponent<MapType> {
|
|
43
53
|
/** The vector field */
|
|
44
54
|
private fields;
|
|
45
55
|
readonly opts: Required<BarbsOptions>;
|
package/lib/Barbs.js
CHANGED
|
@@ -108,6 +108,15 @@ const barb_opt_defaults = {
|
|
|
108
108
|
/**
|
|
109
109
|
* 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
|
|
110
110
|
* thinning factor at zoom level 1.
|
|
111
|
+
*
|
|
112
|
+
* ## Grid Compatibility
|
|
113
|
+
* - :white_check_mark: `PlateCarreeGrid`
|
|
114
|
+
* - :white_check_mark: `PlateCarreeRotatedGrid`
|
|
115
|
+
* - :white_check_mark: `LambertGrid`
|
|
116
|
+
* - :white_check_mark: `UnstructuredGrid`
|
|
117
|
+
* - :x: `RadarSweepGrid`
|
|
118
|
+
* - :x: `Geostationary`
|
|
119
|
+
*
|
|
111
120
|
* @example
|
|
112
121
|
* // Create a barb field with black barbs and plotting every 16th wind barb in both i and j at zoom level 1
|
|
113
122
|
* const vector_field = new RawVectorField(grid, u_data, v_data);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BillboardSpec, RenderMethodArg, TypedArray, WebGLAnyRenderingContext } from "./AutumnTypes";
|
|
2
2
|
import { Color } from "./Color";
|
|
3
3
|
import { ColorMap } from "./Colormap";
|
|
4
|
-
import {
|
|
4
|
+
import { AutoZoomGrid } from "./grids/AutoZoom";
|
|
5
5
|
import { RawVectorField } from "./RawField";
|
|
6
6
|
import { WGLTextureSpec } from "autumn-wgl";
|
|
7
7
|
interface BillboardCollectionOpts {
|
|
@@ -9,7 +9,7 @@ interface BillboardCollectionOpts {
|
|
|
9
9
|
cmap?: ColorMap;
|
|
10
10
|
rotate_with_map?: boolean;
|
|
11
11
|
}
|
|
12
|
-
declare class BillboardCollection<ArrayType extends TypedArray, GridType extends
|
|
12
|
+
declare class BillboardCollection<ArrayType extends TypedArray, GridType extends AutoZoomGrid> {
|
|
13
13
|
private field;
|
|
14
14
|
readonly spec: BillboardSpec;
|
|
15
15
|
readonly color: Color;
|
|
@@ -3,6 +3,7 @@ import { Color } from "./Color";
|
|
|
3
3
|
import { ColorMapGPUInterface } from "./Colormap";
|
|
4
4
|
import { WGLBuffer, WGLTexture } from "autumn-wgl";
|
|
5
5
|
import { ShaderProgramManager } from "./ShaderManager";
|
|
6
|
+
import { applySamplerCodeVector } from "./utils";
|
|
6
7
|
const billboard_vertex_shader_src = `#version 300 es
|
|
7
8
|
|
|
8
9
|
uniform int u_offset;
|
|
@@ -19,8 +20,6 @@ uniform highp float u_bb_mag_bin_size;
|
|
|
19
20
|
uniform highp float u_bb_mag_wrap;
|
|
20
21
|
uniform int u_rotate_with_map;
|
|
21
22
|
|
|
22
|
-
uniform sampler2D u_u_sampler;
|
|
23
|
-
uniform sampler2D u_v_sampler;
|
|
24
23
|
uniform sampler2D u_rot_sampler;
|
|
25
24
|
|
|
26
25
|
out highp vec2 v_tex_coord;
|
|
@@ -77,8 +76,8 @@ void main() {
|
|
|
77
76
|
vec2 data_texcoord = a_tex_coord;
|
|
78
77
|
data_texcoord.x = fract(data_texcoord.x);
|
|
79
78
|
|
|
80
|
-
highp float u =
|
|
81
|
-
highp float v =
|
|
79
|
+
highp float u = get_field_value_u(data_texcoord);
|
|
80
|
+
highp float v = get_field_value_v(data_texcoord);
|
|
82
81
|
highp float rot = texture(u_rot_sampler, data_texcoord).r;
|
|
83
82
|
|
|
84
83
|
lowp float bb_aspect = u_bb_width / u_bb_height;
|
|
@@ -168,14 +167,7 @@ class BillboardCollection {
|
|
|
168
167
|
return;
|
|
169
168
|
const gl = this.gl_elems.gl;
|
|
170
169
|
const data = this.field.getThinnedField(this.thin_fac, this.max_zoom);
|
|
171
|
-
|
|
172
|
-
if (this.wind_textures === null) {
|
|
173
|
-
this.wind_textures = { u: new WGLTexture(gl, u_image), v: new WGLTexture(gl, v_image) };
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
this.wind_textures.u.setImageData(u_image);
|
|
177
|
-
this.wind_textures.v.setImageData(v_image);
|
|
178
|
-
}
|
|
170
|
+
this.wind_textures = data.updateTexImageData(gl, gl.NEAREST, this.wind_textures);
|
|
179
171
|
}
|
|
180
172
|
async setup(gl) {
|
|
181
173
|
const thinned_grid = this.field.grid.getThinnedGrid(this.thin_fac, this.max_zoom);
|
|
@@ -193,7 +185,10 @@ class BillboardCollection {
|
|
|
193
185
|
cmap_gpu.setupShaderVariables(gl, gl.NEAREST);
|
|
194
186
|
shader_defines.push('COLORMAP');
|
|
195
187
|
}
|
|
196
|
-
const
|
|
188
|
+
const sampler_keys = this.field.getSamplerIds();
|
|
189
|
+
const sampler_expressions = this.field.getExpressions();
|
|
190
|
+
const vertex_shader_src = applySamplerCodeVector(billboard_vertex_shader_src, sampler_keys, sampler_expressions);
|
|
191
|
+
const shader_manager = new ShaderProgramManager(vertex_shader_src, fragment_src, shader_defines);
|
|
197
192
|
this.gl_elems = { gl: gl, shader_manager: shader_manager, geom_vertices: geom_buffer, vertices: vertices, texcoords: texcoords, texture: texture,
|
|
198
193
|
proj_rot_texture: proj_rotation_tex, cmap_gpu: cmap_gpu };
|
|
199
194
|
}
|
|
@@ -206,10 +201,15 @@ class BillboardCollection {
|
|
|
206
201
|
const bb_size = this.spec.BB_HEIGHT * (map_height / map_width) * this.size_multiplier;
|
|
207
202
|
const bb_width = this.spec.BB_WIDTH / this.spec.BB_TEX_WIDTH;
|
|
208
203
|
const bb_height = this.spec.BB_HEIGHT / this.spec.BB_TEX_HEIGHT;
|
|
204
|
+
const samplers = {
|
|
205
|
+
'u_sampler': gl_elems.texture, 'u_rot_sampler': gl_elems.proj_rot_texture,
|
|
206
|
+
...Object.fromEntries([...this.wind_textures.u.entries()]),
|
|
207
|
+
...Object.fromEntries([...this.wind_textures.v.entries()])
|
|
208
|
+
};
|
|
209
209
|
program.use({ 'a_geom': gl_elems.geom_vertices, 'a_pos': gl_elems.vertices, 'a_tex_coord': gl_elems.texcoords }, { 'u_bb_size': bb_size, 'u_bb_width': bb_width, 'u_bb_height': bb_height,
|
|
210
210
|
'u_bb_mag_bin_size': this.spec.BB_MAG_BIN_SIZE, 'u_bb_mag_wrap': this.spec.BB_MAG_WRAP, 'u_offset': 0,
|
|
211
211
|
'u_map_aspect': map_height / map_width, 'u_zoom': map_zoom, 'u_rotate_with_map': this.rotate_with_map ? 1 : 0,
|
|
212
|
-
...this.gl_elems.shader_manager.getShaderUniforms(render_data) },
|
|
212
|
+
...this.gl_elems.shader_manager.getShaderUniforms(render_data) }, samplers);
|
|
213
213
|
if (gl_elems.cmap_gpu !== null) {
|
|
214
214
|
gl_elems.cmap_gpu.bindShaderVariables(program);
|
|
215
215
|
}
|
package/lib/Color.d.ts
CHANGED
package/lib/Color.js
CHANGED
package/lib/ColorBar.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ColorMap } from "./Colormap";
|
|
2
2
|
import { Color } from "./Color";
|
|
3
|
+
/** The orientation for color bars (horizontal or vertical) */
|
|
3
4
|
type ColorbarOrientation = 'horizontal' | 'vertical';
|
|
5
|
+
/** Which side of a color bar the ticks are on */
|
|
4
6
|
type ColorbarTickDirection = 'top' | 'bottom' | 'left' | 'right';
|
|
7
|
+
/** Options for {@link makeColorBar} */
|
|
5
8
|
interface ColorBarOptions {
|
|
6
9
|
/** The label to place along the color bar */
|
|
7
10
|
label?: string;
|
|
@@ -41,6 +44,11 @@ interface ColorBarOptions {
|
|
|
41
44
|
* @default 12
|
|
42
45
|
*/
|
|
43
46
|
ticklabelsize?: number;
|
|
47
|
+
/**
|
|
48
|
+
* The color for the color bar outline and the text
|
|
49
|
+
* @default '#000000'
|
|
50
|
+
*/
|
|
51
|
+
outline_and_text_color?: string;
|
|
44
52
|
}
|
|
45
53
|
/**
|
|
46
54
|
* Make an SVG containing a color bar. The color bar can either be oriented horizontal or vertical, and a label can be provided.
|
|
@@ -56,12 +64,18 @@ interface ColorBarOptions {
|
|
|
56
64
|
* document.getElementById('colorbar-container').appendChild(svg);
|
|
57
65
|
*/
|
|
58
66
|
declare function makeColorBar(colormap: ColorMap, opts: ColorBarOptions): SVGElement;
|
|
67
|
+
/** Options for {@link makePaintballKey | makePaintballKey()} */
|
|
59
68
|
interface PaintballKeyOptions {
|
|
60
69
|
/**
|
|
61
70
|
* The number of columns of entries in the key
|
|
62
71
|
* @default 1
|
|
63
72
|
*/
|
|
64
73
|
n_cols?: number;
|
|
74
|
+
/**
|
|
75
|
+
* The space allocated for the text for each color swatch in pixels
|
|
76
|
+
* @default 100
|
|
77
|
+
*/
|
|
78
|
+
swatch_text_space?: number;
|
|
65
79
|
/**
|
|
66
80
|
* A font face to use for the label and tick values.
|
|
67
81
|
* @default 'sans-serif'
|
package/lib/ColorBar.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeOptions } from "./utils";
|
|
1
2
|
;
|
|
2
3
|
const createElement = (tagname, attributes, parent) => {
|
|
3
4
|
const elem = document.createElementNS('http://www.w3.org/2000/svg', tagname);
|
|
@@ -32,6 +33,7 @@ function makeColorBar(colormap, opts) {
|
|
|
32
33
|
const tickfontsize = opts.ticklabelsize || 12;
|
|
33
34
|
const size_long = opts.size_long || 600;
|
|
34
35
|
const size_short = opts.size_short || size_long / 9;
|
|
36
|
+
const outline_and_text_color = opts.outline_and_text_color || '#000000';
|
|
35
37
|
const tick_dir = opts.tick_direction || (orientation == 'vertical' ? 'left' : 'bottom');
|
|
36
38
|
if (orientation == 'vertical' && (tick_dir == 'top' || tick_dir == 'bottom') ||
|
|
37
39
|
orientation == 'horizontal' && (tick_dir == 'left' || tick_dir == 'right')) {
|
|
@@ -143,7 +145,7 @@ function makeColorBar(colormap, opts) {
|
|
|
143
145
|
else {
|
|
144
146
|
lineattrs = tick_dir == 'bottom' ? { y2: 6 } : { y2: -6 };
|
|
145
147
|
}
|
|
146
|
-
createElement('line', { ...lineattrs, stroke:
|
|
148
|
+
createElement('line', { ...lineattrs, stroke: outline_and_text_color, 'stroke-width': 1.5 }, gtick);
|
|
147
149
|
let textattrs;
|
|
148
150
|
if (orientation == 'vertical') {
|
|
149
151
|
textattrs = tick_dir == 'left' ? { x: -9, dy: '0.32em' } : { x: 9, dy: '0.32em' };
|
|
@@ -151,7 +153,7 @@ function makeColorBar(colormap, opts) {
|
|
|
151
153
|
else {
|
|
152
154
|
textattrs = tick_dir == 'bottom' ? { y: 9, dy: '0.8em' } : { y: -9, dy: '0em' };
|
|
153
155
|
}
|
|
154
|
-
const text = createElement('text', { ...textattrs, fill:
|
|
156
|
+
const text = createElement('text', { ...textattrs, fill: outline_and_text_color, style: `font-family: ${fontface}; font-size: ${tickfontsize}pt` }, gtick);
|
|
155
157
|
text.textContent = level.toString();
|
|
156
158
|
});
|
|
157
159
|
// Draw the outline
|
|
@@ -166,7 +168,7 @@ function makeColorBar(colormap, opts) {
|
|
|
166
168
|
}
|
|
167
169
|
const outline_attrs = {
|
|
168
170
|
points: point_list,
|
|
169
|
-
stroke:
|
|
171
|
+
stroke: outline_and_text_color,
|
|
170
172
|
'stroke-width': 1.5,
|
|
171
173
|
fill: 'none'
|
|
172
174
|
};
|
|
@@ -179,10 +181,15 @@ function makeColorBar(colormap, opts) {
|
|
|
179
181
|
else {
|
|
180
182
|
labelattrs = tick_dir == 'bottom' ? { transform: `translate(${width / 2}, ${height - 5})` } : { transform: `translate(${width / 2}, 15)` };
|
|
181
183
|
}
|
|
182
|
-
const label_elem = createElement('text', { ...labelattrs, fill:
|
|
184
|
+
const label_elem = createElement('text', { ...labelattrs, fill: outline_and_text_color, 'text-anchor': 'middle', style: `font-family: ${fontface};` }, root);
|
|
183
185
|
label_elem.textContent = label;
|
|
184
186
|
return root;
|
|
185
187
|
}
|
|
188
|
+
const paintball_key_opt_defaults = {
|
|
189
|
+
n_cols: 1,
|
|
190
|
+
swatch_text_space: 100,
|
|
191
|
+
fontface: 'sans-serif',
|
|
192
|
+
};
|
|
186
193
|
/**
|
|
187
194
|
* Make an SVG containing a color key for a paintball plot. The key can be split over any number of columns.
|
|
188
195
|
* @param colors - A list of colors
|
|
@@ -200,16 +207,16 @@ function makePaintballKey(colors, labels, opts) {
|
|
|
200
207
|
if (colors.length != labels.length) {
|
|
201
208
|
throw `Mismatch between the number of colors (${colors.length}) and the number of labels (${labels.length})`;
|
|
202
209
|
}
|
|
203
|
-
|
|
204
|
-
const n_cols = opts.n_cols === undefined ? 1 : opts.n_cols;
|
|
205
|
-
const fontface = opts.fontface === undefined ? 'sans-serif' : opts.fontface;
|
|
210
|
+
const opts_ = normalizeOptions(opts, paintball_key_opt_defaults);
|
|
206
211
|
let height, width;
|
|
207
212
|
const swatch_width = 20;
|
|
208
213
|
const swatch_height = 20;
|
|
209
214
|
const swatch_text_pad = 3;
|
|
210
|
-
const swatch_text_space =
|
|
215
|
+
const swatch_text_space = opts_.swatch_text_space;
|
|
211
216
|
const swatch_width_pad = 5;
|
|
212
217
|
const swatch_height_pad = 5;
|
|
218
|
+
const n_cols = opts_.n_cols;
|
|
219
|
+
const fontface = opts_.fontface;
|
|
213
220
|
const n_rows = Math.ceil(colors.length / n_cols);
|
|
214
221
|
width = (swatch_width + swatch_text_pad + swatch_text_space) * n_cols + swatch_width_pad * (n_cols + 1);
|
|
215
222
|
height = swatch_height * n_rows + swatch_height_pad * (n_rows + 1);
|
package/lib/Colormap.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { WGLProgram, WGLTexture } from "autumn-wgl";
|
|
2
2
|
import { WebGLAnyRenderingContext } from "./AutumnTypes";
|
|
3
3
|
import { Color } from "./Color";
|
|
4
|
+
/** Options for {@link ColorMap}s */
|
|
4
5
|
interface ColorMapOptions {
|
|
5
6
|
/** The color to use for areas where the value is above the highest value in the color map */
|
|
6
7
|
overflow_color?: Color | string;
|
|
@@ -28,6 +29,12 @@ declare class ColorMap {
|
|
|
28
29
|
* @returns an array of opacities, one for each color in the color map
|
|
29
30
|
*/
|
|
30
31
|
getOpacities(): number[];
|
|
32
|
+
/**
|
|
33
|
+
* Sample from the color map
|
|
34
|
+
* @param val - The value to sample from the color map
|
|
35
|
+
* @returns A color as an RGBA hex string
|
|
36
|
+
*/
|
|
37
|
+
getColor(val: number): string;
|
|
31
38
|
/**
|
|
32
39
|
* Make a new color map with different opacities. The opacities are set by func.
|
|
33
40
|
* @param func - A function which takes the two levels associated with a color (an upper and lower bound) and returns an opacity in the range from 0 to 1.
|
|
@@ -51,6 +58,7 @@ declare const pw_cape: ColorMap;
|
|
|
51
58
|
declare const pw_t2m: ColorMap;
|
|
52
59
|
declare const pw_td2m: ColorMap;
|
|
53
60
|
declare const nws_storm_clear_refl: ColorMap;
|
|
61
|
+
declare const wv_cimss: ColorMap;
|
|
54
62
|
/**
|
|
55
63
|
* Create a diverging red/blue colormap, where red corresponds to the lowest value and blue corresponds to the highest value
|
|
56
64
|
* @param level_min - The lowest value in the color map
|
|
@@ -79,5 +87,5 @@ declare class ColorMapGPUInterface {
|
|
|
79
87
|
setupShaderVariables(gl: WebGLAnyRenderingContext, mag_filter: number): void;
|
|
80
88
|
bindShaderVariables(program: WGLProgram): void;
|
|
81
89
|
}
|
|
82
|
-
export { ColorMap, ColorMapGPUInterface, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m, nws_storm_clear_refl };
|
|
90
|
+
export { ColorMap, ColorMapGPUInterface, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m, nws_storm_clear_refl, wv_cimss };
|
|
83
91
|
export type { ColorMapOptions };
|
package/lib/Colormap.js
CHANGED
|
@@ -4,6 +4,7 @@ const cape_colormap_data = { "levels": [0, 100, 200, 300, 400, 500, 600, 700
|
|
|
4
4
|
const t2m_colormap_data = { "levels": [-60, -59, -58, -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120], "colors": [ "#235877", "#2a5f7c", "#316782", "#396e87", "#40768c", "#477d91", "#4e8497", "#558c9c", "#5d93a1", "#649ba6", "#6ba2ac", "#72a9b1", "#79b1b6", "#81b8bb", "#88c0c1", "#8fc7c6", "#96cecb", "#9dd6d0", "#a5ddd6", "#ace5db", "#b3ece0", "#b3ece0", "#b1e7df", "#b0e1dd", "#aedcdc", "#add7da", "#abd2d9", "#aaccd8", "#a8c7d6", "#a7c2d5", "#a5bcd4", "#a4b7d2", "#a2b2d1", "#9fa7ce", "#9ea2cd", "#9c9dcb", "#9c9dcb", "#9b97ca", "#9992c8", "#988dc7", "#9688c6", "#9582c4", "#9278c2", "#9073c0", "#8f6dbf", "#8d68bd", "#8c63bc", "#8a5dbb", "#8958b9", "#8753b8", "#864eb6", "#8448b5", "#8343b4", "#813eb2", "#8038b1", "#7e33b0", "#7d33ae", "#7b29ad", "#7a23ab", "#781eaa", "#a037af", "#a443b3", "#a74fb7", "#ab5cbb", "#af68bf", "#b374c3", "#b680c7", "#ba8dcc", "#be99d0", "#c1a5d4", "#c5b1d8", "#c9bddc", "#cdcae0", "#d0d6e4", "#d4e2e8", "#deecf2", "#d1e2ee", "#c5d9ea", "#b8cfe6", "#acc5e3", "#9fbbdf", "#92b2db", "#86a8d7", "#799ed3", "#6c94cf", "#608bcb", "#5381c7", "#4777c4", "#3a6dc0", "#2d64bc", "#215ab8", "#1450b4", "#0f4455", "#1c4e5a", "#2a585f", "#376363", "#456d68", "#52776d", "#5f8172", "#6d8c77", "#7a967c", "#88a080", "#95aa85", "#a3b58a", "#b0bf8f", "#bdc994", "#cbd399", "#d8de9d", "#e6e8a2", "#f3f2a7", "#f8eea2", "#f0e199", "#e8d591", "#e1c888", "#d9bc80", "#d1af77", "#c9a36f", "#c19666", "#ba8a5e", "#b27d55", "#aa714d", "#a26444", "#9b583c", "#8b3f2b", "#833222", "#7b261a", "#7b261a", "#741911", "#6c0d09", "#640000", "#5f0000", "#630507", "#670a0e", "#6c0f15", "#70141c", "#741824", "#781d2b", "#7d2232", "#812739", "#852c40", "#73372d", "#7a4036", "#80493f", "#875349", "#8e5c52", "#94655b", "#9b6e64", "#a88177", "#af8a80", "#b69389", "#bd9c92", "#c3a69c", "#caafa5", "#d1b8ae", "#d7c1b7", "#decac0", "#e5d4ca", "#ebddd3", "#f2e6dc", "#e8dfd6", "#e0d7cf", "#d8d0c8", "#d0c8c0", "#c8c0b9", "#c0b9b2", "#b7b1ab", "#afa9a4", "#a7a29c", "#9f9a95", "#97938e", "#8f8b87", "#878380", "#7f7c78", "#777471", "#6f6c6a", "#666563", "#5e5d5c", "#565554", "#4e4e4d", "#464646" ] }
|
|
5
5
|
const td2m_colormap_data = { "levels": [-40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90], "colors": [ "#986d4d", "#966c4c", "#946b4c", "#926a4b", "#90694b", "#8e684a", "#8c664a", "#8a6549", "#886448", "#866348", "#846247", "#826147", "#806046", "#7e5f46", "#7c5e45", "#7a5d44", "#785b44", "#765a43", "#745943", "#725842", "#715742", "#6f5641", "#6d5540", "#6b5440", "#69533f", "#67523f", "#65503e", "#634f3d", "#614e3d", "#5f4d3c", "#5d4c3c", "#5b4b3b", "#594a3b", "#57493a", "#554839", "#534739", "#514538", "#4f4438", "#4d4337", "#4b4237", "#494136", "#4d4334", "#514738", "#564c3c", "#5a5041", "#5e5545", "#625949", "#675e4d", "#6b6251", "#6f6755", "#746b5a", "#78705e", "#7c7462", "#807966", "#857d6a", "#89826f", "#8d8673", "#928b77", "#968f7b", "#9a947f", "#9e9883", "#a39d88", "#a7a18c", "#aba690", "#afaa94", "#b8b39c", "#b8b39c", "#bcb8a1", "#c1bca5", "#c9c5ad", "#c9cab1", "#d2ceb6", "#d2ceb6", "#d6d3ba", "#dfdcc2", "#e3e0c6", "#e7e5ca", "#ebe9cf", "#f0eed3", "#f4f2d7", "#e6f5e6", "#d7f0d7", "#c8eac8", "#b9e5b9", "#aadfaa", "#9bda9b", "#8cd48c", "#7dcf7d", "#6ec96e", "#5fc45f", "#30ae30", "#2ca32c", "#279927", "#238e23", "#1e831e", "#1a791a", "#156e15", "#116311", "#0c590c", "#084e08", "#61a3af", "#5896a0", "#508992", "#477b83", "#3e6e74", "#366166", "#2d5457", "#244648", "#1c393a", "#132c2b", "#66669a", "#605e94", "#59568e", "#534e88", "#4d4682", "#463e7c", "#403676", "#3a2e70", "#33266a", "#2d1e64", "#724071", "#784573", "#7d4b75", "#835076", "#885678", "#8e5b7a", "#93617c", "#99667d", "#9e6c7f", "#a47181" ] }
|
|
6
6
|
const nws_storm_clear_refl_colormap_data = { "levels": [ -15, -14.53608247, -14.07216495, -13.60824742, -13.1443299, -12.68041237, -12.21649485, -11.75257732, -11.28865979, -10.82474227, -10.36082474, -9.89690722, -9.43298969, -8.96907216, -8.50515464, -8.04123711, -7.57731959, -7.11340206, -6.64948454, -6.18556701, -5.72164948, -5.25773196, -4.79381443, -4.32989691, -3.86597938, -3.40206186, -2.93814433, -2.4742268, -2.01030928, -1.54639175, -1.08247423, -0.6185567, -0.15463918, 0.30927835, 0.77319588, 1.2371134, 1.70103093, 2.16494845, 2.62886598, 3.09278351, 3.55670103, 4.02061856, 4.48453608, 4.94845361, 5.41237113, 5.87628866, 6.34020619, 6.80412371, 7.26804124, 7.73195876, 8.19587629, 8.65979381, 9.12371134, 9.58762887, 10.05154639, 10.51546392, 10.97938144, 11.44329897, 11.90721649, 12.37113402, 12.83505155, 13.29896907, 13.7628866, 14.22680412, 14.69072165, 15.15463918, 15.6185567, 16.08247423, 16.54639175, 17.01030928, 17.4742268, 17.93814433, 18.40206186, 18.86597938, 19.32989691, 19.79381443, 20.25773196, 20.72164948, 21.18556701, 21.64948454, 22.11340206, 22.57731959, 23.04123711, 23.50515464, 23.96907216, 24.43298969, 24.89690722, 25.36082474, 25.82474227, 26.28865979, 26.75257732, 27.21649485, 27.68041237, 28.1443299, 28.60824742, 29.07216495, 29.53608247, 30, 30.46391753, 30.92783505, 31.39175258, 31.8556701, 32.31958763, 32.78350515, 33.24742268, 33.71134021, 34.17525773, 34.63917526, 35.10309278, 35.56701031, 36.03092784, 36.49484536, 36.95876289, 37.42268041, 37.88659794, 38.35051546, 38.81443299, 39.27835052, 39.74226804, 40.20618557, 40.67010309, 41.13402062, 41.59793814, 42.06185567, 42.5257732, 42.98969072, 43.45360825, 43.91752577, 44.3814433, 44.84536082, 45.30927835, 45.77319588, 46.2371134, 46.70103093, 47.16494845, 47.62886598, 48.09278351, 48.55670103, 49.02061856, 49.48453608, 49.94845361, 50.41237113, 50.87628866, 51.34020619, 51.80412371, 52.26804124, 52.73195876, 53.19587629, 53.65979381, 54.12371134, 54.58762887, 55.05154639, 55.51546392, 55.97938144, 56.44329897, 56.90721649, 57.37113402, 57.83505155, 58.29896907, 58.7628866, 59.22680412, 59.69072165, 60.15463918, 60.6185567, 61.08247423, 61.54639175, 62.01030928, 62.4742268, 62.93814433, 63.40206186, 63.86597938, 64.32989691, 64.79381443, 65.25773196, 65.72164948, 66.18556701, 66.64948454, 67.11340206, 67.57731959, 68.04123711, 68.50515464, 68.96907216, 69.43298969, 69.89690722, 70.36082474, 70.82474227, 71.28865979, 71.75257732, 72.21649485, 72.68041237, 73.1443299, 73.60824742, 74.07216495, 74.53608247, 75 ], "colors": [ "#959052", "#979356", "#9c9a60", "#a09c64", "#a3a067", "#a8a570", "#aaa875", "#acac79", "#b1b182", "#b5b587", "#b6b88c", "#bcbd93", "#bfc199", "#c1c39c", "#c1c39c", "#c6caa5", "#cacdaa", "#cccfaf", "#cfd1b3", "#cccfb3", "#c8ccb3", "#c6c8b3", "#bfc3b3", "#bfc3b3", "#bcc1b3", "#b8bdb3", "#b5bab3", "#afb5b3", "#acb3b3", "#aaafb3", "#a7aeb3", "#a3aab3", "#a0a8b3", "#9ca5b3", "#9aa1b3", "#97a0b3", "#939cb3", "#909ab3", "#939ab5", "#8c95b3", "#8791b1", "#838eb1", "#808caf", "#7c89af", "#7785ae", "#7482ac", "#7080aa", "#6b7caa", "#6275a8", "#5e72a7", "#5e72a7", "#5b70a5", "#566da3", "#5269a3", "#4f67a1", "#4b64a1", "#4660a0", "#425d9e", "#4260a1", "#4467a5", "#486eaa", "#4975ae", "#4d7cb1", "#4f83b5", "#508aba", "#5491bf", "#5699c3", "#599ec6", "#5ba5ca", "#5daccf", "#60b3d4", "#62bad8", "#64c1db", "#67c8df", "#69cfe4", "#6ed6e8", "#67d6d6", "#60d6c4", "#59d6b3", "#52d6a1", "#4bd690", "#42d67e", "#3bd66d", "#34d65b", "#11d418", "#11d116", "#0fcd16", "#0fc816", "#0fc316", "#0fbf15", "#0fbc15", "#0fb613", "#0eb313", "#0eaf13", "#0eaa13", "#0ca511", "#0ca111", "#0c9e11", "#0c9911", "#0c950f", "#0c900f", "#0a8c0f", "#0a870f", "#0a830e", "#0a800e", "#0a7c0c", "#0a770c", "#08720c", "#086e0c", "#086b0a", "#08660a", "#08620a", "#085d08", "#1c6708", "#317208", "#467c08", "#5b8707", "#6e9107", "#839c05", "#97a805", "#acb105", "#c1bc05", "#d6c603", "#e9d103", "#ffe200", "#ffd800", "#ffd300", "#ffc800", "#ffc300", "#ffba00", "#ffb500", "#ffb000", "#ffac00", "#ffa700", "#ff9e00", "#ff9900", "#ff9300", "#ff8900", "#ff8500", "#ff7f00", "#ff0000", "#f70000", "#f00000", "#e90000", "#e20000", "#db0000", "#d40000", "#cd0000", "#c60000", "#bf0000", "#b80000", "#b10000", "#aa0000", "#a30000", "#9a0000", "#930000", "#8c0000", "#850000", "#7e0000", "#770000", "#700000", "#ffffff", "#fff4ff", "#ffe9ff", "#ffdfff", "#ffd4ff", "#ffc8ff", "#ffbdff", "#ffb3ff", "#ffa8ff", "#ff9cff", "#ff91ff", "#ff75ff", "#fb6bfd", "#f960f9", "#f656f6", "#f24bf4", "#ef3ff0", "#ed36ef", "#e92aeb", "#e61fe8", "#e416e6", "#e10ae2", "#b100ff", "#ac00fb", "#a300f6", "#9a00f4", "#9300ef", "#8700e9", "#8200e8", "#7900e2", "#7200dd", "#6900db", "#6200d6" ] }
|
|
7
|
+
const wv_cimss_data = { "levels": [ 164, 164.75694444, 165.51388889, 166.27083333, 167.02777778, 167.78472222, 168.54166667, 169.29861111, 170.05555556, 170.8125, 171.56944444, 172.32638889, 173.08333333, 173.84027778, 174.59722222, 175.35416667, 176.11111111, 176.86805556, 177.625, 178.38194444, 179.13888889, 179.89583333, 180.65277778, 181.40972222, 182.16666667, 182.92361111, 183.68055556, 184.4375, 185.19444444, 185.95138889, 186.70833333, 187.46527778, 188.22222222, 188.97916667, 189.73611111, 190.49305556, 191.25, 192.00694444, 192.76388889, 193.52083333, 194.27777778, 195.03472222, 195.79166667, 196.54861111, 197.30555556, 198.0625, 198.81944444, 199.57638889, 200.33333333, 201.09027778, 201.84722222, 202.60416667, 203.36111111, 204.11805556, 204.875, 205.63194444, 206.38888889, 207.14583333, 207.90277778, 208.65972222, 209.41666667, 210.17361111, 210.93055556, 211.6875, 212.44444444, 213.20138889, 213.95833333, 214.71527778, 215.47222222, 216.22916667, 216.98611111, 217.74305556, 218.5, 219.25694444, 220.01388889, 220.77083333, 221.52777778, 222.28472222, 223.04166667, 223.79861111, 224.55555556, 225.3125, 226.06944444, 226.82638889, 227.58333333, 228.34027778, 229.09722222, 229.85416667, 230.61111111, 231.36805556, 232.125, 232.88194444, 233.63888889, 234.39583333, 235.15277778, 235.90972222, 236.66666667, 237.42361111, 238.18055556, 238.9375, 239.69444444, 240.45138889, 241.20833333, 241.96527778, 242.72222222, 243.47916667, 244.23611111, 244.99305556, 245.75, 246.50694444, 247.26388889, 248.02083333, 248.77777778, 249.53472222, 250.29166667, 251.04861111, 251.80555556, 252.5625, 253.31944444, 254.07638889, 254.83333333, 255.59027778, 256.34722222, 257.10416667, 257.86111111, 258.61805556, 259.375, 260.13194444, 260.88888889, 261.64583333, 262.40277778, 263.15972222, 263.91666667, 264.67361111, 265.43055556, 266.1875, 266.94444444, 267.70138889, 268.45833333, 269.21527778, 269.97222222, 270.72916667, 271.48611111, 272.24305556, 273 ], "colors": [ "#ff0000", "#ff0800", "#ff0f00", "#ff1800", "#ff1f00", "#ff2800", "#ff2f00", "#ff3800", "#ff3f00", "#ff4800", "#ff4f00", "#ff5901", "#ff6001", "#ff6901", "#ff7001", "#ff7901", "#ff8901", "#ff9001", "#ff9901", "#ffa101", "#ffaa01", "#ffb101", "#ffba01", "#ffc101", "#ffca01", "#ffd101", "#ffda01", "#ffe201", "#ffe901", "#fff201", "#fffb03", "#f6f208", "#efeb0c", "#e6e213", "#ddda18", "#d4d11d", "#cdc823", "#c4c128", "#bcb82d", "#b3af33", "#aaa838", "#a39e3d", "#9a9744", "#918e49", "#89854f", "#827e54", "#797559", "#706d5e", "#676464", "#605d69", "#56546e", "#4f4b75", "#464279", "#3d3b7e", "#363385", "#2d2a89", "#242190", "#1c1a95", "#13119a", "#0c08a0", "#0300a5", "#0f0caa", "#1c18ae", "#2826b3", "#3433b6", "#423fbc", "#4d4bbf", "#5b59c4", "#6766c8", "#7472cd", "#807ed1", "#8c8cd6", "#9a99db", "#a5a5df", "#b3b1e4", "#bfbfe8", "#cccced", "#d8d8f0", "#e4e4f6", "#f2f2f9", "#ffffff", "#f6f9f6", "#edf4ed", "#e2efe2", "#dae9da", "#cfe4cf", "#c6dfc6", "#bdd8bd", "#b3d4b3", "#aacdaa", "#a1c8a1", "#97c397", "#8ebd8e", "#85b885", "#7cb37c", "#72ac72", "#69a869", "#60a160", "#569c56", "#4d974d", "#429142", "#3a8c3a", "#318731", "#268026", "#1d7c1d", "#137513", "#0a700a", "#016b01", "#016e07", "#01720e", "#017515", "#01791c", "#017e23", "#01822a", "#018531", "#018936", "#018e3d", "#019044", "#01954b", "#019952", "#019c59", "#01a160", "#01a567", "#01a86e", "#01ac75", "#01b17c", "#03b382", "#03b889", "#03bc90", "#03bf97", "#03c39e", "#03c8a5", "#03ccac", "#03cfb3", "#03d4ba", "#03d6c1", "#03dbc8", "#03dfcd", "#03e2d4", "#03e6db", "#03ebe2", "#03efe9", "#03f2f0", "#03f6f7" ] }
|
|
7
8
|
import { Float16Array } from "@petamoriken/float16";
|
|
8
9
|
import { WGLTexture } from "autumn-wgl";
|
|
9
10
|
import { getGLFormatTypeAlignment } from "./PlotComponent";
|
|
@@ -67,6 +68,25 @@ class ColorMap {
|
|
|
67
68
|
getOpacities() {
|
|
68
69
|
return this.colors.map(s => s.a);
|
|
69
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Sample from the color map
|
|
73
|
+
* @param val - The value to sample from the color map
|
|
74
|
+
* @returns A color as an RGBA hex string
|
|
75
|
+
*/
|
|
76
|
+
getColor(val) {
|
|
77
|
+
if (val < this.levels[0]) {
|
|
78
|
+
return this.underflow_color === null ? '#00000000' : this.underflow_color.toRGBAHex();
|
|
79
|
+
}
|
|
80
|
+
if (val > this.levels[this.levels.length - 1]) {
|
|
81
|
+
return this.overflow_color === null ? '#00000000' : this.overflow_color.toRGBAHex();
|
|
82
|
+
}
|
|
83
|
+
let ilev = -1;
|
|
84
|
+
for (ilev = 0; ilev < this.levels.length - 1; ilev++) {
|
|
85
|
+
if (this.levels[ilev] <= val && val < this.levels[ilev + 1])
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
return this.colors[Math.min(ilev, this.levels.length - 2)].toRGBAHex();
|
|
89
|
+
}
|
|
70
90
|
/**
|
|
71
91
|
* Make a new color map with different opacities. The opacities are set by func.
|
|
72
92
|
* @param func - A function which takes the two levels associated with a color (an upper and lower bound) and returns an opacity in the range from 0 to 1.
|
|
@@ -161,6 +181,8 @@ function buildColormap(cm_data, overflow) {
|
|
|
161
181
|
}
|
|
162
182
|
return new ColorMap(cm_data.levels, cm_data.colors, opts);
|
|
163
183
|
}
|
|
184
|
+
// This was dumb. Fix this later.
|
|
185
|
+
wv_cimss_data.colors = wv_cimss_data.colors.reverse();
|
|
164
186
|
// Some built-in colormaps
|
|
165
187
|
const pw_speed500mb = buildColormap(spd500_colormap_data, 'over').withOpacity((levl, levu) => Math.min((levu - 20) / 10, 1.));
|
|
166
188
|
const pw_speed850mb = buildColormap(spd850_colormap_data, 'over').withOpacity((levl, levu) => Math.min((levu - 20) / 10, 1.));
|
|
@@ -168,6 +190,7 @@ const pw_cape = buildColormap(cape_colormap_data, 'over').withOpacity((levl, lev
|
|
|
168
190
|
const pw_t2m = buildColormap(t2m_colormap_data, 'both');
|
|
169
191
|
const pw_td2m = buildColormap(td2m_colormap_data, 'both');
|
|
170
192
|
const nws_storm_clear_refl = buildColormap(nws_storm_clear_refl_colormap_data, 'over');
|
|
193
|
+
const wv_cimss = buildColormap(wv_cimss_data, 'neither');
|
|
171
194
|
/**
|
|
172
195
|
* Create a diverging red/blue colormap, where red corresponds to the lowest value and blue corresponds to the highest value
|
|
173
196
|
* @param level_min - The lowest value in the color map
|
|
@@ -261,4 +284,4 @@ function makeIndexMap(colormap) {
|
|
|
261
284
|
});
|
|
262
285
|
return new Float16Array(inv_cmap_norm);
|
|
263
286
|
}
|
|
264
|
-
export { ColorMap, ColorMapGPUInterface, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m, nws_storm_clear_refl };
|
|
287
|
+
export { ColorMap, ColorMapGPUInterface, bluered, redblue, pw_speed500mb, pw_speed850mb, pw_cape, pw_t2m, pw_td2m, nws_storm_clear_refl, wv_cimss };
|
package/lib/Contour.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { PlotComponent } from './PlotComponent';
|
|
|
4
4
|
import { RawScalarField } from './RawField';
|
|
5
5
|
import { LineStyle } from './PolylineCollection';
|
|
6
6
|
import { ColorMap } from './Colormap';
|
|
7
|
-
import { StructuredGrid } from './
|
|
7
|
+
import { StructuredGrid } from './grids/StructuredGrid';
|
|
8
|
+
/** Options for {@link Contour} components */
|
|
8
9
|
interface ContourOptions {
|
|
9
10
|
/**
|
|
10
11
|
* The color of the contours as a hex color string
|
|
@@ -47,6 +48,15 @@ interface ContourOptions {
|
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
49
50
|
* A field of contoured data.
|
|
51
|
+
*
|
|
52
|
+
* ## Grid Compatibility
|
|
53
|
+
* - :white_check_mark: `PlateCarreeGrid`
|
|
54
|
+
* - :white_check_mark: `PlateCarreeRotatedGrid`
|
|
55
|
+
* - :white_check_mark: `LambertGrid`
|
|
56
|
+
* - :x: `UnstructuredGrid`
|
|
57
|
+
* - :white_check_mark: `RadarSweepGrid`
|
|
58
|
+
* - :white_check_mark: `Geostationary`
|
|
59
|
+
*
|
|
50
60
|
* @example
|
|
51
61
|
* // Create a contoured height field, with black contours every 30 m (assuming the height field is in
|
|
52
62
|
* // meters).
|
|
@@ -80,6 +90,7 @@ declare class Contour<ArrayType extends TypedArray, GridType extends StructuredG
|
|
|
80
90
|
*/
|
|
81
91
|
render(gl: WebGLAnyRenderingContext, arg: RenderMethodArg): void;
|
|
82
92
|
}
|
|
93
|
+
/** Options for {@link ContourLabels} */
|
|
83
94
|
interface ContourLabelOptions {
|
|
84
95
|
/**
|
|
85
96
|
* Number of decimal places to use in the contour labels
|
|
@@ -100,6 +111,12 @@ interface ContourLabelOptions {
|
|
|
100
111
|
* URL template to use in retrieving the font data for the labels. The default is to use the template from the map style.
|
|
101
112
|
*/
|
|
102
113
|
font_url_template?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Function to format the labels from numbers to a string
|
|
116
|
+
* @example val => Math.round(val).toString() // Round a number before to the nearest integer before converting to a string
|
|
117
|
+
* @default val => val.toString()
|
|
118
|
+
*/
|
|
119
|
+
label_formatter?: (val: number) => string;
|
|
103
120
|
/**
|
|
104
121
|
* Text color for the contour labels
|
|
105
122
|
* @default '#000000'
|
|
@@ -121,6 +138,14 @@ interface ContourLabelOptions {
|
|
|
121
138
|
*/
|
|
122
139
|
density?: number;
|
|
123
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Label the contours on a plot
|
|
143
|
+
* @example
|
|
144
|
+
* // Contour some data
|
|
145
|
+
* const contours = new Contour(height_field, {color: '#000000', interval: 30});
|
|
146
|
+
* // Label the contours
|
|
147
|
+
* const labels = new ContourLabels(contours, {text_color: '#ffffff', halo: true});
|
|
148
|
+
*/
|
|
124
149
|
declare class ContourLabels<ArrayType extends TypedArray, GridType extends StructuredGrid, MapType extends MapLikeType> extends PlotComponent<MapType> {
|
|
125
150
|
private readonly contours;
|
|
126
151
|
private gl_elems;
|
package/lib/Contour.js
CHANGED
|
@@ -4,7 +4,7 @@ import { PolylineCollection, isLineStyle } from './PolylineCollection';
|
|
|
4
4
|
import { TextCollection } from './TextCollection';
|
|
5
5
|
import { Color } from './Color';
|
|
6
6
|
import { normalizeOptions } from './utils';
|
|
7
|
-
import { UnstructuredGrid } from './
|
|
7
|
+
import { UnstructuredGrid } from './grids/UnstructuredGrid';
|
|
8
8
|
const contour_opt_defaults = {
|
|
9
9
|
color: '#000000',
|
|
10
10
|
cmap: null,
|
|
@@ -16,6 +16,15 @@ const contour_opt_defaults = {
|
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
18
|
* A field of contoured data.
|
|
19
|
+
*
|
|
20
|
+
* ## Grid Compatibility
|
|
21
|
+
* - :white_check_mark: `PlateCarreeGrid`
|
|
22
|
+
* - :white_check_mark: `PlateCarreeRotatedGrid`
|
|
23
|
+
* - :white_check_mark: `LambertGrid`
|
|
24
|
+
* - :x: `UnstructuredGrid`
|
|
25
|
+
* - :white_check_mark: `RadarSweepGrid`
|
|
26
|
+
* - :white_check_mark: `Geostationary`
|
|
27
|
+
*
|
|
19
28
|
* @example
|
|
20
29
|
* // Create a contoured height field, with black contours every 30 m (assuming the height field is in
|
|
21
30
|
* // meters).
|
|
@@ -113,6 +122,7 @@ class Contour extends PlotComponent {
|
|
|
113
122
|
const map_height = gl_elems.map.getCanvas().height;
|
|
114
123
|
const bearing = gl_elems.map.getBearing();
|
|
115
124
|
const pitch = gl_elems.map.getPitch();
|
|
125
|
+
// XXX: This will compile another shader each time updateField() is called. Is there a way to not do that?
|
|
116
126
|
this.contours.forEach(cnt => cnt.render(gl, arg, [map_width, map_height], zoom, bearing, pitch));
|
|
117
127
|
}
|
|
118
128
|
}
|
|
@@ -121,11 +131,20 @@ const contour_label_opt_defaults = {
|
|
|
121
131
|
font_face: 'Trebuchet MS',
|
|
122
132
|
font_size: 12,
|
|
123
133
|
font_url_template: '',
|
|
134
|
+
label_formatter: (val) => val.toString(),
|
|
124
135
|
text_color: '#000000',
|
|
125
136
|
halo_color: '#000000',
|
|
126
137
|
halo: false,
|
|
127
138
|
density: 1
|
|
128
139
|
};
|
|
140
|
+
/**
|
|
141
|
+
* Label the contours on a plot
|
|
142
|
+
* @example
|
|
143
|
+
* // Contour some data
|
|
144
|
+
* const contours = new Contour(height_field, {color: '#000000', interval: 30});
|
|
145
|
+
* // Label the contours
|
|
146
|
+
* const labels = new ContourLabels(contours, {text_color: '#ffffff', halo: true});
|
|
147
|
+
*/
|
|
129
148
|
class ContourLabels extends PlotComponent {
|
|
130
149
|
constructor(contours, opts) {
|
|
131
150
|
super();
|
|
@@ -155,7 +174,7 @@ class ContourLabels extends PlotComponent {
|
|
|
155
174
|
const contour_label_spacing = 0.006 / this.opts.density * Math.pow(2, 7 - map_max_zoom);
|
|
156
175
|
Object.entries(contour_data).forEach(([level, contours]) => {
|
|
157
176
|
const icntr = (parseFloat(level) - contour_levels[0]);
|
|
158
|
-
const level_str =
|
|
177
|
+
const level_str = this.opts.label_formatter(level);
|
|
159
178
|
contours.forEach(contour => {
|
|
160
179
|
const c_map = contour.map(v => {
|
|
161
180
|
const v_ll = new LngLat(...v).toMercatorCoord();
|
|
@@ -175,6 +194,8 @@ class ContourLabels extends PlotComponent {
|
|
|
175
194
|
let n_labels_placed = 0;
|
|
176
195
|
for (let idist = 1; idist < dist.length; idist++) {
|
|
177
196
|
const target_dist = contour_label_spacing * (n_labels_placed + (icntr / 2) % 1);
|
|
197
|
+
// This works fine when contour_label_spacing > the spacing between points along a contour, but when you allow the map to zoom in
|
|
198
|
+
// (and therefore contour_label_spacing gets small), dist[idist] outruns target_dist, so it doesn't put any more labels after the first.
|
|
178
199
|
if (dist[idist - 1] <= target_dist && target_dist < dist[idist]) {
|
|
179
200
|
const pt1 = contour[idist - 1];
|
|
180
201
|
const pt2 = contour[idist];
|
|
@@ -219,6 +240,7 @@ class ContourLabels extends PlotComponent {
|
|
|
219
240
|
const map_width = gl_elems.map.getCanvas().width;
|
|
220
241
|
const map_height = gl_elems.map.getCanvas().height;
|
|
221
242
|
const map_zoom = gl_elems.map.getZoom();
|
|
243
|
+
// XXX: This will compile another shader each time updateField() is called. Is there a way to not do that?
|
|
222
244
|
this.text_collection.render(gl, arg, [map_width, map_height], map_zoom);
|
|
223
245
|
}
|
|
224
246
|
}
|