@neo4j-nvl/base 1.1.0 → 1.2.0-090ec876
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/CHANGELOG.md +25 -0
- package/dist/base.mjs +1 -1
- package/dist/types/index.d.ts +20 -1
- package/dist/types/layouts/d3forcelayout/__mocks__/d3ForceLayout.d.ts +10 -0
- package/dist/types/layouts/d3forcelayout/constants.d.ts +0 -1
- package/dist/types/layouts/d3forcelayout/d3ForceLayout.d.ts +20 -20
- package/dist/types/layouts/d3forcelayout/d3ForceLayout.test.d.ts +1 -0
- package/dist/types/layouts/d3forcelayout/types.d.ts +5 -6
- package/dist/types/layouts/forcedirectedlayout/physlayout/PhysLayout.d.ts +17 -13
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment.d.ts +1 -1
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment.d.ts +1 -1
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-update-fragment.d.ts +1 -1
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/sim-vertex.d.ts +1 -1
- package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/SolarMerger.bench.d.ts +1 -0
- package/dist/types/layouts/gridLayout/GridLayout.d.ts +25 -9
- package/dist/types/modules/NvlController.d.ts +25 -4
- package/dist/types/modules/NvlController.test.d.ts +1 -0
- package/dist/types/modules/Shader.d.ts +1 -1
- package/dist/types/modules/state/types.d.ts +32 -13
- package/dist/types/renderers/domrenderer/BaseRenderer.d.ts +1 -1
- package/dist/types/renderers/domrenderer/BaseRenderer.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/canvasrenderer/CanvasRenderer.d.ts +2 -36
- package/dist/types/renderers/domrenderer/canvasrenderer/arrowDrawing.d.ts +168 -0
- package/dist/types/renderers/domrenderer/canvasrenderer/arrowDrawing.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/canvasrenderer/nodeDrawing.d.ts +109 -0
- package/dist/types/renderers/domrenderer/canvasrenderer/nodeDrawing.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/shared/ImageCache.d.ts +3 -2
- package/dist/types/renderers/domrenderer/shared/arrows/ArrowBundle.d.ts +18 -2
- package/dist/types/renderers/domrenderer/shared/arrows/ArrowBundler.d.ts +10 -0
- package/dist/types/renderers/domrenderer/shared/nodes/nodes.d.ts +53 -1
- package/dist/types/renderers/domrenderer/shared/util.d.ts +6 -1
- package/dist/types/renderers/domrenderer/shared/wordwrap.d.ts +12 -1
- package/dist/types/renderers/domrenderer/svgrenderer/SvgRenderer.d.ts +1 -3
- package/dist/types/renderers/domrenderer/svgrenderer/arrowDrawing.d.ts +59 -0
- package/dist/types/renderers/domrenderer/svgrenderer/arrowDrawing.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/svgrenderer/nodeDrawing.d.ts +16 -0
- package/dist/types/renderers/domrenderer/svgrenderer/nodeDrawing.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/svgrenderer/svgUtils.d.ts +33 -141
- package/dist/types/renderers/domrenderer/svgrenderer/svgUtils.test.d.ts +1 -0
- package/dist/types/renderers/webglrenderer/Renderer.d.ts +1 -2
- package/dist/types/renderers/webglrenderer/node-animation-fragment.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/node-animation-vertex.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/node-fragment-point.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/node-vertex-point.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/rel-fragment-line.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/rel-vertex-line.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/viewport-box-fragment.d.ts +1 -1
- package/dist/types/renderers/webglrenderer/viewport-box-vertex.d.ts +1 -1
- package/dist/types/utils/canvasManagement.d.ts +1 -1
- package/dist/types/utils/constants.d.ts +8 -2
- package/dist/types/utils/geometry.d.ts +4 -0
- package/dist/types/utils/layoutSeeding.d.ts +7 -0
- package/dist/types/utils/layoutSeeding.test.d.ts +1 -0
- package/dist/types/utils/segmentAnalytics.d.ts +2 -2
- package/package.json +8 -6
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment-verlet.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment-verlet.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/workaround-fragment.d.ts +0 -2
- package/dist/types/renderers/domrenderer/canvasrenderer/canvasUtils.d.ts +0 -56
- package/dist/types/renderers/domrenderer/shared/nodes/nodeUtils.d.ts +0 -29
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExternalCallbacks } from './modules/ExternalCallbackHandler';
|
|
2
2
|
import type { CircularOptions, ForceDirectedOptions, HierarchicalOptions, Renderer as InternalRenderer, Layout, LayoutOptions, NvlOptions, NvlState, ZoomOptions } from './modules/state/types';
|
|
3
3
|
import { CanvasRendererType, CircularLayoutType, ForceDirectedLayoutType, FreeLayoutType, GridLayoutType, HierarchicalLayoutType, SvgRendererType, WebGLRendererType, d3ForceLayoutType } from './modules/state/types';
|
|
4
|
-
import { drawCircleBand } from './renderers/domrenderer/canvasrenderer/
|
|
4
|
+
import { drawCircleBand } from './renderers/domrenderer/canvasrenderer/nodeDrawing';
|
|
5
5
|
import type { StyledCaption } from './renderers/domrenderer/shared/types';
|
|
6
6
|
import type { Node, PartialNode, PartialRelationship, Relationship } from './types/graph-element';
|
|
7
7
|
import { CompatibilityError } from './utils/errors';
|
|
@@ -289,6 +289,25 @@ declare class NVL {
|
|
|
289
289
|
getImageDataUrl(options?: {
|
|
290
290
|
backgroundColor?: string;
|
|
291
291
|
}): string;
|
|
292
|
+
/**
|
|
293
|
+
* Returns the entire graph visualization as an SVG data URL.
|
|
294
|
+
* @param options - Options for the SVG export
|
|
295
|
+
* @param options.backgroundColor - The background color of the SVG (defaults to transparent).
|
|
296
|
+
* @returns A Promise resolving to a data URL string representing the graph as SVG (data:image/svg+xml;...)
|
|
297
|
+
* @experimental
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```typescript
|
|
301
|
+
* const svgDataUrl = await nvl.getSvgDataUrl({ backgroundColor: '#ffffff' })
|
|
302
|
+
* const img = document.createElement('img')
|
|
303
|
+
* img.src = svgDataUrl
|
|
304
|
+
* img.alt = 'Graph Visualization'
|
|
305
|
+
* document.body.appendChild(img)
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
getSvgDataUrl(options?: {
|
|
309
|
+
backgroundColor?: string;
|
|
310
|
+
}): Promise<string>;
|
|
292
311
|
/**
|
|
293
312
|
* Saves the entire graph visualization canvas as a png to the client.
|
|
294
313
|
* @param {{ filename: string, backgroundColor: string }} options The filename and background color of the png.
|
|
@@ -12,7 +12,6 @@ export declare const BARNES_HUT_THETA = 1.2;
|
|
|
12
12
|
export declare const FORCE_LINK_DISTANCE: (relationship: SimulationLinkDatum<D3Node>) => number;
|
|
13
13
|
export declare const FORCE_LINK_STRENGTH: (link: SimulationLinkDatum<SimulationNodeDatum>, count: number[]) => number;
|
|
14
14
|
export declare const FORCE_COLLIDE_RADIUS: (node: D3Node) => number;
|
|
15
|
-
export declare const LAYOUT_RADIUS: (numberOfNodes: number) => number;
|
|
16
15
|
export declare const FORCE_CHARGE: () => number;
|
|
17
16
|
export declare const FORCE_CHARGE_START: () => number;
|
|
18
17
|
export declare const FORCE_CENTER_X = 0.03;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { Simulation, SimulationLinkDatum, SimulationNodeDatum } from 'd3-force';
|
|
2
|
+
import type { NvlState } from '../../modules/state/types';
|
|
3
|
+
import type { Node, Relationship } from '../../types/graph-element';
|
|
4
|
+
import type { Point } from '../../utils/geometry';
|
|
5
|
+
import type { D3Node } from './types';
|
|
6
|
+
export declare class D3ForceLayout {
|
|
7
|
+
state: NvlState;
|
|
8
|
+
d3Nodes: Record<string, D3Node>;
|
|
9
|
+
d3RelList: SimulationLinkDatum<D3Node>[];
|
|
6
10
|
computing: boolean;
|
|
7
|
-
center:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
nodeRelCount: any[];
|
|
12
|
-
simulation: import("d3-force").Simulation<import("d3-force").SimulationNodeDatum, undefined>;
|
|
11
|
+
center: Point;
|
|
12
|
+
nodeRelCount: number[];
|
|
13
|
+
simulation: Simulation<SimulationNodeDatum, undefined>;
|
|
13
14
|
simulationStopped: boolean;
|
|
14
15
|
shouldUpdate: boolean;
|
|
15
16
|
shouldReheatNodes: boolean;
|
|
16
17
|
shouldCountNodeRels: boolean;
|
|
17
|
-
stateDisposers:
|
|
18
|
+
stateDisposers: (() => void)[];
|
|
19
|
+
constructor(config: {
|
|
20
|
+
state: NvlState;
|
|
21
|
+
});
|
|
18
22
|
setOptions(options: any): void;
|
|
19
|
-
updateNodes(positionList:
|
|
23
|
+
updateNodes(positionList: D3Node[]): void;
|
|
20
24
|
update(refreshPositions?: boolean): void;
|
|
21
|
-
layout(_nodes:
|
|
22
|
-
getNodePositions(nodeList:
|
|
23
|
-
id: any;
|
|
24
|
-
x: any;
|
|
25
|
-
y: any;
|
|
26
|
-
}[];
|
|
25
|
+
layout(_nodes: Node[], _rels: Relationship[], firstTimeAddingNodes: boolean): void;
|
|
26
|
+
getNodePositions(nodeList: D3Node[]): any[];
|
|
27
27
|
getShouldUpdate(): boolean;
|
|
28
28
|
getComputing(): boolean;
|
|
29
29
|
terminateUpdate(): void;
|
|
30
30
|
destroy(): void;
|
|
31
|
-
setAlpha(alpha:
|
|
31
|
+
setAlpha(alpha: number): void;
|
|
32
32
|
countNodeRels(): any[];
|
|
33
33
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
y: number | undefined;
|
|
1
|
+
import type { Node } from '../../types/graph-element';
|
|
2
|
+
export type D3Node = Node & {
|
|
4
3
|
vx?: number;
|
|
5
4
|
vy?: number;
|
|
6
|
-
fx?: number
|
|
7
|
-
fy?: number
|
|
8
|
-
|
|
5
|
+
fx?: number;
|
|
6
|
+
fy?: number;
|
|
7
|
+
index?: number;
|
|
9
8
|
};
|
|
@@ -7,7 +7,6 @@ export declare class PhysLayout {
|
|
|
7
7
|
private physProjection;
|
|
8
8
|
private physSmallProjection;
|
|
9
9
|
private gl;
|
|
10
|
-
private useReadpixelWorkaround;
|
|
11
10
|
private averageNodeSize;
|
|
12
11
|
private shouldUpdate;
|
|
13
12
|
private iterationCount;
|
|
@@ -19,7 +18,6 @@ export declare class PhysLayout {
|
|
|
19
18
|
private stateDisposers;
|
|
20
19
|
private state;
|
|
21
20
|
private dpr;
|
|
22
|
-
private intelWorkaround;
|
|
23
21
|
private simulationStopVelocitySquared;
|
|
24
22
|
private gravity;
|
|
25
23
|
private force;
|
|
@@ -31,6 +29,9 @@ export declare class PhysLayout {
|
|
|
31
29
|
private subGraphs;
|
|
32
30
|
private nodeSortMap;
|
|
33
31
|
private firstUpdate;
|
|
32
|
+
private precomputeMs;
|
|
33
|
+
private precomputeStarted;
|
|
34
|
+
private precomputing;
|
|
34
35
|
private curPhysData;
|
|
35
36
|
private apprxRepForceShader;
|
|
36
37
|
private levelsClusterTexture;
|
|
@@ -40,26 +41,22 @@ export declare class PhysLayout {
|
|
|
40
41
|
private collisionDetectionMultiplier;
|
|
41
42
|
private physShader;
|
|
42
43
|
private physData;
|
|
43
|
-
private workaroundData;
|
|
44
44
|
private pinData;
|
|
45
45
|
private updateData;
|
|
46
46
|
private updateShader;
|
|
47
|
-
private workaroundShader;
|
|
48
47
|
private physPositions;
|
|
49
48
|
private springTexture;
|
|
50
49
|
private sizeTexture;
|
|
51
50
|
private offsetTexture;
|
|
52
51
|
private pinTexture;
|
|
53
52
|
private addedNodes;
|
|
53
|
+
private seedingMethod;
|
|
54
54
|
private updateTexture;
|
|
55
|
-
private vaoExt;
|
|
56
55
|
private physVao;
|
|
57
56
|
private physSmallVao;
|
|
58
57
|
private updateVao;
|
|
59
|
-
private workaroundVao;
|
|
60
|
-
enableVerlet: boolean;
|
|
61
58
|
constructor(config: ForceDirectedOptions & {
|
|
62
|
-
webGLContext:
|
|
59
|
+
webGLContext: WebGL2RenderingContext;
|
|
63
60
|
state: NvlState;
|
|
64
61
|
});
|
|
65
62
|
/**
|
|
@@ -77,6 +74,17 @@ export declare class PhysLayout {
|
|
|
77
74
|
nodes: Node[];
|
|
78
75
|
rels: Relationship[];
|
|
79
76
|
}): import("./solarmerger/types").CoarsenedGraph;
|
|
77
|
+
/**
|
|
78
|
+
* Synchronously runs physics simulation for the configured time budget before
|
|
79
|
+
* the layout is first rendered.
|
|
80
|
+
* Sets `getComputing()` to `true` while running and clears
|
|
81
|
+
* it when precompute finishes (including early exit when the layout halts).
|
|
82
|
+
*/
|
|
83
|
+
private runPrecompute;
|
|
84
|
+
private isPrecomputeEnabled;
|
|
85
|
+
private hasPendingPrecompute;
|
|
86
|
+
private hasInteractingNodes;
|
|
87
|
+
private shouldRunPrecompute;
|
|
80
88
|
/**
|
|
81
89
|
* Updates the node's positions for the next step in the physics layout iterations if the layout needs to update
|
|
82
90
|
* @param refreshPositions whether the entire layout should be reheated
|
|
@@ -93,9 +101,7 @@ export declare class PhysLayout {
|
|
|
93
101
|
*/
|
|
94
102
|
getShouldUpdate(): boolean;
|
|
95
103
|
/**
|
|
96
|
-
*
|
|
97
|
-
* Always returns false because the force-directed layout has no computing step
|
|
98
|
-
* @returns Whether the layout is computing.
|
|
104
|
+
* @returns Whether the layout is running the precompute step.
|
|
99
105
|
*/
|
|
100
106
|
getComputing(): boolean;
|
|
101
107
|
/**
|
|
@@ -169,7 +175,5 @@ export declare class PhysLayout {
|
|
|
169
175
|
private setupPhysicsForCoarse;
|
|
170
176
|
private setupPinData;
|
|
171
177
|
private setupUpdates;
|
|
172
|
-
private setupReadpixelWorkaround;
|
|
173
|
-
private doReadpixelWorkaround;
|
|
174
178
|
private definePhysicsArrays;
|
|
175
179
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision mediump float;\n\nuniform sampler2D u_physData;\nuniform sampler2D u_connections;\nuniform sampler2D u_connectionOffsets;\nuniform sampler2D u_pinnedNodes;\nuniform sampler2D u_sizeTexture;\nuniform float u_baseLength;\nuniform float u_curIteration;\nuniform float u_iterationMultiplier;\nuniform vec2 u_gravityCenter;\nuniform float u_numNodes;\nuniform float u_gravity;\n\nuniform sampler2D u_clusterData;\nuniform sampler2D u_prevForce;\nuniform float u_collisionMultiplier;\n\nout vec4 fragColor;\n\nfloat DAMP = 0.6;\nfloat COOL = 0.99998;\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 0.6;\nfloat accLimitLow = 500000.0;\nfloat accLimitHigh = 750000.0;\nfloat accLimitPosHigh = 10000000.0;\n\nconst float denseNodeThreshold = 1000.0;\nconst float MIN_DISTANCE = 0.00000001;\nconst float MAX_DISTANCE = 1000000000.0;\nconst float MAX_ACCELERATION = 50000.0;\n\nvec4 getTextureData(sampler2D tex, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture(tex, vec2(x + 0.5, y + 0.5) / base);\n}\n\nbool isNan(float val) {\n return (val < 0.0 || 0.0 < val || val == 0.0) ? false : true;\n}\n\nconst float BIG_NUMBER = 999999999999999999.0;\nbool isInf(float val) {\n return val > BIG_NUMBER || val < -BIG_NUMBER;\n}\n\nvec2 getDelta(vec2 v1, vec2 v2) {\n vec2 delta = v1 - v2;\n float dist = length(delta);\n if (dist < MIN_DISTANCE || isNan(dist)) {\n return vec2(MIN_DISTANCE, MIN_DISTANCE);\n }\n if (dist > MAX_DISTANCE) {\n vec2 normDelta = delta / dist;\n return normDelta * MAX_DISTANCE;\n }\n return delta;\n}\n\nvec4 getOtherNodePosition(float i) {\n return getTextureData(u_physData, i, 256.0);\n}\n\nfloat getCombinedNodeSize(float i, float nodeSize) {\n float otherNodeSize = getTextureData(u_sizeTexture, i, 256.0).r;\n return nodeSize + otherNodeSize;\n}\n\nvec2 getSpringForce(float curConnection, float numConnections, float springFScale, vec4 myPosition, float i) {\n float curSpring = getTextureData(u_connections, curConnection + i, 4096.0).r;\n\n vec4 otherPosition = getTextureData(u_physData, curSpring, 256.0);\n float otherDataPosition = getTextureData(u_connectionOffsets, curSpring, 256.0).r;\n float otherNumConnections = getTextureData(u_connections, otherDataPosition, 4096.0).r;\n float avgDegree = max((otherNumConnections + numConnections * 3.0) / 4.0, 4.0);\n\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n\n float F = (dist * dist * springFScale) / (u_baseLength * avgDegree);\n if (u_collisionMultiplier > 0.0) {\n F *= u_collisionMultiplier;\n }\n return (-delta / dist) * F;\n}\n\nvec2 getCollisionForce(float combinedNodeSize, float dist, float fScale, vec2 delta) {\n float collisionForce = (combinedNodeSize - dist) / (dist);\n if (u_collisionMultiplier > 0.0) {\n collisionForce *= u_collisionMultiplier;\n }\n return (delta * collisionForce * fScale * combinedNodeSize) / (combinedNodeSize + 1.0);\n}\n\nvec2 getRepulsionForce(float dist, float fScale, vec2 delta) {\n float F = (u_baseLength * u_baseLength * fScale) / (dist);\n return (delta / dist) * F * 0.05;\n}\n\nvoid main(void) {\n float textureSide = 256.0; //#TEXTURE_SIDE#;\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * textureSide;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n float clusterWeight = clusterData.w;\n\n vec4 myPosition = getTextureData(u_physData, index, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n\n vec2 acceleration = previousForce.xy;\n\n float isPinned = getTextureData(u_pinnedNodes, index, 256.0).r;\n float nodeSize = getTextureData(u_sizeTexture, index, 256.0).r;\n\n if (isPinned > 0.5) {\n fragColor = vec4(myPosition.xy, 0.0, 0.0);\n return;\n }\n\n float curConnection = getTextureData(u_connectionOffsets, index, 256.0).r;\n float numConnections = getTextureData(u_connections, curConnection, 4096.0).r;\n\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n float springFScale = fScale;\n\n if (numConnections > denseNodeThreshold) {\n springFScale = sqrt(fScale);\n }\n\n float numOfRels = 0.0;\n\n // Springs\n for (float i = 1.0; i <= 256.0 * 256.0; i++) {\n if (numOfRels >= numConnections) {\n break;\n }\n acceleration += getSpringForce(curConnection, numConnections, springFScale, myPosition, i);\n numOfRels += 1.0;\n }\n\n // Repulsion && collision detection\n if (u_collisionMultiplier > 0.0) {\n float number_of_collisions = 0.0;\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= u_numNodes) {\n break;\n }\n\n if (i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize) * 2.0;\n\n if (dist < combinedNodeSize && number_of_collisions < 40.0) {\n number_of_collisions++;\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n if (i >= clusterStartIndex && i < clusterStartIndex + clusterSize) {\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n } else {\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherPosition = getOtherNodePosition(i);\n vec2 delta = getDelta(myPosition.xy, otherPosition.xy);\n float dist = length(delta);\n float combinedNodeSize = getCombinedNodeSize(i, nodeSize);\n\n if (dist < combinedNodeSize) {\n acceleration += getCollisionForce(combinedNodeSize, dist, fScale, delta);\n }\n\n acceleration += getRepulsionForce(dist, fScale, delta);\n }\n }\n\n // Gravity\n vec2 delta = getDelta(u_gravityCenter, myPosition.xy);\n float dist = length(delta);\n\n vec2 grav = (delta / dist) * u_gravity * fScale * (dist / 1000.0);\n acceleration += grav;\n\n float accMagnitude = length(acceleration);\n acceleration *= min(MAX_ACCELERATION, accMagnitude) / accMagnitude;\n\n float iterationFrictionThreshold = 1000.0;\n\n if (u_curIteration > iterationFrictionThreshold) {\n float friction = 1.0 + pow((u_curIteration - iterationFrictionThreshold), 2.0) / 100.0;\n acceleration *= 1.0 / friction;\n }\n\n if (u_curIteration == 0.0) {\n fragColor = vec4(myPosition.xy, myPosition.zw);\n } else {\n float TEMP = max(0.02, pow(COOL, u_curIteration));\n vec2 prevVelocity = myPosition.zw;\n vec2 currentPos = myPosition.xy;\n\n vec2 newPos = currentPos + TEMP * ( DAMP * (prevVelocity) + acceleration * TIMESTEP * TIMESTEP);\n vec2 newVelocity = newPos - currentPos;\n fragColor = vec4(newPos, newVelocity);\n }\n}";
|
|
2
2
|
export default _default;
|
package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision mediump float;\nuniform sampler2D u_physData;\nuniform sampler2D u_clusterData;\nuniform sampler2D u_finestIndexes;\nuniform sampler2D u_prevForce;\n\nuniform float u_baseLength;\nuniform float u_numNodes;\nuniform float u_iterationMultiplier;\nuniform float u_isTopLevel;\n\nout vec4 fragColor;\n\nfloat PI = 3.1415926535897932384626433832795;\nfloat TIMESTEP = 1.0 / 30.0;\nfloat VELOCITYDECAY = 1.0;\n\nvec4 getTextureData(sampler2D tex, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture(tex, vec2(x + 0.5, y + 0.5) / base);\n}\n\nfloat getSquaredLogClusterWeight(float value) {\n return pow(log(value), 2.0);\n}\n\nvoid main(void) {\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5) * 256.0;\n\n if (index >= u_numNodes) {\n discard;\n }\n\n vec4 clusterData = getTextureData(u_clusterData, index, 256.0);\n\n float clusterIndex = clusterData.x;\n float clusterStartIndex = clusterData.y;\n float clusterSize = clusterData.z;\n float clusterArea = pow(clusterSize + u_baseLength * 2.0, 2.0);\n\n float finestIndex = getTextureData(u_finestIndexes, index, 256.0).r;\n vec4 myPosition = getTextureData(u_physData, finestIndex, 256.0);\n vec4 previousForce = getTextureData(u_prevForce, clusterIndex, 256.0);\n float fScale = 1.0 + sqrt(u_iterationMultiplier);\n\n vec2 acceleration = previousForce.xy;\n\n // Repulsion & Collision Detection\n for (float i = 0.0; i < 256.0 * 256.0; i++) {\n if (i >= clusterStartIndex + clusterSize || i >= u_numNodes) {\n break;\n }\n if (i < clusterStartIndex || i == index) {\n continue;\n }\n\n vec4 otherClusterData = getTextureData(u_clusterData, i, 256.0);\n float otherClusterWeight = getSquaredLogClusterWeight(otherClusterData.w);\n\n float otherFinestIndex = getTextureData(u_finestIndexes, i, 256.0).r;\n vec4 otherPosition = getTextureData(u_physData, otherFinestIndex, 256.0);\n\n vec2 delta = myPosition.xy - otherPosition.xy;\n float dist = max(length(delta), 0.0000001);\n float maxDist = 25.0;\n float repulsionForceScale = 0.1;\n\n float F = (clusterArea * fScale) / (dist * dist);\n\n if (u_isTopLevel == 1.0) {\n repulsionForceScale = 0.2;\n }\n\n acceleration += ((delta / sqrt(dist)) * F) * repulsionForceScale * otherClusterWeight;\n\n if (dist < maxDist) {\n float collide = (maxDist - dist) / (dist * dist);\n acceleration += delta * collide * fScale * maxDist / (maxDist + 1.0);\n }\n }\n\n fragColor = vec4(acceleration, vec2(finestIndex, 0));\n}";
|
|
2
2
|
export default _default;
|
package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-update-fragment.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision mediump float;\n\nuniform sampler2D u_physData;\nuniform sampler2D u_updateData;\nuniform float u_numNodesNew;\n\nout vec4 fragColor;\n\nconst float INDEX_FLAG = 999999.0;\n\nvec4 getTextureData(sampler2D tex, float index, float base) {\n float x = mod(index, base);\n float y = (index - x) / base;\n return texture(tex, vec2(x + 0.5, y + 0.5) / base);\n}\n\nvoid main(void) {\n float textureSide = 256.0; //#TEXTURE_SIDE#;\n float index = (gl_FragCoord.x - 0.5) + (gl_FragCoord.y - 0.5)*textureSide;\n\n if (index >= u_numNodesNew) {\n discard;\n }\n\n float firstValue = getTextureData(u_updateData, index * 2.0, 256.0).r;\n float secondValue = getTextureData(u_updateData, index * 2.0 + 1.0, 256.0).r;\n\n if (secondValue == INDEX_FLAG) {\n vec4 myPosition = getTextureData(u_physData, firstValue, 256.0);\n fragColor = myPosition;\n } else {\n fragColor = vec4(firstValue, secondValue, 0.0, 0.0);\n }\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nuniform mat4 u_projection;\n\nin vec2 a_position;\n//in float a_index;\n\n//out highp float index;\n\nvoid main() {\n// index = a_index;\n gl_Position = u_projection * vec4(a_position, 0.0, 1.0);\n}";
|
|
2
2
|
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,14 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { NvlState } from '../../modules/state/types';
|
|
2
|
+
import type { Node } from '../../types/graph-element';
|
|
3
|
+
import type { Point } from '../../utils/geometry';
|
|
4
|
+
export declare class GridLayout {
|
|
5
|
+
state: NvlState;
|
|
6
|
+
positions: Record<string, Node & Point>;
|
|
7
|
+
stateDisposers: (() => void)[];
|
|
6
8
|
shouldUpdate: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
constructor(config: {
|
|
10
|
+
state: NvlState;
|
|
11
|
+
});
|
|
12
|
+
setOptions(): void;
|
|
13
|
+
updateNodes(positionList: {
|
|
14
|
+
id: string;
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}[]): void;
|
|
9
18
|
update(refreshPositions?: boolean): void;
|
|
10
|
-
layout(mobxNodes: any
|
|
11
|
-
|
|
19
|
+
layout(mobxNodes: any): void;
|
|
20
|
+
setNodePositions(idToPosition: Record<string, Node & Point>): void;
|
|
21
|
+
getNodePositions(nodeList: {
|
|
22
|
+
id: string;
|
|
23
|
+
}[]): {
|
|
24
|
+
id: string;
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}[];
|
|
12
28
|
getShouldUpdate(): boolean;
|
|
13
29
|
getComputing(): boolean;
|
|
14
30
|
terminateUpdate(): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Node, type PartialNode, type PartialRelationship, type Relationship } from '../types/graph-element';
|
|
2
2
|
import '../types/nvl-window-functions';
|
|
3
3
|
import type { Point } from '../utils/geometry';
|
|
4
4
|
import type { ExternalCallbacks } from './ExternalCallbackHandler';
|
|
@@ -37,7 +37,7 @@ export default class NvlController {
|
|
|
37
37
|
private readonly c2dCanvas;
|
|
38
38
|
private readonly svg;
|
|
39
39
|
private isInRenderSwitchAnimation;
|
|
40
|
-
private
|
|
40
|
+
private previousRenderer;
|
|
41
41
|
private justSwitchedLayout;
|
|
42
42
|
private layoutUpdating;
|
|
43
43
|
private layoutComputing;
|
|
@@ -46,12 +46,16 @@ export default class NvlController {
|
|
|
46
46
|
private readonly stateDisposers;
|
|
47
47
|
private readonly zoomTransitionHandler;
|
|
48
48
|
private currentLayout;
|
|
49
|
+
private lastTimestamp;
|
|
50
|
+
private accumulator;
|
|
49
51
|
private readonly layoutTimeLimit;
|
|
52
|
+
private readonly smoothFrameBudgetMs;
|
|
50
53
|
private pixelRatio;
|
|
51
54
|
private readonly removeResizeListener;
|
|
52
55
|
private readonly removeMinimapResizeListener;
|
|
53
|
-
private
|
|
54
|
-
private
|
|
56
|
+
private pendingZoom;
|
|
57
|
+
private pendingPan;
|
|
58
|
+
private pendingViewportOverride;
|
|
55
59
|
private animationRequestId;
|
|
56
60
|
private layoutDoneCallback;
|
|
57
61
|
private layoutComputingCallback;
|
|
@@ -59,8 +63,13 @@ export default class NvlController {
|
|
|
59
63
|
private descriptionElement;
|
|
60
64
|
constructor(state: NvlState, frame: HTMLElement, options: NvlOptions);
|
|
61
65
|
private onWebGLContextLost;
|
|
66
|
+
private fpsToFrameBudgetMs;
|
|
67
|
+
private getLayoutNeedsToUpdate;
|
|
68
|
+
private isWithinBudget;
|
|
62
69
|
private updateMinimapZoom;
|
|
63
70
|
private startMainLoop;
|
|
71
|
+
private renderNodeHtmlOverlays;
|
|
72
|
+
private renderRelationshipHtmlOverlays;
|
|
64
73
|
updateHtmlOverlay(): void;
|
|
65
74
|
dumpNodes(): Node[];
|
|
66
75
|
dumpRelationships(): Relationship[];
|
|
@@ -116,10 +125,22 @@ export default class NvlController {
|
|
|
116
125
|
private initiateFileDownload;
|
|
117
126
|
private updateLayoutAndPositions;
|
|
118
127
|
saveToFile(options: SaveToFileOptions): void;
|
|
128
|
+
private createSvgString;
|
|
119
129
|
saveToSvg(options?: SaveToFileOptions): Promise<void>;
|
|
120
130
|
getImageDataURL(options: SaveToFileOptions): string;
|
|
131
|
+
getSvgDataUrl(options?: SaveToFileOptions): Promise<string>;
|
|
121
132
|
private prepareLargeFileForDownload;
|
|
122
133
|
private createCanvasAndRenderImage;
|
|
123
134
|
saveFullGraphToLargeFile(options: SaveToFileOptions): Promise<void>;
|
|
135
|
+
addAndUpdateElementsInGraph(nodes?: Node[] | PartialNode[], relationships?: Relationship[] | PartialRelationship[]): void;
|
|
136
|
+
updateElementsInGraph(nodes: Node[] | PartialNode[], relationships: Relationship[] | PartialRelationship[]): void;
|
|
137
|
+
/**
|
|
138
|
+
* Adds nodes and relationships in the current scene.
|
|
139
|
+
* @param {Node[]} nodes The nodes to be added.
|
|
140
|
+
* @param {Relationship[]} relationships The relationships to be added.
|
|
141
|
+
*/
|
|
142
|
+
addElementsToGraph(nodes: Node[], relationships: Relationship[]): void;
|
|
143
|
+
private validateNodes;
|
|
144
|
+
private validateRelationships;
|
|
124
145
|
}
|
|
125
146
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,7 +4,7 @@ export default class Shader {
|
|
|
4
4
|
private curTexture;
|
|
5
5
|
private attributeInfo;
|
|
6
6
|
private uniformInfo;
|
|
7
|
-
constructor(gl:
|
|
7
|
+
constructor(gl: WebGL2RenderingContext, vsSource: string, fsSource: string, defines?: {});
|
|
8
8
|
setUniform(name: string, value: any): void;
|
|
9
9
|
setAttributePointer(name: string, size: number, start: number, stride: number): void;
|
|
10
10
|
setAttributePointerFloat(name: string, size: number, start: number, stride: number): void;
|
|
@@ -38,25 +38,31 @@ export type DisabledItemStyles = {
|
|
|
38
38
|
*/
|
|
39
39
|
export interface ForceDirectedOptions {
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* rendering problems on Intel graphics hardware.
|
|
44
|
-
*
|
|
45
|
-
* @remarks Requires a restart of NVL as shaders need to be recompiled.
|
|
41
|
+
* @deprecated No longer has any effect. The physics layout now uses WebGL2 which does not
|
|
42
|
+
* require the Intel GPU shader workaround. This option will be removed in a future release.
|
|
46
43
|
*/
|
|
47
44
|
intelWorkaround?: boolean;
|
|
48
45
|
/**
|
|
46
|
+
* @deprecated This option will be removed in a future release. For small datasets, use the d3Force layout instead.
|
|
49
47
|
* Whether to enable automatic switching to CoseBilkent layout for small graphs.
|
|
50
48
|
* When enabled, small graphs will automatically use the CoseBilkent layout algorithm
|
|
51
49
|
* which can provide better initial positioning for smaller datasets.
|
|
50
|
+
* @defaultValue true
|
|
52
51
|
*/
|
|
53
52
|
enableCytoscape?: boolean;
|
|
54
53
|
/**
|
|
55
|
-
*
|
|
56
|
-
* @defaultValue
|
|
57
|
-
* @internal
|
|
54
|
+
* How initial node positions are seeded before the physics simulation runs.
|
|
55
|
+
* @defaultValue 'box'
|
|
58
56
|
*/
|
|
59
|
-
|
|
57
|
+
seedingMethod?: 'box' | 'circle';
|
|
58
|
+
/**
|
|
59
|
+
* @experimental
|
|
60
|
+
* Milliseconds of synchronous physics simulation to run before the layout is first rendered.
|
|
61
|
+
* Precompute stops early if the simulation stabilizes before the time budget is reached.
|
|
62
|
+
* @defaultValue 0
|
|
63
|
+
* @note Blocks the main thread, so use sparingly. Will be capped at 1000.
|
|
64
|
+
*/
|
|
65
|
+
precomputeMs?: number;
|
|
60
66
|
}
|
|
61
67
|
/**
|
|
62
68
|
* The options for the hierarchical layout
|
|
@@ -231,11 +237,24 @@ export interface NvlOptions {
|
|
|
231
237
|
minimapViewportBoxColor?: string;
|
|
232
238
|
};
|
|
233
239
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
240
|
+
* Target minimum presentation rate (fps) while layout is active.
|
|
241
|
+
* Rendering will not drop below this rate at the cost of stabilization speed.
|
|
242
|
+
*
|
|
243
|
+
* @defaultValue 3
|
|
244
|
+
*
|
|
245
|
+
* @note Must be within range of 1 and 120.
|
|
246
|
+
*/
|
|
247
|
+
minFps?: number;
|
|
248
|
+
/**
|
|
249
|
+
* Target maximum presentation rate (fps) while layout is active.
|
|
250
|
+
* Rendering will not go above with rate. Any additional
|
|
251
|
+
* computation available is used to speed up layout stabilization.
|
|
252
|
+
*
|
|
253
|
+
* @defaultValue 30
|
|
254
|
+
*
|
|
255
|
+
* @note Must be within range of 1 and 120.
|
|
237
256
|
*/
|
|
238
|
-
|
|
257
|
+
maxFps?: number;
|
|
239
258
|
/**
|
|
240
259
|
* Disables tracking of library usage
|
|
241
260
|
* @defaultValue false
|
|
@@ -31,7 +31,7 @@ export default abstract class BaseRenderer {
|
|
|
31
31
|
* @param clientHeight - Height of the rendering area
|
|
32
32
|
* @returns Array of relationships to render, sorted (disabled, normal, selected)
|
|
33
33
|
*/
|
|
34
|
-
protected getRelationshipsToRender(showCaptions
|
|
34
|
+
protected getRelationshipsToRender(showCaptions?: boolean, zoom?: number, clientWidth?: number, clientHeight?: number): RelationshipToRender[];
|
|
35
35
|
/**
|
|
36
36
|
* Gets nodes to render, sorted by their rendering order
|
|
37
37
|
* @param positionArray - Array of nodes with positions
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,7 +2,8 @@ import type { NvlState } from '../../../modules/state/types';
|
|
|
2
2
|
import type { Node } from '../../../types/graph-element';
|
|
3
3
|
import type { Point } from '../../../utils/geometry';
|
|
4
4
|
import type { HitTargetNode, HitTargetRelationship } from '../../../utils/hittest';
|
|
5
|
-
import
|
|
5
|
+
import type { RendererOptions } from '../BaseRenderer';
|
|
6
|
+
import BaseRenderer from '../BaseRenderer';
|
|
6
7
|
export default class CanvasRenderer extends BaseRenderer {
|
|
7
8
|
private canvas;
|
|
8
9
|
private context;
|
|
@@ -30,13 +31,6 @@ export default class CanvasRenderer extends BaseRenderer {
|
|
|
30
31
|
* Draws a single node on the canvas with all its visual elements (circle, icons, captions, etc.)
|
|
31
32
|
* @param ctx - The canvas rendering context
|
|
32
33
|
* @param node - The node to draw
|
|
33
|
-
* @param imageCache - The image cache for icons
|
|
34
|
-
* @param animationHandler - The animation handler for transitions
|
|
35
|
-
* @param nodeBorderStyles - The border styles for nodes
|
|
36
|
-
* @param disabledItemStyles - The styles for disabled items
|
|
37
|
-
* @param defaultNodeColor - The default node color
|
|
38
|
-
* @param ellipsisWidth - The width of the ellipsis character
|
|
39
|
-
* @param zoomLevel - The current zoom level
|
|
40
34
|
*/
|
|
41
35
|
private drawNode;
|
|
42
36
|
/**
|
|
@@ -47,18 +41,6 @@ export default class CanvasRenderer extends BaseRenderer {
|
|
|
47
41
|
* Helper method to disable shadow on canvas context
|
|
48
42
|
*/
|
|
49
43
|
private disableShadow;
|
|
50
|
-
/**
|
|
51
|
-
* Draws line segments on canvas (straight or curved)
|
|
52
|
-
*/
|
|
53
|
-
private drawSegments;
|
|
54
|
-
/**
|
|
55
|
-
* Draws a self-referencing loop on canvas
|
|
56
|
-
*/
|
|
57
|
-
private drawLoop;
|
|
58
|
-
/**
|
|
59
|
-
* Draws a label for a relationship
|
|
60
|
-
*/
|
|
61
|
-
private drawLabel;
|
|
62
44
|
/**
|
|
63
45
|
* Renders a waypoint arrow (relationship between two different nodes)
|
|
64
46
|
*/
|
|
@@ -67,10 +49,6 @@ export default class CanvasRenderer extends BaseRenderer {
|
|
|
67
49
|
* Renders a self-referencing arrow (relationship from node to itself)
|
|
68
50
|
*/
|
|
69
51
|
private renderSelfArrow;
|
|
70
|
-
/**
|
|
71
|
-
* Main arrow rendering method that delegates to waypoint or self-arrow rendering
|
|
72
|
-
*/
|
|
73
|
-
private renderArrow;
|
|
74
52
|
/**
|
|
75
53
|
* Draws the nodes and relationships to their positions on the canvas.
|
|
76
54
|
* @param positionArray {Node[]} - The array of nodes to draw
|
|
@@ -99,18 +77,6 @@ export default class CanvasRenderer extends BaseRenderer {
|
|
|
99
77
|
* @todo: sort relationships by distance descending
|
|
100
78
|
*/
|
|
101
79
|
getRelsAt(pointer: Point): HitTargetRelationship[];
|
|
102
|
-
/**
|
|
103
|
-
* Returns an array of styles for the rings of a node.
|
|
104
|
-
* It takes the node as an argument, and an optional array of size animations.
|
|
105
|
-
* If the node is selected, it returns the selectedStyle.rings array.
|
|
106
|
-
* If the node is not selected, it returns an array containing only one object with
|
|
107
|
-
* a width of 0 and an empty color.
|
|
108
|
-
* @param node - The node to get the ring styles for.
|
|
109
|
-
* @param animationHandler - The animation handler.
|
|
110
|
-
* @param nodeBorderStyles - The node border styles.
|
|
111
|
-
* @returns An array of ring styles.
|
|
112
|
-
*/
|
|
113
|
-
private getRingStyles;
|
|
114
80
|
/**
|
|
115
81
|
* Handles zoom and pan on the canvas.
|
|
116
82
|
* @param context {CanvasRenderingContext2D} - The canvas context
|