@flowmap.gl/layers 8.0.0-alpha.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/LICENSE +199 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.d.ts +76 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.d.ts.map +1 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.js +139 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.d.ts +3 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.d.ts.map +1 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.js +37 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.d.ts +3 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.d.ts.map +1 -0
- package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.js +91 -0
- package/dist/AnimatedFlowLinesLayer/index.d.ts +3 -0
- package/dist/AnimatedFlowLinesLayer/index.d.ts.map +1 -0
- package/dist/AnimatedFlowLinesLayer/index.js +3 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts +59 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts.map +1 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayer.js +115 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts +3 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts.map +1 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.js +73 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.d.ts +3 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.d.ts.map +1 -0
- package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.js +63 -0
- package/dist/FlowCirclesLayer/index.d.ts +3 -0
- package/dist/FlowCirclesLayer/index.d.ts.map +1 -0
- package/dist/FlowCirclesLayer/index.js +3 -0
- package/dist/FlowLinesLayer/FlowLinesLayer.d.ts +64 -0
- package/dist/FlowLinesLayer/FlowLinesLayer.d.ts.map +1 -0
- package/dist/FlowLinesLayer/FlowLinesLayer.js +182 -0
- package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.d.ts +3 -0
- package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.d.ts.map +1 -0
- package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.js +36 -0
- package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts +3 -0
- package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts.map +1 -0
- package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.js +102 -0
- package/dist/FlowLinesLayer/index.d.ts +3 -0
- package/dist/FlowLinesLayer/index.d.ts.map +1 -0
- package/dist/FlowLinesLayer/index.js +3 -0
- package/dist/FlowMapLayer.d.ts +70 -0
- package/dist/FlowMapLayer.d.ts.map +1 -0
- package/dist/FlowMapLayer.js +304 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/package.json +24 -0
- package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.ts +189 -0
- package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.ts +37 -0
- package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.ts +90 -0
- package/src/AnimatedFlowLinesLayer/index.ts +3 -0
- package/src/FlowCirclesLayer/FlowCirclesLayer.ts +150 -0
- package/src/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.ts +72 -0
- package/src/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.ts +62 -0
- package/src/FlowCirclesLayer/index.ts +3 -0
- package/src/FlowLinesLayer/FlowLinesLayer.ts +238 -0
- package/src/FlowLinesLayer/FlowLinesLayerFragment.glsl.ts +35 -0
- package/src/FlowLinesLayer/FlowLinesLayerVertex.glsl.ts +101 -0
- package/src/FlowLinesLayer/index.ts +3 -0
- package/src/FlowMapLayer.ts +448 -0
- package/src/index.ts +7 -0
- package/src/types.ts +67 -0
- package/tsconfig.json +11 -0
- package/typings.d.ts +4 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export default `\
|
|
20
|
+
#define SHADER_NAME animated-flow-lines-layer-fragment-shader
|
|
21
|
+
|
|
22
|
+
precision highp float;
|
|
23
|
+
|
|
24
|
+
uniform float animationTailLength;
|
|
25
|
+
|
|
26
|
+
varying vec4 vColor;
|
|
27
|
+
varying float sourceToTarget;
|
|
28
|
+
varying vec2 uv;
|
|
29
|
+
|
|
30
|
+
void main(void) {
|
|
31
|
+
geometry.uv = uv;
|
|
32
|
+
|
|
33
|
+
gl_FragColor = vec4(vColor.xyz, vColor.w * smoothstep(1.0 - animationTailLength, 1.0, fract(sourceToTarget)));
|
|
34
|
+
|
|
35
|
+
DECKGL_FILTER_COLOR(gl_FragColor, geometry);
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export default `\
|
|
19
|
+
#define SHADER_NAME animated-flow-lines-layer-vertex-shader
|
|
20
|
+
#define SPEED 0.015
|
|
21
|
+
#define NUM_PARTS 5.0
|
|
22
|
+
|
|
23
|
+
attribute vec3 positions;
|
|
24
|
+
attribute vec3 instanceSourcePositions;
|
|
25
|
+
attribute vec3 instanceTargetPositions;
|
|
26
|
+
attribute vec3 instanceSourcePositions64Low;
|
|
27
|
+
attribute vec3 instanceTargetPositions64Low;
|
|
28
|
+
attribute vec4 instanceColors;
|
|
29
|
+
attribute vec3 instancePickingColors;
|
|
30
|
+
attribute float instanceWidths;
|
|
31
|
+
attribute float instancePickable;
|
|
32
|
+
attribute float instanceStaggering;
|
|
33
|
+
|
|
34
|
+
uniform float opacity;
|
|
35
|
+
uniform float currentTime;
|
|
36
|
+
uniform float thicknessUnit;
|
|
37
|
+
|
|
38
|
+
varying vec4 vColor;
|
|
39
|
+
varying float sourceToTarget;
|
|
40
|
+
varying vec2 uv;
|
|
41
|
+
|
|
42
|
+
// offset vector by strokeWidth pixels
|
|
43
|
+
// offset_direction is -1 (left) or 1 (right)
|
|
44
|
+
vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction, float width) {
|
|
45
|
+
// normalized direction of the line
|
|
46
|
+
vec2 dir_screenspace = normalize(line_clipspace * project_uViewportSize);
|
|
47
|
+
// rotate by 90 degrees
|
|
48
|
+
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
|
49
|
+
|
|
50
|
+
return dir_screenspace * offset_direction * width / 2.0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
void main(void) {
|
|
54
|
+
geometry.worldPosition = instanceSourcePositions;
|
|
55
|
+
geometry.worldPositionAlt = instanceTargetPositions;
|
|
56
|
+
|
|
57
|
+
// Position
|
|
58
|
+
vec4 source_commonspace;
|
|
59
|
+
vec4 target_commonspace;
|
|
60
|
+
vec4 source = project_position_to_clipspace(instanceSourcePositions, instanceSourcePositions64Low, vec3(0.), source_commonspace);
|
|
61
|
+
vec4 target = project_position_to_clipspace(instanceTargetPositions, instanceTargetPositions64Low, vec3(0.), target_commonspace);
|
|
62
|
+
|
|
63
|
+
float widthPixels = instanceWidths * thicknessUnit;
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// linear interpolation of source & target to pick right coord
|
|
67
|
+
float segmentIndex = positions.x;
|
|
68
|
+
vec4 p = mix(source, target, segmentIndex);
|
|
69
|
+
geometry.position = mix(source_commonspace, target_commonspace, segmentIndex);
|
|
70
|
+
uv = positions.xy;
|
|
71
|
+
geometry.uv = uv;
|
|
72
|
+
if (instancePickable > 0.5) {
|
|
73
|
+
geometry.pickingColor = instancePickingColors;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// extrude
|
|
77
|
+
vec3 offset = vec3(
|
|
78
|
+
getExtrusionOffset(target.xy - source.xy, positions.y, widthPixels),
|
|
79
|
+
0.0);
|
|
80
|
+
DECKGL_FILTER_SIZE(offset, geometry);
|
|
81
|
+
gl_Position = p + vec4(project_pixel_size_to_clipspace(offset.xy), 0.0, 0.0);
|
|
82
|
+
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
|
|
83
|
+
|
|
84
|
+
// Color
|
|
85
|
+
vColor = vec4(instanceColors.rgb, instanceColors.a * opacity) / 255.;
|
|
86
|
+
DECKGL_FILTER_COLOR(vColor, geometry);
|
|
87
|
+
|
|
88
|
+
sourceToTarget = positions.x * length(source - target) * NUM_PARTS - currentTime * SPEED + instanceStaggering;
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {Layer, picking, project32} from '@deck.gl/core';
|
|
20
|
+
import GL from '@luma.gl/constants';
|
|
21
|
+
import {Geometry, Model} from '@luma.gl/core';
|
|
22
|
+
import FragmentShader from './FlowCirclesLayerFragment.glsl';
|
|
23
|
+
import VertexShader from './FlowCirclesLayerVertex.glsl';
|
|
24
|
+
import {FlowCirclesLayerAttributes, RGBA} from '@flowmap.gl/data';
|
|
25
|
+
import {LayerProps} from '../types';
|
|
26
|
+
|
|
27
|
+
export type FlowCirclesDatum = Record<string, unknown>;
|
|
28
|
+
|
|
29
|
+
export interface Props extends LayerProps {
|
|
30
|
+
id: string;
|
|
31
|
+
opacity?: number;
|
|
32
|
+
pickable?: boolean;
|
|
33
|
+
emptyColor?: RGBA;
|
|
34
|
+
emptyOutlineColor?: RGBA;
|
|
35
|
+
getColor?: (d: FlowCirclesDatum) => RGBA;
|
|
36
|
+
getPosition?: (d: FlowCirclesDatum) => [number, number];
|
|
37
|
+
getInRadius?: (d: FlowCirclesDatum) => number;
|
|
38
|
+
getOutRadius?: (d: FlowCirclesDatum) => number;
|
|
39
|
+
data: FlowCirclesDatum[] | FlowCirclesLayerAttributes;
|
|
40
|
+
updateTriggers?: {[key: string]: Record<string, unknown>};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const DEFAULT_COLOR = [0, 0, 0, 255];
|
|
44
|
+
const DEFAULT_EMPTY_COLOR = [255, 255, 255, 255];
|
|
45
|
+
const DEFAULT_EMPTY_OUTLINE_COLOR = [180, 180, 180, 255];
|
|
46
|
+
|
|
47
|
+
class FlowCirclesLayer extends Layer {
|
|
48
|
+
static layerName = 'FlowCirclesLayer';
|
|
49
|
+
|
|
50
|
+
static defaultProps = {
|
|
51
|
+
getColor: {type: 'accessor', value: DEFAULT_COLOR},
|
|
52
|
+
emptyColor: {type: 'accessor', value: DEFAULT_EMPTY_COLOR},
|
|
53
|
+
emptyOutlineColor: {type: 'accessor', value: DEFAULT_EMPTY_OUTLINE_COLOR},
|
|
54
|
+
getPosition: {type: 'accessor', value: (d: FlowCirclesDatum) => d.position},
|
|
55
|
+
getInRadius: {type: 'accessor', value: 1},
|
|
56
|
+
getOutRadius: {type: 'accessor', value: 1},
|
|
57
|
+
parameters: {
|
|
58
|
+
depthTest: false,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
// props!: Props;
|
|
62
|
+
|
|
63
|
+
constructor(props: Props) {
|
|
64
|
+
super(props);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getShaders() {
|
|
68
|
+
return super.getShaders({
|
|
69
|
+
vs: VertexShader,
|
|
70
|
+
fs: FragmentShader,
|
|
71
|
+
modules: [project32, picking],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
initializeState() {
|
|
76
|
+
this.getAttributeManager().addInstanced({
|
|
77
|
+
instancePositions: {
|
|
78
|
+
size: 3,
|
|
79
|
+
type: GL.DOUBLE,
|
|
80
|
+
fp64: this.use64bitPositions(),
|
|
81
|
+
transition: true,
|
|
82
|
+
accessor: 'getPosition',
|
|
83
|
+
},
|
|
84
|
+
instanceInRadius: {
|
|
85
|
+
size: 1,
|
|
86
|
+
transition: true,
|
|
87
|
+
accessor: 'getInRadius',
|
|
88
|
+
defaultValue: 1,
|
|
89
|
+
},
|
|
90
|
+
instanceOutRadius: {
|
|
91
|
+
size: 1,
|
|
92
|
+
transition: true,
|
|
93
|
+
accessor: 'getOutRadius',
|
|
94
|
+
defaultValue: 1,
|
|
95
|
+
},
|
|
96
|
+
instanceColors: {
|
|
97
|
+
size: 4,
|
|
98
|
+
transition: true,
|
|
99
|
+
type: GL.UNSIGNED_BYTE,
|
|
100
|
+
accessor: 'getColor',
|
|
101
|
+
defaultValue: DEFAULT_COLOR,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
updateState({props, oldProps, changeFlags}: any) {
|
|
107
|
+
super.updateState({props, oldProps, changeFlags});
|
|
108
|
+
if (changeFlags.extensionsChanged) {
|
|
109
|
+
const {gl} = this.context;
|
|
110
|
+
if (this.state.model) {
|
|
111
|
+
this.state.model.delete();
|
|
112
|
+
}
|
|
113
|
+
this.setState({model: this._getModel(gl)});
|
|
114
|
+
this.getAttributeManager().invalidateAll();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
draw({uniforms}: any) {
|
|
119
|
+
const {emptyColor, emptyOutlineColor} = this.props;
|
|
120
|
+
this.state.model
|
|
121
|
+
.setUniforms({
|
|
122
|
+
...uniforms,
|
|
123
|
+
emptyColor,
|
|
124
|
+
emptyOutlineColor,
|
|
125
|
+
})
|
|
126
|
+
.draw();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_getModel(gl: WebGLRenderingContext) {
|
|
130
|
+
// a square that minimally cover the unit circle
|
|
131
|
+
const positions = [-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0];
|
|
132
|
+
|
|
133
|
+
return new Model(
|
|
134
|
+
gl,
|
|
135
|
+
Object.assign(this.getShaders(), {
|
|
136
|
+
id: this.props.id,
|
|
137
|
+
geometry: new Geometry({
|
|
138
|
+
drawMode: GL.TRIANGLE_FAN,
|
|
139
|
+
vertexCount: 4,
|
|
140
|
+
attributes: {
|
|
141
|
+
positions: {size: 3, value: new Float32Array(positions)},
|
|
142
|
+
},
|
|
143
|
+
}),
|
|
144
|
+
isInstanced: true,
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export default FlowCirclesLayer;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export default `\
|
|
19
|
+
#define SHADER_NAME flow-circles-layer-fragment-shader
|
|
20
|
+
#define SOFT_OUTLINE 0.1
|
|
21
|
+
#define EPS 0.05
|
|
22
|
+
precision highp float;
|
|
23
|
+
|
|
24
|
+
uniform vec4 emptyColor;
|
|
25
|
+
uniform vec4 emptyOutlineColor;
|
|
26
|
+
|
|
27
|
+
varying vec4 vColor;
|
|
28
|
+
varying vec2 unitPosition;
|
|
29
|
+
varying float unitInRadius;
|
|
30
|
+
varying float unitOutRadius;
|
|
31
|
+
|
|
32
|
+
float when_gt(float x, float y) {
|
|
33
|
+
return max(sign(x - y), 0.0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void main(void) {
|
|
37
|
+
geometry.uv = unitPosition;
|
|
38
|
+
float distToCenter = length(unitPosition);
|
|
39
|
+
if (distToCenter > 1.0) {
|
|
40
|
+
discard;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// See https://stackoverflow.com/questions/47285778
|
|
44
|
+
vec4 ringColor = mix(
|
|
45
|
+
emptyColor / 255., vColor,
|
|
46
|
+
when_gt(unitInRadius, unitOutRadius)
|
|
47
|
+
);
|
|
48
|
+
vec4 outlineColor = mix(
|
|
49
|
+
emptyOutlineColor / 255., vColor,
|
|
50
|
+
when_gt(unitInRadius, unitOutRadius)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
float innerR = min(unitInRadius, unitOutRadius) * (1.0 - SOFT_OUTLINE);
|
|
54
|
+
|
|
55
|
+
// Inner circle
|
|
56
|
+
float step2 = innerR - EPS;
|
|
57
|
+
float step3 = innerR;
|
|
58
|
+
|
|
59
|
+
// Ring
|
|
60
|
+
float step4 = innerR + EPS;
|
|
61
|
+
float step5 = 1.0 - SOFT_OUTLINE - EPS*2.0;
|
|
62
|
+
float step6 = 1.0 - SOFT_OUTLINE;
|
|
63
|
+
|
|
64
|
+
gl_FragColor = vColor;
|
|
65
|
+
gl_FragColor = mix(gl_FragColor, emptyColor / 255., smoothstep(step2, step3, distToCenter));
|
|
66
|
+
gl_FragColor = mix(gl_FragColor, ringColor, smoothstep(step3, step4, distToCenter));
|
|
67
|
+
gl_FragColor = mix(gl_FragColor, outlineColor, smoothstep(step5, step6, distToCenter));
|
|
68
|
+
gl_FragColor = mix(gl_FragColor, emptyColor / 255., smoothstep(step6, 1.0, distToCenter));
|
|
69
|
+
gl_FragColor.a *= smoothstep(0.0, SOFT_OUTLINE, 1.0 - distToCenter);
|
|
70
|
+
DECKGL_FILTER_COLOR(gl_FragColor, geometry);
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export default `\
|
|
19
|
+
#define SHADER_NAME flow-circles-layer-vertex-shader
|
|
20
|
+
#define radiusScale 100
|
|
21
|
+
|
|
22
|
+
attribute vec3 positions;
|
|
23
|
+
|
|
24
|
+
attribute vec3 instancePositions;
|
|
25
|
+
attribute vec3 instancePositions64Low;
|
|
26
|
+
attribute float instanceInRadius;
|
|
27
|
+
attribute float instanceOutRadius;
|
|
28
|
+
attribute vec4 instanceColors;
|
|
29
|
+
attribute vec3 instancePickingColors;
|
|
30
|
+
|
|
31
|
+
uniform float opacity;
|
|
32
|
+
uniform vec4 emptyColor;
|
|
33
|
+
uniform vec4 emptyOutlineColor;
|
|
34
|
+
|
|
35
|
+
varying vec4 vColor;
|
|
36
|
+
varying vec2 unitPosition;
|
|
37
|
+
varying float unitInRadius;
|
|
38
|
+
varying float unitOutRadius;
|
|
39
|
+
|
|
40
|
+
void main(void) {
|
|
41
|
+
geometry.worldPosition = instancePositions;
|
|
42
|
+
|
|
43
|
+
float outerRadiusPixels = max(instanceInRadius, instanceOutRadius);
|
|
44
|
+
unitInRadius = instanceInRadius / outerRadiusPixels;
|
|
45
|
+
unitOutRadius = instanceOutRadius / outerRadiusPixels;
|
|
46
|
+
|
|
47
|
+
// position on the containing square in [-1, 1] space
|
|
48
|
+
unitPosition = positions.xy;
|
|
49
|
+
geometry.uv = unitPosition;
|
|
50
|
+
geometry.pickingColor = instancePickingColors;
|
|
51
|
+
|
|
52
|
+
// Find the center of the point and add the current vertex
|
|
53
|
+
vec3 offset = positions * project_pixel_size(outerRadiusPixels);
|
|
54
|
+
DECKGL_FILTER_SIZE(offset, geometry);
|
|
55
|
+
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, offset, geometry.position);
|
|
56
|
+
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
|
|
57
|
+
|
|
58
|
+
// Apply opacity to instance color, or return instance picking color
|
|
59
|
+
vColor = vec4(instanceColors.rgb / 255., instanceColors.a / 255. * opacity);
|
|
60
|
+
DECKGL_FILTER_COLOR(vColor, geometry);
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {Layer, picking, project32} from '@deck.gl/core';
|
|
20
|
+
import GL from '@luma.gl/constants';
|
|
21
|
+
import {Geometry, Model} from '@luma.gl/core';
|
|
22
|
+
import FragmentShader from './FlowLinesLayerFragment.glsl';
|
|
23
|
+
import VertexShader from './FlowLinesLayerVertex.glsl';
|
|
24
|
+
import {FlowLinesLayerAttributes, RGBA} from '@flowmap.gl/data';
|
|
25
|
+
import {LayerProps} from '../types';
|
|
26
|
+
|
|
27
|
+
export interface Props<F> extends LayerProps {
|
|
28
|
+
id: string;
|
|
29
|
+
opacity?: number;
|
|
30
|
+
pickable?: boolean;
|
|
31
|
+
updateTriggers?: {[key: string]: Record<string, unknown>};
|
|
32
|
+
data: F[] | FlowLinesLayerAttributes;
|
|
33
|
+
drawOutline: boolean;
|
|
34
|
+
outlineColor?: RGBA;
|
|
35
|
+
outlineThickness?: number;
|
|
36
|
+
thicknessUnit?: number;
|
|
37
|
+
getSourcePosition?: (d: F) => [number, number];
|
|
38
|
+
getTargetPosition?: (d: F) => [number, number];
|
|
39
|
+
getColor?: (d: F) => RGBA;
|
|
40
|
+
getThickness?: (d: F) => number;
|
|
41
|
+
getPickable?: (d: F, {index}: {index: number}) => number; // >= 1.0 -> true
|
|
42
|
+
getEndpointOffsets?: (d: F) => [number, number];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const DEFAULT_COLOR: RGBA = [0, 132, 193, 255];
|
|
46
|
+
const INNER_SIDE_OUTLINE_THICKNESS = 1;
|
|
47
|
+
|
|
48
|
+
class FlowLinesLayer<F> extends Layer {
|
|
49
|
+
static layerName = 'FlowLinesLayer';
|
|
50
|
+
static defaultProps = {
|
|
51
|
+
getSourcePosition: {type: 'accessor', value: (d: any) => [0, 0]},
|
|
52
|
+
getTargetPosition: {type: 'accessor', value: (d: any) => [0, 0]},
|
|
53
|
+
getColor: {type: 'accessor', value: DEFAULT_COLOR},
|
|
54
|
+
getThickness: {type: 'accessor', value: (d: any) => d.count}, // 0..0.5
|
|
55
|
+
getPickable: {type: 'accessor', value: (d: any) => 1.0},
|
|
56
|
+
drawOutline: true,
|
|
57
|
+
thicknessUnit: 12,
|
|
58
|
+
outlineThickness: 1,
|
|
59
|
+
outlineColor: [255, 255, 255, 255],
|
|
60
|
+
parameters: {
|
|
61
|
+
depthTest: false,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
// props!: Props;
|
|
65
|
+
|
|
66
|
+
constructor(props: Props<F>) {
|
|
67
|
+
super(props);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getShaders(): Record<string, unknown> {
|
|
71
|
+
return super.getShaders({
|
|
72
|
+
vs: VertexShader,
|
|
73
|
+
fs: FragmentShader,
|
|
74
|
+
modules: [project32, picking],
|
|
75
|
+
shaderCache: this.context.shaderCache,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
initializeState(): void {
|
|
80
|
+
const {attributeManager} = this.state;
|
|
81
|
+
|
|
82
|
+
attributeManager.addInstanced({
|
|
83
|
+
instanceSourcePositions: {
|
|
84
|
+
accessor: 'getSourcePosition',
|
|
85
|
+
size: 3,
|
|
86
|
+
transition: false,
|
|
87
|
+
type: GL.DOUBLE,
|
|
88
|
+
},
|
|
89
|
+
instanceTargetPositions: {
|
|
90
|
+
accessor: 'getTargetPosition',
|
|
91
|
+
size: 3,
|
|
92
|
+
transition: false,
|
|
93
|
+
type: GL.DOUBLE,
|
|
94
|
+
},
|
|
95
|
+
instanceThickness: {
|
|
96
|
+
accessor: 'getThickness',
|
|
97
|
+
size: 1,
|
|
98
|
+
transition: false,
|
|
99
|
+
},
|
|
100
|
+
instanceEndpointOffsets: {
|
|
101
|
+
accessor: 'getEndpointOffsets',
|
|
102
|
+
size: 2,
|
|
103
|
+
transition: false,
|
|
104
|
+
},
|
|
105
|
+
instanceColors: {
|
|
106
|
+
accessor: 'getColor',
|
|
107
|
+
size: 4,
|
|
108
|
+
type: GL.UNSIGNED_BYTE,
|
|
109
|
+
transition: false,
|
|
110
|
+
},
|
|
111
|
+
instancePickable: {
|
|
112
|
+
accessor: 'getPickable',
|
|
113
|
+
size: 1,
|
|
114
|
+
transition: false,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
updateState({props, oldProps, changeFlags}: Record<string, any>): void {
|
|
120
|
+
super.updateState({props, oldProps, changeFlags});
|
|
121
|
+
|
|
122
|
+
if (changeFlags.extensionsChanged) {
|
|
123
|
+
const {gl} = this.context;
|
|
124
|
+
if (this.state.model) {
|
|
125
|
+
this.state.model.delete();
|
|
126
|
+
}
|
|
127
|
+
this.setState({model: this._getModel(gl)});
|
|
128
|
+
this.getAttributeManager().invalidateAll();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
draw({uniforms}: Record<string, any>): void {
|
|
133
|
+
const {gl} = this.context;
|
|
134
|
+
const {outlineColor, thicknessUnit} = this.props;
|
|
135
|
+
gl.lineWidth(1);
|
|
136
|
+
this.state.model
|
|
137
|
+
.setUniforms({
|
|
138
|
+
...uniforms,
|
|
139
|
+
outlineColor: outlineColor.map((x: number) => x / 255),
|
|
140
|
+
thicknessUnit: thicknessUnit * 2.0,
|
|
141
|
+
gap: 0.5,
|
|
142
|
+
})
|
|
143
|
+
.draw();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
_getModel(gl: WebGLRenderingContext): Record<string, any> {
|
|
147
|
+
let positions: number[] = [];
|
|
148
|
+
let pixelOffsets: number[] = [];
|
|
149
|
+
|
|
150
|
+
const {drawOutline, outlineThickness} = this.props;
|
|
151
|
+
if (drawOutline) {
|
|
152
|
+
// source_target_mix, perpendicular_offset_in_thickness_units, direction_of_travel_offset_in_thickness_units
|
|
153
|
+
// prettier-ignore
|
|
154
|
+
positions = positions.concat([
|
|
155
|
+
// Outline
|
|
156
|
+
0, 0, 0,
|
|
157
|
+
0, 1, 0,
|
|
158
|
+
1, 0, 0,
|
|
159
|
+
|
|
160
|
+
0, 1, 0,
|
|
161
|
+
1, 0, -3,
|
|
162
|
+
1, 1, -3,
|
|
163
|
+
|
|
164
|
+
1, 0, 0,
|
|
165
|
+
1, 2, -3,
|
|
166
|
+
1, 0, -3,
|
|
167
|
+
],
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const tout = outlineThickness;
|
|
171
|
+
const tin = INNER_SIDE_OUTLINE_THICKNESS; // the outline shouldn't cover the opposite arrow
|
|
172
|
+
// perpendicular_offset_in_pixels, direction_of_travel_offset_in_pixels, fill_outline_color_mix
|
|
173
|
+
// prettier-ignore
|
|
174
|
+
pixelOffsets = pixelOffsets.concat([
|
|
175
|
+
// Outline
|
|
176
|
+
-tin, -tout, 1,
|
|
177
|
+
tout, -tout, 1,
|
|
178
|
+
-tin, tout, 1,
|
|
179
|
+
|
|
180
|
+
tout, -tout, 1,
|
|
181
|
+
-tin, 0, 1,
|
|
182
|
+
tout, 0, 1,
|
|
183
|
+
|
|
184
|
+
-tin, 3 * tout, 1,
|
|
185
|
+
2 * tout, -tout, 1,
|
|
186
|
+
-tin, -tout, 1,
|
|
187
|
+
]);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// prettier-ignore
|
|
191
|
+
positions = positions.concat([
|
|
192
|
+
// Fill
|
|
193
|
+
0, 0, 0,
|
|
194
|
+
0, 1, 0,
|
|
195
|
+
1, 0, 0,
|
|
196
|
+
|
|
197
|
+
0, 1, 0,
|
|
198
|
+
1, 0, -3,
|
|
199
|
+
1, 1, -3,
|
|
200
|
+
|
|
201
|
+
1, 0, 0,
|
|
202
|
+
1, 2, -3,
|
|
203
|
+
1, 0, -3,
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
// prettier-ignore
|
|
207
|
+
pixelOffsets = pixelOffsets.concat([
|
|
208
|
+
// Fill
|
|
209
|
+
0, 0, 0,
|
|
210
|
+
0, 0, 0,
|
|
211
|
+
0, 0, 0,
|
|
212
|
+
|
|
213
|
+
0, 0, 0,
|
|
214
|
+
0, 0, 0,
|
|
215
|
+
0, 0, 0,
|
|
216
|
+
|
|
217
|
+
0, 0, 0,
|
|
218
|
+
0, 0, 0,
|
|
219
|
+
0, 0, 0,
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
return new Model(gl, {
|
|
223
|
+
id: this.props.id,
|
|
224
|
+
...this.getShaders(),
|
|
225
|
+
geometry: new Geometry({
|
|
226
|
+
drawType: GL.TRIANGLES,
|
|
227
|
+
attributes: {
|
|
228
|
+
positions: new Float32Array(positions),
|
|
229
|
+
normals: new Float32Array(pixelOffsets),
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
232
|
+
isInstanced: true,
|
|
233
|
+
shaderCache: this.context.shaderCache,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export default FlowLinesLayer;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 FlowmapBlue
|
|
3
|
+
* Copyright 2018-2020 Teralytics, modified by FlowmapBlue
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export default `\
|
|
19
|
+
#define SHADER_NAME flow-line-layer-fragment-shader
|
|
20
|
+
|
|
21
|
+
precision highp float;
|
|
22
|
+
|
|
23
|
+
varying vec4 vColor;
|
|
24
|
+
varying vec2 uv;
|
|
25
|
+
|
|
26
|
+
void main(void) {
|
|
27
|
+
if (vColor.a == 0.0) {
|
|
28
|
+
discard;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
geometry.uv = uv;
|
|
32
|
+
gl_FragColor = vColor;
|
|
33
|
+
DECKGL_FILTER_COLOR(gl_FragColor, geometry);
|
|
34
|
+
}
|
|
35
|
+
`;
|