landscape-widget 0.2.0 → 0.3.0-alpha

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.
@@ -0,0 +1,282 @@
1
+ /* eslint no-constant-condition: 0 */
2
+ /* eslint no-restricted-properties: "warn" */
3
+ /* eslint prefer-destructuring: "warn" */
4
+ /* eslint no-param-reassign: "warn" */
5
+ /**
6
+ * Graphology ForceAtlas2 Iteration
7
+ * =================================
8
+ *
9
+ * Function used to perform a single iteration of the algorithm.
10
+ */
11
+ import { NODE_X, NODE_Y, NODE_DX, NODE_DY, NODE_FIXED, NODE_SIZE, NODE_MASS, NODE_CONVERGENCE, NODE_OLD_DX, NODE_OLD_DY, PPN, PPE, EDGE_SOURCE, EDGE_TARGET, EDGE_WEIGHT, } from './enum/layout';
12
+ const MAX_FORCE = 10;
13
+ /**
14
+ * Function used to calculate dx, dy for each node due to repulsion forces.
15
+ *
16
+ * @param {object} options - Layout options.
17
+ * @param {Float32Array} NodeMatrix - Node data. (operates in place)
18
+ * @param {string[][]} graphComponents - Graph data.
19
+ * @return {object} - Some metadata.
20
+ */
21
+ function getMovementDifferentialsDueToRepulsion(options, NodeMatrix, graphComponents) {
22
+ var _a;
23
+ const coefficient = (_a = options.scalingRatio) !== null && _a !== void 0 ? _a : 1;
24
+ const adjustSizes = options.adjustSizes;
25
+ let xDist;
26
+ let yDist;
27
+ let distance;
28
+ let factor;
29
+ let n1;
30
+ let n2;
31
+ if (adjustSizes === true) {
32
+ graphComponents.forEach((component) => {
33
+ for (let i = 0; i < component.length; i += 1) {
34
+ n1 = Number(component[i]) * PPN;
35
+ for (let j = 0; j < i; j += 1) {
36
+ n2 = Number(component[j]) * PPN;
37
+ xDist = NodeMatrix[n1 + NODE_X] - NodeMatrix[n2 + NODE_X];
38
+ yDist = NodeMatrix[n1 + NODE_Y] - NodeMatrix[n2 + NODE_Y];
39
+ // -- Anticollision Linear Repulsion
40
+ distance =
41
+ Math.sqrt(xDist * xDist + yDist * yDist) -
42
+ NodeMatrix[n1 + NODE_SIZE] -
43
+ NodeMatrix[n2 + NODE_SIZE];
44
+ if (distance > 0) {
45
+ factor =
46
+ (coefficient * NodeMatrix[n1 + NODE_MASS] * NodeMatrix[n2 + NODE_MASS]) /
47
+ distance /
48
+ distance;
49
+ // Updating nodes' dx and dy
50
+ NodeMatrix[n1 + NODE_DX] += xDist * factor;
51
+ NodeMatrix[n1 + NODE_DY] += yDist * factor;
52
+ NodeMatrix[n2 + NODE_DX] -= xDist * factor;
53
+ NodeMatrix[n2 + NODE_DY] -= yDist * factor;
54
+ }
55
+ else if (distance < 0) {
56
+ factor = 100 * coefficient * NodeMatrix[n1 + NODE_MASS] * NodeMatrix[n2 + NODE_MASS];
57
+ // Updating nodes' dx and dy
58
+ NodeMatrix[n1 + NODE_DX] += xDist * factor;
59
+ NodeMatrix[n1 + NODE_DY] += yDist * factor;
60
+ NodeMatrix[n2 + NODE_DX] -= xDist * factor;
61
+ NodeMatrix[n2 + NODE_DY] -= yDist * factor;
62
+ }
63
+ }
64
+ }
65
+ });
66
+ }
67
+ else {
68
+ graphComponents.forEach((component, c) => {
69
+ for (let i = 0; i < component.length; i += 1) {
70
+ n1 = Number(component[i]) * PPN;
71
+ for (let j = 0; j < i; j += 1) {
72
+ n2 = Number(component[j]) * PPN;
73
+ xDist = NodeMatrix[n1 + NODE_X] - NodeMatrix[n2 + NODE_X];
74
+ yDist = NodeMatrix[n1 + NODE_Y] - NodeMatrix[n2 + NODE_Y];
75
+ // -- Linear Repulsion
76
+ const distance_squared = xDist * xDist + yDist * yDist;
77
+ if (distance_squared > 0) {
78
+ distance = Math.sqrt(distance_squared);
79
+ factor =
80
+ (coefficient * NodeMatrix[n1 + NODE_MASS] * NodeMatrix[n2 + NODE_MASS]) /
81
+ distance_squared;
82
+ const norm_x = xDist / distance;
83
+ const norm_y = yDist / distance;
84
+ // Updating nodes' dx and dy
85
+ NodeMatrix[n1 + NODE_DX] += norm_x * factor;
86
+ NodeMatrix[n1 + NODE_DY] += norm_y * factor;
87
+ NodeMatrix[n2 + NODE_DX] -= norm_x * factor;
88
+ NodeMatrix[n2 + NODE_DY] -= norm_y * factor;
89
+ }
90
+ }
91
+ }
92
+ });
93
+ }
94
+ }
95
+ /**
96
+ * Function used to perform a single interation of the algorithm.
97
+ *
98
+ * @param {object} options - Layout options.
99
+ * @param {Float32Array} NodeMatrix - Node data.
100
+ * @param {Float32Array} EdgeMatrix - Edge data.
101
+ * @param {string[][]} graphComponents - Graph Components
102
+ * @return {object} - Some metadata.
103
+ */
104
+ export function iterateNoIntercomponentRepel(options, NodeMatrix, EdgeMatrix, graphComponents) {
105
+ var _a, _b, _c, _d;
106
+ // Initializing variables
107
+ let n;
108
+ let n1;
109
+ let n2;
110
+ let e;
111
+ const adjustSizes = options.adjustSizes;
112
+ let outboundAttCompensation;
113
+ let xDist;
114
+ let yDist;
115
+ let ewc;
116
+ let distance;
117
+ let factor = 0;
118
+ let force;
119
+ let swinging;
120
+ let traction;
121
+ let nodespeed;
122
+ // 1) Initializing layout data
123
+ //-----------------------------
124
+ // Resetting movements.
125
+ for (n = 0; n < NodeMatrix.length; n += PPN) {
126
+ NodeMatrix[n + NODE_OLD_DX] = NodeMatrix[n + NODE_DX];
127
+ NodeMatrix[n + NODE_OLD_DY] = NodeMatrix[n + NODE_DY];
128
+ NodeMatrix[n + NODE_DX] = 0;
129
+ NodeMatrix[n + NODE_DY] = 0;
130
+ }
131
+ const numberVertices = NodeMatrix.length / PPN;
132
+ // If outbound attraction distribution, compensate
133
+ if (options.outboundAttractionDistribution) {
134
+ outboundAttCompensation = 0;
135
+ for (n = 0; n < NodeMatrix.length; n += PPN) {
136
+ outboundAttCompensation += NodeMatrix[n + NODE_MASS];
137
+ }
138
+ outboundAttCompensation /= numberVertices;
139
+ }
140
+ // Repulsion
141
+ //--------------
142
+ // NOTES: adjustSizes = antiCollision & scalingRatio = coefficient
143
+ // Writes to NodeMatrix.
144
+ getMovementDifferentialsDueToRepulsion(options, NodeMatrix, graphComponents);
145
+ // 4) Attraction
146
+ //---------------
147
+ const coefficient = options.outboundAttractionDistribution ? outboundAttCompensation : 1;
148
+ if (!coefficient)
149
+ return;
150
+ const size = EdgeMatrix.length;
151
+ for (e = 0; e < size; e += PPE) {
152
+ n1 = EdgeMatrix[e + EDGE_SOURCE];
153
+ n2 = EdgeMatrix[e + EDGE_TARGET];
154
+ const w = EdgeMatrix[e + EDGE_WEIGHT];
155
+ // Edge weight influence
156
+ ewc = Math.pow(w, ((_a = options.edgeWeightInfluence) !== null && _a !== void 0 ? _a : 1));
157
+ // Common measures
158
+ xDist = NodeMatrix[n1 + NODE_X] - NodeMatrix[n2 + NODE_X];
159
+ yDist = NodeMatrix[n1 + NODE_Y] - NodeMatrix[n2 + NODE_Y];
160
+ // Applying attraction to nodes
161
+ if (adjustSizes === true) {
162
+ distance =
163
+ Math.sqrt(xDist * xDist + yDist * yDist) -
164
+ NodeMatrix[n1 + NODE_SIZE] -
165
+ NodeMatrix[n2 + NODE_SIZE];
166
+ if (options.linLogMode) {
167
+ if (options.outboundAttractionDistribution) {
168
+ // -- LinLog Degree Distributed Anti-collision Attraction
169
+ if (distance > 0) {
170
+ factor =
171
+ (-coefficient * ewc * Math.log(1 + distance)) / distance / NodeMatrix[n1 + NODE_MASS];
172
+ }
173
+ }
174
+ else if (distance > 0) {
175
+ // -- LinLog Anti-collision Attraction
176
+ factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
177
+ }
178
+ }
179
+ else if (options.outboundAttractionDistribution) {
180
+ // -- Linear Degree Distributed Anti-collision Attraction
181
+ if (distance > 0) {
182
+ factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
183
+ }
184
+ }
185
+ else if (distance > 0) {
186
+ // -- Linear Anti-collision Attraction
187
+ factor = -coefficient * ewc;
188
+ }
189
+ }
190
+ else {
191
+ distance = Math.sqrt(xDist * xDist + yDist * yDist);
192
+ if (options.linLogMode) {
193
+ if (options.outboundAttractionDistribution) {
194
+ // -- LinLog Degree Distributed Attraction
195
+ if (distance > 0) {
196
+ factor =
197
+ (-coefficient * ewc * Math.log(1 + distance)) / distance / NodeMatrix[n1 + NODE_MASS];
198
+ }
199
+ }
200
+ else if (distance > 0) {
201
+ factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
202
+ }
203
+ }
204
+ else if (options.outboundAttractionDistribution) {
205
+ // -- Linear Attraction Mass Distributed
206
+ // NOTE: Distance is set to 1 to override next condition
207
+ distance = 1;
208
+ factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
209
+ }
210
+ else {
211
+ // -- Linear Attraction
212
+ // NOTE: Distance is set to 1 to override next condition
213
+ distance = 1;
214
+ factor = -coefficient * ewc;
215
+ }
216
+ }
217
+ // Updating nodes' dx and dy
218
+ // TODO: if condition or factor = 1?
219
+ if (distance > 0) {
220
+ // Updating nodes' dx and dy
221
+ NodeMatrix[n1 + NODE_DX] += xDist * factor;
222
+ NodeMatrix[n1 + NODE_DY] += yDist * factor;
223
+ NodeMatrix[n2 + NODE_DX] -= xDist * factor;
224
+ NodeMatrix[n2 + NODE_DY] -= yDist * factor;
225
+ }
226
+ }
227
+ // Apply Forces
228
+ // -----------------
229
+ // MATH: sqrt and square distances
230
+ if (adjustSizes === true) {
231
+ for (n = 0; n < NodeMatrix.length; n += PPN) {
232
+ if (NodeMatrix[n + NODE_FIXED] !== 1) {
233
+ force = Math.sqrt(Math.pow(NodeMatrix[n + NODE_DX], 2) + Math.pow(NodeMatrix[n + NODE_DY], 2));
234
+ if (force > MAX_FORCE) {
235
+ NodeMatrix[n + NODE_DX] = (NodeMatrix[n + NODE_DX] * MAX_FORCE) / force;
236
+ NodeMatrix[n + NODE_DY] = (NodeMatrix[n + NODE_DY] * MAX_FORCE) / force;
237
+ }
238
+ swinging =
239
+ NodeMatrix[n + NODE_MASS] *
240
+ Math.sqrt((NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) *
241
+ (NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
242
+ (NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
243
+ (NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]));
244
+ traction =
245
+ Math.sqrt((NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
246
+ (NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
247
+ (NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
248
+ (NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])) / 2;
249
+ nodespeed = (0.1 * Math.log(1 + traction)) / (1 + Math.sqrt(swinging));
250
+ // Updating node's positon
251
+ const deltaX = NodeMatrix[n + NODE_DX] * (nodespeed / ((_b = options.slowDown) !== null && _b !== void 0 ? _b : 1));
252
+ NodeMatrix[n + NODE_X] += deltaX;
253
+ const deltaY = NodeMatrix[n + NODE_DY] * (nodespeed / ((_c = options.slowDown) !== null && _c !== void 0 ? _c : 1));
254
+ NodeMatrix[n + NODE_Y] += deltaY;
255
+ }
256
+ }
257
+ }
258
+ else {
259
+ for (n = 0; n < NodeMatrix.length; n += PPN) {
260
+ if (NodeMatrix[n + NODE_FIXED] !== 1) {
261
+ const ddx = NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX];
262
+ const ddy = NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY];
263
+ swinging = NodeMatrix[n + NODE_MASS] * Math.sqrt(Math.pow(ddx, 2) + Math.pow(ddy, 2));
264
+ const dxSum = NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX];
265
+ const dySum = NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY];
266
+ const swingingNormTerm = 1 + Math.sqrt(swinging);
267
+ traction = Math.sqrt(Math.pow(dxSum, 2) + Math.pow(dySum, 2)) / 2;
268
+ nodespeed = (NodeMatrix[n + NODE_CONVERGENCE] * Math.log(1 + traction)) / swingingNormTerm;
269
+ // Updating node convergence
270
+ NodeMatrix[n + NODE_CONVERGENCE] = Math.min(1, Math.sqrt((nodespeed * (Math.pow(NodeMatrix[n + NODE_DX], 2) + Math.pow(NodeMatrix[n + NODE_DY], 2))) /
271
+ swingingNormTerm));
272
+ // Updating node's positon
273
+ const stepSize = nodespeed / ((_d = options.slowDown) !== null && _d !== void 0 ? _d : 1);
274
+ NodeMatrix[n + NODE_X] += NodeMatrix[n + NODE_DX] * stepSize;
275
+ NodeMatrix[n + NODE_Y] += NodeMatrix[n + NODE_DY] * stepSize;
276
+ }
277
+ }
278
+ }
279
+ // We return the information about the layout (no need to return the matrices)
280
+ return {};
281
+ }
282
+ //# sourceMappingURL=IterateNoIntercomponentRepel.js.map
@@ -0,0 +1,132 @@
1
+ import { useCallback, useEffect } from 'react';
2
+ import { useRegisterEvents, useSigma } from '@react-sigma/core';
3
+ export const LoadGraph = ({ graph, animator, animate, selectedNodes, setSelectedNodes, addSelectedNodes, }) => {
4
+ const sigma = useSigma();
5
+ const registerEvents = useRegisterEvents();
6
+ useEffect(() => {
7
+ sigma.setGraph(graph);
8
+ sigma.refresh();
9
+ }, [graph]);
10
+ useEffect(() => {
11
+ graph.updateEachNodeAttributes((key, attr) => {
12
+ const n = Number(key);
13
+ if (selectedNodes.some((node) => node === n)) {
14
+ return Object.assign(Object.assign({}, attr), { highlighted: true });
15
+ }
16
+ return Object.assign(Object.assign({}, attr), { highlighted: false });
17
+ });
18
+ }, [selectedNodes, graph]);
19
+ const handleSelectionClear = useCallback(() => {
20
+ setSelectedNodes([]);
21
+ selectedNodes.forEach((node) => {
22
+ graph.setNodeAttribute(node, 'highlighted', false);
23
+ });
24
+ }, [setSelectedNodes, selectedNodes, graph]);
25
+ const onNodeDoubleClick = (e) => {
26
+ e.preventSigmaDefault();
27
+ const nodeValue = Number(e.node);
28
+ const isNodeSelectedAlready = selectedNodes.some((n) => n === nodeValue);
29
+ if (isNodeSelectedAlready) {
30
+ setSelectedNodes(selectedNodes.filter((n) => n !== nodeValue));
31
+ }
32
+ else {
33
+ addSelectedNodes([nodeValue]);
34
+ }
35
+ };
36
+ useEffect(() => {
37
+ let draggedNode;
38
+ let isDragging = false;
39
+ let isDraggedNodeSelected = false;
40
+ let previousPosition = null;
41
+ registerEvents({
42
+ downNode: (e) => {
43
+ isDragging = true;
44
+ draggedNode = e.node;
45
+ const nodeValue = Number(e.node);
46
+ graph.setNodeAttribute(draggedNode, 'highlighted', true);
47
+ isDraggedNodeSelected = selectedNodes.some((n) => n === nodeValue);
48
+ if (isDraggedNodeSelected) {
49
+ selectedNodes.map((node) => graph.updateNodeAttribute(node, 'fixed', () => true));
50
+ }
51
+ else {
52
+ graph.setNodeAttribute(draggedNode, 'fixed', true);
53
+ }
54
+ previousPosition = sigma.viewportToGraph(e.event);
55
+ if (!animator.isRunning() && animate) {
56
+ animator.start();
57
+ }
58
+ animator.resetNIters();
59
+ },
60
+ mousemovebody: (e) => {
61
+ if (!isDragging || !draggedNode || !previousPosition)
62
+ return;
63
+ animator.resetNIters();
64
+ const pos = sigma.viewportToGraph(e);
65
+ const dx = pos.x - previousPosition.x;
66
+ const dy = pos.y - previousPosition.y;
67
+ previousPosition = pos;
68
+ if (isDraggedNodeSelected) {
69
+ selectedNodes.map((node) => graph.updateNodeAttributes(node, (attr) => (Object.assign(Object.assign({}, attr), { x: attr.x + dx, y: attr.y + dy }))));
70
+ }
71
+ else {
72
+ graph.updateNodeAttributes(draggedNode, (attr) => (Object.assign(Object.assign({}, attr), { x: attr.x + dx, y: attr.y + dy })));
73
+ }
74
+ // Prevent sigma to move camera:
75
+ e.preventSigmaDefault();
76
+ e.original.preventDefault();
77
+ e.original.stopPropagation();
78
+ },
79
+ mouseup: () => {
80
+ if (draggedNode) {
81
+ if (isDraggedNodeSelected) {
82
+ selectedNodes.map((node) => graph.removeNodeAttribute(node, 'fixed'));
83
+ }
84
+ else {
85
+ graph.removeNodeAttribute(draggedNode, 'fixed');
86
+ graph.removeNodeAttribute(draggedNode, 'highlighted');
87
+ }
88
+ previousPosition = null;
89
+ }
90
+ isDragging = false;
91
+ draggedNode = null;
92
+ isDraggedNodeSelected = false;
93
+ },
94
+ mousedown: () => {
95
+ if (!sigma.getCustomBBox())
96
+ sigma.setCustomBBox(sigma.getBBox());
97
+ },
98
+ doubleClickNode: (e) => onNodeDoubleClick(e),
99
+ doubleClickStage: (e) => {
100
+ handleSelectionClear();
101
+ e.preventSigmaDefault();
102
+ },
103
+ wheel: (e) => {
104
+ const camera = sigma.getCamera();
105
+ const cameraState = camera.getState();
106
+ // too large a step makes the motion very unsmooth
107
+ const delta = Math.max(-1.5, Math.min(1.5, e.delta));
108
+ const newRatio = camera.getBoundedRatio(cameraState.ratio * (1 - delta / 8));
109
+ const event = e.original;
110
+ if (event.deltaMode !== WheelEvent.DOM_DELTA_PIXEL) {
111
+ console.warn('WheelEvent.deltaMode is not DOM_DELTA_PIXEL. Zoom behavior may not be as expected.');
112
+ }
113
+ // shift the center so that the mouse cursor is the fixed point of the zoom
114
+ const newState = sigma.getViewportZoomedState(e, newRatio);
115
+ camera.setState(newState);
116
+ e.preventSigmaDefault(); // this call is supposed to work but doesn't
117
+ // eslint-disable-next-line no-param-reassign
118
+ e.sigmaDefaultPrevented = true; // so we have to set this flag manually
119
+ },
120
+ });
121
+ }, [
122
+ registerEvents,
123
+ setSelectedNodes,
124
+ addSelectedNodes,
125
+ selectedNodes,
126
+ handleSelectionClear,
127
+ graph,
128
+ animate,
129
+ ]);
130
+ return null;
131
+ };
132
+ //# sourceMappingURL=LoadGraph.js.map
@@ -0,0 +1,118 @@
1
+ import React, { useCallback, useRef } from 'react';
2
+ import { useSigma } from '@react-sigma/core';
3
+ export const SigmaLasso = ({ active, setSelectedNodes, addSelectedNodes }) => {
4
+ const sigma = useSigma();
5
+ const lassoCanvasRef = useRef(null);
6
+ const getLassoCanvas = useCallback(() => {
7
+ if (active)
8
+ return lassoCanvasRef.current;
9
+ return null;
10
+ }, [active]);
11
+ const isDrawing = useRef(false);
12
+ const drawnPoints = useRef([]);
13
+ const onDrawingStart = (event) => {
14
+ const lassoCanvas = getLassoCanvas();
15
+ if (!lassoCanvas)
16
+ return;
17
+ isDrawing.current = true;
18
+ drawnPoints.current = [];
19
+ const drawingRectangle = lassoCanvas.getBoundingClientRect();
20
+ drawnPoints.current.push({
21
+ x: event.clientX - drawingRectangle.left,
22
+ y: event.clientY - drawingRectangle.top,
23
+ });
24
+ event.stopPropagation();
25
+ };
26
+ const onDrawing = (event) => {
27
+ const lassoCanvas = getLassoCanvas();
28
+ if (!lassoCanvas)
29
+ return;
30
+ if (isDrawing.current) {
31
+ let x;
32
+ let y;
33
+ const drawingRectangle = lassoCanvas.getBoundingClientRect();
34
+ const drawingContext = lassoCanvas.getContext('2d');
35
+ switch (event.type) {
36
+ case 'touchmove':
37
+ x = event.touches[0].clientX;
38
+ y = event.touches[0].clientY;
39
+ break;
40
+ default:
41
+ x = event.clientX;
42
+ y = event.clientY;
43
+ break;
44
+ }
45
+ drawnPoints.current.push({
46
+ x: x - drawingRectangle.left,
47
+ y: y - drawingRectangle.top,
48
+ });
49
+ // Drawing styles
50
+ drawingContext.strokeStyle = 'black';
51
+ drawingContext.lineWidth = 2;
52
+ drawingContext.fillStyle = 'rgba(200, 200, 200, 0.25)';
53
+ drawingContext.lineJoin = 'round';
54
+ drawingContext.lineCap = 'round';
55
+ // Clear the canvas
56
+ drawingContext.clearRect(0, 0, drawingContext.canvas.width, drawingContext.canvas.height);
57
+ // Redraw the complete path for a smoother effect
58
+ // Even smoother with quadratic curves
59
+ let sourcePoint = drawnPoints.current[0];
60
+ let destinationPoint = drawnPoints.current[1];
61
+ const pointsLength = drawnPoints.current.length;
62
+ const getMiddlePointCoordinates = (firstPoint, secondPoint) => ({
63
+ x: firstPoint.x + (secondPoint.x - firstPoint.x) / 2,
64
+ y: firstPoint.y + (secondPoint.y - firstPoint.y) / 2,
65
+ });
66
+ drawingContext.beginPath();
67
+ drawingContext.moveTo(sourcePoint.x, sourcePoint.y);
68
+ for (let i = 1; i < pointsLength; i += 1) {
69
+ const middlePoint = getMiddlePointCoordinates(sourcePoint, destinationPoint);
70
+ drawingContext.quadraticCurveTo(sourcePoint.x, sourcePoint.y, middlePoint.x, middlePoint.y);
71
+ sourcePoint = drawnPoints.current[i];
72
+ destinationPoint = drawnPoints.current[i + 1];
73
+ }
74
+ drawingContext.lineTo(sourcePoint.x, sourcePoint.y);
75
+ drawingContext.stroke();
76
+ drawingContext.fill();
77
+ event.stopPropagation();
78
+ }
79
+ };
80
+ const onDrawingEnd = useCallback((event) => {
81
+ const lassoCanvas = getLassoCanvas();
82
+ const viewRectangle = sigma.viewRectangle();
83
+ const graph = sigma.getGraph();
84
+ if (!lassoCanvas)
85
+ return;
86
+ isDrawing.current = false;
87
+ // @ts-ignore - There are no other ways to get visible nodes
88
+ const quadtreeRectangle = sigma.quadtree.rectangle(viewRectangle.x1, 1 - viewRectangle.y1, viewRectangle.x2, 1 - viewRectangle.y2, viewRectangle.height);
89
+ const visibleNodes = Array.from(new Set(quadtreeRectangle));
90
+ const drawingContext = lassoCanvas.getContext('2d');
91
+ const newSelectedNodes = [];
92
+ visibleNodes.forEach((key) => {
93
+ const nodeValue = Number(key);
94
+ const { x, y } = graph.getNodeAttributes(nodeValue);
95
+ const coordinates = sigma.graphToViewport({ x, y });
96
+ if (drawingContext.isPointInPath(coordinates.x, coordinates.y)) {
97
+ newSelectedNodes.push(nodeValue);
98
+ }
99
+ });
100
+ if (event.shiftKey) {
101
+ addSelectedNodes(newSelectedNodes);
102
+ }
103
+ else {
104
+ setSelectedNodes(newSelectedNodes);
105
+ }
106
+ drawingContext.clearRect(0, 0, lassoCanvas.width, lassoCanvas.height);
107
+ drawnPoints.current = [];
108
+ event.stopPropagation();
109
+ }, [setSelectedNodes, addSelectedNodes, getLassoCanvas, sigma]);
110
+ const onLassoScroll = (e) => {
111
+ const mouseCaptor = sigma.getMouseCaptor();
112
+ mouseCaptor.handleWheel(e.nativeEvent);
113
+ };
114
+ if (!active)
115
+ return null;
116
+ return (React.createElement("canvas", { ref: lassoCanvasRef, width: sigma.getContainer().offsetWidth, height: sigma.getContainer().offsetHeight, style: { position: 'absolute', top: '0px', cursor: 'crosshair' }, onMouseDown: onDrawingStart, onMouseMove: onDrawing, onMouseUp: onDrawingEnd, onWheel: onLassoScroll }));
117
+ };
118
+ //# sourceMappingURL=SigmaLasso.js.map
@@ -0,0 +1,24 @@
1
+ export var LayoutEnum;
2
+ (function (LayoutEnum) {
3
+ LayoutEnum["GRID"] = "grid";
4
+ LayoutEnum["TABLE"] = "table";
5
+ })(LayoutEnum || (LayoutEnum = {}));
6
+ /**
7
+ * Matrices properties accessors.
8
+ */
9
+ export const NODE_X = 0;
10
+ export const NODE_Y = 1;
11
+ export const NODE_DX = 2;
12
+ export const NODE_DY = 3;
13
+ export const NODE_OLD_DX = 4;
14
+ export const NODE_OLD_DY = 5;
15
+ export const NODE_MASS = 6;
16
+ export const NODE_CONVERGENCE = 7;
17
+ export const NODE_SIZE = 8;
18
+ export const NODE_FIXED = 9;
19
+ export const PPN = 10;
20
+ export const PPE = 3;
21
+ export const EDGE_SOURCE = 0;
22
+ export const EDGE_TARGET = 1;
23
+ export const EDGE_WEIGHT = 2;
24
+ //# sourceMappingURL=layout.js.map