@graphty/layout 1.2.7 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +1 -1
  2. package/dist/layout.d.ts +17 -0
  3. package/dist/layout.js +15 -14
  4. package/dist/layout.js.map +1 -1
  5. package/dist/src/algorithms/index.d.ts +5 -0
  6. package/dist/src/algorithms/index.js +6 -0
  7. package/dist/src/algorithms/index.js.map +1 -0
  8. package/dist/src/algorithms/optimization/index.d.ts +7 -0
  9. package/dist/src/algorithms/optimization/index.js +7 -0
  10. package/dist/src/algorithms/optimization/index.js.map +1 -0
  11. package/dist/src/algorithms/optimization/kamada-kawai-solver.d.ts +32 -0
  12. package/dist/src/algorithms/optimization/kamada-kawai-solver.js +176 -0
  13. package/dist/src/algorithms/optimization/kamada-kawai-solver.js.map +1 -0
  14. package/dist/src/algorithms/optimization/lbfgs.d.ts +13 -0
  15. package/dist/src/algorithms/optimization/lbfgs.js +56 -0
  16. package/dist/src/algorithms/optimization/lbfgs.js.map +1 -0
  17. package/dist/src/algorithms/optimization/line-search.d.ts +15 -0
  18. package/dist/src/algorithms/optimization/line-search.js +37 -0
  19. package/dist/src/algorithms/optimization/line-search.js.map +1 -0
  20. package/dist/src/algorithms/optimization/types.d.ts +5 -0
  21. package/dist/src/algorithms/optimization/types.js +5 -0
  22. package/dist/src/algorithms/optimization/types.js.map +1 -0
  23. package/dist/src/algorithms/planarity/check.d.ts +17 -0
  24. package/dist/src/algorithms/planarity/check.js +30 -0
  25. package/dist/src/algorithms/planarity/check.js.map +1 -0
  26. package/dist/src/algorithms/planarity/embedding.d.ts +29 -0
  27. package/dist/src/algorithms/planarity/embedding.js +182 -0
  28. package/dist/src/algorithms/planarity/embedding.js.map +1 -0
  29. package/dist/src/algorithms/planarity/index.d.ts +7 -0
  30. package/dist/src/algorithms/planarity/index.js +8 -0
  31. package/dist/src/algorithms/planarity/index.js.map +1 -0
  32. package/dist/src/algorithms/planarity/lr-test.d.ts +15 -0
  33. package/dist/src/algorithms/planarity/lr-test.js +54 -0
  34. package/dist/src/algorithms/planarity/lr-test.js.map +1 -0
  35. package/dist/src/algorithms/planarity/special-graphs.d.ts +28 -0
  36. package/dist/src/algorithms/planarity/special-graphs.js +108 -0
  37. package/dist/src/algorithms/planarity/special-graphs.js.map +1 -0
  38. package/dist/src/generators/basic.d.ts +28 -0
  39. package/dist/src/generators/basic.js +79 -0
  40. package/dist/src/generators/basic.js.map +1 -0
  41. package/dist/src/generators/bipartite.d.ts +16 -0
  42. package/dist/src/generators/bipartite.js +40 -0
  43. package/dist/src/generators/bipartite.js.map +1 -0
  44. package/dist/src/generators/grid.d.ts +11 -0
  45. package/dist/src/generators/grid.js +37 -0
  46. package/dist/src/generators/grid.js.map +1 -0
  47. package/dist/src/generators/index.d.ts +8 -0
  48. package/dist/src/generators/index.js +9 -0
  49. package/dist/src/generators/index.js.map +1 -0
  50. package/dist/src/generators/random.d.ts +12 -0
  51. package/dist/src/generators/random.js +34 -0
  52. package/dist/src/generators/random.js.map +1 -0
  53. package/dist/src/generators/scale-free.d.ts +12 -0
  54. package/dist/src/generators/scale-free.js +62 -0
  55. package/dist/src/generators/scale-free.js.map +1 -0
  56. package/dist/src/index.d.ts +10 -0
  57. package/dist/src/index.js +15 -0
  58. package/dist/src/index.js.map +1 -0
  59. package/dist/src/layouts/basic/index.d.ts +4 -0
  60. package/dist/src/layouts/basic/index.js +5 -0
  61. package/dist/src/layouts/basic/index.js.map +1 -0
  62. package/dist/src/layouts/basic/random.d.ts +14 -0
  63. package/dist/src/layouts/basic/random.js +27 -0
  64. package/dist/src/layouts/basic/random.js.map +1 -0
  65. package/dist/src/layouts/force-directed/arf.d.ts +13 -0
  66. package/dist/src/layouts/force-directed/arf.js +103 -0
  67. package/dist/src/layouts/force-directed/arf.js.map +1 -0
  68. package/dist/src/layouts/force-directed/forceatlas2.d.ts +22 -0
  69. package/dist/src/layouts/force-directed/forceatlas2.js +340 -0
  70. package/dist/src/layouts/force-directed/forceatlas2.js.map +1 -0
  71. package/dist/src/layouts/force-directed/fruchterman-reingold.d.ts +19 -0
  72. package/dist/src/layouts/force-directed/fruchterman-reingold.js +131 -0
  73. package/dist/src/layouts/force-directed/fruchterman-reingold.js.map +1 -0
  74. package/dist/src/layouts/force-directed/index.d.ts +8 -0
  75. package/dist/src/layouts/force-directed/index.js +9 -0
  76. package/dist/src/layouts/force-directed/index.js.map +1 -0
  77. package/dist/src/layouts/force-directed/kamada-kawai.d.ts +15 -0
  78. package/dist/src/layouts/force-directed/kamada-kawai.js +87 -0
  79. package/dist/src/layouts/force-directed/kamada-kawai.js.map +1 -0
  80. package/dist/src/layouts/force-directed/spring.d.ts +19 -0
  81. package/dist/src/layouts/force-directed/spring.js +23 -0
  82. package/dist/src/layouts/force-directed/spring.js.map +1 -0
  83. package/dist/src/layouts/geometric/circular.d.ts +14 -0
  84. package/dist/src/layouts/geometric/circular.js +67 -0
  85. package/dist/src/layouts/geometric/circular.js.map +1 -0
  86. package/dist/src/layouts/geometric/index.d.ts +6 -0
  87. package/dist/src/layouts/geometric/index.js +7 -0
  88. package/dist/src/layouts/geometric/index.js.map +1 -0
  89. package/dist/src/layouts/geometric/shell.d.ts +15 -0
  90. package/dist/src/layouts/geometric/shell.js +67 -0
  91. package/dist/src/layouts/geometric/shell.js.map +1 -0
  92. package/dist/src/layouts/geometric/spiral.d.ts +16 -0
  93. package/dist/src/layouts/geometric/spiral.js +73 -0
  94. package/dist/src/layouts/geometric/spiral.js.map +1 -0
  95. package/dist/src/layouts/hierarchical/bfs.d.ts +12 -0
  96. package/dist/src/layouts/hierarchical/bfs.js +62 -0
  97. package/dist/src/layouts/hierarchical/bfs.js.map +1 -0
  98. package/dist/src/layouts/hierarchical/bipartite.d.ts +16 -0
  99. package/dist/src/layouts/hierarchical/bipartite.js +72 -0
  100. package/dist/src/layouts/hierarchical/bipartite.js.map +1 -0
  101. package/dist/src/layouts/hierarchical/index.d.ts +6 -0
  102. package/dist/src/layouts/hierarchical/index.js +7 -0
  103. package/dist/src/layouts/hierarchical/index.js.map +1 -0
  104. package/dist/src/layouts/hierarchical/multipartite.d.ts +12 -0
  105. package/dist/src/layouts/hierarchical/multipartite.js +73 -0
  106. package/dist/src/layouts/hierarchical/multipartite.js.map +1 -0
  107. package/dist/src/layouts/index.d.ts +8 -0
  108. package/dist/src/layouts/index.js +9 -0
  109. package/dist/src/layouts/index.js.map +1 -0
  110. package/dist/src/layouts/specialized/index.d.ts +5 -0
  111. package/dist/src/layouts/specialized/index.js +6 -0
  112. package/dist/src/layouts/specialized/index.js.map +1 -0
  113. package/dist/src/layouts/specialized/planar.d.ts +15 -0
  114. package/dist/src/layouts/specialized/planar.js +48 -0
  115. package/dist/src/layouts/specialized/planar.js.map +1 -0
  116. package/dist/src/layouts/specialized/spectral.d.ts +14 -0
  117. package/dist/src/layouts/specialized/spectral.js +106 -0
  118. package/dist/src/layouts/specialized/spectral.js.map +1 -0
  119. package/dist/src/types/embedding.d.ts +9 -0
  120. package/dist/src/types/embedding.js +5 -0
  121. package/dist/src/types/embedding.js.map +1 -0
  122. package/dist/src/types/graph.d.ts +10 -0
  123. package/dist/src/types/graph.js +5 -0
  124. package/dist/src/types/graph.js.map +1 -0
  125. package/dist/src/types/index.d.ts +6 -0
  126. package/dist/src/types/index.js +7 -0
  127. package/dist/src/types/index.js.map +1 -0
  128. package/dist/src/types/layout.d.ts +6 -0
  129. package/dist/src/types/layout.js +5 -0
  130. package/dist/src/types/layout.js.map +1 -0
  131. package/dist/src/utils/graph.d.ts +34 -0
  132. package/dist/src/utils/graph.js +69 -0
  133. package/dist/src/utils/graph.js.map +1 -0
  134. package/dist/src/utils/index.d.ts +8 -0
  135. package/dist/src/utils/index.js +9 -0
  136. package/dist/src/utils/index.js.map +1 -0
  137. package/dist/src/utils/numpy.d.ts +17 -0
  138. package/dist/src/utils/numpy.js +101 -0
  139. package/dist/src/utils/numpy.js.map +1 -0
  140. package/dist/src/utils/params.d.ts +17 -0
  141. package/dist/src/utils/params.js +22 -0
  142. package/dist/src/utils/params.js.map +1 -0
  143. package/dist/src/utils/random.d.ts +14 -0
  144. package/dist/src/utils/random.js +42 -0
  145. package/dist/src/utils/random.js.map +1 -0
  146. package/dist/src/utils/rescale.d.ts +21 -0
  147. package/dist/src/utils/rescale.js +194 -0
  148. package/dist/src/utils/rescale.js.map +1 -0
  149. package/dist/vitest.config.d.ts +2 -0
  150. package/dist/vitest.config.js +30 -0
  151. package/dist/vitest.config.js.map +1 -0
  152. package/package.json +3 -3
  153. package/src/algorithms/planarity/check.ts +4 -3
  154. package/src/algorithms/planarity/embedding.ts +11 -6
  155. package/src/algorithms/planarity/lr-test.ts +4 -3
  156. package/src/layouts/specialized/planar.ts +4 -2
@@ -0,0 +1,340 @@
1
+ import { getNodesFromGraph } from '../../utils/graph';
2
+ import { _processParams } from '../../utils/params';
3
+ import { rescaleLayout } from '../../utils/rescale';
4
+ import { RandomNumberGenerator } from '../../utils/random';
5
+ /**
6
+ * Position nodes using the ForceAtlas2 force-directed algorithm.
7
+ *
8
+ * @param G - Graph
9
+ * @param pos - Initial positions for nodes
10
+ * @param maxIter - Maximum number of iterations
11
+ * @param jitterTolerance - Controls tolerance for node speed adjustments
12
+ * @param scalingRatio - Scaling of attraction and repulsion forces
13
+ * @param gravity - Attraction to center to prevent disconnected components from drifting
14
+ * @param distributedAction - Distributes attraction force among nodes
15
+ * @param strongGravity - Uses a stronger gravity model
16
+ * @param nodeMass - Dictionary mapping nodes to their masses
17
+ * @param nodeSize - Dictionary mapping nodes to their sizes
18
+ * @param weight - Edge attribute for weight
19
+ * @param dissuadeHubs - Whether to prevent hub nodes from clustering
20
+ * @param linlog - Whether to use logarithmic attraction
21
+ * @param seed - Random seed for initial positions
22
+ * @param dim - Dimension of layout
23
+ * @returns Positions dictionary keyed by node
24
+ */
25
+ export function forceatlas2Layout(G, pos = null, maxIter = 100, jitterTolerance = 1.0, scalingRatio = 2.0, gravity = 1.0, distributedAction = false, strongGravity = false, nodeMass = null, nodeSize = null, weight = null, dissuadeHubs = false, linlog = false, seed = null, dim = 2) {
26
+ const processed = _processParams(G, null, dim);
27
+ const graph = processed.G;
28
+ const nodes = getNodesFromGraph(graph);
29
+ if (nodes.length === 0) {
30
+ return {};
31
+ }
32
+ // Initialize random number generator
33
+ const rng = new RandomNumberGenerator(seed ?? undefined);
34
+ // Initialize positions if not provided
35
+ let posArray;
36
+ if (pos === null) {
37
+ pos = {};
38
+ posArray = new Array(nodes.length);
39
+ for (let i = 0; i < nodes.length; i++) {
40
+ posArray[i] = Array(dim).fill(0).map(() => rng.rand() * 2 - 1);
41
+ pos[nodes[i]] = posArray[i];
42
+ }
43
+ }
44
+ else if (Object.keys(pos).length === nodes.length) {
45
+ // Use provided positions
46
+ posArray = new Array(nodes.length);
47
+ for (let i = 0; i < nodes.length; i++) {
48
+ const nodePos = pos[nodes[i]];
49
+ posArray[i] = new Array(dim);
50
+ for (let d = 0; d < dim; d++) {
51
+ posArray[i][d] = d < nodePos.length ? nodePos[d] : (rng.rand() * 2 - 1);
52
+ }
53
+ }
54
+ }
55
+ else {
56
+ // Some nodes don't have positions, initialize within the range of existing positions
57
+ let minPos = Array(dim).fill(Number.POSITIVE_INFINITY);
58
+ let maxPos = Array(dim).fill(Number.NEGATIVE_INFINITY);
59
+ // Find min and max of existing positions
60
+ for (const node in pos) {
61
+ const nodePos = pos[node];
62
+ for (let d = 0; d < dim; d++) {
63
+ if (d < nodePos.length) {
64
+ minPos[d] = Math.min(minPos[d], nodePos[d]);
65
+ maxPos[d] = Math.max(maxPos[d], nodePos[d]);
66
+ }
67
+ }
68
+ }
69
+ // If min/max are still infinity for some dimensions, use default range
70
+ for (let d = 0; d < dim; d++) {
71
+ if (!isFinite(minPos[d]) || !isFinite(maxPos[d])) {
72
+ minPos[d] = -1;
73
+ maxPos[d] = 1;
74
+ }
75
+ }
76
+ posArray = new Array(nodes.length);
77
+ for (let i = 0; i < nodes.length; i++) {
78
+ const node = nodes[i];
79
+ if (pos[node]) {
80
+ const nodePos = pos[node];
81
+ posArray[i] = new Array(dim);
82
+ for (let d = 0; d < dim; d++) {
83
+ posArray[i][d] = d < nodePos.length ? nodePos[d] : (rng.rand() * 2 - 1);
84
+ }
85
+ }
86
+ else {
87
+ posArray[i] = Array(dim).fill(0).map((_, d) => minPos[d] + rng.rand() * (maxPos[d] - minPos[d]));
88
+ pos[node] = posArray[i];
89
+ }
90
+ }
91
+ }
92
+ // Initialize mass and size arrays
93
+ const mass = new Array(nodes.length).fill(0);
94
+ const size = new Array(nodes.length).fill(0);
95
+ // Flag to track whether to adjust for node sizes
96
+ const adjustSizes = nodeSize !== null;
97
+ // Set node masses and sizes
98
+ for (let i = 0; i < nodes.length; i++) {
99
+ const node = nodes[i];
100
+ mass[i] = nodeMass && nodeMass[node] ?
101
+ nodeMass[node] :
102
+ (Array.isArray(graph) ? 1 : getNodeDegree(graph, node) + 1);
103
+ size[i] = nodeSize && nodeSize[node] ? nodeSize[node] : 1;
104
+ }
105
+ // Create adjacency matrix
106
+ const n = nodes.length;
107
+ const A = Array(n).fill(0).map(() => Array(n).fill(0));
108
+ // Populate adjacency matrix with edge weights
109
+ const edges = Array.isArray(graph) ? [] : graph.edges();
110
+ const nodeIndices = {};
111
+ nodes.forEach((node, i) => { nodeIndices[node] = i; });
112
+ for (const [source, target] of edges) {
113
+ const i = nodeIndices[source];
114
+ const j = nodeIndices[target];
115
+ // Use edge weight if provided, otherwise default to 1
116
+ let edgeWeight = 1;
117
+ if (weight && !Array.isArray(graph) && graph.getEdgeData) {
118
+ edgeWeight = graph.getEdgeData(source, target, weight) || 1;
119
+ }
120
+ A[i][j] = edgeWeight;
121
+ A[j][i] = edgeWeight; // For undirected graphs
122
+ }
123
+ // Initialize force arrays
124
+ const gravities = Array(n).fill(0).map(() => Array(dim).fill(0));
125
+ const attraction = Array(n).fill(0).map(() => Array(dim).fill(0));
126
+ const repulsion = Array(n).fill(0).map(() => Array(dim).fill(0));
127
+ // Simulation parameters
128
+ let speed = 1;
129
+ let speedEfficiency = 1;
130
+ let swing = 1;
131
+ let traction = 1;
132
+ // Helper function to estimate factor for force scaling
133
+ function estimateFactor(n, swing, traction, speed, speedEfficiency, jitterTolerance) {
134
+ // Optimal jitter parameters
135
+ const optJitter = 0.05 * Math.sqrt(n);
136
+ const minJitter = Math.sqrt(optJitter);
137
+ const maxJitter = 10;
138
+ const minSpeedEfficiency = 0.05;
139
+ // Estimate jitter based on current state
140
+ const other = Math.min(maxJitter, optJitter * traction / (n * n));
141
+ let jitter = jitterTolerance * Math.max(minJitter, other);
142
+ // Adjust speed efficiency based on swing/traction ratio
143
+ if (swing / traction > 2.0) {
144
+ if (speedEfficiency > minSpeedEfficiency) {
145
+ speedEfficiency *= 0.5;
146
+ }
147
+ jitter = Math.max(jitter, jitterTolerance);
148
+ }
149
+ // Calculate target speed
150
+ let targetSpeed = swing === 0 ?
151
+ Number.POSITIVE_INFINITY :
152
+ jitter * speedEfficiency * traction / swing;
153
+ // Further adjust speed efficiency
154
+ if (swing > jitter * traction) {
155
+ if (speedEfficiency > minSpeedEfficiency) {
156
+ speedEfficiency *= 0.7;
157
+ }
158
+ }
159
+ else if (speed < 1000) {
160
+ speedEfficiency *= 1.3;
161
+ }
162
+ // Limit the speed increase
163
+ const maxRise = 0.5;
164
+ speed = speed + Math.min(targetSpeed - speed, maxRise * speed);
165
+ return [speed, speedEfficiency];
166
+ }
167
+ // Main simulation loop
168
+ for (let iter = 0; iter < maxIter; iter++) {
169
+ // Reset forces for this iteration
170
+ for (let i = 0; i < n; i++) {
171
+ for (let d = 0; d < dim; d++) {
172
+ attraction[i][d] = 0;
173
+ repulsion[i][d] = 0;
174
+ gravities[i][d] = 0;
175
+ }
176
+ }
177
+ // Compute pairwise differences and distances
178
+ const diff = Array(n).fill(0).map(() => Array(n).fill(0).map(() => Array(dim).fill(0)));
179
+ const distance = Array(n).fill(0).map(() => Array(n).fill(0));
180
+ for (let i = 0; i < n; i++) {
181
+ for (let j = 0; j < n; j++) {
182
+ if (i === j)
183
+ continue;
184
+ for (let d = 0; d < dim; d++) {
185
+ diff[i][j][d] = posArray[i][d] - posArray[j][d];
186
+ }
187
+ distance[i][j] = Math.sqrt(diff[i][j].reduce((sum, d) => sum + d * d, 0));
188
+ // Prevent division by zero
189
+ if (distance[i][j] < 0.01)
190
+ distance[i][j] = 0.01;
191
+ }
192
+ }
193
+ // Calculate attraction forces
194
+ if (linlog) {
195
+ // Logarithmic attraction model
196
+ for (let i = 0; i < n; i++) {
197
+ for (let j = 0; j < n; j++) {
198
+ if (i === j || A[i][j] === 0)
199
+ continue;
200
+ const dist = distance[i][j];
201
+ const factor = -Math.log(1 + dist) / dist * A[i][j];
202
+ for (let d = 0; d < dim; d++) {
203
+ const force = factor * diff[i][j][d];
204
+ attraction[i][d] += force;
205
+ }
206
+ }
207
+ }
208
+ }
209
+ else {
210
+ // Linear attraction model
211
+ for (let i = 0; i < n; i++) {
212
+ for (let j = 0; j < n; j++) {
213
+ if (i === j || A[i][j] === 0)
214
+ continue;
215
+ for (let d = 0; d < dim; d++) {
216
+ const force = -diff[i][j][d] * A[i][j];
217
+ attraction[i][d] += force;
218
+ }
219
+ }
220
+ }
221
+ }
222
+ // Apply distributed attraction if enabled
223
+ if (distributedAction) {
224
+ for (let i = 0; i < n; i++) {
225
+ for (let d = 0; d < dim; d++) {
226
+ attraction[i][d] /= mass[i];
227
+ }
228
+ }
229
+ }
230
+ // Calculate repulsion forces
231
+ for (let i = 0; i < n; i++) {
232
+ for (let j = 0; j < n; j++) {
233
+ if (i === j)
234
+ continue;
235
+ let dist = distance[i][j];
236
+ // Adjust distance for node sizes if needed
237
+ if (adjustSizes) {
238
+ dist -= size[i] - size[j];
239
+ dist = Math.max(dist, 0.01); // Prevent negative or zero distances
240
+ }
241
+ const distSquared = dist * dist;
242
+ const massProduct = mass[i] * mass[j];
243
+ const factor = (massProduct / distSquared) * scalingRatio;
244
+ for (let d = 0; d < dim; d++) {
245
+ const direction = diff[i][j][d] / dist;
246
+ repulsion[i][d] += direction * factor;
247
+ }
248
+ }
249
+ }
250
+ // Calculate gravity forces
251
+ // First find the center of mass
252
+ const centerOfMass = Array(dim).fill(0);
253
+ for (let i = 0; i < n; i++) {
254
+ for (let d = 0; d < dim; d++) {
255
+ centerOfMass[d] += posArray[i][d] / n;
256
+ }
257
+ }
258
+ for (let i = 0; i < n; i++) {
259
+ const posCentered = Array(dim);
260
+ for (let d = 0; d < dim; d++) {
261
+ posCentered[d] = posArray[i][d] - centerOfMass[d];
262
+ }
263
+ if (strongGravity) {
264
+ // Strong gravity model
265
+ for (let d = 0; d < dim; d++) {
266
+ gravities[i][d] = -gravity * mass[i] * posCentered[d];
267
+ }
268
+ }
269
+ else {
270
+ // Regular gravity model
271
+ const dist = Math.sqrt(posCentered.reduce((sum, val) => sum + val * val, 0));
272
+ if (dist > 0.01) {
273
+ for (let d = 0; d < dim; d++) {
274
+ const direction = posCentered[d] / dist;
275
+ gravities[i][d] = -gravity * mass[i] * direction;
276
+ }
277
+ }
278
+ }
279
+ }
280
+ // Calculate total forces and update positions
281
+ const update = Array(n).fill(0).map(() => Array(dim).fill(0));
282
+ let totalSwing = 0;
283
+ let totalTraction = 0;
284
+ for (let i = 0; i < n; i++) {
285
+ for (let d = 0; d < dim; d++) {
286
+ update[i][d] = attraction[i][d] + repulsion[i][d] + gravities[i][d];
287
+ }
288
+ // Calculate swing and traction for this node
289
+ const oldPos = [...posArray[i]];
290
+ const newPos = oldPos.map((p, d) => p + update[i][d]);
291
+ const swingVector = oldPos.map((p, d) => p - newPos[d]);
292
+ const tractionVector = oldPos.map((p, d) => p + newPos[d]);
293
+ const swingMagnitude = Math.sqrt(swingVector.reduce((sum, val) => sum + val * val, 0));
294
+ const tractionMagnitude = Math.sqrt(tractionVector.reduce((sum, val) => sum + val * val, 0));
295
+ totalSwing += mass[i] * swingMagnitude;
296
+ totalTraction += 0.5 * mass[i] * tractionMagnitude;
297
+ }
298
+ // Update speed and efficiency
299
+ [speed, speedEfficiency] = estimateFactor(n, totalSwing, totalTraction, speed, speedEfficiency, jitterTolerance);
300
+ // Apply forces to update positions
301
+ let totalMovement = 0;
302
+ for (let i = 0; i < n; i++) {
303
+ let factor;
304
+ if (adjustSizes) {
305
+ // Calculate displacement magnitude
306
+ const df = Math.sqrt(update[i].reduce((sum, val) => sum + val * val, 0));
307
+ const swinging = mass[i] * df;
308
+ // Determine scaling factor with size adjustments
309
+ factor = 0.1 * speed / (1 + Math.sqrt(speed * swinging));
310
+ factor = Math.min(factor * df, 10) / df;
311
+ }
312
+ else {
313
+ // Standard scaling factor
314
+ const swinging = mass[i] * Math.sqrt(update[i].reduce((sum, val) => sum + val * val, 0));
315
+ factor = speed / (1 + Math.sqrt(speed * swinging));
316
+ }
317
+ // Apply factor to update position
318
+ for (let d = 0; d < dim; d++) {
319
+ const movement = update[i][d] * factor;
320
+ posArray[i][d] += movement;
321
+ totalMovement += Math.abs(movement);
322
+ }
323
+ }
324
+ // Check for convergence
325
+ if (totalMovement < 1e-10) {
326
+ break;
327
+ }
328
+ }
329
+ // Create position dictionary
330
+ const positions = {};
331
+ for (let i = 0; i < n; i++) {
332
+ positions[nodes[i]] = posArray[i];
333
+ }
334
+ return rescaleLayout(positions);
335
+ }
336
+ // Helper function to get node degree
337
+ function getNodeDegree(graph, node) {
338
+ return graph.edges().filter((edge) => edge[0] === node || edge[1] === node).length;
339
+ }
340
+ //# sourceMappingURL=forceatlas2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forceatlas2.js","sourceRoot":"","sources":["../../../../src/layouts/force-directed/forceatlas2.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,CAAQ,EACR,MAA0B,IAAI,EAC9B,UAAkB,GAAG,EACrB,kBAA0B,GAAG,EAC7B,eAAuB,GAAG,EAC1B,UAAkB,GAAG,EACrB,oBAA6B,KAAK,EAClC,gBAAyB,KAAK,EAC9B,WAAwC,IAAI,EAC5C,WAAwC,IAAI,EAC5C,SAAwB,IAAI,EAC5B,eAAwB,KAAK,EAC7B,SAAkB,KAAK,EACvB,OAAsB,IAAI,EAC1B,MAAc,CAAC;IAEf,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC;IAE1B,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,qCAAqC;IACrC,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC;IAEzD,uCAAuC;IACvC,IAAI,QAAoB,CAAC;IACzB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,GAAG,GAAG,EAAE,CAAC;QACT,QAAQ,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,EAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACzE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;QACpD,yBAAyB;QACzB,QAAQ,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,qFAAqF;QACrF,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACvD,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAEvD,yCAAyC;QACzC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;oBACvB,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5C,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjD,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACf,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;QAED,QAAQ,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5C,MAAM,CAAC,CAAC,CAAC,GAAI,GAAG,CAAC,IAAI,EAAa,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAC7D,CAAC;gBACF,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE7C,iDAAiD;IACjD,MAAM,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC;IAEtC,4BAA4B;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAChB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE9D,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,0BAA0B;IAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvD,8CAA8C;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAClE,MAAM,WAAW,GAAyB,EAAE,CAAC;IAC7C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvD,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAE9B,sDAAsD;QACtD,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACzD,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9D,CAAC;QAED,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;QACrB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,wBAAwB;IAChD,CAAC;IAED,0BAA0B;IAC1B,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjE,wBAAwB;IACxB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,uDAAuD;IACvD,SAAS,cAAc,CACrB,CAAS,EACT,KAAa,EACb,QAAgB,EAChB,KAAa,EACb,eAAuB,EACvB,eAAuB;QAEvB,4BAA4B;QAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,EAAE,CAAC;QACrB,MAAM,kBAAkB,GAAG,IAAI,CAAC;QAEhC,yCAAyC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,MAAM,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAE1D,wDAAwD;QACxD,IAAI,KAAK,GAAG,QAAQ,GAAG,GAAG,EAAE,CAAC;YAC3B,IAAI,eAAe,GAAG,kBAAkB,EAAE,CAAC;gBACzC,eAAe,IAAI,GAAG,CAAC;YACzB,CAAC;YACD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAC7C,CAAC;QAED,yBAAyB;QACzB,IAAI,WAAW,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,iBAAiB,CAAC,CAAC;YAC1B,MAAM,GAAG,eAAe,GAAG,QAAQ,GAAG,KAAK,CAAC;QAE9C,kCAAkC;QAClC,IAAI,KAAK,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC;YAC9B,IAAI,eAAe,GAAG,kBAAkB,EAAE,CAAC;gBACzC,eAAe,IAAI,GAAG,CAAC;YACzB,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;YACxB,eAAe,IAAI,GAAG,CAAC;QACzB,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,GAAG,CAAC;QACpB,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC;QAE/D,OAAO,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAClC,CAAC;IAED,uBAAuB;IACvB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1C,kCAAkC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACrB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACpB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CACrC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAC/C,CAAC;QAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClD,CAAC;gBAED,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC1E,2BAA2B;gBAC3B,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;oBAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACnD,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,IAAI,MAAM,EAAE,CAAC;YACX,+BAA+B;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;wBAAE,SAAS;oBAEvC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC5B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC7B,MAAM,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACrC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;oBAC5B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;wBAAE,SAAS;oBAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC7B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACvC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;oBAC5B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,iBAAiB,EAAE,CAAC;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBAEtB,IAAI,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE1B,2CAA2C;gBAC3C,IAAI,WAAW,EAAE,CAAC;oBAChB,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;oBAC1B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,qCAAqC;gBACpE,CAAC;gBAED,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;gBAChC,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,YAAY,CAAC;gBAE1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;oBACvC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,GAAG,MAAM,CAAC;gBACxC,CAAC;YACH,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,gCAAgC;QAChC,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,YAAY,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YACpD,CAAC;YAED,IAAI,aAAa,EAAE,CAAC;gBAClB,uBAAuB;gBACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,wBAAwB;gBACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBAE7E,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;oBAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;wBAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;wBACxC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;oBACnD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;YAED,6CAA6C;YAC7C,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEtD,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAE3D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAE7F,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;YACvC,aAAa,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC;QACrD,CAAC;QAED,8BAA8B;QAC9B,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,cAAc,CACvC,CAAC,EACD,UAAU,EACV,aAAa,EACb,KAAK,EACL,eAAe,EACf,eAAe,CAChB,CAAC;QAEF,mCAAmC;QACnC,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,IAAI,MAAM,CAAC;YAEX,IAAI,WAAW,EAAE,CAAC;gBAChB,mCAAmC;gBACnC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;gBAE9B,iDAAiD;gBACjD,MAAM,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACzD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,0BAA0B;gBAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzF,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;YACrD,CAAC;YAED,kCAAkC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;gBACvC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;gBAC3B,aAAa,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,IAAI,aAAa,GAAG,KAAK,EAAE,CAAC;YAC1B,MAAM;QACR,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,MAAM,SAAS,GAAgB,EAAE,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,aAAa,CAAC,SAAS,CAAgB,CAAC;AACjD,CAAC;AAED,qCAAqC;AACrC,SAAS,aAAa,CAAC,KAAY,EAAE,IAAU;IAC7C,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,IAAU,EAAE,EAAE,CACzC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CACrC,CAAC,MAAM,CAAC;AACX,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Fruchterman-Reingold force-directed layout algorithm
3
+ */
4
+ import { Graph, Node, PositionMap } from '../../types';
5
+ /**
6
+ * Position nodes using Fruchterman-Reingold force-directed algorithm.
7
+ *
8
+ * @param {Object} G - Graph or list of nodes
9
+ * @param {number} k - Optimal distance between nodes
10
+ * @param {Object} pos - Initial positions for nodes
11
+ * @param {Array} fixed - Nodes to keep fixed at initial position
12
+ * @param {number} iterations - Maximum number of iterations
13
+ * @param {number} scale - Scale factor for positions
14
+ * @param {Array|null} center - Coordinate pair around which to center the layout
15
+ * @param {number} dim - Dimension of layout
16
+ * @param {number} seed - Random seed for initial positions
17
+ * @returns {Object} Positions dictionary keyed by node
18
+ */
19
+ export declare function fruchtermanReingoldLayout(G: Graph, k?: number | null, pos?: PositionMap | null, fixed?: Node[] | null, iterations?: number, scale?: number, center?: number[] | null, dim?: number, seed?: number | null): PositionMap;
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Fruchterman-Reingold force-directed layout algorithm
3
+ */
4
+ import { _processParams } from '../../utils/params';
5
+ import { getNodesFromGraph, getEdgesFromGraph } from '../../utils/graph';
6
+ import { RandomNumberGenerator } from '../../utils/random';
7
+ import { rescaleLayout } from '../../utils/rescale';
8
+ /**
9
+ * Position nodes using Fruchterman-Reingold force-directed algorithm.
10
+ *
11
+ * @param {Object} G - Graph or list of nodes
12
+ * @param {number} k - Optimal distance between nodes
13
+ * @param {Object} pos - Initial positions for nodes
14
+ * @param {Array} fixed - Nodes to keep fixed at initial position
15
+ * @param {number} iterations - Maximum number of iterations
16
+ * @param {number} scale - Scale factor for positions
17
+ * @param {Array|null} center - Coordinate pair around which to center the layout
18
+ * @param {number} dim - Dimension of layout
19
+ * @param {number} seed - Random seed for initial positions
20
+ * @returns {Object} Positions dictionary keyed by node
21
+ */
22
+ export function fruchtermanReingoldLayout(G, k = null, pos = null, fixed = null, iterations = 50, scale = 1, center = null, dim = 2, seed = null) {
23
+ const processed = _processParams(G, center, dim);
24
+ let graph = processed.G;
25
+ center = processed.center;
26
+ const nodes = getNodesFromGraph(graph);
27
+ const edges = getEdgesFromGraph(graph);
28
+ if (nodes.length === 0) {
29
+ return {};
30
+ }
31
+ if (nodes.length === 1) {
32
+ const singlePos = {};
33
+ singlePos[nodes[0]] = center;
34
+ return singlePos;
35
+ }
36
+ // Set up initial positions
37
+ let positions = {};
38
+ if (pos) {
39
+ // Use provided positions
40
+ for (const node of nodes) {
41
+ if (pos[node]) {
42
+ positions[node] = [...pos[node]];
43
+ }
44
+ else {
45
+ const rng = new RandomNumberGenerator(seed ?? undefined);
46
+ positions[node] = rng.rand(dim);
47
+ }
48
+ }
49
+ }
50
+ else {
51
+ // Random initial positions
52
+ const rng = new RandomNumberGenerator(seed ?? undefined);
53
+ for (const node of nodes) {
54
+ positions[node] = rng.rand(dim);
55
+ }
56
+ }
57
+ // Set up fixed nodes
58
+ const fixedNodes = new Set(fixed || []);
59
+ // Optimal distance between nodes
60
+ if (!k) {
61
+ k = 1.0 / Math.sqrt(nodes.length);
62
+ }
63
+ // Initialize temperature
64
+ let t = 0.1;
65
+ // Calculate temperature reduction
66
+ const dt = t / (iterations + 1);
67
+ // Simple cooling schedule
68
+ for (let i = 0; i < iterations; i++) {
69
+ // Calculate repulsive forces
70
+ const displacement = {};
71
+ for (const node of nodes) {
72
+ displacement[node] = Array(dim).fill(0);
73
+ }
74
+ // Repulsive forces between nodes
75
+ for (let v1i = 0; v1i < nodes.length; v1i++) {
76
+ const v1 = nodes[v1i];
77
+ for (let v2i = v1i + 1; v2i < nodes.length; v2i++) {
78
+ const v2 = nodes[v2i];
79
+ // Difference vector
80
+ const delta = positions[v1].map((p, i) => p - positions[v2][i]);
81
+ // Distance
82
+ const distance = Math.sqrt(delta.reduce((sum, d) => sum + d * d, 0)) || 0.1;
83
+ // Force
84
+ const force = (k * k) / distance;
85
+ // Add force to displacement
86
+ for (let j = 0; j < dim; j++) {
87
+ const direction = delta[j] / distance;
88
+ displacement[v1][j] += direction * force;
89
+ displacement[v2][j] -= direction * force;
90
+ }
91
+ }
92
+ }
93
+ // Attractive forces between connected nodes
94
+ for (const [source, target] of edges) {
95
+ // Difference vector
96
+ const delta = positions[source].map((p, i) => p - positions[target][i]);
97
+ // Distance
98
+ const distance = Math.sqrt(delta.reduce((sum, d) => sum + d * d, 0)) || 0.1;
99
+ // Force
100
+ const force = (distance * distance) / k;
101
+ // Add force to displacement
102
+ for (let j = 0; j < dim; j++) {
103
+ const direction = delta[j] / distance;
104
+ displacement[source][j] -= direction * force;
105
+ displacement[target][j] += direction * force;
106
+ }
107
+ }
108
+ // Update positions
109
+ for (const node of nodes) {
110
+ if (fixedNodes.has(node))
111
+ continue;
112
+ // Calculate displacement magnitude
113
+ const magnitude = Math.sqrt(displacement[node].reduce((sum, d) => sum + d * d, 0));
114
+ // Limit maximum displacement by temperature
115
+ const limitedMagnitude = Math.min(magnitude, t);
116
+ // Update position
117
+ for (let j = 0; j < dim; j++) {
118
+ const direction = magnitude === 0 ? 0 : displacement[node][j] / magnitude;
119
+ positions[node][j] += direction * limitedMagnitude;
120
+ }
121
+ }
122
+ // Cool temperature
123
+ t -= dt;
124
+ }
125
+ // Rescale positions
126
+ if (!fixed) {
127
+ positions = rescaleLayout(positions, scale, center);
128
+ }
129
+ return positions;
130
+ }
131
+ //# sourceMappingURL=fruchterman-reingold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fruchterman-reingold.js","sourceRoot":"","sources":["../../../../src/layouts/force-directed/fruchterman-reingold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Force-directed layout algorithms
3
+ */
4
+ export { springLayout } from './spring';
5
+ export { fruchtermanReingoldLayout } from './fruchterman-reingold';
6
+ export { kamadaKawaiLayout } from './kamada-kawai';
7
+ export { forceatlas2Layout } from './forceatlas2';
8
+ export { arfLayout } from './arf';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Force-directed layout algorithms
3
+ */
4
+ export { springLayout } from './spring';
5
+ export { fruchtermanReingoldLayout } from './fruchterman-reingold';
6
+ export { kamadaKawaiLayout } from './kamada-kawai';
7
+ export { forceatlas2Layout } from './forceatlas2';
8
+ export { arfLayout } from './arf';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/layouts/force-directed/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Graph, PositionMap } from '../../types';
2
+ import type { DistanceMap } from '../../algorithms/optimization';
3
+ /**
4
+ * Position nodes using Kamada-Kawai path-length cost-function.
5
+ *
6
+ * @param G - NetworkX graph or list of nodes
7
+ * @param dist - A two-level dictionary of optimal distances between nodes
8
+ * @param pos - Initial positions for nodes
9
+ * @param weight - The edge attribute used for edge weights
10
+ * @param scale - Scale factor for positions
11
+ * @param center - Coordinate pair around which to center the layout
12
+ * @param dim - Dimension of layout
13
+ * @returns Positions dictionary keyed by node
14
+ */
15
+ export declare function kamadaKawaiLayout(G: Graph, dist?: DistanceMap | null, pos?: PositionMap | null, weight?: string, scale?: number, center?: number[] | null, dim?: number): PositionMap;
@@ -0,0 +1,87 @@
1
+ import { getNodesFromGraph } from '../../utils/graph';
2
+ import { _processParams } from '../../utils/params';
3
+ import { rescaleLayout } from '../../utils/rescale';
4
+ import { circularLayout } from '../geometric/circular';
5
+ import { _computeShortestPathDistances, _kamadaKawaiSolve } from '../../algorithms/optimization';
6
+ /**
7
+ * Position nodes using Kamada-Kawai path-length cost-function.
8
+ *
9
+ * @param G - NetworkX graph or list of nodes
10
+ * @param dist - A two-level dictionary of optimal distances between nodes
11
+ * @param pos - Initial positions for nodes
12
+ * @param weight - The edge attribute used for edge weights
13
+ * @param scale - Scale factor for positions
14
+ * @param center - Coordinate pair around which to center the layout
15
+ * @param dim - Dimension of layout
16
+ * @returns Positions dictionary keyed by node
17
+ */
18
+ export function kamadaKawaiLayout(G, dist = null, pos = null, weight = 'weight', scale = 1, center = null, dim = 2) {
19
+ const processed = _processParams(G, center, dim);
20
+ const graph = processed.G;
21
+ center = processed.center;
22
+ const nodes = getNodesFromGraph(graph);
23
+ if (nodes.length === 0) {
24
+ return {};
25
+ }
26
+ if (nodes.length === 1) {
27
+ return { [nodes[0]]: center };
28
+ }
29
+ // Initialize distance matrix
30
+ if (!dist) {
31
+ // Kamada-Kawai requires a proper Graph, not just a list of nodes
32
+ if (Array.isArray(graph)) {
33
+ throw new Error('Kamada-Kawai layout requires a Graph with edges, not just a list of nodes');
34
+ }
35
+ dist = _computeShortestPathDistances(graph, weight);
36
+ }
37
+ // Convert distances to a matrix
38
+ const nodesArray = Array.from(nodes);
39
+ const nNodes = nodesArray.length;
40
+ const distMatrix = Array(nNodes).fill(0).map(() => Array(nNodes).fill(1e6));
41
+ for (let i = 0; i < nNodes; i++) {
42
+ const nodeI = nodesArray[i];
43
+ distMatrix[i][i] = 0;
44
+ if (!dist[nodeI])
45
+ continue;
46
+ for (let j = 0; j < nNodes; j++) {
47
+ const nodeJ = nodesArray[j];
48
+ if (dist[nodeI][nodeJ] !== undefined) {
49
+ distMatrix[i][j] = dist[nodeI][nodeJ];
50
+ }
51
+ }
52
+ }
53
+ // Initialize positions if not provided
54
+ if (!pos) {
55
+ if (dim >= 2) {
56
+ // Use circular/spherical layout for 2D and 3D
57
+ pos = circularLayout(G, 1, center, dim);
58
+ }
59
+ else {
60
+ // For 1D, use a linear layout
61
+ const posArray = {};
62
+ nodesArray.forEach((node, i) => {
63
+ posArray[node] = [i / (nNodes - 1 || 1)];
64
+ });
65
+ pos = posArray;
66
+ }
67
+ }
68
+ // Convert positions to array for computation
69
+ const posArray = new Array(nNodes);
70
+ for (let i = 0; i < nNodes; i++) {
71
+ const node = nodesArray[i];
72
+ posArray[i] = pos[node] ? [...pos[node]] : Array(dim).fill(0);
73
+ // Ensure correct dimensionality
74
+ while (posArray[i].length < dim) {
75
+ posArray[i].push(0);
76
+ }
77
+ }
78
+ // Run the Kamada-Kawai algorithm
79
+ const newPositions = _kamadaKawaiSolve(distMatrix, posArray, dim);
80
+ // Convert positions array back to dictionary and rescale
81
+ const finalPos = {};
82
+ for (let i = 0; i < nNodes; i++) {
83
+ finalPos[nodesArray[i]] = newPositions[i];
84
+ }
85
+ return rescaleLayout(finalPos, scale, center);
86
+ }
87
+ //# sourceMappingURL=kamada-kawai.js.map