ol 10.1.1-dev.1724341529501 → 10.1.1-dev.1724487165147

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.
@@ -0,0 +1,199 @@
1
+ export default FlowLayer;
2
+ export type ParsedStyle = {
3
+ /**
4
+ * The flow tile vertex shader.
5
+ */
6
+ tileVertexShader: string;
7
+ /**
8
+ * The flow tile fragment shader.
9
+ */
10
+ tileFragmentShader: string;
11
+ /**
12
+ * Generic texture fragment shader.
13
+ */
14
+ textureVertexShader: string;
15
+ /**
16
+ * Generic texture fragment shader.
17
+ */
18
+ textureFragmentShader: string;
19
+ /**
20
+ * The particle position vertex shader.
21
+ */
22
+ particlePositionVertexShader: string;
23
+ /**
24
+ * The particle position fragment shader.
25
+ */
26
+ particlePositionFragmentShader: string;
27
+ /**
28
+ * The particle color vertex shader.
29
+ */
30
+ particleColorVertexShader: string;
31
+ /**
32
+ * The particle color fragment shader.
33
+ */
34
+ particleColorFragmentShader: string;
35
+ };
36
+ export type SourceType = import("../source/DataTile.js").default;
37
+ /**
38
+ * Translates tile data to rendered pixels.
39
+ */
40
+ export type Style = {
41
+ /**
42
+ * Style variables. Each variable must hold a number or string. These
43
+ * variables can be used in the `color` {@link import ("../expr/expression.js").ExpressionValue expression} using
44
+ * the `['var', 'varName']` operator. To update style variables, use the {@link import ("./WebGLTile.js").default#updateStyleVariables} method.
45
+ */
46
+ variables?: {
47
+ [x: string]: string | number;
48
+ } | undefined;
49
+ /**
50
+ * An expression applied to color values.
51
+ */
52
+ color?: import("../expr/expression.js").ExpressionValue | undefined;
53
+ };
54
+ export type Options = {
55
+ /**
56
+ * The maximum particle speed.
57
+ */
58
+ maxSpeed: number;
59
+ /**
60
+ * A larger factor increases the rate at which particles cross the screen.
61
+ */
62
+ speedFactor?: number | undefined;
63
+ /**
64
+ * The number of particles to render.
65
+ */
66
+ particles?: number | undefined;
67
+ /**
68
+ * Style to apply to the layer.
69
+ */
70
+ style?: Style | undefined;
71
+ /**
72
+ * A CSS class name to set to the layer element.
73
+ */
74
+ className?: string | undefined;
75
+ /**
76
+ * Opacity (0, 1).
77
+ */
78
+ opacity?: number | undefined;
79
+ /**
80
+ * Visibility.
81
+ */
82
+ visible?: boolean | undefined;
83
+ /**
84
+ * The bounding extent for layer rendering. The layer will not be
85
+ * rendered outside of this extent.
86
+ */
87
+ extent?: import("../extent.js").Extent | undefined;
88
+ /**
89
+ * The z-index for layer rendering. At rendering time, the layers
90
+ * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed
91
+ * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()`
92
+ * method was used.
93
+ */
94
+ zIndex?: number | undefined;
95
+ /**
96
+ * The minimum resolution (inclusive) at which this layer will be
97
+ * visible.
98
+ */
99
+ minResolution?: number | undefined;
100
+ /**
101
+ * The maximum resolution (exclusive) below which this layer will
102
+ * be visible.
103
+ */
104
+ maxResolution?: number | undefined;
105
+ /**
106
+ * The minimum view zoom level (exclusive) above which this layer will be
107
+ * visible.
108
+ */
109
+ minZoom?: number | undefined;
110
+ /**
111
+ * The maximum view zoom level (inclusive) at which this layer will
112
+ * be visible.
113
+ */
114
+ maxZoom?: number | undefined;
115
+ /**
116
+ * Preload. Load low-resolution tiles up to `preload` levels. `0`
117
+ * means no preloading.
118
+ */
119
+ preload?: number | undefined;
120
+ /**
121
+ * Source for this layer.
122
+ */
123
+ source?: import("../source/DataTile.js").default<import("../DataTile.js").default> | undefined;
124
+ /**
125
+ * Sets the layer as overlay on a map. The map will not manage
126
+ * this layer in its layers collection, and the layer will be rendered on top. This is useful for
127
+ * temporary layers. The standard way to add a layer to a map and have it managed by the map is to
128
+ * use {@link module :ol/Map~Map#addLayer}.
129
+ */
130
+ map?: import("../Map.js").default | undefined;
131
+ /**
132
+ * Use interim tiles on error.
133
+ */
134
+ useInterimTilesOnError?: boolean | undefined;
135
+ /**
136
+ * The internal texture cache size. This needs to be large enough to render
137
+ * two zoom levels worth of tiles.
138
+ */
139
+ cacheSize?: number | undefined;
140
+ };
141
+ /**
142
+ * @classdesc
143
+ * Experimental layer that renders particles moving through a vector field.
144
+ *
145
+ * @extends BaseTileLayer<SourceType, FlowLayerRenderer>
146
+ * @fires import("../render/Event.js").RenderEvent
147
+ */
148
+ declare class FlowLayer extends BaseTileLayer<import("../source/DataTile.js").default<import("../DataTile.js").default>, FlowLayerRenderer> {
149
+ /**
150
+ * @param {Options} options Flow layer options.
151
+ */
152
+ constructor(options: Options);
153
+ /**
154
+ * @type {Style}
155
+ * @private
156
+ */
157
+ private style_;
158
+ /**
159
+ * @type {number}
160
+ * @private
161
+ */
162
+ private maxSpeed_;
163
+ /**
164
+ * @type {number}
165
+ * @private
166
+ */
167
+ private speedFactor_;
168
+ /**
169
+ * @type {number}
170
+ * @private
171
+ */
172
+ private particles_;
173
+ /**
174
+ * @type {Object<string, (string|number)>}
175
+ * @private
176
+ */
177
+ private styleVariables_;
178
+ /**
179
+ * @private
180
+ */
181
+ private handleSourceUpdate_;
182
+ /**
183
+ * Update any variables used by the layer style and trigger a re-render.
184
+ * @param {Object<string, number>} variables Variables to update.
185
+ */
186
+ updateStyleVariables(variables: {
187
+ [x: string]: number;
188
+ }): void;
189
+ /**
190
+ * Gets the sources for this layer, for a given extent and resolution.
191
+ * @param {import("../extent.js").Extent} extent Extent.
192
+ * @param {number} resolution Resolution.
193
+ * @return {Array<SourceType>} Sources.
194
+ */
195
+ getSources(extent: import("../extent.js").Extent, resolution: number): Array<SourceType>;
196
+ }
197
+ import FlowLayerRenderer from '../renderer/webgl/FlowLayer.js';
198
+ import BaseTileLayer from './BaseTile.js';
199
+ //# sourceMappingURL=Flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Flow.d.ts","sourceRoot":"","sources":["Flow.js"],"names":[],"mappings":";;;;;sBAuRc,MAAM;;;;wBACN,MAAM;;;;yBACN,MAAM;;;;2BACN,MAAM;;;;kCACN,MAAM;;;;oCACN,MAAM;;;;+BACN,MAAM;;;;iCACN,MAAM;;yBA9QP,OAAO,uBAAuB,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;cAetC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8WpB;;;;;;GAMG;AACH;IACE;;OAEG;IACH,qBAFW,OAAO,EA2CjB;IAlCC;;;OAGG;IACH,eAAiC;IAKjC;;;OAGG;IACH,kBAAiC;IAEjC;;;OAGG;IACH,qBAAuC;IAEvC;;;OAGG;IACH,mBAAmC;IAEnC;;;OAGG;IACH,wBAAkD;IAKpD;;OAEG;IACH,4BAIC;IAED;;;OAGG;IACH,gCAFW;YAAO,MAAM,GAAE,MAAM;KAAC,QAKhC;IAED;;;;;OAKG;IACH,mBAJW,OAAO,cAAc,EAAE,MAAM,cAC7B,MAAM,GACL,KAAK,CAAC,UAAU,CAAC,CAM5B;CAgBF;8BA3ewC,gCAAgC;0BAD/C,eAAe"}
package/layer/Flow.js ADDED
@@ -0,0 +1,504 @@
1
+ /**
2
+ * @module ol/layer/Flow
3
+ */
4
+ import BaseTileLayer from './BaseTile.js';
5
+ import FlowLayerRenderer, {A, U, V} from '../renderer/webgl/FlowLayer.js';
6
+ import LayerProperty from './Property.js';
7
+ import {Attributes as BA, Uniforms as BU} from '../renderer/webgl/TileLayer.js';
8
+ import {ColorType} from '../expr/expression.js';
9
+ import {expressionToGlsl} from '../webgl/styleparser.js';
10
+ import {
11
+ getStringNumberEquivalent,
12
+ newCompilationContext,
13
+ uniformNameForVariable,
14
+ } from '../expr/gpu.js';
15
+
16
+ /**
17
+ * @typedef {import("../source/DataTile.js").default} SourceType
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} Style
22
+ * Translates tile data to rendered pixels.
23
+ *
24
+ * @property {Object<string, (string|number)>} [variables] Style variables. Each variable must hold a number or string. These
25
+ * variables can be used in the `color` {@link import("../expr/expression.js").ExpressionValue expression} using
26
+ * the `['var', 'varName']` operator. To update style variables, use the {@link import("./WebGLTile.js").default#updateStyleVariables} method.
27
+ * @property {import("../expr/expression.js").ExpressionValue} [color] An expression applied to color values.
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} Options
32
+ * @property {number} maxSpeed The maximum particle speed.
33
+ * @property {number} [speedFactor=0.001] A larger factor increases the rate at which particles cross the screen.
34
+ * @property {number} [particles=65536] The number of particles to render.
35
+ * @property {Style} [style] Style to apply to the layer.
36
+ * @property {string} [className='ol-layer'] A CSS class name to set to the layer element.
37
+ * @property {number} [opacity=1] Opacity (0, 1).
38
+ * @property {boolean} [visible=true] Visibility.
39
+ * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be
40
+ * rendered outside of this extent.
41
+ * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers
42
+ * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed
43
+ * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()`
44
+ * method was used.
45
+ * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be
46
+ * visible.
47
+ * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
48
+ * be visible.
49
+ * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be
50
+ * visible.
51
+ * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will
52
+ * be visible.
53
+ * @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`
54
+ * means no preloading.
55
+ * @property {SourceType} [source] Source for this layer.
56
+ * @property {import("../Map.js").default} [map] Sets the layer as overlay on a map. The map will not manage
57
+ * this layer in its layers collection, and the layer will be rendered on top. This is useful for
58
+ * temporary layers. The standard way to add a layer to a map and have it managed by the map is to
59
+ * use {@link module:ol/Map~Map#addLayer}.
60
+ * @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error.
61
+ * @property {number} [cacheSize=512] The internal texture cache size. This needs to be large enough to render
62
+ * two zoom levels worth of tiles.
63
+ */
64
+
65
+ const tileVertexShader = `
66
+ attribute vec2 ${BA.TEXTURE_COORD};
67
+ uniform mat4 ${BU.TILE_TRANSFORM};
68
+ uniform float ${BU.TEXTURE_PIXEL_WIDTH};
69
+ uniform float ${BU.TEXTURE_PIXEL_HEIGHT};
70
+ uniform float ${BU.TEXTURE_RESOLUTION};
71
+ uniform float ${BU.TEXTURE_ORIGIN_X};
72
+ uniform float ${BU.TEXTURE_ORIGIN_Y};
73
+ uniform float ${BU.DEPTH};
74
+
75
+ varying vec2 v_textureCoord;
76
+ varying vec2 v_mapCoord;
77
+
78
+ void main() {
79
+ v_textureCoord = ${BA.TEXTURE_COORD};
80
+ v_mapCoord = vec2(
81
+ ${BU.TEXTURE_ORIGIN_X} + ${BU.TEXTURE_RESOLUTION} * ${BU.TEXTURE_PIXEL_WIDTH} * v_textureCoord[0],
82
+ ${BU.TEXTURE_ORIGIN_Y} - ${BU.TEXTURE_RESOLUTION} * ${BU.TEXTURE_PIXEL_HEIGHT} * v_textureCoord[1]
83
+ );
84
+ gl_Position = ${BU.TILE_TRANSFORM} * vec4(${BA.TEXTURE_COORD}, ${BU.DEPTH}, 1.0);
85
+ }
86
+ `;
87
+
88
+ const tileFragmentShader = `
89
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
90
+ precision highp float;
91
+ #else
92
+ precision mediump float;
93
+ #endif
94
+
95
+ uniform vec4 ${BU.RENDER_EXTENT};
96
+ uniform float ${U.MAX_SPEED};
97
+ uniform sampler2D ${BU.TILE_TEXTURE_ARRAY}[1];
98
+
99
+ varying vec2 v_textureCoord;
100
+ varying vec2 v_mapCoord;
101
+
102
+ void main() {
103
+ if (
104
+ v_mapCoord[0] < ${BU.RENDER_EXTENT}[0] ||
105
+ v_mapCoord[1] < ${BU.RENDER_EXTENT}[1] ||
106
+ v_mapCoord[0] > ${BU.RENDER_EXTENT}[2] ||
107
+ v_mapCoord[1] > ${BU.RENDER_EXTENT}[3]
108
+ ) {
109
+ discard;
110
+ }
111
+
112
+ vec4 velocity = texture2D(${BU.TILE_TEXTURE_ARRAY}[0], v_textureCoord);
113
+ gl_FragColor = vec4((velocity.xy + ${U.MAX_SPEED}) / (2.0 * ${U.MAX_SPEED}), 0, 1);
114
+ }
115
+ `;
116
+
117
+ /**
118
+ * Sets up a varying position for rendering textures.
119
+ */
120
+ const quadVertexShader = `
121
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
122
+ precision highp float;
123
+ #else
124
+ precision mediump float;
125
+ #endif
126
+
127
+ attribute vec2 ${A.POSITION};
128
+
129
+ varying vec2 ${V.POSITION};
130
+
131
+ void main() {
132
+ ${V.POSITION} = ${A.POSITION};
133
+ gl_Position = vec4(1.0 - 2.0 * ${A.POSITION}, 0, 1);
134
+ }
135
+ `;
136
+
137
+ /**
138
+ * Sampes a texture and renders it with a new opacity.
139
+ */
140
+ const textureFragmentShader = `
141
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
142
+ precision highp float;
143
+ #else
144
+ precision mediump float;
145
+ #endif
146
+
147
+ uniform sampler2D ${U.TEXTURE};
148
+ uniform float ${U.OPACITY};
149
+
150
+ varying vec2 ${V.POSITION};
151
+
152
+ void main() {
153
+ vec4 color = texture2D(${U.TEXTURE}, 1.0 - ${V.POSITION});
154
+ gl_FragColor = vec4(floor(255.0 * color * ${U.OPACITY}) / 255.0);
155
+ }
156
+ `;
157
+
158
+ /**
159
+ * Samples current particle positions, determines new positions based on velocity, and
160
+ * encodes the new position as a color.
161
+ */
162
+ const particlePositionFragmentShader = `
163
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
164
+ precision highp float;
165
+ #else
166
+ precision mediump float;
167
+ #endif
168
+
169
+ uniform sampler2D ${U.POSITION_TEXTURE};
170
+ uniform sampler2D ${U.VELOCITY_TEXTURE};
171
+ uniform float ${U.RANDOM_SEED};
172
+ uniform float ${U.SPEED_FACTOR};
173
+ uniform float ${U.DROP_RATE};
174
+ uniform float ${U.DROP_RATE_BUMP};
175
+ uniform vec2 ${U.ROTATION};
176
+ uniform vec2 ${U.VIEWPORT_SIZE_PX};
177
+
178
+ varying vec2 ${V.POSITION};
179
+
180
+ // pseudo-random generator
181
+ const vec3 randConstants = vec3(12.9898, 78.233, 4375.85453);
182
+
183
+ float rand(const vec2 co) {
184
+ float t = dot(randConstants.xy, co);
185
+ return fract(sin(t) * (randConstants.z + t));
186
+ }
187
+
188
+ void main() {
189
+ vec4 positionColor = texture2D(${U.POSITION_TEXTURE}, ${V.POSITION});
190
+
191
+ // decode particle position from pixel RGBA
192
+ vec2 particlePosition = vec2(
193
+ positionColor.r / 255.0 + positionColor.b,
194
+ positionColor.g / 255.0 + positionColor.a
195
+ );
196
+
197
+ vec4 velocityColor = texture2D(${U.VELOCITY_TEXTURE}, particlePosition);
198
+ if (velocityColor.a == 0.0) {
199
+ discard;
200
+ }
201
+
202
+ float vx = 2.0 * velocityColor.r - 1.0;
203
+ float vy = 2.0 * velocityColor.g - 1.0;
204
+
205
+ // normalized veloicty (magnitude 0 - 1)
206
+ vec2 velocity = vec2(
207
+ vx * ${U.ROTATION}.x - vy * ${U.ROTATION}.y,
208
+ vx * ${U.ROTATION}.y + vy * ${U.ROTATION}.x
209
+ );
210
+
211
+ // account for aspect ratio (square particle position texture, non-square map)
212
+ float aspectRatio = ${U.VIEWPORT_SIZE_PX}.x / ${U.VIEWPORT_SIZE_PX}.y;
213
+ vec2 offset = vec2(velocity.x / aspectRatio, velocity.y) * ${U.SPEED_FACTOR};
214
+
215
+ // update particle position, wrapping around the edge
216
+ particlePosition = fract(1.0 + particlePosition + offset);
217
+
218
+ // a random seed to use for the particle drop
219
+ vec2 seed = (particlePosition + ${V.POSITION}) * ${U.RANDOM_SEED};
220
+
221
+ // drop rate is a chance a particle will restart at random position, to avoid degeneration
222
+ float dropRate = ${U.DROP_RATE} + length(velocity) * ${U.DROP_RATE_BUMP};
223
+ float drop = step(1.0 - dropRate, rand(seed));
224
+
225
+ vec2 randomPosition = vec2(rand(seed + 1.3), rand(seed + 2.1));
226
+ particlePosition = mix(particlePosition, randomPosition, drop);
227
+
228
+ // encode the new particle position back into RGBA
229
+ gl_FragColor = vec4(
230
+ fract(particlePosition * 255.0),
231
+ floor(particlePosition * 255.0) / 255.0
232
+ );
233
+ }
234
+ `;
235
+
236
+ /**
237
+ * Samples the particle position texture to decode the particle position
238
+ * based on pixel color.
239
+ */
240
+ const particleColorVertexShader = `
241
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
242
+ precision highp float;
243
+ #else
244
+ precision mediump float;
245
+ #endif
246
+
247
+ attribute float ${A.INDEX};
248
+
249
+ uniform sampler2D ${U.POSITION_TEXTURE};
250
+ uniform float ${U.PARTICLE_COUNT_SQRT};
251
+
252
+ varying vec2 ${V.POSITION};
253
+
254
+ void main() {
255
+ vec4 color = texture2D(
256
+ ${U.POSITION_TEXTURE},
257
+ vec2(
258
+ fract(${A.INDEX} / ${U.PARTICLE_COUNT_SQRT}),
259
+ floor(${A.INDEX} / ${U.PARTICLE_COUNT_SQRT}) / ${U.PARTICLE_COUNT_SQRT}
260
+ )
261
+ );
262
+
263
+ ${V.POSITION} = vec2(
264
+ color.r / 255.0 + color.b,
265
+ color.g / 255.0 + color.a
266
+ );
267
+
268
+ gl_PointSize = 1.0;
269
+ gl_Position = vec4(
270
+ 2.0 * ${V.POSITION}.x - 1.0,
271
+ 2.0 * ${V.POSITION}.y - 1.0,
272
+ 0,
273
+ 1
274
+ );
275
+ }
276
+ `;
277
+
278
+ /**
279
+ * @typedef {Object} ParsedStyle
280
+ * @property {string} tileVertexShader The flow tile vertex shader.
281
+ * @property {string} tileFragmentShader The flow tile fragment shader.
282
+ * @property {string} textureVertexShader Generic texture fragment shader.
283
+ * @property {string} textureFragmentShader Generic texture fragment shader.
284
+ * @property {string} particlePositionVertexShader The particle position vertex shader.
285
+ * @property {string} particlePositionFragmentShader The particle position fragment shader.
286
+ * @property {string} particleColorVertexShader The particle color vertex shader.
287
+ * @property {string} particleColorFragmentShader The particle color fragment shader.
288
+ */
289
+
290
+ /**
291
+ * @param {Style} style The layer style.
292
+ * @return {ParsedStyle} Shaders and uniforms generated from the style.
293
+ */
294
+ function parseStyle(style) {
295
+ const context = newCompilationContext();
296
+ context.inFragmentShader = true;
297
+ const pipeline = [];
298
+
299
+ if (style.color !== undefined) {
300
+ const color = expressionToGlsl(context, style.color, ColorType);
301
+ pipeline.push(`color = ${color};`);
302
+ }
303
+
304
+ const variableNames = Object.keys(context.variables);
305
+ if (variableNames.length > 1 && !style.variables) {
306
+ throw new Error(
307
+ `Missing variables in style (expected ${context.variables})`,
308
+ );
309
+ }
310
+
311
+ /** @type {Object<string,import("../webgl/Helper").UniformValue>} */
312
+ const uniforms = {};
313
+
314
+ for (const variableName of variableNames) {
315
+ if (!(variableName in style.variables)) {
316
+ throw new Error(`Missing '${variableName}' in style variables`);
317
+ }
318
+
319
+ const uniformName = uniformNameForVariable(variableName);
320
+ uniforms[uniformName] = function () {
321
+ let value = style.variables[variableName];
322
+ if (typeof value === 'string') {
323
+ value = getStringNumberEquivalent(value);
324
+ }
325
+ return value !== undefined ? value : -9999999; // to avoid matching with the first string literal
326
+ };
327
+ }
328
+
329
+ const uniformDeclarations = Object.keys(uniforms).map(function (name) {
330
+ return `uniform float ${name};`;
331
+ });
332
+
333
+ const functionDefintions = Object.keys(context.functions).map(
334
+ function (name) {
335
+ return context.functions[name];
336
+ },
337
+ );
338
+
339
+ const particleColorFragmentShader = `
340
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
341
+ precision highp float;
342
+ #else
343
+ precision mediump float;
344
+ #endif
345
+
346
+ uniform sampler2D ${U.VELOCITY_TEXTURE};
347
+ uniform float ${U.MAX_SPEED};
348
+ uniform vec2 ${U.ROTATION};
349
+
350
+ ${uniformDeclarations.join('\n')}
351
+
352
+ varying vec2 ${V.POSITION};
353
+
354
+ ${functionDefintions.join('\n')}
355
+
356
+ void main() {
357
+ vec4 velocityColor = texture2D(${U.VELOCITY_TEXTURE}, ${V.POSITION});
358
+
359
+ float vx = mix(-${U.MAX_SPEED}, ${U.MAX_SPEED}, velocityColor.r);
360
+ float vy = mix(-${U.MAX_SPEED}, ${U.MAX_SPEED}, velocityColor.g);
361
+
362
+ vec2 velocity = vec2(
363
+ vx * ${U.ROTATION}.x - vy * ${U.ROTATION}.y,
364
+ vx * ${U.ROTATION}.y + vy * ${U.ROTATION}.x
365
+ );
366
+
367
+ float v_prop_speed = length(velocity);
368
+
369
+ vec4 color;
370
+
371
+ ${pipeline.join('\n')}
372
+
373
+ if (color.a == 0.0) {
374
+ discard;
375
+ }
376
+
377
+ gl_FragColor = color;
378
+ }
379
+ `;
380
+
381
+ return {
382
+ tileVertexShader,
383
+ tileFragmentShader,
384
+ particleColorVertexShader,
385
+ particleColorFragmentShader,
386
+ particlePositionVertexShader: quadVertexShader,
387
+ particlePositionFragmentShader,
388
+ textureVertexShader: quadVertexShader,
389
+ textureFragmentShader,
390
+ };
391
+ }
392
+
393
+ /**
394
+ * @type {Array<SourceType>}
395
+ */
396
+ const sources = [];
397
+
398
+ /**
399
+ * @classdesc
400
+ * Experimental layer that renders particles moving through a vector field.
401
+ *
402
+ * @extends BaseTileLayer<SourceType, FlowLayerRenderer>
403
+ * @fires import("../render/Event.js").RenderEvent
404
+ */
405
+ class FlowLayer extends BaseTileLayer {
406
+ /**
407
+ * @param {Options} options Flow layer options.
408
+ */
409
+ constructor(options) {
410
+ const baseOptions = Object.assign({}, options);
411
+ delete baseOptions.maxSpeed;
412
+ delete baseOptions.speedFactor;
413
+ delete baseOptions.particles;
414
+ super(baseOptions);
415
+
416
+ /**
417
+ * @type {Style}
418
+ * @private
419
+ */
420
+ this.style_ = options.style || {};
421
+
422
+ if (!(options.maxSpeed > 0)) {
423
+ throw new Error('maxSpeed is required');
424
+ }
425
+ /**
426
+ * @type {number}
427
+ * @private
428
+ */
429
+ this.maxSpeed_ = options.maxSpeed;
430
+
431
+ /**
432
+ * @type {number}
433
+ * @private
434
+ */
435
+ this.speedFactor_ = options.speedFactor;
436
+
437
+ /**
438
+ * @type {number}
439
+ * @private
440
+ */
441
+ this.particles_ = options.particles;
442
+
443
+ /**
444
+ * @type {Object<string, (string|number)>}
445
+ * @private
446
+ */
447
+ this.styleVariables_ = this.style_.variables || {};
448
+
449
+ this.addChangeListener(LayerProperty.SOURCE, this.handleSourceUpdate_);
450
+ }
451
+
452
+ /**
453
+ * @private
454
+ */
455
+ handleSourceUpdate_() {
456
+ if (this.hasRenderer()) {
457
+ this.getRenderer().clearCache();
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Update any variables used by the layer style and trigger a re-render.
463
+ * @param {Object<string, number>} variables Variables to update.
464
+ */
465
+ updateStyleVariables(variables) {
466
+ Object.assign(this.styleVariables_, variables);
467
+ this.changed();
468
+ }
469
+
470
+ /**
471
+ * Gets the sources for this layer, for a given extent and resolution.
472
+ * @param {import("../extent.js").Extent} extent Extent.
473
+ * @param {number} resolution Resolution.
474
+ * @return {Array<SourceType>} Sources.
475
+ */
476
+ getSources(extent, resolution) {
477
+ const source = this.getSource();
478
+ sources[0] = source;
479
+ return sources;
480
+ }
481
+
482
+ /**
483
+ * @override
484
+ */
485
+ createRenderer() {
486
+ const parsedStyle = parseStyle(this.style_);
487
+
488
+ return new FlowLayerRenderer(this, {
489
+ ...parsedStyle,
490
+ cacheSize: this.getCacheSize(),
491
+ maxSpeed: this.maxSpeed_,
492
+ speedFactor: this.speedFactor_,
493
+ particles: this.particles_,
494
+ });
495
+ }
496
+ }
497
+
498
+ /**
499
+ * Clean up underlying WebGL resources.
500
+ * @function
501
+ */
502
+ FlowLayer.prototype.dispose;
503
+
504
+ export default FlowLayer;