@deck.gl/aggregation-layers 9.0.0-beta.1 → 9.0.0-beta.2
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/dist/dist.dev.js +3287 -310
- package/dist/es5/heatmap-layer/heatmap-layer-utils.js +0 -15
- package/dist/es5/heatmap-layer/heatmap-layer-utils.js.map +1 -1
- package/dist/es5/heatmap-layer/heatmap-layer.js +103 -97
- package/dist/es5/heatmap-layer/heatmap-layer.js.map +1 -1
- package/dist/es5/heatmap-layer/max-vs.glsl.js +1 -1
- package/dist/es5/heatmap-layer/triangle-layer-fragment.glsl.js +1 -1
- package/dist/es5/heatmap-layer/triangle-layer.js +26 -27
- package/dist/es5/heatmap-layer/triangle-layer.js.map +1 -1
- package/dist/es5/heatmap-layer/weights-vs.glsl.js +1 -1
- package/dist/esm/heatmap-layer/heatmap-layer-utils.js +0 -13
- package/dist/esm/heatmap-layer/heatmap-layer-utils.js.map +1 -1
- package/dist/esm/heatmap-layer/heatmap-layer.js +99 -87
- package/dist/esm/heatmap-layer/heatmap-layer.js.map +1 -1
- package/dist/esm/heatmap-layer/max-vs.glsl.js +11 -5
- package/dist/esm/heatmap-layer/max-vs.glsl.js.map +1 -1
- package/dist/esm/heatmap-layer/triangle-layer-fragment.glsl.js +2 -2
- package/dist/esm/heatmap-layer/triangle-layer-fragment.glsl.js.map +1 -1
- package/dist/esm/heatmap-layer/triangle-layer.js +21 -23
- package/dist/esm/heatmap-layer/triangle-layer.js.map +1 -1
- package/dist/esm/heatmap-layer/weights-vs.glsl.js +4 -2
- package/dist/esm/heatmap-layer/weights-vs.glsl.js.map +1 -1
- package/dist.min.js +85 -75
- package/package.json +7 -7
- package/src/heatmap-layer/heatmap-layer-utils.ts +0 -23
- package/src/heatmap-layer/heatmap-layer.ts +87 -105
- package/src/heatmap-layer/max-vs.glsl.ts +11 -5
- package/src/heatmap-layer/triangle-layer-fragment.glsl.ts +2 -2
- package/src/heatmap-layer/triangle-layer.ts +17 -23
- package/src/heatmap-layer/weights-vs.glsl.ts +4 -2
- package/typed/heatmap-layer/heatmap-layer-utils.d.ts +0 -9
- package/typed/heatmap-layer/heatmap-layer-utils.d.ts.map +1 -1
- package/typed/heatmap-layer/heatmap-layer.d.ts +4 -4
- package/typed/heatmap-layer/heatmap-layer.d.ts.map +1 -1
- package/typed/heatmap-layer/max-vs.glsl.d.ts +1 -1
- package/typed/heatmap-layer/max-vs.glsl.d.ts.map +1 -1
- package/typed/heatmap-layer/triangle-layer-fragment.glsl.d.ts +1 -1
- package/typed/heatmap-layer/triangle-layer.d.ts +10 -2
- package/typed/heatmap-layer/triangle-layer.d.ts.map +1 -1
- package/typed/heatmap-layer/weights-vs.glsl.d.ts +1 -1
- package/typed/heatmap-layer/weights-vs.glsl.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@deck.gl/aggregation-layers",
|
|
3
3
|
"description": "deck.gl layers that aggregate the input data into alternative representations",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "9.0.0-beta.
|
|
5
|
+
"version": "9.0.0-beta.2",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -32,17 +32,17 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@babel/runtime": "^7.0.0",
|
|
35
|
-
"@luma.gl/constants": "9.0.0-
|
|
36
|
-
"@luma.gl/core": "9.0.0-
|
|
37
|
-
"@luma.gl/shadertools": "9.0.0-
|
|
35
|
+
"@luma.gl/constants": "9.0.0-beta.1",
|
|
36
|
+
"@luma.gl/core": "9.0.0-beta.1",
|
|
37
|
+
"@luma.gl/shadertools": "9.0.0-beta.1",
|
|
38
38
|
"@math.gl/web-mercator": "^4.0.0",
|
|
39
39
|
"d3-hexbin": "^0.2.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@deck.gl/core": "^9.0.0-alpha",
|
|
43
43
|
"@deck.gl/layers": "^9.0.0-alpha",
|
|
44
|
-
"@luma.gl/core": "9.0.0-
|
|
45
|
-
"@luma.gl/engine": "9.0.0-
|
|
44
|
+
"@luma.gl/core": "9.0.0-beta.1",
|
|
45
|
+
"@luma.gl/engine": "9.0.0-beta.1"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "ed132efaf84a75ea71c89dd8555b6ffc1fe839d5"
|
|
48
48
|
}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {Device} from '@luma.gl/core';
|
|
2
|
-
import {GL} from '@luma.gl/constants';
|
|
3
|
-
|
|
4
1
|
export function getBounds(points: number[][]): number[] {
|
|
5
2
|
// Now build bounding box in world space (aligned to world coordiante system)
|
|
6
3
|
const x = points.map(p => p[0]);
|
|
@@ -77,23 +74,3 @@ export function getTextureCoordinates(point: number[], bounds: number[]) {
|
|
|
77
74
|
const [xMin, yMin, xMax, yMax] = bounds;
|
|
78
75
|
return [(point[0] - xMin) / (xMax - xMin), (point[1] - yMin) / (yMax - yMin)];
|
|
79
76
|
}
|
|
80
|
-
|
|
81
|
-
// Returns format and type for creating texture objects
|
|
82
|
-
export function getTextureParams({
|
|
83
|
-
device,
|
|
84
|
-
floatTargetSupport
|
|
85
|
-
}: {
|
|
86
|
-
device: Device;
|
|
87
|
-
floatTargetSupport?: boolean;
|
|
88
|
-
}) {
|
|
89
|
-
return floatTargetSupport
|
|
90
|
-
? {
|
|
91
|
-
// format: should be RGBA32F on WebGL2 (float textures), RGBA in WebGL1 for float or non float textures
|
|
92
|
-
format: device.info.type === 'webgl2' ? GL.RGBA32F : GL.RGBA,
|
|
93
|
-
type: GL.FLOAT
|
|
94
|
-
}
|
|
95
|
-
: {
|
|
96
|
-
format: GL.RGBA,
|
|
97
|
-
type: GL.UNSIGNED_BYTE
|
|
98
|
-
};
|
|
99
|
-
}
|
|
@@ -24,13 +24,11 @@ import {
|
|
|
24
24
|
boundsContain,
|
|
25
25
|
packVertices,
|
|
26
26
|
scaleToAspectRatio,
|
|
27
|
-
getTextureCoordinates
|
|
28
|
-
getTextureParams
|
|
27
|
+
getTextureCoordinates
|
|
29
28
|
} from './heatmap-layer-utils';
|
|
30
29
|
import {Buffer, DeviceFeature, Texture, TextureProps, TextureFormat} from '@luma.gl/core';
|
|
31
30
|
import {GL} from '@luma.gl/constants';
|
|
32
31
|
import {TextureTransform, TextureTransformProps} from '@luma.gl/engine';
|
|
33
|
-
import {withGLParameters} from '@luma.gl/webgl';
|
|
34
32
|
import {
|
|
35
33
|
Accessor,
|
|
36
34
|
AccessorFunction,
|
|
@@ -51,16 +49,16 @@ import AggregationLayer, {AggregationLayerProps} from '../aggregation-layer';
|
|
|
51
49
|
import {defaultColorRange, colorRangeToFlatArray} from '../utils/color-utils';
|
|
52
50
|
import weightsVs from './weights-vs.glsl';
|
|
53
51
|
import weightsFs from './weights-fs.glsl';
|
|
54
|
-
import
|
|
55
|
-
import
|
|
52
|
+
import maxVs from './max-vs.glsl';
|
|
53
|
+
import maxFs from './max-fs.glsl';
|
|
56
54
|
|
|
57
55
|
const RESOLUTION = 2; // (number of common space pixels) / (number texels)
|
|
58
56
|
const TEXTURE_PROPS: TextureProps = {
|
|
59
57
|
format: 'rgba8unorm',
|
|
60
58
|
mipmaps: false,
|
|
61
59
|
sampler: {
|
|
62
|
-
minFilter: '
|
|
63
|
-
magFilter: '
|
|
60
|
+
minFilter: 'linear',
|
|
61
|
+
magFilter: 'linear',
|
|
64
62
|
addressModeU: 'clamp-to-edge',
|
|
65
63
|
addressModeV: 'clamp-to-edge'
|
|
66
64
|
}
|
|
@@ -205,7 +203,6 @@ export default class HeatmapLayer<
|
|
|
205
203
|
maxWeightTransform?: TextureTransform;
|
|
206
204
|
textureSize: number;
|
|
207
205
|
format: TextureFormat;
|
|
208
|
-
type: GL;
|
|
209
206
|
weightsScale: number;
|
|
210
207
|
visibleWorldBounds: number[];
|
|
211
208
|
viewportCorners: number[][];
|
|
@@ -303,7 +300,7 @@ export default class HeatmapLayer<
|
|
|
303
300
|
maxTexture: maxWeightsTexture,
|
|
304
301
|
colorTexture,
|
|
305
302
|
aggregationMode: AGGREGATION_MODE[aggregation] || 0,
|
|
306
|
-
|
|
303
|
+
weightsTexture,
|
|
307
304
|
intensity,
|
|
308
305
|
threshold,
|
|
309
306
|
colorDomain
|
|
@@ -369,17 +366,21 @@ export default class HeatmapLayer<
|
|
|
369
366
|
}
|
|
370
367
|
|
|
371
368
|
_createTextures() {
|
|
372
|
-
const {textureSize, format
|
|
369
|
+
const {textureSize, format} = this.state;
|
|
373
370
|
|
|
374
371
|
this.setState({
|
|
375
372
|
weightsTexture: this.context.device.createTexture({
|
|
373
|
+
...TEXTURE_PROPS,
|
|
376
374
|
width: textureSize,
|
|
377
375
|
height: textureSize,
|
|
378
|
-
format
|
|
379
|
-
type,
|
|
380
|
-
...TEXTURE_PROPS
|
|
376
|
+
format
|
|
381
377
|
}),
|
|
382
|
-
maxWeightsTexture: this.context.device.createTexture({
|
|
378
|
+
maxWeightsTexture: this.context.device.createTexture({
|
|
379
|
+
...TEXTURE_PROPS,
|
|
380
|
+
width: 1,
|
|
381
|
+
height: 1,
|
|
382
|
+
format
|
|
383
|
+
})
|
|
383
384
|
});
|
|
384
385
|
}
|
|
385
386
|
|
|
@@ -398,61 +399,71 @@ export default class HeatmapLayer<
|
|
|
398
399
|
|
|
399
400
|
const textureSize = Math.min(weightsTextureSize, device.limits.maxTextureDimension2D as number);
|
|
400
401
|
const floatTargetSupport = FLOAT_TARGET_FEATURES.every(feature => device.features.has(feature));
|
|
401
|
-
const
|
|
402
|
+
const format: TextureFormat = floatTargetSupport ? 'rgba32float' : 'rgba8unorm';
|
|
402
403
|
const weightsScale = floatTargetSupport ? 1 : 1 / 255;
|
|
403
|
-
this.setState({textureSize, format,
|
|
404
|
+
this.setState({textureSize, format, weightsScale});
|
|
404
405
|
if (!floatTargetSupport) {
|
|
405
406
|
log.warn(
|
|
406
|
-
`HeatmapLayer: ${this.id} rendering to float texture not supported,
|
|
407
|
+
`HeatmapLayer: ${this.id} rendering to float texture not supported, falling back to low precision format`
|
|
407
408
|
)();
|
|
408
409
|
}
|
|
409
410
|
}
|
|
410
411
|
|
|
411
|
-
|
|
412
|
-
return super.getShaders(
|
|
413
|
-
type === 'max-weights-transform'
|
|
414
|
-
? {
|
|
415
|
-
vs: vsMax,
|
|
416
|
-
_fs: fsMax
|
|
417
|
-
}
|
|
418
|
-
: {
|
|
419
|
-
vs: weightsVs,
|
|
420
|
-
_fs: weightsFs
|
|
421
|
-
}
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
_createWeightsTransform(shaders = {}) {
|
|
412
|
+
_createWeightsTransform(shaders: {vs: string; fs?: string}) {
|
|
426
413
|
let {weightsTransform} = this.state;
|
|
427
|
-
|
|
414
|
+
const {weightsTexture} = this.state;
|
|
415
|
+
const attributeManager = this.getAttributeManager()!;
|
|
428
416
|
|
|
417
|
+
weightsTransform?.destroy();
|
|
429
418
|
weightsTransform = new TextureTransform(this.context.device, {
|
|
430
419
|
id: `${this.id}-weights-transform`,
|
|
420
|
+
bufferLayout: attributeManager.getBufferLayouts(),
|
|
431
421
|
vertexCount: 1,
|
|
432
|
-
targetTexture:
|
|
433
|
-
|
|
422
|
+
targetTexture: weightsTexture!,
|
|
423
|
+
parameters: {
|
|
424
|
+
depthWriteEnabled: false,
|
|
425
|
+
blendColorOperation: 'add',
|
|
426
|
+
blendColorSrcFactor: 'one',
|
|
427
|
+
blendColorDstFactor: 'one',
|
|
428
|
+
blendAlphaSrcFactor: 'one',
|
|
429
|
+
blendAlphaDstFactor: 'one'
|
|
430
|
+
},
|
|
431
|
+
topology: 'point-list',
|
|
434
432
|
...shaders
|
|
435
433
|
} as TextureTransformProps);
|
|
434
|
+
|
|
436
435
|
this.setState({weightsTransform});
|
|
437
436
|
}
|
|
438
437
|
|
|
439
438
|
_setupResources() {
|
|
440
439
|
this._createTextures();
|
|
440
|
+
const {device} = this.context;
|
|
441
441
|
const {textureSize, weightsTexture, maxWeightsTexture} = this.state;
|
|
442
442
|
|
|
443
|
-
const weightsTransformShaders = this.getShaders(
|
|
443
|
+
const weightsTransformShaders = this.getShaders({
|
|
444
|
+
vs: weightsVs,
|
|
445
|
+
fs: weightsFs
|
|
446
|
+
});
|
|
444
447
|
this._createWeightsTransform(weightsTransformShaders);
|
|
445
448
|
|
|
446
|
-
const maxWeightsTransformShaders = this.getShaders(
|
|
447
|
-
const maxWeightTransform = new TextureTransform(
|
|
449
|
+
const maxWeightsTransformShaders = this.getShaders({vs: maxVs, fs: maxFs});
|
|
450
|
+
const maxWeightTransform = new TextureTransform(device, {
|
|
448
451
|
id: `${this.id}-max-weights-transform`,
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
_targetTexture: maxWeightsTexture,
|
|
453
|
-
_targetTextureVarying: 'outTexture',
|
|
452
|
+
bindings: {inTexture: weightsTexture},
|
|
453
|
+
uniforms: {textureSize},
|
|
454
|
+
targetTexture: maxWeightsTexture,
|
|
454
455
|
...maxWeightsTransformShaders,
|
|
455
|
-
|
|
456
|
+
vertexCount: textureSize * textureSize,
|
|
457
|
+
topology: 'point-list',
|
|
458
|
+
parameters: {
|
|
459
|
+
depthWriteEnabled: false,
|
|
460
|
+
blendColorOperation: 'max',
|
|
461
|
+
blendAlphaOperation: 'max',
|
|
462
|
+
blendColorSrcFactor: 'one',
|
|
463
|
+
blendColorDstFactor: 'one',
|
|
464
|
+
blendAlphaSrcFactor: 'one',
|
|
465
|
+
blendAlphaDstFactor: 'one'
|
|
466
|
+
}
|
|
456
467
|
});
|
|
457
468
|
|
|
458
469
|
this.setState({
|
|
@@ -460,35 +471,27 @@ export default class HeatmapLayer<
|
|
|
460
471
|
maxWeightsTexture,
|
|
461
472
|
maxWeightTransform,
|
|
462
473
|
zoom: null,
|
|
463
|
-
triPositionBuffer:
|
|
464
|
-
|
|
465
|
-
// @ts-expect-error
|
|
466
|
-
accessor: {size: 3}
|
|
467
|
-
}),
|
|
468
|
-
triTexCoordBuffer: this.context.device.createBuffer({
|
|
469
|
-
byteLength: 48,
|
|
470
|
-
// @ts-expect-error
|
|
471
|
-
accessor: {size: 2}
|
|
472
|
-
})
|
|
474
|
+
triPositionBuffer: device.createBuffer({byteLength: 48}),
|
|
475
|
+
triTexCoordBuffer: device.createBuffer({byteLength: 48})
|
|
473
476
|
});
|
|
474
477
|
}
|
|
475
478
|
|
|
476
479
|
// overwrite super class method to update transform model
|
|
477
480
|
updateShaders(shaderOptions) {
|
|
478
|
-
//
|
|
479
|
-
this._createWeightsTransform(
|
|
481
|
+
// shader params (modules, injects) changed, update model object
|
|
482
|
+
this._createWeightsTransform({
|
|
483
|
+
vs: weightsVs,
|
|
484
|
+
fs: weightsFs,
|
|
485
|
+
...shaderOptions
|
|
486
|
+
});
|
|
480
487
|
}
|
|
481
488
|
|
|
482
489
|
_updateMaxWeightValue() {
|
|
483
|
-
const {maxWeightTransform} = this.state;
|
|
490
|
+
const {maxWeightTransform, textureSize} = this.state;
|
|
491
|
+
|
|
484
492
|
maxWeightTransform!.run({
|
|
485
|
-
parameters: {
|
|
486
|
-
|
|
487
|
-
blend: true,
|
|
488
|
-
depthTest: false,
|
|
489
|
-
blendFunc: [GL.ONE, GL.ONE],
|
|
490
|
-
blendEquation: GL.MAX
|
|
491
|
-
}
|
|
493
|
+
parameters: {viewport: [0, 0, 1, 1]},
|
|
494
|
+
clearColor: [0, 0, 0, 0]
|
|
492
495
|
});
|
|
493
496
|
}
|
|
494
497
|
|
|
@@ -563,18 +566,16 @@ export default class HeatmapLayer<
|
|
|
563
566
|
let {colorTexture} = this.state;
|
|
564
567
|
const colors = colorRangeToFlatArray(colorRange, false, Uint8Array as any);
|
|
565
568
|
|
|
566
|
-
if (colorTexture) {
|
|
567
|
-
//
|
|
568
|
-
colorTexture.
|
|
569
|
-
data: colors,
|
|
570
|
-
width: colorRange.length
|
|
571
|
-
});
|
|
569
|
+
if (colorTexture && colorTexture?.width === colorRange.length) {
|
|
570
|
+
// TODO(v9): Unclear whether `setSubImageData` is a public API, or what to use if not.
|
|
571
|
+
(colorTexture as any).setSubImageData({data: colors});
|
|
572
572
|
} else {
|
|
573
|
+
colorTexture?.destroy();
|
|
573
574
|
colorTexture = this.context.device.createTexture({
|
|
575
|
+
...TEXTURE_PROPS,
|
|
574
576
|
data: colors,
|
|
575
577
|
width: colorRange.length,
|
|
576
|
-
height: 1
|
|
577
|
-
...TEXTURE_PROPS
|
|
578
|
+
height: 1
|
|
578
579
|
});
|
|
579
580
|
}
|
|
580
581
|
this.setState({colorTexture});
|
|
@@ -602,41 +603,22 @@ export default class HeatmapLayer<
|
|
|
602
603
|
this.state.colorDomain = colorDomain || DEFAULT_COLOR_DOMAIN;
|
|
603
604
|
}
|
|
604
605
|
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
weightsTransform.
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
weightsTransform.run({
|
|
619
|
-
uniforms,
|
|
620
|
-
parameters: {
|
|
621
|
-
// @ts-expect-error TODO(v9): Resolve errors.
|
|
622
|
-
blend: true,
|
|
623
|
-
depthTest: false,
|
|
624
|
-
blendFunc: [GL.ONE, GL.ONE],
|
|
625
|
-
blendEquation: GL.FUNC_ADD
|
|
626
|
-
},
|
|
627
|
-
clearRenderTarget: true,
|
|
628
|
-
attributes: this.getAttributes(),
|
|
629
|
-
moduleSettings: this.getModuleSettings()
|
|
630
|
-
});
|
|
606
|
+
const attributeManager = this.getAttributeManager()!;
|
|
607
|
+
const attributes = attributeManager.getAttributes();
|
|
608
|
+
const moduleSettings = this.getModuleSettings();
|
|
609
|
+
const positions = attributes.positions.buffer;
|
|
610
|
+
const uniforms = {radiusPixels, commonBounds, textureWidth: textureSize, weightsScale};
|
|
611
|
+
const weights = attributes.weights.buffer;
|
|
612
|
+
weightsTransform.model.setAttributes({positions, weights});
|
|
613
|
+
weightsTransform.model.setVertexCount(this.getNumInstances());
|
|
614
|
+
weightsTransform.model.setUniforms(uniforms);
|
|
615
|
+
weightsTransform.model.updateModuleSettings(moduleSettings);
|
|
616
|
+
weightsTransform.run({
|
|
617
|
+
parameters: {viewport: [0, 0, textureSize, textureSize]},
|
|
618
|
+
clearColor: [0, 0, 0, 0]
|
|
631
619
|
});
|
|
632
|
-
this._updateMaxWeightValue();
|
|
633
620
|
|
|
634
|
-
|
|
635
|
-
// TODO v9 sampler support in luma.gl needs to improve
|
|
636
|
-
// weightsTexture.setSampler({
|
|
637
|
-
// magFilter: 'linear',
|
|
638
|
-
// minFilter: 'linear'
|
|
639
|
-
// });
|
|
621
|
+
this._updateMaxWeightValue();
|
|
640
622
|
}
|
|
641
623
|
|
|
642
624
|
_debouncedUpdateWeightmap(fromTimer = false) {
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
export default `\
|
|
2
2
|
#version 300 es
|
|
3
|
-
|
|
3
|
+
uniform sampler2D inTexture;
|
|
4
|
+
uniform float textureSize;
|
|
4
5
|
out vec4 outTexture;
|
|
5
6
|
|
|
6
7
|
void main()
|
|
7
8
|
{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
// Sample every pixel in texture
|
|
10
|
+
int yIndex = gl_VertexID / int(textureSize);
|
|
11
|
+
int xIndex = gl_VertexID - (yIndex * int(textureSize));
|
|
12
|
+
vec2 uv = (0.5 + vec2(float(xIndex), float(yIndex))) / textureSize;
|
|
13
|
+
outTexture = texture(inTexture, uv);
|
|
14
|
+
|
|
15
|
+
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
|
16
|
+
// Enforce default value for ANGLE issue (https://bugs.chromium.org/p/angleproject/issues/detail?id=3941)
|
|
17
|
+
gl_PointSize = 1.0;
|
|
12
18
|
}
|
|
13
19
|
`;
|
|
@@ -25,7 +25,7 @@ export default `\
|
|
|
25
25
|
precision highp float;
|
|
26
26
|
|
|
27
27
|
uniform float opacity;
|
|
28
|
-
uniform sampler2D
|
|
28
|
+
uniform sampler2D weightsTexture;
|
|
29
29
|
uniform sampler2D colorTexture;
|
|
30
30
|
uniform float aggregationMode;
|
|
31
31
|
|
|
@@ -43,7 +43,7 @@ vec4 getLinearColor(float value) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
void main(void) {
|
|
46
|
-
vec4 weights = texture(
|
|
46
|
+
vec4 weights = texture(weightsTexture, vTexCoords);
|
|
47
47
|
float weight = weights.r;
|
|
48
48
|
|
|
49
49
|
if (aggregationMode > 0.5) {
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
19
|
// THE SOFTWARE.
|
|
20
20
|
|
|
21
|
-
import type {Device, Texture} from '@luma.gl/core';
|
|
22
|
-
import {Model
|
|
21
|
+
import type {Buffer, Device, Texture} from '@luma.gl/core';
|
|
22
|
+
import {Model} from '@luma.gl/engine';
|
|
23
23
|
import {Layer, LayerContext, project32} from '@deck.gl/core';
|
|
24
24
|
import vs from './triangle-layer-vertex.glsl';
|
|
25
25
|
import fs from './triangle-layer-fragment.glsl';
|
|
26
26
|
|
|
27
27
|
type _TriangleLayerProps = {
|
|
28
|
+
data: {attributes: {positions: Buffer; texCoords: Buffer}};
|
|
28
29
|
colorDomain: number[];
|
|
29
30
|
aggregationMode: string;
|
|
30
31
|
threshold: number;
|
|
@@ -32,7 +33,7 @@ type _TriangleLayerProps = {
|
|
|
32
33
|
vertexCount: number;
|
|
33
34
|
colorTexture: Texture;
|
|
34
35
|
maxTexture: Texture;
|
|
35
|
-
|
|
36
|
+
weightsTexture: Texture;
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
export default class TriangleLayer extends Layer<_TriangleLayerProps> {
|
|
@@ -40,6 +41,8 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> {
|
|
|
40
41
|
|
|
41
42
|
state!: {
|
|
42
43
|
model: Model;
|
|
44
|
+
positions: Buffer;
|
|
45
|
+
texCoords: Buffer;
|
|
43
46
|
};
|
|
44
47
|
|
|
45
48
|
getShaders() {
|
|
@@ -47,40 +50,31 @@ export default class TriangleLayer extends Layer<_TriangleLayerProps> {
|
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
initializeState({device}: LayerContext): void {
|
|
50
|
-
|
|
51
|
-
attributeManager.add({
|
|
52
|
-
positions: {size: 3, noAlloc: true},
|
|
53
|
-
texCoords: {size: 2, noAlloc: true}
|
|
54
|
-
});
|
|
55
|
-
this.setState({
|
|
56
|
-
model: this._getModel(device)
|
|
57
|
-
});
|
|
53
|
+
this.setState({model: this._getModel(device)});
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
_getModel(device: Device): Model {
|
|
61
|
-
const {vertexCount} = this.props;
|
|
57
|
+
const {vertexCount, data, weightsTexture, maxTexture, colorTexture} = this.props;
|
|
62
58
|
|
|
63
59
|
return new Model(device, {
|
|
64
60
|
...this.getShaders(),
|
|
65
61
|
id: this.props.id,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
bindings: {weightsTexture, maxTexture, colorTexture},
|
|
63
|
+
attributes: data.attributes,
|
|
64
|
+
bufferLayout: [
|
|
65
|
+
{name: 'positions', format: 'float32x3'},
|
|
66
|
+
{name: 'texCoords', format: 'float32x2'}
|
|
67
|
+
],
|
|
68
|
+
topology: 'triangle-fan-webgl',
|
|
69
|
+
vertexCount
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
draw({uniforms}): void {
|
|
74
74
|
const {model} = this.state;
|
|
75
|
-
|
|
76
|
-
const {texture, maxTexture, colorTexture, intensity, threshold, aggregationMode, colorDomain} =
|
|
77
|
-
this.props;
|
|
78
|
-
|
|
75
|
+
const {intensity, threshold, aggregationMode, colorDomain} = this.props;
|
|
79
76
|
model.setUniforms({
|
|
80
77
|
...uniforms,
|
|
81
|
-
texture,
|
|
82
|
-
maxTexture,
|
|
83
|
-
colorTexture,
|
|
84
78
|
intensity,
|
|
85
79
|
threshold,
|
|
86
80
|
aggregationMode,
|
|
@@ -8,17 +8,19 @@ uniform float radiusPixels;
|
|
|
8
8
|
uniform float textureWidth;
|
|
9
9
|
uniform vec4 commonBounds;
|
|
10
10
|
uniform float weightsScale;
|
|
11
|
+
|
|
11
12
|
void main()
|
|
12
13
|
{
|
|
13
14
|
weightsTexture = vec4(weights * weightsScale, 0., 0., 1.);
|
|
14
15
|
|
|
15
|
-
float radiusTexels
|
|
16
|
+
float radiusTexels = project_pixel_size(radiusPixels) * textureWidth / (commonBounds.z - commonBounds.x);
|
|
16
17
|
gl_PointSize = radiusTexels * 2.;
|
|
17
18
|
|
|
18
19
|
vec3 commonPosition = project_position(positions, positions64Low);
|
|
19
20
|
|
|
20
|
-
// map xy from commonBounds to [-1, 1]
|
|
21
|
+
// // map xy from commonBounds to [-1, 1]
|
|
21
22
|
gl_Position.xy = (commonPosition.xy - commonBounds.xy) / (commonBounds.zw - commonBounds.xy) ;
|
|
22
23
|
gl_Position.xy = (gl_Position.xy * 2.) - (1.);
|
|
24
|
+
gl_Position.w = 1.0;
|
|
23
25
|
}
|
|
24
26
|
`;
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import { Device } from '@luma.gl/core';
|
|
2
|
-
import { GL } from '@luma.gl/constants';
|
|
3
1
|
export declare function getBounds(points: number[][]): number[];
|
|
4
2
|
export declare function boundsContain(currentBounds: number[], targetBounds: number[]): boolean;
|
|
5
3
|
export declare function packVertices(points: number[][], dimensions?: number): Float32Array;
|
|
6
4
|
export declare function scaleToAspectRatio(boundingBox: number[], width: number, height: number): number[];
|
|
7
5
|
export declare function getTextureCoordinates(point: number[], bounds: number[]): number[];
|
|
8
|
-
export declare function getTextureParams({ device, floatTargetSupport }: {
|
|
9
|
-
device: Device;
|
|
10
|
-
floatTargetSupport?: boolean;
|
|
11
|
-
}): {
|
|
12
|
-
format: GL;
|
|
13
|
-
type: GL;
|
|
14
|
-
};
|
|
15
6
|
//# sourceMappingURL=heatmap-layer-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heatmap-layer-utils.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/heatmap-layer-utils.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"heatmap-layer-utils.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/heatmap-layer-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAWtD;AAGD,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAUtF;AAKD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAE,MAAU,GAAG,YAAY,CAQrF;AAGD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA6BjG;AAGD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAGtE"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Buffer, Texture, TextureFormat } from '@luma.gl/core';
|
|
2
|
-
import { GL } from '@luma.gl/constants';
|
|
3
2
|
import { TextureTransform } from '@luma.gl/engine';
|
|
4
3
|
import { Accessor, AccessorFunction, AttributeManager, ChangeFlags, Color, Layer, LayerContext, LayersList, Position, UpdateParameters, DefaultProps } from '@deck.gl/core';
|
|
5
4
|
import AggregationLayer, { AggregationLayerProps } from '../aggregation-layer';
|
|
@@ -91,7 +90,6 @@ export default class HeatmapLayer<DataT = any, ExtraPropsT extends {} = {}> exte
|
|
|
91
90
|
maxWeightTransform?: TextureTransform;
|
|
92
91
|
textureSize: number;
|
|
93
92
|
format: TextureFormat;
|
|
94
|
-
type: GL;
|
|
95
93
|
weightsScale: number;
|
|
96
94
|
visibleWorldBounds: number[];
|
|
97
95
|
viewportCorners: number[][];
|
|
@@ -110,8 +108,10 @@ export default class HeatmapLayer<DataT = any, ExtraPropsT extends {} = {}> exte
|
|
|
110
108
|
_createTextures(): void;
|
|
111
109
|
_setupAttributes(): void;
|
|
112
110
|
_setupTextureParams(): void;
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
_createWeightsTransform(shaders: {
|
|
112
|
+
vs: string;
|
|
113
|
+
fs?: string;
|
|
114
|
+
}): void;
|
|
115
115
|
_setupResources(): void;
|
|
116
116
|
updateShaders(shaderOptions: any): void;
|
|
117
117
|
_updateMaxWeightValue(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heatmap-layer.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/heatmap-layer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"heatmap-layer.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/heatmap-layer.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAC,MAAM,EAAiB,OAAO,EAAgB,aAAa,EAAC,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAC,gBAAgB,EAAwB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,KAAK,EAEL,KAAK,EACL,YAAY,EACZ,UAAU,EAEV,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACb,MAAM,eAAe,CAAC;AAEvB,OAAO,gBAAgB,EAAE,EAAC,qBAAqB,EAAC,MAAM,sBAAsB,CAAC;AAsD7E,MAAM,MAAM,iBAAiB,CAAC,KAAK,GAAG,OAAO,IAAI,kBAAkB,CAAC,KAAK,CAAC,GACxE,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAE/B,KAAK,kBAAkB,CAAC,KAAK,IAAI;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC;IAErB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAEtC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAE7B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAEhD;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC;AAEF,mDAAmD;AACnD,MAAM,CAAC,OAAO,OAAO,YAAY,CAC/B,KAAK,GAAG,GAAG,EACX,WAAW,SAAS,EAAE,GAAG,EAAE,CAC3B,SAAQ,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IAClF,MAAM,CAAC,SAAS,SAAkB;IAClC,MAAM,CAAC,YAAY,2CAAgB;IAEnC,KAAK,EAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG;QACzC,SAAS,EAAE,OAAO,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;QAClC,WAAW,CAAC,EAAE,GAAG,CAAC;QAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;QACpC,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;QACtC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,aAAa,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,eAAe,EAAE,MAAM,EAAE,EAAE,CAAC;KAC7B,CAAC;IAEF,eAAe;IAaf,iBAAiB,CAAC,EAAC,WAAW,EAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAMvD,WAAW,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAQxC,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;IA8BhD,YAAY,IAAI,UAAU,GAAG,KAAK;IA2ClC,aAAa,CAAC,OAAO,EAAE,YAAY;IA2BnC,oBAAoB;IAOpB,eAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;;;;IAuB5C,eAAe;IAmBf,gBAAgB;IAShB,mBAAmB;IAgBnB,uBAAuB,CAAC,OAAO,EAAE;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAC;IA0B1D,eAAe;IA0Cf,aAAa,CAAC,aAAa,KAAA;IAS3B,qBAAqB;IAUrB,aAAa,CAAC,WAAW,GAAE,GAAW,GAAG,OAAO;IAkDhD,6BAA6B;IAe7B,mBAAmB,CAAC,IAAI,KAAA;IAoBxB,gBAAgB;IAwChB,yBAAyB,CAAC,SAAS,UAAQ;IAsB3C,oBAAoB,CAAC,WAAW,KAAA,EAAE,IAAI,GAAE;QAAC,wBAAwB,CAAC,EAAE,OAAO,CAAA;KAAM;IA0CjF,oBAAoB,CAAC,YAAY,KAAA;CAQlC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare const _default: "#version 300 es\
|
|
1
|
+
declare const _default: "#version 300 es\nuniform sampler2D inTexture;\nuniform float textureSize;\nout vec4 outTexture;\n\nvoid main()\n{\n // Sample every pixel in texture\n int yIndex = gl_VertexID / int(textureSize);\n int xIndex = gl_VertexID - (yIndex * int(textureSize));\n vec2 uv = (0.5 + vec2(float(xIndex), float(yIndex))) / textureSize;\n outTexture = texture(inTexture, uv);\n\n gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n // Enforce default value for ANGLE issue (https://bugs.chromium.org/p/angleproject/issues/detail?id=3941)\n gl_PointSize = 1.0;\n}\n";
|
|
2
2
|
export default _default;
|
|
3
3
|
//# sourceMappingURL=max-vs.glsl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"max-vs.glsl.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/max-vs.glsl.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"max-vs.glsl.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/max-vs.glsl.ts"],"names":[],"mappings":";AAAA,wBAkBE"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare const _default: "#version 300 es\n#define SHADER_NAME triangle-layer-fragment-shader\n\nprecision highp float;\n\nuniform float opacity;\nuniform sampler2D
|
|
1
|
+
declare const _default: "#version 300 es\n#define SHADER_NAME triangle-layer-fragment-shader\n\nprecision highp float;\n\nuniform float opacity;\nuniform sampler2D weightsTexture;\nuniform sampler2D colorTexture;\nuniform float aggregationMode;\n\nin vec2 vTexCoords;\nin float vIntensityMin;\nin float vIntensityMax;\n\nout vec4 fragColor;\n\nvec4 getLinearColor(float value) {\n float factor = clamp(value * vIntensityMax, 0., 1.);\n vec4 color = texture(colorTexture, vec2(factor, 0.5));\n color.a *= min(value * vIntensityMin, 1.0);\n return color;\n}\n\nvoid main(void) {\n vec4 weights = texture(weightsTexture, vTexCoords);\n float weight = weights.r;\n\n if (aggregationMode > 0.5) {\n weight /= max(1.0, weights.a);\n }\n\n // discard pixels with 0 weight.\n if (weight <= 0.) {\n discard;\n }\n\n vec4 linearColor = getLinearColor(weight);\n linearColor.a *= opacity;\n fragColor = linearColor;\n}\n";
|
|
2
2
|
export default _default;
|
|
3
3
|
//# sourceMappingURL=triangle-layer-fragment.glsl.d.ts.map
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import type { Device, Texture } from '@luma.gl/core';
|
|
1
|
+
import type { Buffer, Device, Texture } from '@luma.gl/core';
|
|
2
2
|
import { Model } from '@luma.gl/engine';
|
|
3
3
|
import { Layer, LayerContext } from '@deck.gl/core';
|
|
4
4
|
type _TriangleLayerProps = {
|
|
5
|
+
data: {
|
|
6
|
+
attributes: {
|
|
7
|
+
positions: Buffer;
|
|
8
|
+
texCoords: Buffer;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
5
11
|
colorDomain: number[];
|
|
6
12
|
aggregationMode: string;
|
|
7
13
|
threshold: number;
|
|
@@ -9,12 +15,14 @@ type _TriangleLayerProps = {
|
|
|
9
15
|
vertexCount: number;
|
|
10
16
|
colorTexture: Texture;
|
|
11
17
|
maxTexture: Texture;
|
|
12
|
-
|
|
18
|
+
weightsTexture: Texture;
|
|
13
19
|
};
|
|
14
20
|
export default class TriangleLayer extends Layer<_TriangleLayerProps> {
|
|
15
21
|
static layerName: string;
|
|
16
22
|
state: {
|
|
17
23
|
model: Model;
|
|
24
|
+
positions: Buffer;
|
|
25
|
+
texCoords: Buffer;
|
|
18
26
|
};
|
|
19
27
|
getShaders(): {
|
|
20
28
|
vs: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"triangle-layer.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/triangle-layer.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAC,MAAM,EAAE,OAAO,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"triangle-layer.d.ts","sourceRoot":"","sources":["../../src/heatmap-layer/triangle-layer.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAC,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAC,KAAK,EAAE,YAAY,EAAY,MAAM,eAAe,CAAC;AAI7D,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE;QAAC,UAAU,EAAE;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC,CAAC;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,KAAK,CAAC,mBAAmB,CAAC;IACnE,MAAM,CAAC,SAAS,SAAmB;IAEnC,KAAK,EAAG;QACN,KAAK,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAEF,UAAU;;;;;IAIV,eAAe,CAAC,EAAC,MAAM,EAAC,EAAE,YAAY,GAAG,IAAI;IAI7C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK;IAiBhC,IAAI,CAAC,EAAC,QAAQ,EAAC;;KAAA,GAAG,IAAI;CAYvB"}
|