@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.
Files changed (64) hide show
  1. package/LICENSE +199 -0
  2. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.d.ts +76 -0
  3. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.d.ts.map +1 -0
  4. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.js +139 -0
  5. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.d.ts +3 -0
  6. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.d.ts.map +1 -0
  7. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.js +37 -0
  8. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.d.ts +3 -0
  9. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.d.ts.map +1 -0
  10. package/dist/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.js +91 -0
  11. package/dist/AnimatedFlowLinesLayer/index.d.ts +3 -0
  12. package/dist/AnimatedFlowLinesLayer/index.d.ts.map +1 -0
  13. package/dist/AnimatedFlowLinesLayer/index.js +3 -0
  14. package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts +59 -0
  15. package/dist/FlowCirclesLayer/FlowCirclesLayer.d.ts.map +1 -0
  16. package/dist/FlowCirclesLayer/FlowCirclesLayer.js +115 -0
  17. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts +3 -0
  18. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.d.ts.map +1 -0
  19. package/dist/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.js +73 -0
  20. package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.d.ts +3 -0
  21. package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.d.ts.map +1 -0
  22. package/dist/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.js +63 -0
  23. package/dist/FlowCirclesLayer/index.d.ts +3 -0
  24. package/dist/FlowCirclesLayer/index.d.ts.map +1 -0
  25. package/dist/FlowCirclesLayer/index.js +3 -0
  26. package/dist/FlowLinesLayer/FlowLinesLayer.d.ts +64 -0
  27. package/dist/FlowLinesLayer/FlowLinesLayer.d.ts.map +1 -0
  28. package/dist/FlowLinesLayer/FlowLinesLayer.js +182 -0
  29. package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.d.ts +3 -0
  30. package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.d.ts.map +1 -0
  31. package/dist/FlowLinesLayer/FlowLinesLayerFragment.glsl.js +36 -0
  32. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts +3 -0
  33. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.d.ts.map +1 -0
  34. package/dist/FlowLinesLayer/FlowLinesLayerVertex.glsl.js +102 -0
  35. package/dist/FlowLinesLayer/index.d.ts +3 -0
  36. package/dist/FlowLinesLayer/index.d.ts.map +1 -0
  37. package/dist/FlowLinesLayer/index.js +3 -0
  38. package/dist/FlowMapLayer.d.ts +70 -0
  39. package/dist/FlowMapLayer.d.ts.map +1 -0
  40. package/dist/FlowMapLayer.js +304 -0
  41. package/dist/index.d.ts +7 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +6 -0
  44. package/dist/types.d.ts +31 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +20 -0
  47. package/package.json +24 -0
  48. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayer.ts +189 -0
  49. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerFragment.glsl.ts +37 -0
  50. package/src/AnimatedFlowLinesLayer/AnimatedFlowLinesLayerVertex.glsl.ts +90 -0
  51. package/src/AnimatedFlowLinesLayer/index.ts +3 -0
  52. package/src/FlowCirclesLayer/FlowCirclesLayer.ts +150 -0
  53. package/src/FlowCirclesLayer/FlowCirclesLayerFragment.glsl.ts +72 -0
  54. package/src/FlowCirclesLayer/FlowCirclesLayerVertex.glsl.ts +62 -0
  55. package/src/FlowCirclesLayer/index.ts +3 -0
  56. package/src/FlowLinesLayer/FlowLinesLayer.ts +238 -0
  57. package/src/FlowLinesLayer/FlowLinesLayerFragment.glsl.ts +35 -0
  58. package/src/FlowLinesLayer/FlowLinesLayerVertex.glsl.ts +101 -0
  59. package/src/FlowLinesLayer/index.ts +3 -0
  60. package/src/FlowMapLayer.ts +448 -0
  61. package/src/index.ts +7 -0
  62. package/src/types.ts +67 -0
  63. package/tsconfig.json +11 -0
  64. 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,3 @@
1
+ import AnimatedFlowLinesLayer from './AnimatedFlowLinesLayer';
2
+
3
+ export default AnimatedFlowLinesLayer;
@@ -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,3 @@
1
+ import FlowCirclesLayer from './FlowCirclesLayer';
2
+
3
+ export default FlowCirclesLayer;
@@ -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
+ `;