@neo4j-nvl/base 1.2.1 → 2.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.
- package/CHANGELOG.md +43 -0
- package/dist/base.mjs +1 -1
- package/dist/types/index.d.ts +21 -16
- package/dist/types/layouts/animatedlayout/AnimatedLayout.d.ts +2 -2
- package/dist/types/layouts/d3forcelayout/constants.d.ts +0 -1
- package/dist/types/layouts/d3forcelayout/d3ForceLayout.d.ts +3 -3
- package/dist/types/layouts/forcedirectedlayout/PhysLayout.d.ts +275 -0
- package/dist/types/layouts/forcedirectedlayout/clustering/ClusterByMerger.d.ts +62 -0
- package/dist/types/layouts/forcedirectedlayout/clustering/SolarMerger.d.ts +56 -0
- package/dist/types/layouts/forcedirectedlayout/clustering/clustering-utils.d.ts +143 -0
- package/dist/types/layouts/forcedirectedlayout/clustering/clustering-utils.test.d.ts +1 -0
- package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger → clustering}/types.d.ts +11 -1
- package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-fragment.d.ts +2 -0
- package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-repulsive-fragment.d.ts +2 -0
- package/dist/types/layouts/forcedirectedlayout/shaders/multilevel-update-fragment.d.ts +2 -0
- package/dist/types/layouts/forcedirectedlayout/shaders/sim-vertex.d.ts +2 -0
- package/dist/types/layouts/freeLayout/FreeLayout.d.ts +2 -4
- package/dist/types/layouts/gridLayout/GridLayout.d.ts +2 -6
- package/dist/types/layouts/hierarchicallayout/HierarchicalLayout.d.ts +5 -0
- package/dist/types/modules/ExternalCallbackHandler.d.ts +3 -3
- package/dist/types/modules/NvlController.d.ts +85 -5
- package/dist/types/modules/Shader.d.ts +1 -1
- package/dist/types/modules/dataset.d.ts +4 -2
- package/dist/types/modules/state/types.d.ts +129 -27
- package/dist/types/modules/state/utils.d.ts +2 -2
- package/dist/types/renderers/ClusterOverlay.d.ts +73 -0
- package/dist/types/renderers/ClusterOverlay.test.d.ts +1 -0
- package/dist/types/renderers/domrenderer/shared/ImageCache.d.ts +1 -0
- package/dist/types/renderers/domrenderer/shared/types.d.ts +1 -2
- package/dist/types/renderers/webglrenderer/Controller.d.ts +27 -6
- package/dist/types/renderers/webglrenderer/IconLayerRegistry.d.ts +14 -0
- package/dist/types/renderers/webglrenderer/IconLayerRegistry.test.d.ts +1 -0
- package/dist/types/renderers/webglrenderer/Renderer.d.ts +43 -3
- 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-glsl-utils.d.ts +1 -0
- package/dist/types/renderers/webglrenderer/rel-vertex-arrow.d.ts +2 -0
- 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/types/graph-element.d.ts +9 -1
- package/dist/types/types/nvl-window-functions.d.ts +2 -2
- package/dist/types/utils/canvasManagement.d.ts +1 -1
- package/dist/types/utils/clusterGeometry.d.ts +14 -0
- package/dist/types/utils/clusterGeometry.test.d.ts +1 -0
- package/dist/types/utils/clusterHitRegions.d.ts +42 -0
- package/dist/types/utils/clusterHitRegions.test.d.ts +1 -0
- package/dist/types/utils/constants.d.ts +6 -0
- package/dist/types/utils/geometry.d.ts +44 -1
- package/dist/types/utils/hittest.d.ts +30 -4
- package/dist/types/utils/jsDriverResultTransformer.d.ts +11 -9
- package/dist/types/utils/layoutSeeding.d.ts +7 -0
- package/dist/types/utils/layoutSeeding.test.d.ts +1 -0
- package/dist/types/utils/webWorkerUtils.d.ts +1 -1
- package/dist/types/utils/zoomFunctions.d.ts +9 -2
- package/package.json +3 -3
- package/dist/types/layouts/forcedirectedlayout/ForceCytoLayout.d.ts +0 -22
- package/dist/types/layouts/forcedirectedlayout/cosebilkentlayout/CoseBilkentLayout.d.ts +0 -33
- package/dist/types/layouts/forcedirectedlayout/physlayout/PhysLayout.d.ts +0 -174
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-fragment.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-repulsive-fragment.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/multilevel-update-fragment.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/sim-vertex.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/shaders/workaround-fragment.d.ts +0 -2
- package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/SolarMerger.d.ts +0 -21
- package/dist/types/layouts/forcedirectedlayout/physlayout/solarmerger/solar-placer.d.ts +0 -2
- /package/dist/types/layouts/forcedirectedlayout/{physlayout/PhysLayout.test.d.ts → PhysLayout.test.d.ts} +0 -0
- /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/SolarMerger.bench.d.ts → clustering/ClusterByMerger.test.d.ts} +0 -0
- /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/SolarMerger.test.d.ts → clustering/SolarMerger.bench.d.ts} +0 -0
- /package/dist/types/layouts/forcedirectedlayout/{physlayout/solarmerger/solar-placer.test.d.ts → clustering/SolarMerger.test.d.ts} +0 -0
- /package/dist/types/layouts/forcedirectedlayout/{physlayout/glwrapper.d.ts → glwrapper.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,7 @@ declare class ImageCache {
|
|
|
4
4
|
private readonly onImageLoadedCb?;
|
|
5
5
|
constructor(onImageLoaded?: () => void);
|
|
6
6
|
getImage(src: string, inverted?: boolean): HTMLCanvasElement;
|
|
7
|
+
isDrawn(src: string, inverted?: boolean): boolean;
|
|
7
8
|
private getOrCreateEntry;
|
|
8
9
|
private invertCanvas;
|
|
9
10
|
private loadImage;
|
|
@@ -11,8 +11,7 @@ export type TextSegment = {
|
|
|
11
11
|
*/
|
|
12
12
|
export type StyledCaption = {
|
|
13
13
|
/**
|
|
14
|
-
* The font styles as an array of style keywords.
|
|
15
|
-
* @example `['bold', 'italic']`
|
|
14
|
+
* The font styles as an array of style keywords, e.g. `['bold', 'italic']`.
|
|
16
15
|
*/
|
|
17
16
|
styles?: string[];
|
|
18
17
|
/** The text value for the caption. */
|
|
@@ -10,8 +10,10 @@ export interface ControllerInterface {
|
|
|
10
10
|
stateDisposers: NvlState['autorun'][];
|
|
11
11
|
state: NvlState;
|
|
12
12
|
needsToRun: () => boolean;
|
|
13
|
-
renderMainScene: (positionArray: Node[]) => void;
|
|
14
|
-
|
|
13
|
+
renderMainScene: (positionArray: Node[], positionsChanged?: boolean) => void;
|
|
14
|
+
renderMainSceneFromTexture: (positionTexture: WebGLTexture) => void;
|
|
15
|
+
setPositionTexelIndices: (map: Readonly<Record<string, number>> | null) => void;
|
|
16
|
+
renderMinimap: (positionArray: Node[], positionsChanged?: boolean) => void;
|
|
15
17
|
checkForUpdates: (nodes: DataSet<Node>, rels: DataSet<Relationship>) => void;
|
|
16
18
|
onResize: () => void;
|
|
17
19
|
updateMainViewport: (zoom: number, panX: number, panY: number) => void;
|
|
@@ -34,8 +36,25 @@ export default class Controller implements ControllerInterface {
|
|
|
34
36
|
state?: NvlState;
|
|
35
37
|
});
|
|
36
38
|
needsToRun(): boolean;
|
|
37
|
-
renderMainScene(positionArray: Node[]): void;
|
|
38
|
-
|
|
39
|
+
renderMainScene(positionArray: Node[], positionsChanged?: boolean): void;
|
|
40
|
+
/**
|
|
41
|
+
* Renders the main scene from a GPU position texture instead of a
|
|
42
|
+
* CPU position array, avoiding the readback + upload round trip.
|
|
43
|
+
* @param positionTexture - Live GPU node-position texture to render from.
|
|
44
|
+
*/
|
|
45
|
+
renderMainSceneFromTexture(positionTexture: WebGLTexture): void;
|
|
46
|
+
/**
|
|
47
|
+
* Sets the node-id -> texel-index map for the main scene renderer so it
|
|
48
|
+
* samples a shared position texture in the layout's order. Pass null to use
|
|
49
|
+
* insertion order.
|
|
50
|
+
* @param map - The node-id-to-texel-index map, or null.
|
|
51
|
+
*
|
|
52
|
+
* @note The minimap keeps insertion-order sampling and uploads lagged CPU
|
|
53
|
+
* positions (async PhysLayout cache) while the main scene may sample the
|
|
54
|
+
* shared GPU texture.
|
|
55
|
+
*/
|
|
56
|
+
setPositionTexelIndices(map: Readonly<Record<string, number>> | null): void;
|
|
57
|
+
renderMinimap(positionArray: Node[], positionsChanged?: boolean): void;
|
|
39
58
|
checkForUpdates(nodes: DataSet<Node>, rels: DataSet<Relationship>): void;
|
|
40
59
|
onResize(): void;
|
|
41
60
|
updateMainViewport(zoom: number, panX: number, panY: number): void;
|
|
@@ -52,8 +71,10 @@ export declare class DummyController implements ControllerInterface {
|
|
|
52
71
|
minimapMouseDown: boolean;
|
|
53
72
|
stateDisposers: NvlState['autorun'][];
|
|
54
73
|
state: NvlState;
|
|
55
|
-
renderMainScene(positionArray: Node[]): void;
|
|
56
|
-
|
|
74
|
+
renderMainScene(positionArray: Node[], positionsChanged?: boolean): void;
|
|
75
|
+
renderMainSceneFromTexture(positionTexture: WebGLTexture): void;
|
|
76
|
+
setPositionTexelIndices(map: Readonly<Record<string, number>> | null): void;
|
|
77
|
+
renderMinimap(positionArray: Node[], positionsChanged?: boolean): void;
|
|
57
78
|
checkForUpdates(nodes: DataSet<Node>, rels: DataSet<Relationship>): void;
|
|
58
79
|
onResize(): void;
|
|
59
80
|
updateMainViewport(zoom: number, panX: number, panY: number): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const MaxIconLayers = 256;
|
|
2
|
+
/**
|
|
3
|
+
* Maps icon URLs to stable layer indices for a WebGL `sampler2DArray`.
|
|
4
|
+
* Delegates image loading and rasterization to {@link ImageCache}.
|
|
5
|
+
*/
|
|
6
|
+
export declare class IconLayerRegistry {
|
|
7
|
+
private readonly imageCache;
|
|
8
|
+
private readonly layerMap;
|
|
9
|
+
constructor(onImageLoaded?: () => void);
|
|
10
|
+
getLayer(url: string, inverted: boolean): number | null;
|
|
11
|
+
hasLoadingLayers(): boolean;
|
|
12
|
+
layerCount(): number;
|
|
13
|
+
getAvailableCanvases(): Map<number, HTMLCanvasElement>;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,11 +2,17 @@ import { mat4 } from 'gl-matrix';
|
|
|
2
2
|
import type { DataSet } from '../../modules/dataset';
|
|
3
3
|
import type { NvlState } from '../../modules/state/types';
|
|
4
4
|
import type { Node, Relationship } from '../../types/graph-element';
|
|
5
|
+
export type RendererOptions = {
|
|
6
|
+
enableIcons?: boolean;
|
|
7
|
+
};
|
|
5
8
|
export default class Renderer {
|
|
6
9
|
private readonly nodeShader;
|
|
7
10
|
private readonly nodeAnimShader;
|
|
8
11
|
private readonly relShader;
|
|
12
|
+
private readonly arrowShader;
|
|
9
13
|
private relDataBuffer;
|
|
14
|
+
private arrowDataBuffer;
|
|
15
|
+
private arrowData;
|
|
10
16
|
private readonly viewportBoxShader;
|
|
11
17
|
private readonly defaultRelColor;
|
|
12
18
|
private readonly defaultNodeColor;
|
|
@@ -14,39 +20,73 @@ export default class Renderer {
|
|
|
14
20
|
private readonly disableNodeColor;
|
|
15
21
|
private readonly gl;
|
|
16
22
|
activeNodes: Record<string, boolean>;
|
|
23
|
+
numActiveNodes: number;
|
|
17
24
|
readonly canvas: HTMLCanvasElement;
|
|
18
25
|
projection: mat4;
|
|
19
26
|
private idToIndex;
|
|
27
|
+
/** Node-id → texel-index map for GPU-shared rendering; null falls back to insertion order. */
|
|
28
|
+
private texelIndexForId;
|
|
29
|
+
/** texelIndexForId value when vertex buffers were last built; used to detect changes in the texel-index mapping. */
|
|
30
|
+
private texelMapAtBuild;
|
|
31
|
+
private lastNodes;
|
|
32
|
+
private lastBundledRels;
|
|
33
|
+
private idToSize;
|
|
20
34
|
private posBuffer;
|
|
35
|
+
private positionsDirty;
|
|
21
36
|
private numRels;
|
|
22
37
|
private numNodes;
|
|
23
38
|
private nodeDataByte;
|
|
24
39
|
private relIdToIndex;
|
|
25
40
|
private relData;
|
|
26
41
|
private viewportBoxBuffer;
|
|
42
|
+
private readonly viewportBoxVertices;
|
|
27
43
|
private relBuffer;
|
|
44
|
+
private arrowBuffer;
|
|
28
45
|
private nodeBuffer;
|
|
29
46
|
private posTexture;
|
|
47
|
+
private iconTexture;
|
|
30
48
|
private nodeVao;
|
|
31
49
|
private relVao;
|
|
50
|
+
private arrowVao;
|
|
32
51
|
private nodeAnimVao;
|
|
33
|
-
private
|
|
34
|
-
|
|
52
|
+
private readonly iconLayers;
|
|
53
|
+
private uploadedIconLayers;
|
|
54
|
+
private nodeColors;
|
|
55
|
+
private nodeDisabled;
|
|
56
|
+
constructor(gl: WebGL2RenderingContext, nodes: DataSet<Node>, rels: DataSet<Relationship>, state: NvlState, options?: RendererOptions);
|
|
35
57
|
private setShaderUniforms;
|
|
36
58
|
setData(data: {
|
|
37
59
|
nodes: Node[];
|
|
38
60
|
rels: Relationship[];
|
|
39
61
|
}): void;
|
|
40
|
-
|
|
62
|
+
/** Sets the texel-index map for GPU-shared rendering, or null for insertion order. */
|
|
63
|
+
setPositionTexelIndices(map: Readonly<Record<string, number>> | null): void;
|
|
64
|
+
/** Texel index for a node id; falls back to insertion index, or 0 if the id is unknown. */
|
|
65
|
+
private getTexelIndex;
|
|
66
|
+
/**
|
|
67
|
+
* Rebuilds vertex buffers when the texel-index mapping has changed since the last build.
|
|
68
|
+
*/
|
|
69
|
+
private rebuildBuffersIfTexelMappingChanged;
|
|
70
|
+
render(positionArray: Node[], positionsChanged?: boolean): void;
|
|
71
|
+
/** Renders using a GPU position texture directly as `u_positions` */
|
|
72
|
+
renderFromGpuTexture(positionTexture: WebGLTexture): void;
|
|
73
|
+
private renderRelationships;
|
|
41
74
|
renderViewbox(): void;
|
|
42
75
|
updateNodes(updates: Node[]): void;
|
|
43
76
|
updateRelationships(relItems: Relationship[]): void;
|
|
44
77
|
private createPositionTexture;
|
|
78
|
+
private createIconTexture;
|
|
79
|
+
private uploadPendingIconLayers;
|
|
80
|
+
hasPendingIcons(): boolean;
|
|
45
81
|
updateViewportBox(zoom: number, panX: number, panY: number, viewportWidth: number, viewportHeight: number): void;
|
|
46
82
|
updateViewport(zoom: number, panX: number, panY: number): void;
|
|
47
83
|
private setupViewportRendering;
|
|
84
|
+
private resolveNodeColor;
|
|
48
85
|
private setupNodeRendering;
|
|
49
86
|
private setupRelationshipRendering;
|
|
87
|
+
private setupArrowRendering;
|
|
88
|
+
private getRelBufferAttributes;
|
|
89
|
+
private updateEndpointSizesForNode;
|
|
50
90
|
private renderAnimations;
|
|
51
91
|
destroy(): void;
|
|
52
92
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision mediump float;\n\nuniform mediump float u_zoom;\nuniform lowp float u_animPos;\nuniform mediump float u_glAdjust;\n\nin lowp vec4 color;\nin mediump float varNodeSize;\n\nout vec4 fragColor;\n\nconst float pulseCircleEdge = 0.50;\n\nvoid main(void) {\n float dist = distance(gl_PointCoord, vec2(0.5));\n\n if (dist > 0.51) {\n discard;\n } else {\n float alpha = 1.0 - smoothstep(pulseCircleEdge - (1.0 / (varNodeSize * 2.0 * u_zoom * u_glAdjust)), pulseCircleEdge, dist);\n float pulseAlpha = 0.9 - 0.9 * u_animPos;\n fragColor = vec4(color.xyz, 1.0) * alpha * pulseAlpha;\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;\nuniform sampler2D u_positions;\nuniform lowp float u_animPos;\nuniform mediump float u_zoom;\nuniform mediump float u_glAdjust;\n\nin float a_size;\nin highp vec2 a_index;\nin lowp vec4 a_color;\nin lowp float a_active;\n\nout mediump float varNodeSize;\nout lowp vec4 color;\n\nvoid main(void) {\n vec4 data = texture(u_positions, a_index);\n\n gl_Position = u_projection * vec4(data.xy, 0.0, 1.0);\n\n float nodeSize = a_size * u_zoom * u_glAdjust;\n nodeSize = nodeSize * 0.8;\n\n gl_PointSize = a_active > 0.5\n ? nodeSize + 0.88 * nodeSize * u_animPos\n : 0.0;\n\n color = a_color;\n varNodeSize = a_size;\n}";
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision mediump float;\n\nuniform lowp vec3 u_nodeBorderColor;\nuniform lowp vec3 u_selectedBorderColor;\nuniform lowp vec3 u_selectedInnerBorderColor;\nuniform lowp vec3 u_shadowColor;\nuniform lowp float u_drawDefaultBorder;\nuniform lowp sampler2DArray u_icons;\nuniform mediump float u_minIconScreenPx;\n\nin lowp vec4 color;\nin lowp float selected;\nin lowp float hovered;\nin mediump float varNodeSize;\nin mediump float iconLayer;\nin lowp float hasIcon;\n\nout vec4 fragColor;\n\nconst float circleSize = 0.40;\nconst float defaultBorderSize = 0.42;\nconst float innerSelectedRingSize = 0.43;\nconst float outerSelectedRingSize = 0.47;\nconst float shadowSize = 0.51;\n\nfloat getShadowAlpha(float size, float dist) {\n return (1.0 - smoothstep(size, shadowSize, dist)) * 0.25;\n}\n\nfloat getCircleAlpha(float ringSize, float nodeSize, float dist) {\n return color.w - smoothstep(ringSize - nodeSize, ringSize, dist);\n}\n\nvoid main() {\n float dist = distance(gl_PointCoord, vec2(0.5));\n\n if (dist > 0.51) {\n discard;\n } else {\n float nodeSize = 1.0 / varNodeSize;\n float nodeAlpha = getCircleAlpha(circleSize, nodeSize, dist);\n float borderAlpha = getCircleAlpha(defaultBorderSize, nodeSize, dist);\n float ringAlpha = getCircleAlpha(innerSelectedRingSize, nodeSize, dist);\n vec3 finalColor = color.xyz;\n float finalAlpha = nodeAlpha;\n\n if (selected > 0.0) {\n float shadowAlpha = getShadowAlpha(outerSelectedRingSize, dist);\n float ringAlpha2 = getCircleAlpha(outerSelectedRingSize, nodeSize, dist);\n\n if (u_drawDefaultBorder > 0.0) {\n finalColor = mix(u_nodeBorderColor, finalColor, nodeAlpha);\n finalColor = mix(u_selectedInnerBorderColor, finalColor, borderAlpha);\n finalColor = mix(u_selectedBorderColor, finalColor, ringAlpha);\n finalColor = mix(u_shadowColor, finalColor, ringAlpha2);\n finalAlpha = max(shadowAlpha, max(nodeAlpha, max(borderAlpha, ringAlpha2)));\n } else {\n finalColor = mix(u_selectedInnerBorderColor, finalColor, nodeAlpha);\n finalColor = mix(u_selectedBorderColor, finalColor, ringAlpha);\n finalColor = mix(u_shadowColor, finalColor, ringAlpha2);\n finalAlpha = max(shadowAlpha, max(nodeAlpha, max(ringAlpha, ringAlpha2)));\n }\n } else if (hovered > 0.0) {\n if (u_drawDefaultBorder > 0.0) {\n float shadowAlpha = getShadowAlpha(defaultBorderSize, dist);\n finalColor = mix(u_nodeBorderColor, finalColor, nodeAlpha);\n finalColor = mix(u_shadowColor, finalColor, borderAlpha);\n finalAlpha = max(shadowAlpha, max(nodeAlpha, ringAlpha));\n } else {\n float shadowAlpha = getShadowAlpha(circleSize, dist);\n finalColor = mix(u_shadowColor, finalColor, nodeAlpha);\n finalAlpha = max(shadowAlpha, nodeAlpha);\n }\n } else {\n if (u_drawDefaultBorder > 0.0) {\n finalColor = mix(u_nodeBorderColor, finalColor, nodeAlpha);\n finalAlpha = borderAlpha;\n }\n }\n\n bool iconLargeEnough = varNodeSize * circleSize >= u_minIconScreenPx;\n if (hasIcon > 0.5 && iconLargeEnough) {\n vec2 uv = (gl_PointCoord - vec2(0.5)) / circleSize + 0.5;\n\n float inX = step(0.0, uv.x) - step(1.0, uv.x);\n float inY = step(0.0, uv.y) - step(1.0, uv.y);\n float isInside = inX * inY;\n\n vec4 ic = texture(u_icons, vec3(uv, iconLayer));\n finalColor = mix(finalColor, ic.rgb, ic.a * isInside);\n }\n\n fragColor = vec4(finalColor, 1.0) * finalAlpha;\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;\nuniform sampler2D u_positions;\nuniform mediump float u_zoom;\nuniform mediump float u_glAdjust;\n\nin float a_size;\nin highp vec2 a_index;\nin lowp vec4 a_color;\nin lowp float a_selected;\nin lowp float a_hovered;\nin lowp float a_iconLayer;\nin lowp float a_hasIcon;\n\nout lowp vec4 color;\nout lowp float selected;\nout lowp float hovered;\nout mediump float varNodeSize;\nout mediump float iconLayer;\nout lowp float hasIcon;\n\nconst float MinNodeSize = 5.0;\n\nvoid main(void) {\n vec4 data = texture(u_positions, a_index);\n gl_Position = u_projection * vec4(data.xy, 0.0, 1.0);\n\n float nodeSize = max(a_size * u_zoom * u_glAdjust, MinNodeSize);\n gl_PointSize = nodeSize;\n varNodeSize = nodeSize;\n\n color = a_color;\n selected = a_selected;\n hovered = a_hovered;\n iconLayer = a_iconLayer * 255.0;\n hasIcon = a_hasIcon;\n}";
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nprecision lowp float;\n\nin lowp vec4 color;\n\nout vec4 fragColor;\n\nvoid main(void) {\n fragColor = vec4(color.xyz, 1.0) * color.w;\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const arrowShaderUtilsGLSL = "\nconst float CircleSize = 0.40;\nconst float HeadHalfWidthScale = 4.0;\nconst float HeadLengthScale = 2.5;\nconst float MaxHeadHalfWidthRatio = 0.6;\nconst float MaxHeadLengthRatio = 1.0;\n\n// Self-referencing relationships aren't supported in WebGL yet.\nbool relationshipIsSelfLoop(vec2 fromTexel, vec2 toTexel) {\n return all(equal(fromTexel, toTexel));\n}\n\nvec2 perpendicular(vec2 dir) {\n return vec2(-dir.y, dir.x);\n}\n\nfloat nodeRadiusFromSize(float size) {\n return size * u_glAdjust * CircleSize;\n}\n\nfloat relationshipHalfWidth(float width) {\n return width * u_glAdjust * 0.25;\n}\n\nfloat naturalArrowHeadHalfWidth(float lineHalfWidth) {\n return lineHalfWidth * HeadHalfWidthScale + u_glAdjust;\n}\n\nfloat naturalArrowHeadLength(float headHalfWidth) {\n return headHalfWidth * HeadLengthScale;\n}\n\nfloat clampArrowHeadHalfWidth(float lineHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadHalfWidth(lineHalfWidth);\n float minHalfWidth = lineHalfWidth;\n float maxHalfWidth = max(minHalfWidth, nodeRadius * MaxHeadHalfWidthRatio);\n return clamp(natural, minHalfWidth, maxHalfWidth);\n}\n\nfloat clampArrowHeadLength(float headHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadLength(headHalfWidth);\n float maxLength = nodeRadius * MaxHeadLengthRatio;\n return min(natural, maxLength);\n}\n\nfloat arrowHeadClearance(float lineHalfWidth, float nodeRadius) {\n float headHalfWidth = clampArrowHeadHalfWidth(lineHalfWidth, nodeRadius);\n return clampArrowHeadLength(headHalfWidth, nodeRadius);\n}\n";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "#version 300 es\nuniform mat4 u_projection;\nuniform sampler2D u_positions;\nuniform mediump float u_glAdjust;\n\nin vec2 a_from;\nin vec2 a_to;\nin lowp vec4 a_color;\nin float a_width;\nin float a_toSize;\n\nout lowp vec4 color;\n\n\nconst float CircleSize = 0.40;\nconst float HeadHalfWidthScale = 4.0;\nconst float HeadLengthScale = 2.5;\nconst float MaxHeadHalfWidthRatio = 0.6;\nconst float MaxHeadLengthRatio = 1.0;\n\n// Self-referencing relationships aren't supported in WebGL yet.\nbool relationshipIsSelfLoop(vec2 fromTexel, vec2 toTexel) {\n return all(equal(fromTexel, toTexel));\n}\n\nvec2 perpendicular(vec2 dir) {\n return vec2(-dir.y, dir.x);\n}\n\nfloat nodeRadiusFromSize(float size) {\n return size * u_glAdjust * CircleSize;\n}\n\nfloat relationshipHalfWidth(float width) {\n return width * u_glAdjust * 0.25;\n}\n\nfloat naturalArrowHeadHalfWidth(float lineHalfWidth) {\n return lineHalfWidth * HeadHalfWidthScale + u_glAdjust;\n}\n\nfloat naturalArrowHeadLength(float headHalfWidth) {\n return headHalfWidth * HeadLengthScale;\n}\n\nfloat clampArrowHeadHalfWidth(float lineHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadHalfWidth(lineHalfWidth);\n float minHalfWidth = lineHalfWidth;\n float maxHalfWidth = max(minHalfWidth, nodeRadius * MaxHeadHalfWidthRatio);\n return clamp(natural, minHalfWidth, maxHalfWidth);\n}\n\nfloat clampArrowHeadLength(float headHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadLength(headHalfWidth);\n float maxLength = nodeRadius * MaxHeadLengthRatio;\n return min(natural, maxLength);\n}\n\nfloat arrowHeadClearance(float lineHalfWidth, float nodeRadius) {\n float headHalfWidth = clampArrowHeadHalfWidth(lineHalfWidth, nodeRadius);\n return clampArrowHeadLength(headHalfWidth, nodeRadius);\n}\n\n\nvoid main(void) {\n vec4 from = texture(u_positions, a_from);\n vec4 to = texture(u_positions, a_to);\n\n if (relationshipIsSelfLoop(a_from, a_to)) {\n color = a_color;\n gl_Position = u_projection * vec4(from.xy, 0.0, 1.0);\n return;\n }\n\n vec2 delta = to.xy - from.xy;\n vec2 dir = normalize(delta);\n vec2 perp = perpendicular(dir);\n\n float toRadius = nodeRadiusFromSize(a_toSize);\n float lineHalfWidth = relationshipHalfWidth(a_width);\n float headHalfWidth = clampArrowHeadHalfWidth(lineHalfWidth, toRadius);\n float headLength = clampArrowHeadLength(headHalfWidth, toRadius);\n\n vec2 tip = to.xy - dir * toRadius;\n vec2 baseCenter = tip - dir * headLength;\n\n int corner = gl_VertexID % 3;\n float isTip = float(corner == 0);\n float perpSign = float(corner == 1) - float(corner == 2);\n vec2 basePos = mix(baseCenter, tip, isTip);\n vec2 vertexPosition = basePos + perp * (headHalfWidth * perpSign);\n\n color = a_color;\n gl_Position = u_projection * vec4(vertexPosition, 0.0, 1.0);\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "
|
|
1
|
+
declare const _default: "#version 300 es\nuniform mat4 u_projection;\nuniform sampler2D u_positions;\nuniform mediump float u_glAdjust;\n\nin vec2 a_from;\nin vec2 a_to;\nin lowp vec4 a_color;\nin lowp float a_triside;\nin lowp float a_isTarget;\nin float a_endpointSize;\nin float a_otherEndpointSize;\nin float a_width;\n\nout lowp vec4 color;\n\n\nconst float CircleSize = 0.40;\nconst float HeadHalfWidthScale = 4.0;\nconst float HeadLengthScale = 2.5;\nconst float MaxHeadHalfWidthRatio = 0.6;\nconst float MaxHeadLengthRatio = 1.0;\n\n// Self-referencing relationships aren't supported in WebGL yet.\nbool relationshipIsSelfLoop(vec2 fromTexel, vec2 toTexel) {\n return all(equal(fromTexel, toTexel));\n}\n\nvec2 perpendicular(vec2 dir) {\n return vec2(-dir.y, dir.x);\n}\n\nfloat nodeRadiusFromSize(float size) {\n return size * u_glAdjust * CircleSize;\n}\n\nfloat relationshipHalfWidth(float width) {\n return width * u_glAdjust * 0.25;\n}\n\nfloat naturalArrowHeadHalfWidth(float lineHalfWidth) {\n return lineHalfWidth * HeadHalfWidthScale + u_glAdjust;\n}\n\nfloat naturalArrowHeadLength(float headHalfWidth) {\n return headHalfWidth * HeadLengthScale;\n}\n\nfloat clampArrowHeadHalfWidth(float lineHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadHalfWidth(lineHalfWidth);\n float minHalfWidth = lineHalfWidth;\n float maxHalfWidth = max(minHalfWidth, nodeRadius * MaxHeadHalfWidthRatio);\n return clamp(natural, minHalfWidth, maxHalfWidth);\n}\n\nfloat clampArrowHeadLength(float headHalfWidth, float nodeRadius) {\n float natural = naturalArrowHeadLength(headHalfWidth);\n float maxLength = nodeRadius * MaxHeadLengthRatio;\n return min(natural, maxLength);\n}\n\nfloat arrowHeadClearance(float lineHalfWidth, float nodeRadius) {\n float headHalfWidth = clampArrowHeadHalfWidth(lineHalfWidth, nodeRadius);\n return clampArrowHeadLength(headHalfWidth, nodeRadius);\n}\n\n\nvoid main(void) {\n vec4 from = texture(u_positions, a_from);\n vec4 to = texture(u_positions, a_to);\n\n if (relationshipIsSelfLoop(a_from, a_to)) {\n color = a_color;\n gl_Position = u_projection * vec4(from.xy, 0.0, 1.0);\n return;\n }\n\n vec2 delta = from.xy - to.xy;\n float halfWidth = relationshipHalfWidth(a_width);\n float ownRadius = nodeRadiusFromSize(a_endpointSize);\n float otherRadius = nodeRadiusFromSize(a_otherEndpointSize);\n float toRadius = mix(otherRadius, ownRadius, a_isTarget);\n float arrowClearance = arrowHeadClearance(halfWidth, toRadius);\n float endpointClearance = ownRadius + a_isTarget * arrowClearance;\n\n vec2 along = normalize(delta);\n from.xy -= along * endpointClearance;\n\n float sideSign = 1.0 - 2.0 * a_triside;\n from.xy += sideSign * halfWidth * perpendicular(along);\n\n color = a_color;\n gl_Position = u_projection * vec4(from.xy, 0.0, 1.0);\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "\
|
|
1
|
+
declare const _default: "#version 300 es\nprecision lowp float;\n\nuniform lowp vec4 u_minimapViewportBoxColor;\n\nout vec4 fragColor;\n\nvoid main(void) {\n fragColor = u_minimapViewportBoxColor;\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "\
|
|
1
|
+
declare const _default: "#version 300 es\nin vec2 coordinates;\nuniform mat4 u_projection;\n\nvoid main(void) {\n gl_Position = u_projection * vec4(coordinates, 0.0, 1.0);\n}\n";
|
|
2
2
|
export default _default;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StyledCaption } from '../renderers/domrenderer/shared/types';
|
|
2
|
+
import type { Point } from '../utils/geometry';
|
|
2
3
|
/**
|
|
3
4
|
* The base type for graph elements.
|
|
4
5
|
* @private
|
|
@@ -97,6 +98,13 @@ interface Node extends GraphElement {
|
|
|
97
98
|
*/
|
|
98
99
|
html?: HTMLElement;
|
|
99
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* A node returned by {@link NVL.getNodes} with layout coordinates and screen position.
|
|
103
|
+
* `x` and `y` are canvas/layout space; `clientPosition` is relative to the canvas element.
|
|
104
|
+
*/
|
|
105
|
+
type NodeWithClientPosition = Node & Point & {
|
|
106
|
+
clientPosition: Point;
|
|
107
|
+
};
|
|
100
108
|
/**
|
|
101
109
|
* A node with only a subset of its properties.
|
|
102
110
|
*/
|
|
@@ -132,4 +140,4 @@ type PartialRelationship = Partial<Relationship> & {
|
|
|
132
140
|
/** The id of the relationship. */
|
|
133
141
|
id: string;
|
|
134
142
|
};
|
|
135
|
-
export type { Node, Relationship, PartialNode, PartialRelationship };
|
|
143
|
+
export type { Node, NodeWithClientPosition, Relationship, PartialNode, PartialRelationship };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Node, Relationship } from './graph-element';
|
|
1
|
+
import type { Node, NodeWithClientPosition, Relationship } from './graph-element';
|
|
2
2
|
export interface NvlWindow {
|
|
3
|
-
__Nvl_dumpNodes: (instanceId?: string) =>
|
|
3
|
+
__Nvl_dumpNodes: (instanceId?: string) => NodeWithClientPosition[];
|
|
4
4
|
__Nvl_dumpRelationships: (instanceId?: string) => Relationship[];
|
|
5
5
|
__Nvl_getNodesOnScreen: (instanceId?: string) => {
|
|
6
6
|
nodes: Node[];
|
|
@@ -13,7 +13,7 @@ export declare const createCanvasForScreenshot: (fullWidth: number, fullHeight:
|
|
|
13
13
|
export declare const createCanvasForRenderer: (parent?: HTMLElement, onContextLostCallback?: (e: WebGLContextEvent) => void) => HTMLCanvasElement;
|
|
14
14
|
export declare const removeCanvas: (canvas: HTMLCanvasElement) => void;
|
|
15
15
|
export declare const getCanvas2DContext: (canvas: HTMLCanvasElement) => CanvasRenderingContext2D;
|
|
16
|
-
export declare const getWebGLContext: (canvas: HTMLCanvasElement) =>
|
|
16
|
+
export declare const getWebGLContext: (canvas: HTMLCanvasElement) => WebGL2RenderingContext | null;
|
|
17
17
|
export declare const removeWebGLContext: (webGLCtx: WebGLRenderingContext) => void;
|
|
18
18
|
export declare const checkWebGLAvailability: (canvas?: HTMLCanvasElement) => boolean;
|
|
19
19
|
/**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Point } from './geometry';
|
|
2
|
+
/** Extra world-space padding around each member disk before taking the cluster hull. */
|
|
3
|
+
export declare const ClusterHullPadding = 14;
|
|
4
|
+
/** Circumference samples per member disk before taking the convex hull. */
|
|
5
|
+
export declare const DiskSampleCount = 8;
|
|
6
|
+
export type ClusterMemberDisk = Point & {
|
|
7
|
+
radius: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Fits a convex hull around the given disks by sampling each member circumference.
|
|
11
|
+
* @param members - The cluster member disks to fit the hull around.
|
|
12
|
+
* @returns The fitted hull, or null if fewer than two members have a usable position/radius.
|
|
13
|
+
*/
|
|
14
|
+
export declare const fitClusterHull: (members: ClusterMemberDisk[]) => Point[] | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type CoarsenedGraph, type Sun } from '../layouts/forcedirectedlayout/clustering/types';
|
|
2
|
+
import type { Cluster, ClusterId } from '../modules/state/types';
|
|
3
|
+
import type { Node } from '../types/graph-element';
|
|
4
|
+
import { type ClusterMemberDisk } from './clusterGeometry';
|
|
5
|
+
import { type Point } from './geometry';
|
|
6
|
+
/**
|
|
7
|
+
* A fitted cluster hull region used for decoration and hit-testing.
|
|
8
|
+
*/
|
|
9
|
+
export type ClusterHitRegion = Cluster & {
|
|
10
|
+
/** Convex hull used for picking / decoration. */
|
|
11
|
+
hull: Point[];
|
|
12
|
+
/** Layout sun original id (e.g. `synth-sun:${id}`). */
|
|
13
|
+
sunOriginalId: string;
|
|
14
|
+
};
|
|
15
|
+
export type MultiMemberCluster = {
|
|
16
|
+
sun: Sun;
|
|
17
|
+
nodeIds: string[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Returns each multi-member first-level sun system in a coarsening hierarchy.
|
|
21
|
+
* @param firstSubGraphLevel - `subGraphs[1]` from the current layout coarsening hierarchy.
|
|
22
|
+
* @returns Suns paired with their original member node ids.
|
|
23
|
+
*/
|
|
24
|
+
export declare const getMultiMemberClusters: (firstSubGraphLevel: CoarsenedGraph) => MultiMemberCluster[];
|
|
25
|
+
/**
|
|
26
|
+
* Collects member disks with usable positions for hull fitting.
|
|
27
|
+
* @param nodeIds - Member node ids.
|
|
28
|
+
* @param idToPosition - Node id to position map.
|
|
29
|
+
* @param idToItem - Node id to graph node map.
|
|
30
|
+
* @returns Member disks for {@link fitClusterHull}.
|
|
31
|
+
*/
|
|
32
|
+
export declare const collectMemberDisks: (nodeIds: string[], idToPosition: Readonly<Record<string, Point>>, idToItem: Record<string, Node>) => ClusterMemberDisk[];
|
|
33
|
+
/**
|
|
34
|
+
* Builds hit regions for {@link ClusteringOptions.clusterBy} multi-member clusters.
|
|
35
|
+
* Structural {@link SolarMerger} suns are skipped, as they have no entry in `clusterIdsBySun`.
|
|
36
|
+
* @param subGraphs - Layout coarsening hierarchy.
|
|
37
|
+
* @param idToPosition - Node id to position map.
|
|
38
|
+
* @param idToItem - Node id to graph node map.
|
|
39
|
+
* @param clusterIdsBySun - Cluster id per synthetic cluster sun, keyed by sun `originalId`.
|
|
40
|
+
* @returns Fitted cluster hit regions.
|
|
41
|
+
*/
|
|
42
|
+
export declare const buildClusterByHitRegions: (subGraphs: CoarsenedGraph[], idToPosition: Readonly<Record<string, Point>>, idToItem: Record<string, Node>, clusterIdsBySun: ReadonlyMap<string, ClusterId>) => ClusterHitRegion[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,6 +5,12 @@ export declare const MinRelLength = 100;
|
|
|
5
5
|
export declare const Gravity = 25;
|
|
6
6
|
export declare const SimulationStopVelocity = 0.25;
|
|
7
7
|
export declare const MappingEnd = 999999;
|
|
8
|
+
export declare const LayoutStepIntervalMs = 13;
|
|
9
|
+
export declare const MaxLayoutStepsPerFrame = 20;
|
|
10
|
+
export declare const DefaultMaxFps = 30;
|
|
11
|
+
export declare const DefaultMinFps = 3;
|
|
12
|
+
export declare const MinAllowedFps = 1;
|
|
13
|
+
export declare const MaxAllowedFps = 120;
|
|
8
14
|
export declare const ActiveAnimDuration = 1000;
|
|
9
15
|
export declare const DefaultNodeSize = 25;
|
|
10
16
|
export declare const DefaultNodeColor = "#FFDF81";
|
|
@@ -8,11 +8,11 @@ export interface Point {
|
|
|
8
8
|
/** The y coordinate of the point. */
|
|
9
9
|
y: number;
|
|
10
10
|
}
|
|
11
|
-
export declare const isPointDefined: (point: Point | Node) => boolean;
|
|
12
11
|
/**
|
|
13
12
|
* Returns true when value is a finite number (not NaN or Infinity).
|
|
14
13
|
*/
|
|
15
14
|
export declare const isValidFiniteNumber: (value: unknown) => value is number;
|
|
15
|
+
export declare const isPointDefined: (point: Point | Node | null | undefined) => point is Point;
|
|
16
16
|
/**
|
|
17
17
|
* This function checks if the coordinates are defined.
|
|
18
18
|
* @param from - The {@link Node} the edge starts from.
|
|
@@ -126,3 +126,46 @@ export declare const getIntersection: (p0: Point, p1: Point, p2: Point, p3: Poin
|
|
|
126
126
|
* @returns The distance between the point and the curve.
|
|
127
127
|
*/
|
|
128
128
|
export declare const getDistanceToQuadratic: (fromCoordinates: Point, toCoordinates: Point, control: Point, point: Point) => number;
|
|
129
|
+
/**
|
|
130
|
+
* Converts a polar coordinate (radius + angle around a centre) to a cartesian point.
|
|
131
|
+
* @param centre - The centre of the circle.
|
|
132
|
+
* @param radius - The radius of the circle.
|
|
133
|
+
* @param angle - The angle around the circle, in radians.
|
|
134
|
+
* @returns The point at that angle and radius from the centre.
|
|
135
|
+
*/
|
|
136
|
+
export declare const pointOnCircle: (centre: Point, radius: number, angle: number) => Point;
|
|
137
|
+
/**
|
|
138
|
+
* Returns the point halfway between two points.
|
|
139
|
+
* @param a - The first point.
|
|
140
|
+
* @param b - The second point.
|
|
141
|
+
* @returns The midpoint of the segment from a to b.
|
|
142
|
+
*/
|
|
143
|
+
export declare const getMidPoint: (a: Point, b: Point) => Point;
|
|
144
|
+
/**
|
|
145
|
+
* Places child points evenly spaced around a circle centred on a point.
|
|
146
|
+
* @param centre - The centre of the circle.
|
|
147
|
+
* @param radius - The radius of the circle.
|
|
148
|
+
* @param noOfChildren - The number of points to place around the circle.
|
|
149
|
+
* @returns The evenly spaced points.
|
|
150
|
+
*/
|
|
151
|
+
export declare const calculateCirclePositions: (centre: Point, radius: number, noOfChildren: number) => Point[];
|
|
152
|
+
/**
|
|
153
|
+
* Andrew's monotone-chain convex hull.
|
|
154
|
+
* @param points - The points to get the convex hull of.
|
|
155
|
+
* @returns The convex hull of the points.
|
|
156
|
+
*/
|
|
157
|
+
export declare const getConvexHull: (points: Point[]) => Point[];
|
|
158
|
+
/**
|
|
159
|
+
* Returns true when the point lies inside or on the boundary of a convex polygon.
|
|
160
|
+
* Works for both clockwise and counter-clockwise vertex order.
|
|
161
|
+
* @param point - The point to test.
|
|
162
|
+
* @param polygon - Convex polygon vertices in order around the boundary.
|
|
163
|
+
* @returns True when the point is inside or on the polygon.
|
|
164
|
+
*/
|
|
165
|
+
export declare const isPointInConvexPolygon: (point: Point, polygon: Point[]) => boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Absolute area of a simple polygon via the shoelace formula.
|
|
168
|
+
* @param polygon - Polygon vertices in order around the boundary.
|
|
169
|
+
* @returns The absolute area of the polygon.
|
|
170
|
+
*/
|
|
171
|
+
export declare const getPolygonArea: (polygon: Point[]) => number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { NvlState } from '../modules/state/types';
|
|
1
|
+
import type { Cluster, NvlState } from '../modules/state/types';
|
|
2
2
|
import type { Node, Relationship } from '../types/graph-element';
|
|
3
|
+
import type { ClusterHitRegion } from './clusterHitRegions';
|
|
3
4
|
import type { Point } from './geometry';
|
|
4
5
|
/**
|
|
5
6
|
* A node that has been hit by a pointer event
|
|
@@ -34,7 +35,18 @@ export interface HitTargetRelationship {
|
|
|
34
35
|
distance: number;
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
|
-
* A
|
|
38
|
+
* A {@link ClusteringOptions.clusterBy} cluster hull that has been hit by a pointer event
|
|
39
|
+
*/
|
|
40
|
+
export interface HitTargetCluster {
|
|
41
|
+
/** The cluster that was hit */
|
|
42
|
+
data: Cluster;
|
|
43
|
+
/** The coordinates of the pointer event */
|
|
44
|
+
pointerCoordinates: Point;
|
|
45
|
+
/** The convex hull used for the hit test */
|
|
46
|
+
hull: Point[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A collection of nodes, relationships and clusters that have been hit by a pointer event
|
|
38
50
|
* Part of the result of a {@link NVL}.{@link NVL.getHits} call
|
|
39
51
|
*/
|
|
40
52
|
export type HitTargets = {
|
|
@@ -42,15 +54,29 @@ export type HitTargets = {
|
|
|
42
54
|
nodes: HitTargetNode[];
|
|
43
55
|
/** The relationships that have been hit by the pointer event. */
|
|
44
56
|
relationships: HitTargetRelationship[];
|
|
57
|
+
/** The cluster hulls that have been hit by the pointer event. */
|
|
58
|
+
clusters: HitTargetCluster[];
|
|
45
59
|
};
|
|
46
|
-
export
|
|
60
|
+
export type HitTestTarget = 'node' | 'relationship' | 'cluster';
|
|
61
|
+
/**
|
|
62
|
+
* Finds all cluster hulls that contain the given point.
|
|
63
|
+
* Overlapping hulls are returned smallest-first (most specific).
|
|
64
|
+
* @param x - X coordinate.
|
|
65
|
+
* @param y - Y coordinate.
|
|
66
|
+
* @param regions - Fitted cluster hit regions.
|
|
67
|
+
* @returns Cluster hits sorted by ascending hull area.
|
|
68
|
+
*/
|
|
69
|
+
export declare const hitClusterTest: (x: number, y: number, regions: ClusterHitRegion[]) => HitTargetCluster[];
|
|
70
|
+
export declare const hitTest: (x: number, y: number, state: NvlState, targets?: HitTestTarget[], options?: {
|
|
47
71
|
hitNodeMarginWidth?: number;
|
|
72
|
+
clusterRegions?: ClusterHitRegion[];
|
|
48
73
|
}) => HitTargets;
|
|
49
74
|
export declare const hitTestCanvas: (x: number, y: number, parentHandler: {
|
|
50
75
|
getCanvasNodesAt: (c: Point, m: number) => HitTargetNode[];
|
|
51
76
|
getCanvasRelsAt: (c: Point) => HitTargetRelationship[];
|
|
52
|
-
}, targets?:
|
|
77
|
+
}, targets?: readonly HitTestTarget[], options?: {
|
|
53
78
|
hitNodeMarginWidth?: number;
|
|
79
|
+
clusterRegions?: ClusterHitRegion[];
|
|
54
80
|
}) => HitTargets;
|
|
55
81
|
export declare const hitTestBox: (x1: number, y1: number, x2: number, y2: number, state: NvlState, targets?: string[]) => {
|
|
56
82
|
nodes: Node[];
|
|
@@ -16,17 +16,19 @@ export declare const recordCollector: (graphElements: NestedGraphElements[]) =>
|
|
|
16
16
|
* @example
|
|
17
17
|
*
|
|
18
18
|
* ```ts
|
|
19
|
-
* import neo4j from
|
|
20
|
-
* import { nvlResultTransformer, NVL } from
|
|
19
|
+
* import * as neo4j from 'neo4j-driver'
|
|
20
|
+
* import { nvlResultTransformer, NVL } from '@neo4j-nvl/base'
|
|
21
21
|
*
|
|
22
|
-
* const
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
22
|
+
* const run = async () => {
|
|
23
|
+
* const driver = neo4j.driver('{uri}', neo4j.auth.basic('{user}', '{password}'))
|
|
24
|
+
* const nvlGraph = await driver.executeQuery(
|
|
25
|
+
* 'MATCH (a)-[r]-(b) RETURN a,r,b LIMIT 25',
|
|
26
|
+
* {},
|
|
27
|
+
* { resultTransformer: nvlResultTransformer }
|
|
28
|
+
* )
|
|
28
29
|
*
|
|
29
|
-
*
|
|
30
|
+
* const nvl = new NVL(document.getElementById('viz'), nvlGraph.nodes, nvlGraph.relationships)
|
|
31
|
+
* }
|
|
30
32
|
* ```
|
|
31
33
|
*
|
|
32
34
|
* @see {@link https://neo4j.com/docs/api/javascript-driver/current/class/lib6/result-transformers.js~ResultTransformers.html|ResultTransformers on Neo4j JS Driver API Docs}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Point } from './geometry';
|
|
2
|
+
export type SeedingMethod = 'box' | 'circle';
|
|
3
|
+
export declare const getCircleSeedRadius: (nodeCount: number, seedSpacing: number) => number;
|
|
4
|
+
export declare const getBoxStartSize: (nodeCount: number) => number;
|
|
5
|
+
export declare const getCirclePositionsForNodeCount: (nodeCount: number, center: Point, radius: number) => Point[];
|
|
6
|
+
export declare const getBoxPositionsForNodeCount: (nodeCount: number, center: Point) => Point[];
|
|
7
|
+
export declare const getSeedPositions: (nodeCount: number, seedingMethod: SeedingMethod, center?: Point) => Point[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Node } from '../index';
|
|
2
2
|
import type { Point } from './geometry';
|
|
3
|
+
/**
|
|
4
|
+
* Gets padding for fitting nodes, which is twice the largest node radius.
|
|
5
|
+
* @param maxNodeRadius - The largest node radius.
|
|
6
|
+
* @returns The padding for fitting nodes.
|
|
7
|
+
*/
|
|
8
|
+
declare const getFitNodesPadding: (maxNodeRadius?: number) => number;
|
|
3
9
|
declare const getExtremeLimits: (nodePositions: Point[]) => Point[];
|
|
4
10
|
declare const getMaxDistance: (extremeLimits?: Point[]) => number;
|
|
5
11
|
/**
|
|
@@ -40,7 +46,8 @@ declare const createZoomTarget: (zoomX: number, zoomY: number, minZoom?: number,
|
|
|
40
46
|
* @param nodePositions - The node positions.
|
|
41
47
|
* @param containerWidth - The width of the container NVL is displayed in.
|
|
42
48
|
* @param containerHeight - The height of the container NVL is displayed in.
|
|
43
|
-
* @param maxNodeRadius - The maximum node radius, which is added as margin to the scene
|
|
49
|
+
* @param maxNodeRadius - The maximum node radius, which is added as margin to the scene
|
|
50
|
+
* (defaults to 2 * {@link DefaultNodeSize}).
|
|
44
51
|
* @returns The zoom and pan targets.
|
|
45
52
|
*/
|
|
46
53
|
declare const getZoomTargetForNodePositions: (nodePositions: Point[], containerWidth: number, containerHeight: number, maxNodeRadius?: number) => {
|
|
@@ -55,4 +62,4 @@ declare const getFlexibleZoomLimit: (nodePositions: Point[], rect: HTMLCanvasEle
|
|
|
55
62
|
declare const getNewZoomWithinLimits: (newZoom: number, oldZoom: number, minZoom: number, maxZoom: number) => number;
|
|
56
63
|
declare const isZoomOutAtLimit: (newZoom: number, oldZoom: number, zoomOutLimit: number) => boolean;
|
|
57
64
|
declare const getDynamicZoom: (nodePositions: Point[] & Node[], minZoom: number, maxZoom: number, rect: HTMLCanvasElement, newZoom: number, currentZoom: number) => number;
|
|
58
|
-
export { getFlexibleZoomLimit, getZoomTargetForNodePositions, isZoomOutAtLimit, getNewZoomWithinLimits, getExtremeLimits, getMaxDistance, getPositionBoundaries, getZoomLevel, createZoomTarget, getDynamicZoom };
|
|
65
|
+
export { getFitNodesPadding, getFlexibleZoomLimit, getZoomTargetForNodePositions, isZoomOutAtLimit, getNewZoomWithinLimits, getExtremeLimits, getMaxDistance, getPositionBoundaries, getZoomLevel, createZoomTarget, getDynamicZoom };
|