@deck.gl-community/graph-layers 9.0.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 (210) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +7 -0
  3. package/dist/core/base-layout.d.ts +71 -0
  4. package/dist/core/base-layout.js +133 -0
  5. package/dist/core/cache.d.ts +14 -0
  6. package/dist/core/cache.js +26 -0
  7. package/dist/core/constants.d.ts +101 -0
  8. package/dist/core/constants.js +48 -0
  9. package/dist/core/edge.d.ts +86 -0
  10. package/dist/core/edge.js +121 -0
  11. package/dist/core/graph-engine.d.ts +54 -0
  12. package/dist/core/graph-engine.js +128 -0
  13. package/dist/core/graph.d.ts +155 -0
  14. package/dist/core/graph.js +301 -0
  15. package/dist/core/interaction-manager.d.ts +40 -0
  16. package/dist/core/interaction-manager.js +169 -0
  17. package/dist/core/node.d.ts +103 -0
  18. package/dist/core/node.js +177 -0
  19. package/dist/index.cjs +3540 -0
  20. package/dist/index.cjs.map +7 -0
  21. package/dist/index.d.ts +19 -0
  22. package/dist/index.js +28 -0
  23. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-fragment.glsl.d.ts +1 -0
  24. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-fragment.glsl.js +49 -0
  25. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-vertex-tf.glsl.d.ts +1 -0
  26. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-vertex-tf.glsl.js +14 -0
  27. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-vertex.glsl.d.ts +1 -0
  28. package/dist/layers/common-layers/flow-path-layer/flow-path-layer-vertex.glsl.js +73 -0
  29. package/dist/layers/common-layers/flow-path-layer/flow-path-layer.d.ts +20 -0
  30. package/dist/layers/common-layers/flow-path-layer/flow-path-layer.js +133 -0
  31. package/dist/layers/common-layers/marker-layer/atlas-data-url.d.ts +3 -0
  32. package/dist/layers/common-layers/marker-layer/atlas-data-url.js +8 -0
  33. package/dist/layers/common-layers/marker-layer/marker-layer.d.ts +13 -0
  34. package/dist/layers/common-layers/marker-layer/marker-layer.js +29 -0
  35. package/dist/layers/common-layers/marker-layer/marker-list.d.ts +62 -0
  36. package/dist/layers/common-layers/marker-layer/marker-list.js +67 -0
  37. package/dist/layers/common-layers/marker-layer/marker-mapping.d.ts +422 -0
  38. package/dist/layers/common-layers/marker-layer/marker-mapping.js +427 -0
  39. package/dist/layers/common-layers/spline-layer/spline-layer.d.ts +24 -0
  40. package/dist/layers/common-layers/spline-layer/spline-layer.js +68 -0
  41. package/dist/layers/common-layers/zoomable-text-layer/zoomable-text-layer.d.ts +16 -0
  42. package/dist/layers/common-layers/zoomable-text-layer/zoomable-text-layer.js +65 -0
  43. package/dist/layers/edge-layer.d.ts +25 -0
  44. package/dist/layers/edge-layer.js +75 -0
  45. package/dist/layers/edge-layers/curved-edge-layer.d.ts +6 -0
  46. package/dist/layers/edge-layers/curved-edge-layer.js +69 -0
  47. package/dist/layers/edge-layers/edge-label-layer.d.ts +6 -0
  48. package/dist/layers/edge-layers/edge-label-layer.js +42 -0
  49. package/dist/layers/edge-layers/flow-layer.d.ts +6 -0
  50. package/dist/layers/edge-layers/flow-layer.js +28 -0
  51. package/dist/layers/edge-layers/path-edge-layer.d.ts +6 -0
  52. package/dist/layers/edge-layers/path-edge-layer.js +27 -0
  53. package/dist/layers/edge-layers/straight-line-edge-layer.d.ts +6 -0
  54. package/dist/layers/edge-layers/straight-line-edge-layer.js +26 -0
  55. package/dist/layers/graph-layer.d.ts +32 -0
  56. package/dist/layers/graph-layer.js +193 -0
  57. package/dist/layers/node-layers/circle-layer.d.ts +6 -0
  58. package/dist/layers/node-layers/circle-layer.js +23 -0
  59. package/dist/layers/node-layers/image-layer.d.ts +6 -0
  60. package/dist/layers/node-layers/image-layer.js +23 -0
  61. package/dist/layers/node-layers/label-layer.d.ts +6 -0
  62. package/dist/layers/node-layers/label-layer.js +23 -0
  63. package/dist/layers/node-layers/path-rounded-rectange-layer.d.ts +6 -0
  64. package/dist/layers/node-layers/path-rounded-rectange-layer.js +46 -0
  65. package/dist/layers/node-layers/rectangle-layer.d.ts +6 -0
  66. package/dist/layers/node-layers/rectangle-layer.js +49 -0
  67. package/dist/layers/node-layers/rounded-rectangle-layer-fragment.d.ts +1 -0
  68. package/dist/layers/node-layers/rounded-rectangle-layer-fragment.js +30 -0
  69. package/dist/layers/node-layers/rounded-rectangle-layer.d.ts +8 -0
  70. package/dist/layers/node-layers/rounded-rectangle-layer.js +28 -0
  71. package/dist/layers/node-layers/zoomable-marker-layer.d.ts +10 -0
  72. package/dist/layers/node-layers/zoomable-marker-layer.js +40 -0
  73. package/dist/layouts/d3-force/d3-force-layout.d.ts +24 -0
  74. package/dist/layouts/d3-force/d3-force-layout.js +116 -0
  75. package/dist/layouts/d3-force/worker.d.ts +0 -0
  76. package/dist/layouts/d3-force/worker.js +46 -0
  77. package/dist/layouts/gpu-force/gpu-force-layout.d.ts +30 -0
  78. package/dist/layouts/gpu-force/gpu-force-layout.js +232 -0
  79. package/dist/layouts/gpu-force/worker.d.ts +0 -0
  80. package/dist/layouts/gpu-force/worker.js +116 -0
  81. package/dist/layouts/simple-layout/simple-layout.d.ts +22 -0
  82. package/dist/layouts/simple-layout/simple-layout.js +64 -0
  83. package/dist/loaders/edge-parsers.d.ts +6 -0
  84. package/dist/loaders/edge-parsers.js +17 -0
  85. package/dist/loaders/json-loader.d.ts +7 -0
  86. package/dist/loaders/json-loader.js +16 -0
  87. package/dist/loaders/node-parsers.d.ts +3 -0
  88. package/dist/loaders/node-parsers.js +11 -0
  89. package/dist/style/style-property.d.ts +14 -0
  90. package/dist/style/style-property.js +195 -0
  91. package/dist/style/style-sheet.d.ts +10 -0
  92. package/dist/style/style-sheet.js +252 -0
  93. package/dist/utils/create-graph.d.ts +8 -0
  94. package/dist/utils/create-graph.js +33 -0
  95. package/dist/utils/layer-utils.d.ts +1 -0
  96. package/dist/utils/layer-utils.js +20 -0
  97. package/dist/utils/log.d.ts +2 -0
  98. package/dist/utils/log.js +6 -0
  99. package/dist/utils/polygon-calculations.d.ts +1 -0
  100. package/dist/utils/polygon-calculations.js +102 -0
  101. package/package.json +55 -0
  102. package/src/core/base-layout.ts +154 -0
  103. package/src/core/cache.ts +31 -0
  104. package/src/core/constants.ts +58 -0
  105. package/src/core/edge.ts +145 -0
  106. package/src/core/graph-engine.ts +170 -0
  107. package/src/core/graph.ts +342 -0
  108. package/src/core/interaction-manager.ts +225 -0
  109. package/src/core/node.ts +205 -0
  110. package/src/index.ts +42 -0
  111. package/src/layers/common-layers/flow-path-layer/flow-path-layer-fragment.glsl.ts +50 -0
  112. package/src/layers/common-layers/flow-path-layer/flow-path-layer-vertex-tf.glsl.ts +15 -0
  113. package/src/layers/common-layers/flow-path-layer/flow-path-layer-vertex.glsl.ts +74 -0
  114. package/src/layers/common-layers/flow-path-layer/flow-path-layer.ts +154 -0
  115. package/src/layers/common-layers/marker-layer/atlas-data-url.ts +10 -0
  116. package/src/layers/common-layers/marker-layer/marker-atlas.png +0 -0
  117. package/src/layers/common-layers/marker-layer/marker-layer.ts +36 -0
  118. package/src/layers/common-layers/marker-layer/marker-list.ts +68 -0
  119. package/src/layers/common-layers/marker-layer/marker-mapping.ts +428 -0
  120. package/src/layers/common-layers/marker-layer/markers/bell-filled.png +0 -0
  121. package/src/layers/common-layers/marker-layer/markers/bell.png +0 -0
  122. package/src/layers/common-layers/marker-layer/markers/bookmark-filled.png +0 -0
  123. package/src/layers/common-layers/marker-layer/markers/bookmark.png +0 -0
  124. package/src/layers/common-layers/marker-layer/markers/cd-filled.png +0 -0
  125. package/src/layers/common-layers/marker-layer/markers/cd.png +0 -0
  126. package/src/layers/common-layers/marker-layer/markers/checkmark.png +0 -0
  127. package/src/layers/common-layers/marker-layer/markers/circle-check-filled.png +0 -0
  128. package/src/layers/common-layers/marker-layer/markers/circle-check.png +0 -0
  129. package/src/layers/common-layers/marker-layer/markers/circle-filled.png +0 -0
  130. package/src/layers/common-layers/marker-layer/markers/circle-i-filled.png +0 -0
  131. package/src/layers/common-layers/marker-layer/markers/circle-i.png +0 -0
  132. package/src/layers/common-layers/marker-layer/markers/circle-minus-filled.png +0 -0
  133. package/src/layers/common-layers/marker-layer/markers/circle-minus.png +0 -0
  134. package/src/layers/common-layers/marker-layer/markers/circle-plus-filled.png +0 -0
  135. package/src/layers/common-layers/marker-layer/markers/circle-plus.png +0 -0
  136. package/src/layers/common-layers/marker-layer/markers/circle-questionmark-filled.png +0 -0
  137. package/src/layers/common-layers/marker-layer/markers/circle-questionmark.png +0 -0
  138. package/src/layers/common-layers/marker-layer/markers/circle-slash-filled.png +0 -0
  139. package/src/layers/common-layers/marker-layer/markers/circle-slash.png +0 -0
  140. package/src/layers/common-layers/marker-layer/markers/circle-x-filled.png +0 -0
  141. package/src/layers/common-layers/marker-layer/markers/circle-x.png +0 -0
  142. package/src/layers/common-layers/marker-layer/markers/circle.png +0 -0
  143. package/src/layers/common-layers/marker-layer/markers/diamond-filled.png +0 -0
  144. package/src/layers/common-layers/marker-layer/markers/diamond.png +0 -0
  145. package/src/layers/common-layers/marker-layer/markers/flag-filled.png +0 -0
  146. package/src/layers/common-layers/marker-layer/markers/flag.png +0 -0
  147. package/src/layers/common-layers/marker-layer/markers/gear.png +0 -0
  148. package/src/layers/common-layers/marker-layer/markers/heart-filled.png +0 -0
  149. package/src/layers/common-layers/marker-layer/markers/heart.png +0 -0
  150. package/src/layers/common-layers/marker-layer/markers/location-marker-filled.png +0 -0
  151. package/src/layers/common-layers/marker-layer/markers/location-marker.png +0 -0
  152. package/src/layers/common-layers/marker-layer/markers/octagonal-star-filled.png +0 -0
  153. package/src/layers/common-layers/marker-layer/markers/octagonal-star.png +0 -0
  154. package/src/layers/common-layers/marker-layer/markers/person-filled.png +0 -0
  155. package/src/layers/common-layers/marker-layer/markers/person.png +0 -0
  156. package/src/layers/common-layers/marker-layer/markers/pin-filled.png +0 -0
  157. package/src/layers/common-layers/marker-layer/markers/pin.png +0 -0
  158. package/src/layers/common-layers/marker-layer/markers/plus-small.png +0 -0
  159. package/src/layers/common-layers/marker-layer/markers/plus.png +0 -0
  160. package/src/layers/common-layers/marker-layer/markers/rectangle-filled.png +0 -0
  161. package/src/layers/common-layers/marker-layer/markers/rectangle.png +0 -0
  162. package/src/layers/common-layers/marker-layer/markers/star-filled.png +0 -0
  163. package/src/layers/common-layers/marker-layer/markers/star.png +0 -0
  164. package/src/layers/common-layers/marker-layer/markers/tag-filled.png +0 -0
  165. package/src/layers/common-layers/marker-layer/markers/tag.png +0 -0
  166. package/src/layers/common-layers/marker-layer/markers/thumb-down-filled.png +0 -0
  167. package/src/layers/common-layers/marker-layer/markers/thumb-down.png +0 -0
  168. package/src/layers/common-layers/marker-layer/markers/thumb-up.png +0 -0
  169. package/src/layers/common-layers/marker-layer/markers/thumb_up-filled.png +0 -0
  170. package/src/layers/common-layers/marker-layer/markers/triangle-down-filled.png +0 -0
  171. package/src/layers/common-layers/marker-layer/markers/triangle-down.png +0 -0
  172. package/src/layers/common-layers/marker-layer/markers/triangle-left-filled.png +0 -0
  173. package/src/layers/common-layers/marker-layer/markers/triangle-left.png +0 -0
  174. package/src/layers/common-layers/marker-layer/markers/triangle-right-filled.png +0 -0
  175. package/src/layers/common-layers/marker-layer/markers/triangle-right.png +0 -0
  176. package/src/layers/common-layers/marker-layer/markers/triangle-up-filled.png +0 -0
  177. package/src/layers/common-layers/marker-layer/markers/triangle-up.png +0 -0
  178. package/src/layers/common-layers/marker-layer/markers/x-small.png +0 -0
  179. package/src/layers/common-layers/marker-layer/markers/x.png +0 -0
  180. package/src/layers/common-layers/spline-layer/spline-layer.ts +83 -0
  181. package/src/layers/common-layers/zoomable-text-layer/zoomable-text-layer.ts +90 -0
  182. package/src/layers/edge-layer.ts +88 -0
  183. package/src/layers/edge-layers/curved-edge-layer.ts +88 -0
  184. package/src/layers/edge-layers/edge-label-layer.ts +48 -0
  185. package/src/layers/edge-layers/flow-layer.ts +34 -0
  186. package/src/layers/edge-layers/path-edge-layer.ts +39 -0
  187. package/src/layers/edge-layers/straight-line-edge-layer.ts +38 -0
  188. package/src/layers/graph-layer.ts +225 -0
  189. package/src/layers/node-layers/circle-layer.ts +29 -0
  190. package/src/layers/node-layers/image-layer.ts +29 -0
  191. package/src/layers/node-layers/label-layer.ts +29 -0
  192. package/src/layers/node-layers/path-rounded-rectange-layer.ts +56 -0
  193. package/src/layers/node-layers/rectangle-layer.ts +58 -0
  194. package/src/layers/node-layers/rounded-rectangle-layer-fragment.ts +31 -0
  195. package/src/layers/node-layers/rounded-rectangle-layer.ts +32 -0
  196. package/src/layers/node-layers/zoomable-marker-layer.ts +49 -0
  197. package/src/layouts/d3-force/d3-force-layout.ts +145 -0
  198. package/src/layouts/d3-force/worker.ts +61 -0
  199. package/src/layouts/gpu-force/gpu-force-layout.ts +249 -0
  200. package/src/layouts/gpu-force/worker.ts +137 -0
  201. package/src/layouts/simple-layout/simple-layout.ts +87 -0
  202. package/src/loaders/edge-parsers.ts +21 -0
  203. package/src/loaders/json-loader.ts +19 -0
  204. package/src/loaders/node-parsers.ts +13 -0
  205. package/src/style/style-property.ts +229 -0
  206. package/src/style/style-sheet.ts +277 -0
  207. package/src/utils/create-graph.ts +38 -0
  208. package/src/utils/layer-utils.ts +23 -0
  209. package/src/utils/log.ts +9 -0
  210. package/src/utils/polygon-calculations.ts +154 -0
@@ -0,0 +1 @@
1
+ export declare const fs = "#define SHADER_NAME rounded-rectangle-layer-fragment-shader\n\nprecision highp float;\n\nuniform float cornerRadius;\n\nvarying vec4 vFillColor;\nvarying vec2 unitPosition;\n\nvoid main(void) {\n\n float distToCenter = length(unitPosition);\n\n /* Calculate the cutoff radius for the rounded corners */\n float threshold = sqrt(2.0) * (1.0 - cornerRadius) + 1.0 * cornerRadius;\n if (distToCenter <= threshold) {\n gl_FragColor = vFillColor;\n } else {\n discard;\n }\n\n gl_FragColor = picking_filterHighlightColor(gl_FragColor);\n\n gl_FragColor = picking_filterPickingColor(gl_FragColor);\n}\n";
@@ -0,0 +1,30 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ export const fs = /* glsl */ `\
5
+ #define SHADER_NAME rounded-rectangle-layer-fragment-shader
6
+
7
+ precision highp float;
8
+
9
+ uniform float cornerRadius;
10
+
11
+ varying vec4 vFillColor;
12
+ varying vec2 unitPosition;
13
+
14
+ void main(void) {
15
+
16
+ float distToCenter = length(unitPosition);
17
+
18
+ /* Calculate the cutoff radius for the rounded corners */
19
+ float threshold = sqrt(2.0) * (1.0 - cornerRadius) + 1.0 * cornerRadius;
20
+ if (distToCenter <= threshold) {
21
+ gl_FragColor = vFillColor;
22
+ } else {
23
+ discard;
24
+ }
25
+
26
+ gl_FragColor = picking_filterHighlightColor(gl_FragColor);
27
+
28
+ gl_FragColor = picking_filterPickingColor(gl_FragColor);
29
+ }
30
+ `;
@@ -0,0 +1,8 @@
1
+ import { RectangleLayer } from './rectangle-layer';
2
+ export declare class RoundedRectangleLayer extends RectangleLayer {
3
+ static layerName: string;
4
+ draw({ uniforms }: {
5
+ uniforms: any;
6
+ }): void;
7
+ getShaders(): any;
8
+ }
@@ -0,0 +1,28 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ // import {ScatterplotLayer} from '@deck.gl/layers';
5
+ import { fs } from './rounded-rectangle-layer-fragment';
6
+ import { RectangleLayer } from './rectangle-layer';
7
+ export class RoundedRectangleLayer extends RectangleLayer {
8
+ static layerName = 'RoundedRectangleLayer';
9
+ draw({ uniforms }) {
10
+ super.draw({
11
+ uniforms: {
12
+ ...uniforms,
13
+ cornerRadius: this.props.cornerRadius
14
+ }
15
+ });
16
+ }
17
+ getShaders() {
18
+ // use object.assign to make sure we don't overwrite existing fields like `vs`, `modules`...
19
+ return Object.assign({}, super.getShaders(undefined), {
20
+ fs
21
+ });
22
+ }
23
+ }
24
+ RoundedRectangleLayer.defaultProps = {
25
+ // cornerRadius: the amount of rounding at the rectangle corners
26
+ // 0 - rectangle. 1 - circle.
27
+ cornerRadius: 0.1
28
+ };
@@ -0,0 +1,10 @@
1
+ import { CompositeLayer } from '@deck.gl/core';
2
+ import { MarkerLayer } from '../common-layers/marker-layer/marker-layer';
3
+ export declare class ZoomableMarkerLayer extends CompositeLayer {
4
+ static layerName: string;
5
+ shouldUpdateState({ props, changeFlags }: {
6
+ props: any;
7
+ changeFlags: any;
8
+ }): any;
9
+ renderLayers(): MarkerLayer[];
10
+ }
@@ -0,0 +1,40 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { CompositeLayer } from '@deck.gl/core';
5
+ import { MarkerLayer } from '../common-layers/marker-layer/marker-layer';
6
+ export class ZoomableMarkerLayer extends CompositeLayer {
7
+ static layerName = 'ZoomableMarkerLayer';
8
+ shouldUpdateState({ props, changeFlags }) {
9
+ const { stylesheet } = this.props;
10
+ const scaleWithZoom = stylesheet.getDeckGLAccessor('scaleWithZoom');
11
+ if (!scaleWithZoom) {
12
+ return changeFlags.somethingChanged;
13
+ }
14
+ return changeFlags.somethingChanged || changeFlags.viewportChanged;
15
+ }
16
+ renderLayers() {
17
+ const { data, getPosition, stylesheet, positionUpdateTrigger = 0 } = this.props;
18
+ const getSize = stylesheet.getDeckGLAccessor('getSize');
19
+ const scaleWithZoom = stylesheet.getDeckGLAccessor('scaleWithZoom');
20
+ const sizeUpdateTrigger = scaleWithZoom ? [getSize, this.context.viewport.zoom] : false;
21
+ const oiginalGetMarker = stylesheet.getDeckGLAccessor('getMarker');
22
+ // getMarker only expects function not plain value (string)
23
+ const getMarker = typeof oiginalGetMarker === 'function' ? oiginalGetMarker : () => oiginalGetMarker;
24
+ return [
25
+ new MarkerLayer(this.getSubLayerProps({
26
+ id: 'zoomable-marker-layer',
27
+ data,
28
+ getPosition,
29
+ sizeScale: scaleWithZoom ? Math.max(0, this.context.viewport.zoom) : 1,
30
+ ...stylesheet.getDeckGLAccessors(),
31
+ getMarker,
32
+ updateTriggers: {
33
+ ...stylesheet.getDeckGLUpdateTriggers(),
34
+ getPosition: positionUpdateTrigger,
35
+ getSize: sizeUpdateTrigger
36
+ }
37
+ }))
38
+ ];
39
+ }
40
+ }
@@ -0,0 +1,24 @@
1
+ import { BaseLayout } from '../../core/base-layout';
2
+ export declare class D3ForceLayout extends BaseLayout {
3
+ protected readonly _name = "D3";
4
+ private _positionsByNodeId;
5
+ private _graph;
6
+ private _worker;
7
+ constructor(options: any);
8
+ initializeGraph(graph: any): void;
9
+ updateGraph(graph: any): void;
10
+ start(): void;
11
+ update(): void;
12
+ _engageWorker(): void;
13
+ resume(): void;
14
+ stop(): void;
15
+ getEdgePosition: (edge: any) => {
16
+ type: string;
17
+ sourcePosition: any;
18
+ targetPosition: any;
19
+ controlPoints: any[];
20
+ };
21
+ getNodePosition: (node: any) => any;
22
+ lockNodePosition: (node: any, x: any, y: any) => void;
23
+ unlockNodePosition: (node: any) => void;
24
+ }
@@ -0,0 +1,116 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { BaseLayout } from '../../core/base-layout';
5
+ import { EDGE_TYPE } from '../../core/constants';
6
+ const defaultOptions = {
7
+ alpha: 0.3,
8
+ resumeAlpha: 0.1,
9
+ nBodyStrength: -900,
10
+ nBodyDistanceMin: 100,
11
+ nBodyDistanceMax: 400,
12
+ getCollisionRadius: 0
13
+ };
14
+ export class D3ForceLayout extends BaseLayout {
15
+ _name = 'D3';
16
+ _positionsByNodeId = new Map();
17
+ _graph;
18
+ _worker;
19
+ constructor(options) {
20
+ super(options);
21
+ this._options = {
22
+ ...defaultOptions,
23
+ ...options
24
+ };
25
+ }
26
+ initializeGraph(graph) {
27
+ this._graph = graph;
28
+ }
29
+ // for streaming new data on the same graph
30
+ updateGraph(graph) {
31
+ this._graph = graph;
32
+ this._positionsByNodeId = new Map(this._graph.getNodes().map((node) => [node.id, this._positionsByNodeId.get(node.id)]));
33
+ }
34
+ start() {
35
+ this._engageWorker();
36
+ this._onLayoutStart();
37
+ }
38
+ update() {
39
+ this._engageWorker();
40
+ }
41
+ _engageWorker() {
42
+ // prevent multiple start
43
+ if (this._worker) {
44
+ this._worker.terminate();
45
+ }
46
+ this._worker = new Worker(new URL('./worker.js', import.meta.url).href);
47
+ this._worker.postMessage({
48
+ nodes: this._graph.getNodes().map((node) => ({
49
+ id: node.id,
50
+ ...this._positionsByNodeId.get(node.id)
51
+ })),
52
+ edges: this._graph.getEdges().map((edge) => ({
53
+ id: edge.id,
54
+ source: edge.getSourceNodeId(),
55
+ target: edge.getTargetNodeId()
56
+ })),
57
+ options: this._options
58
+ });
59
+ this._worker.onmessage = (event) => {
60
+ if (event.data.type !== 'end') {
61
+ return;
62
+ }
63
+ event.data.nodes.forEach(({ id, ...d3 }) => this._positionsByNodeId.set(id, {
64
+ ...d3,
65
+ // precompute so that when we return the node position we do not need to do the conversion
66
+ coordinates: [d3.x, d3.y]
67
+ }));
68
+ this._onLayoutChange();
69
+ this._onLayoutDone();
70
+ };
71
+ }
72
+ resume() {
73
+ throw new Error('Resume unavailable');
74
+ }
75
+ stop() {
76
+ this._worker.terminate();
77
+ }
78
+ getEdgePosition = (edge) => {
79
+ const sourceNode = this._graph.findNode(edge.getSourceNodeId());
80
+ const targetNode = this._graph.findNode(edge.getTargetNodeId());
81
+ if (!this.getNodePosition(sourceNode) || !this.getNodePosition(targetNode)) {
82
+ return null;
83
+ }
84
+ return {
85
+ type: EDGE_TYPE.LINE,
86
+ sourcePosition: this.getNodePosition(sourceNode),
87
+ targetPosition: this.getNodePosition(targetNode),
88
+ controlPoints: []
89
+ };
90
+ };
91
+ getNodePosition = (node) => {
92
+ const d3Node = this._positionsByNodeId.get(node.id);
93
+ if (d3Node) {
94
+ return d3Node.coordinates;
95
+ }
96
+ return null;
97
+ };
98
+ lockNodePosition = (node, x, y) => {
99
+ const d3Node = this._positionsByNodeId.get(node.id);
100
+ this._positionsByNodeId.set(node.id, {
101
+ ...d3Node,
102
+ x,
103
+ y,
104
+ fx: x,
105
+ fy: y,
106
+ coordinates: [x, y]
107
+ });
108
+ this._onLayoutChange();
109
+ this._onLayoutDone();
110
+ };
111
+ unlockNodePosition = (node) => {
112
+ const d3Node = this._positionsByNodeId.get(node.id);
113
+ d3Node.fx = null;
114
+ d3Node.fy = null;
115
+ };
116
+ }
File without changes
@@ -0,0 +1,46 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ /* global importScripts, d3 */
5
+ importScripts('https://d3js.org/d3-collection.v1.min.js');
6
+ importScripts('https://d3js.org/d3-dispatch.v1.min.js');
7
+ importScripts('https://d3js.org/d3-quadtree.v1.min.js');
8
+ importScripts('https://d3js.org/d3-timer.v1.min.js');
9
+ importScripts('https://d3js.org/d3-force.v1.min.js');
10
+ onmessage = function (event) {
11
+ const { nodes, edges } = event.data;
12
+ const { nBodyStrength, nBodyDistanceMin, nBodyDistanceMax, getCollisionRadius } = event.data.options;
13
+ // @ts-expect-error TODO
14
+ const simulation = d3
15
+ .forceSimulation(nodes)
16
+ .force('edge',
17
+ // @ts-expect-error TODO
18
+ d3.forceLink(edges).id((n) => n.id))
19
+ .force('charge',
20
+ // @ts-expect-error TODO
21
+ d3
22
+ .forceManyBody()
23
+ .strength(nBodyStrength)
24
+ .distanceMin(nBodyDistanceMin)
25
+ .distanceMax(nBodyDistanceMax))
26
+ // @ts-expect-error TODO
27
+ .force('center', d3.forceCenter())
28
+ // @ts-expect-error TODO
29
+ .force('collision', d3.forceCollide().radius(getCollisionRadius))
30
+ .stop();
31
+ for (let i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
32
+ postMessage({
33
+ type: 'tick',
34
+ progress: i / n,
35
+ options: event.data.options
36
+ });
37
+ simulation.tick();
38
+ }
39
+ postMessage({
40
+ type: 'end',
41
+ nodes,
42
+ edges,
43
+ options: event.data.options
44
+ });
45
+ this.self.close();
46
+ };
@@ -0,0 +1,30 @@
1
+ import { BaseLayout } from '../../core/base-layout';
2
+ export declare class GPUForceLayout extends BaseLayout {
3
+ protected readonly _name: string;
4
+ private _d3Graph;
5
+ private _nodeMap;
6
+ private _edgeMap;
7
+ private _graph;
8
+ private _worker;
9
+ private _callbacks;
10
+ constructor(options: any);
11
+ initializeGraph(graph: any): void;
12
+ start(): void;
13
+ update(): void;
14
+ _engageWorker(): void;
15
+ ticked(data: any): void;
16
+ ended(data: any): void;
17
+ resume(): void;
18
+ stop(): void;
19
+ updateGraph(graph: any): void;
20
+ updateD3Graph(graph: any): void;
21
+ getNodePosition: (node: any) => [number, number];
22
+ getEdgePosition: (edge: any) => {
23
+ type: string;
24
+ sourcePosition: any[];
25
+ targetPosition: any[];
26
+ controlPoints: any[];
27
+ };
28
+ lockNodePosition: (node: any, x: any, y: any) => void;
29
+ unlockNodePosition: (node: any) => void;
30
+ }
@@ -0,0 +1,232 @@
1
+ // deck.gl-community
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { BaseLayout } from '../../core/base-layout';
5
+ import { EDGE_TYPE } from '../../core/constants';
6
+ const defaultOptions = {
7
+ alpha: 0.3,
8
+ resumeAlpha: 0.1,
9
+ nBodyStrength: -900,
10
+ nBodyDistanceMin: 100,
11
+ nBodyDistanceMax: 400,
12
+ getCollisionRadius: 0
13
+ };
14
+ // TODO: this layout should be updated with the organizational and logic improvements made in d3-force
15
+ export class GPUForceLayout extends BaseLayout {
16
+ _name = 'GPU';
17
+ _d3Graph;
18
+ _nodeMap;
19
+ _edgeMap;
20
+ _graph;
21
+ _worker;
22
+ _callbacks;
23
+ constructor(options) {
24
+ super(options);
25
+ this._name = 'GPU';
26
+ this._options = {
27
+ ...defaultOptions,
28
+ ...options
29
+ };
30
+ // store graph and prepare internal data
31
+ this._d3Graph = { nodes: [], edges: [] };
32
+ this._nodeMap = {};
33
+ this._edgeMap = {};
34
+ }
35
+ initializeGraph(graph) {
36
+ this._graph = graph;
37
+ this._nodeMap = {};
38
+ this._edgeMap = {};
39
+ // nodes
40
+ const d3Nodes = graph.getNodes().map((node) => {
41
+ const id = node.id;
42
+ const locked = node.getPropertyValue('locked') || false;
43
+ const x = node.getPropertyValue('x') || 0;
44
+ const y = node.getPropertyValue('y') || 0;
45
+ const collisionRadius = node.getPropertyValue('collisionRadius') || 0;
46
+ const d3Node = {
47
+ id,
48
+ x,
49
+ y,
50
+ fx: locked ? x : null,
51
+ fy: locked ? y : null,
52
+ collisionRadius,
53
+ locked
54
+ };
55
+ this._nodeMap[node.id] = d3Node;
56
+ return d3Node;
57
+ });
58
+ // edges
59
+ const d3Edges = graph.getEdges().map((edge) => {
60
+ const d3Edge = {
61
+ id: edge.id,
62
+ source: this._nodeMap[edge.getSourceNodeId()],
63
+ target: this._nodeMap[edge.getTargetNodeId()]
64
+ };
65
+ this._edgeMap[edge.id] = d3Edge;
66
+ return d3Edge;
67
+ });
68
+ this._d3Graph = {
69
+ nodes: d3Nodes,
70
+ edges: d3Edges
71
+ };
72
+ }
73
+ start() {
74
+ this._engageWorker();
75
+ }
76
+ update() {
77
+ this._engageWorker();
78
+ }
79
+ _engageWorker() {
80
+ // prevent multiple start
81
+ if (this._worker) {
82
+ this._worker.terminate();
83
+ }
84
+ this._worker = new Worker(new URL('./worker.js', import.meta.url).href);
85
+ const { alpha, nBodyStrength, nBodyDistanceMin, nBodyDistanceMax, getCollisionRadius } = this
86
+ ._options;
87
+ this._worker.postMessage({
88
+ nodes: this._d3Graph.nodes,
89
+ edges: this._d3Graph.edges,
90
+ options: {
91
+ alpha,
92
+ nBodyStrength,
93
+ nBodyDistanceMin,
94
+ nBodyDistanceMax,
95
+ getCollisionRadius
96
+ }
97
+ });
98
+ this._worker.onmessage = (event) => {
99
+ switch (event.data.type) {
100
+ case 'tick':
101
+ this.ticked(event.data);
102
+ break;
103
+ case 'end':
104
+ this.ended(event.data);
105
+ break;
106
+ default:
107
+ break;
108
+ }
109
+ };
110
+ }
111
+ ticked(data) { }
112
+ ended(data) {
113
+ const { nodes, edges } = data;
114
+ this.updateD3Graph({ nodes, edges });
115
+ this._onLayoutChange();
116
+ this._onLayoutDone();
117
+ }
118
+ resume() {
119
+ throw new Error('Resume unavailable');
120
+ }
121
+ stop() {
122
+ this._worker.terminate();
123
+ }
124
+ // for steaming new data on the same graph
125
+ updateGraph(graph) {
126
+ if (this._graph.getGraphName() !== graph.getGraphName()) {
127
+ // reset the maps
128
+ this._nodeMap = {};
129
+ this._edgeMap = {};
130
+ }
131
+ this._graph = graph;
132
+ // update internal layout data
133
+ // nodes
134
+ const newNodeMap = {};
135
+ const newD3Nodes = graph.getNodes().map((node) => {
136
+ const id = node.id;
137
+ const locked = node.getPropertyValue('locked') || false;
138
+ const x = node.getPropertyValue('x') || 0;
139
+ const y = node.getPropertyValue('y') || 0;
140
+ const fx = locked ? x : null;
141
+ const fy = locked ? y : null;
142
+ const collisionRadius = node.getPropertyValue('collisionRadius') || 0;
143
+ const oldD3Node = this._nodeMap[node.id];
144
+ const newD3Node = oldD3Node ? oldD3Node : { id, x, y, fx, fy, collisionRadius };
145
+ newNodeMap[node.id] = newD3Node;
146
+ return newD3Node;
147
+ });
148
+ this._nodeMap = newNodeMap;
149
+ this._d3Graph.nodes = newD3Nodes;
150
+ // edges
151
+ const newEdgeMap = {};
152
+ const newD3Edges = graph.getEdges().map((edge) => {
153
+ const oldD3Edge = this._edgeMap[edge.id];
154
+ const newD3Edge = oldD3Edge || {
155
+ id: edge.id,
156
+ source: newNodeMap[edge.getSourceNodeId()],
157
+ target: newNodeMap[edge.getTargetNodeId()]
158
+ };
159
+ newEdgeMap[edge.id] = newD3Edge;
160
+ return newD3Edge;
161
+ });
162
+ this._edgeMap = newEdgeMap;
163
+ this._d3Graph.edges = newD3Edges;
164
+ }
165
+ updateD3Graph(graph) {
166
+ const existingNodes = this._graph.getNodes();
167
+ // update internal layout data
168
+ // nodes
169
+ const newNodeMap = {};
170
+ const newD3Nodes = graph.nodes.map((node) => {
171
+ // Update existing _graph with the new values
172
+ const existingNode = existingNodes.find((n) => n.getId() === node.id);
173
+ existingNode.setDataProperty('locked', node.locked);
174
+ existingNode.setDataProperty('x', node.x);
175
+ existingNode.setDataProperty('y', node.y);
176
+ existingNode.setDataProperty('collisionRadius', node.collisionRadius);
177
+ newNodeMap[node.id] = node;
178
+ return node;
179
+ });
180
+ this._nodeMap = newNodeMap;
181
+ this._d3Graph.nodes = newD3Nodes;
182
+ // edges
183
+ const newEdgeMap = {};
184
+ const newD3Edges = graph.edges.map((edge) => {
185
+ newEdgeMap[edge.id] = edge;
186
+ return edge;
187
+ });
188
+ this._graph.triggerUpdate();
189
+ this._edgeMap = newEdgeMap;
190
+ this._d3Graph.edges = newD3Edges;
191
+ }
192
+ getNodePosition = (node) => {
193
+ const d3Node = this._nodeMap[node.id];
194
+ if (d3Node) {
195
+ return [d3Node.x, d3Node.y];
196
+ }
197
+ return [0, 0];
198
+ };
199
+ getEdgePosition = (edge) => {
200
+ const d3Edge = this._edgeMap[edge.id];
201
+ const sourcePosition = d3Edge && d3Edge.source;
202
+ const targetPosition = d3Edge && d3Edge.target;
203
+ if (d3Edge && sourcePosition && targetPosition) {
204
+ return {
205
+ type: EDGE_TYPE.LINE,
206
+ sourcePosition: [sourcePosition.x, sourcePosition.y],
207
+ targetPosition: [targetPosition.x, targetPosition.y],
208
+ controlPoints: []
209
+ };
210
+ }
211
+ return {
212
+ type: EDGE_TYPE.LINE,
213
+ sourcePosition: [0, 0],
214
+ targetPosition: [0, 0],
215
+ controlPoints: []
216
+ };
217
+ };
218
+ lockNodePosition = (node, x, y) => {
219
+ const d3Node = this._nodeMap[node.id];
220
+ d3Node.x = x;
221
+ d3Node.y = y;
222
+ d3Node.fx = x;
223
+ d3Node.fy = y;
224
+ this._callbacks.onLayoutChange();
225
+ this._callbacks.onLayoutDone();
226
+ };
227
+ unlockNodePosition = (node) => {
228
+ const d3Node = this._nodeMap[node.id];
229
+ d3Node.fx = null;
230
+ d3Node.fy = null;
231
+ };
232
+ }
File without changes