@graphty/layout 1.2.3 → 1.2.4

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 (201) hide show
  1. package/dist/src/algorithms/index.d.ts +5 -0
  2. package/dist/src/algorithms/index.js +6 -0
  3. package/dist/src/algorithms/index.js.map +1 -0
  4. package/dist/src/algorithms/optimization/index.d.ts +7 -0
  5. package/dist/src/algorithms/optimization/index.js +7 -0
  6. package/dist/src/algorithms/optimization/index.js.map +1 -0
  7. package/dist/src/algorithms/optimization/kamada-kawai-solver.d.ts +32 -0
  8. package/dist/src/algorithms/optimization/kamada-kawai-solver.js +176 -0
  9. package/dist/src/algorithms/optimization/kamada-kawai-solver.js.map +1 -0
  10. package/dist/src/algorithms/optimization/lbfgs.d.ts +13 -0
  11. package/dist/src/algorithms/optimization/lbfgs.js +56 -0
  12. package/dist/src/algorithms/optimization/lbfgs.js.map +1 -0
  13. package/dist/src/algorithms/optimization/line-search.d.ts +15 -0
  14. package/dist/src/algorithms/optimization/line-search.js +37 -0
  15. package/dist/src/algorithms/optimization/line-search.js.map +1 -0
  16. package/dist/src/algorithms/optimization/types.d.ts +5 -0
  17. package/dist/src/algorithms/optimization/types.js +5 -0
  18. package/dist/src/algorithms/optimization/types.js.map +1 -0
  19. package/dist/src/algorithms/planarity/check.d.ts +17 -0
  20. package/dist/src/algorithms/planarity/check.js +30 -0
  21. package/dist/src/algorithms/planarity/check.js.map +1 -0
  22. package/dist/src/algorithms/planarity/embedding.d.ts +29 -0
  23. package/dist/src/algorithms/planarity/embedding.js +179 -0
  24. package/dist/src/algorithms/planarity/embedding.js.map +1 -0
  25. package/dist/src/algorithms/planarity/index.d.ts +7 -0
  26. package/dist/src/algorithms/planarity/index.js +8 -0
  27. package/dist/src/algorithms/planarity/index.js.map +1 -0
  28. package/dist/src/algorithms/planarity/lr-test.d.ts +15 -0
  29. package/dist/src/algorithms/planarity/lr-test.js +54 -0
  30. package/dist/src/algorithms/planarity/lr-test.js.map +1 -0
  31. package/dist/src/algorithms/planarity/special-graphs.d.ts +28 -0
  32. package/dist/src/algorithms/planarity/special-graphs.js +108 -0
  33. package/dist/src/algorithms/planarity/special-graphs.js.map +1 -0
  34. package/dist/src/generators/basic.d.ts +28 -0
  35. package/dist/src/generators/basic.js +79 -0
  36. package/dist/src/generators/basic.js.map +1 -0
  37. package/dist/src/generators/bipartite.d.ts +16 -0
  38. package/dist/src/generators/bipartite.js +40 -0
  39. package/dist/src/generators/bipartite.js.map +1 -0
  40. package/dist/src/generators/grid.d.ts +11 -0
  41. package/dist/src/generators/grid.js +37 -0
  42. package/dist/src/generators/grid.js.map +1 -0
  43. package/dist/src/generators/index.d.ts +8 -0
  44. package/dist/src/generators/index.js +9 -0
  45. package/dist/src/generators/index.js.map +1 -0
  46. package/dist/src/generators/random.d.ts +12 -0
  47. package/dist/src/generators/random.js +34 -0
  48. package/dist/src/generators/random.js.map +1 -0
  49. package/dist/src/generators/scale-free.d.ts +12 -0
  50. package/dist/src/generators/scale-free.js +62 -0
  51. package/dist/src/generators/scale-free.js.map +1 -0
  52. package/dist/src/index.d.ts +10 -0
  53. package/dist/src/index.js +15 -0
  54. package/dist/src/index.js.map +1 -0
  55. package/dist/src/layouts/basic/index.d.ts +4 -0
  56. package/dist/src/layouts/basic/index.js +5 -0
  57. package/dist/src/layouts/basic/index.js.map +1 -0
  58. package/dist/src/layouts/basic/random.d.ts +14 -0
  59. package/dist/src/layouts/basic/random.js +27 -0
  60. package/dist/src/layouts/basic/random.js.map +1 -0
  61. package/dist/src/layouts/force-directed/arf.d.ts +13 -0
  62. package/dist/src/layouts/force-directed/arf.js +103 -0
  63. package/dist/src/layouts/force-directed/arf.js.map +1 -0
  64. package/dist/src/layouts/force-directed/forceatlas2.d.ts +22 -0
  65. package/dist/src/layouts/force-directed/forceatlas2.js +322 -0
  66. package/dist/src/layouts/force-directed/forceatlas2.js.map +1 -0
  67. package/dist/src/layouts/force-directed/fruchterman-reingold.d.ts +19 -0
  68. package/dist/src/layouts/force-directed/fruchterman-reingold.js +131 -0
  69. package/dist/src/layouts/force-directed/fruchterman-reingold.js.map +1 -0
  70. package/dist/src/layouts/force-directed/index.d.ts +8 -0
  71. package/dist/src/layouts/force-directed/index.js +9 -0
  72. package/dist/src/layouts/force-directed/index.js.map +1 -0
  73. package/dist/src/layouts/force-directed/kamada-kawai.d.ts +15 -0
  74. package/dist/src/layouts/force-directed/kamada-kawai.js +87 -0
  75. package/dist/src/layouts/force-directed/kamada-kawai.js.map +1 -0
  76. package/dist/src/layouts/force-directed/spring.d.ts +19 -0
  77. package/dist/src/layouts/force-directed/spring.js +23 -0
  78. package/dist/src/layouts/force-directed/spring.js.map +1 -0
  79. package/dist/src/layouts/geometric/circular.d.ts +14 -0
  80. package/dist/src/layouts/geometric/circular.js +67 -0
  81. package/dist/src/layouts/geometric/circular.js.map +1 -0
  82. package/dist/src/layouts/geometric/index.d.ts +6 -0
  83. package/dist/src/layouts/geometric/index.js +7 -0
  84. package/dist/src/layouts/geometric/index.js.map +1 -0
  85. package/dist/src/layouts/geometric/shell.d.ts +15 -0
  86. package/dist/src/layouts/geometric/shell.js +67 -0
  87. package/dist/src/layouts/geometric/shell.js.map +1 -0
  88. package/dist/src/layouts/geometric/spiral.d.ts +16 -0
  89. package/dist/src/layouts/geometric/spiral.js +73 -0
  90. package/dist/src/layouts/geometric/spiral.js.map +1 -0
  91. package/dist/src/layouts/hierarchical/bfs.d.ts +12 -0
  92. package/dist/src/layouts/hierarchical/bfs.js +62 -0
  93. package/dist/src/layouts/hierarchical/bfs.js.map +1 -0
  94. package/dist/src/layouts/hierarchical/bipartite.d.ts +16 -0
  95. package/dist/src/layouts/hierarchical/bipartite.js +72 -0
  96. package/dist/src/layouts/hierarchical/bipartite.js.map +1 -0
  97. package/dist/src/layouts/hierarchical/index.d.ts +6 -0
  98. package/dist/src/layouts/hierarchical/index.js +7 -0
  99. package/dist/src/layouts/hierarchical/index.js.map +1 -0
  100. package/dist/src/layouts/hierarchical/multipartite.d.ts +12 -0
  101. package/dist/src/layouts/hierarchical/multipartite.js +73 -0
  102. package/dist/src/layouts/hierarchical/multipartite.js.map +1 -0
  103. package/dist/src/layouts/index.d.ts +8 -0
  104. package/dist/src/layouts/index.js +9 -0
  105. package/dist/src/layouts/index.js.map +1 -0
  106. package/dist/src/layouts/specialized/index.d.ts +5 -0
  107. package/dist/src/layouts/specialized/index.js +6 -0
  108. package/dist/src/layouts/specialized/index.js.map +1 -0
  109. package/dist/src/layouts/specialized/planar.d.ts +14 -0
  110. package/dist/src/layouts/specialized/planar.js +47 -0
  111. package/dist/src/layouts/specialized/planar.js.map +1 -0
  112. package/dist/src/layouts/specialized/spectral.d.ts +14 -0
  113. package/dist/src/layouts/specialized/spectral.js +106 -0
  114. package/dist/src/layouts/specialized/spectral.js.map +1 -0
  115. package/dist/src/types/embedding.d.ts +9 -0
  116. package/dist/src/types/embedding.js +5 -0
  117. package/dist/src/types/embedding.js.map +1 -0
  118. package/dist/src/types/graph.d.ts +10 -0
  119. package/dist/src/types/graph.js +5 -0
  120. package/dist/src/types/graph.js.map +1 -0
  121. package/dist/src/types/index.d.ts +6 -0
  122. package/dist/src/types/index.js +7 -0
  123. package/dist/src/types/index.js.map +1 -0
  124. package/dist/src/types/layout.d.ts +6 -0
  125. package/dist/src/types/layout.js +5 -0
  126. package/dist/src/types/layout.js.map +1 -0
  127. package/dist/src/utils/graph.d.ts +34 -0
  128. package/dist/src/utils/graph.js +69 -0
  129. package/dist/src/utils/graph.js.map +1 -0
  130. package/dist/src/utils/index.d.ts +8 -0
  131. package/dist/src/utils/index.js +9 -0
  132. package/dist/src/utils/index.js.map +1 -0
  133. package/dist/src/utils/numpy.d.ts +17 -0
  134. package/dist/src/utils/numpy.js +101 -0
  135. package/dist/src/utils/numpy.js.map +1 -0
  136. package/dist/src/utils/params.d.ts +17 -0
  137. package/dist/src/utils/params.js +22 -0
  138. package/dist/src/utils/params.js.map +1 -0
  139. package/dist/src/utils/random.d.ts +14 -0
  140. package/dist/src/utils/random.js +42 -0
  141. package/dist/src/utils/random.js.map +1 -0
  142. package/dist/src/utils/rescale.d.ts +21 -0
  143. package/dist/src/utils/rescale.js +119 -0
  144. package/dist/src/utils/rescale.js.map +1 -0
  145. package/dist/vitest.config.js +1 -1
  146. package/dist/vitest.config.js.map +1 -1
  147. package/package.json +14 -1
  148. package/.env.example +0 -11
  149. package/.github/workflows/ci.yml +0 -101
  150. package/.releaserc.json +0 -22
  151. package/CHANGELOG.md +0 -52
  152. package/CLAUDE.md +0 -104
  153. package/CONTRIBUTING.md +0 -1
  154. package/DEPLOYMENT.md +0 -59
  155. package/build-examples-script.js +0 -26
  156. package/commitlint.config.js +0 -37
  157. package/examples/3d-force-directed.html +0 -611
  158. package/examples/3d-kamada-kawai.html +0 -379
  159. package/examples/3d-layout-comparison.html +0 -448
  160. package/examples/3d-spherical-layout.html +0 -319
  161. package/examples/arf-layout.html +0 -524
  162. package/examples/bfs-layout.html +0 -487
  163. package/examples/bipartite-layout.html +0 -382
  164. package/examples/circular-layout.html +0 -292
  165. package/examples/forceatlas2-layout.html +0 -588
  166. package/examples/index.html +0 -241
  167. package/examples/kamada-kawai-layout.html +0 -425
  168. package/examples/layout-helpers.js +0 -23
  169. package/examples/layout.js +0 -2304
  170. package/examples/multipartite-layout.html +0 -410
  171. package/examples/planar-layout.html +0 -388
  172. package/examples/random-layout.html +0 -328
  173. package/examples/shell-layout.html +0 -323
  174. package/examples/spectral-layout.html +0 -335
  175. package/examples/spiral-layout.html +0 -447
  176. package/examples/spring-layout.html +0 -313
  177. package/test/arf-layout.test.ts +0 -443
  178. package/test/bfs-layout.test.ts +0 -427
  179. package/test/bipartite-layout.test.ts +0 -344
  180. package/test/circular-layout.test.ts +0 -442
  181. package/test/forceatlas2-layout.test.ts +0 -405
  182. package/test/fruchterman-reingold-layout.test.ts +0 -477
  183. package/test/graph-generators.test.ts +0 -450
  184. package/test/kamada-kawai-layout.test.ts +0 -623
  185. package/test/multipartite-layout.test.ts +0 -404
  186. package/test/planar-layout.test.ts +0 -266
  187. package/test/random-layout.test.ts +0 -254
  188. package/test/rescale-layout.test.ts +0 -373
  189. package/test/shell-layout.test.ts +0 -347
  190. package/test/spectral-layout.test.ts +0 -378
  191. package/test/spiral-layout.test.ts +0 -338
  192. package/test/spring-layout.test.ts +0 -241
  193. package/test/test-utils.ts +0 -34
  194. package/test/utils-graph.test.ts +0 -155
  195. package/test/utils-index.test.ts +0 -77
  196. package/test/utils-numpy.test.ts +0 -272
  197. package/test/utils-params.test.ts +0 -99
  198. package/test/utils-random.test.ts +0 -229
  199. package/tsconfig.json +0 -16
  200. package/vite.config.js +0 -36
  201. package/vitest.config.ts +0 -30
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Spring layout algorithm (Fruchterman-Reingold variant)
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 springLayout(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,23 @@
1
+ /**
2
+ * Spring layout algorithm (Fruchterman-Reingold variant)
3
+ */
4
+ import { fruchtermanReingoldLayout } from './fruchterman-reingold';
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 function springLayout(G, k = null, pos = null, fixed = null, iterations = 50, scale = 1, center = null, dim = 2, seed = null) {
20
+ // Legacy compatibility alias
21
+ return fruchtermanReingoldLayout(G, k, pos, fixed, iterations, scale, center, dim, seed);
22
+ }
23
+ //# sourceMappingURL=spring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spring.js","sourceRoot":"","sources":["../../../../src/layouts/force-directed/spring.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,CAAQ,EACR,IAAmB,IAAI,EACvB,MAA0B,IAAI,EAC9B,QAAuB,IAAI,EAC3B,aAAqB,EAAE,EACvB,QAAgB,CAAC,EACjB,SAA0B,IAAI,EAC9B,MAAc,CAAC,EACf,OAAsB,IAAI;IAE1B,6BAA6B;IAC7B,OAAO,yBAAyB,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Circular layout algorithm
3
+ */
4
+ import { Graph, PositionMap } from '../../types';
5
+ /**
6
+ * Position nodes on a circle (2D) or sphere (3D).
7
+ *
8
+ * @param G - Graph or list of nodes
9
+ * @param scale - Scale factor for positions
10
+ * @param center - Coordinate pair around which to center the layout
11
+ * @param dim - Dimension of layout (supports 2D circle or 3D sphere)
12
+ * @returns Positions dictionary keyed by node
13
+ */
14
+ export declare function circularLayout(G: Graph, scale?: number, center?: number[] | null, dim?: number): PositionMap;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Circular layout algorithm
3
+ */
4
+ import { _processParams } from '../../utils/params';
5
+ import { getNodesFromGraph } from '../../utils/graph';
6
+ import { RandomNumberGenerator } from '../../utils/random';
7
+ import { np } from '../../utils/numpy';
8
+ /**
9
+ * Position nodes on a circle (2D) or sphere (3D).
10
+ *
11
+ * @param G - Graph or list of nodes
12
+ * @param scale - Scale factor for positions
13
+ * @param center - Coordinate pair around which to center the layout
14
+ * @param dim - Dimension of layout (supports 2D circle or 3D sphere)
15
+ * @returns Positions dictionary keyed by node
16
+ */
17
+ export function circularLayout(G, scale = 1, center = null, dim = 2) {
18
+ if (dim < 2) {
19
+ throw new Error("cannot handle dimensions < 2");
20
+ }
21
+ const processed = _processParams(G, center, dim);
22
+ const nodes = getNodesFromGraph(processed.G);
23
+ center = processed.center;
24
+ const pos = {};
25
+ if (nodes.length === 0) {
26
+ return pos;
27
+ }
28
+ if (nodes.length === 1) {
29
+ pos[nodes[0]] = center;
30
+ return pos;
31
+ }
32
+ if (dim === 2) {
33
+ // 2D circle layout
34
+ const theta = np.linspace(0, 2 * Math.PI, nodes.length + 1).slice(0, -1);
35
+ nodes.forEach((node, i) => {
36
+ const x = Math.cos(theta[i]) * scale + center[0];
37
+ const y = Math.sin(theta[i]) * scale + center[1];
38
+ pos[node] = [x, y];
39
+ });
40
+ }
41
+ else if (dim === 3) {
42
+ // 3D sphere layout using Fibonacci spiral
43
+ const n = nodes.length;
44
+ const goldenRatio = (1 + Math.sqrt(5)) / 2;
45
+ nodes.forEach((node, i) => {
46
+ // Use Fibonacci spiral for even distribution on sphere
47
+ const theta = 2 * Math.PI * i / goldenRatio;
48
+ const phi = Math.acos(1 - 2 * (i + 0.5) / n);
49
+ const x = Math.sin(phi) * Math.cos(theta) * scale + center[0];
50
+ const y = Math.sin(phi) * Math.sin(theta) * scale + center[1];
51
+ const z = Math.cos(phi) * scale + center[2];
52
+ pos[node] = [x, y, z];
53
+ });
54
+ }
55
+ else {
56
+ // For higher dimensions, fall back to random on hypersphere
57
+ const rng = new RandomNumberGenerator();
58
+ nodes.forEach((node) => {
59
+ // Generate random point on unit hypersphere
60
+ const coords = Array(dim).fill(0).map(() => rng.rand() * 2 - 1);
61
+ const norm = Math.sqrt(coords.reduce((sum, c) => sum + c * c, 0));
62
+ pos[node] = coords.map((c, j) => c / norm * scale + center[j]);
63
+ });
64
+ }
65
+ return pos;
66
+ }
67
+ //# sourceMappingURL=circular.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circular.js","sourceRoot":"","sources":["../../../../src/layouts/geometric/circular.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Geometric layout algorithms
3
+ */
4
+ export { circularLayout } from './circular';
5
+ export { shellLayout } from './shell';
6
+ export { spiralLayout } from './spiral';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Geometric layout algorithms
3
+ */
4
+ export { circularLayout } from './circular';
5
+ export { shellLayout } from './shell';
6
+ export { spiralLayout } from './spiral';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/layouts/geometric/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shell layout algorithm
3
+ */
4
+ import { Graph, Node, PositionMap } from '../../types';
5
+ /**
6
+ * Position nodes in concentric circles.
7
+ *
8
+ * @param G - Graph or list of nodes
9
+ * @param nlist - List of node lists for each shell
10
+ * @param scale - Scale factor for positions
11
+ * @param center - Coordinate pair around which to center the layout
12
+ * @param dim - Dimension of layout (currently only supports dim=2)
13
+ * @returns Positions dictionary keyed by node
14
+ */
15
+ export declare function shellLayout(G: Graph, nlist?: Node[][] | null, scale?: number, center?: number[] | null, dim?: number): PositionMap;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Shell layout algorithm
3
+ */
4
+ import { _processParams } from '../../utils/params';
5
+ import { getNodesFromGraph } from '../../utils/graph';
6
+ import { np } from '../../utils/numpy';
7
+ /**
8
+ * Position nodes in concentric circles.
9
+ *
10
+ * @param G - Graph or list of nodes
11
+ * @param nlist - List of node lists for each shell
12
+ * @param scale - Scale factor for positions
13
+ * @param center - Coordinate pair around which to center the layout
14
+ * @param dim - Dimension of layout (currently only supports dim=2)
15
+ * @returns Positions dictionary keyed by node
16
+ */
17
+ export function shellLayout(G, nlist = null, scale = 1, center = null, dim = 2) {
18
+ if (dim !== 2) {
19
+ throw new Error("can only handle 2 dimensions");
20
+ }
21
+ const processed = _processParams(G, center, dim);
22
+ const nodes = getNodesFromGraph(processed.G);
23
+ center = processed.center;
24
+ const pos = {};
25
+ if (nodes.length === 0) {
26
+ return pos;
27
+ }
28
+ if (nodes.length === 1) {
29
+ pos[nodes[0]] = center;
30
+ return pos;
31
+ }
32
+ // If no nlist is specified, put all nodes in a single shell
33
+ if (!nlist) {
34
+ nlist = [nodes];
35
+ }
36
+ const radiusBump = scale / nlist.length;
37
+ let radius;
38
+ if (nlist[0].length === 1) {
39
+ // Single node at center
40
+ radius = 0;
41
+ pos[nlist[0][0]] = [...center];
42
+ radius += radiusBump;
43
+ }
44
+ else {
45
+ // Start at radius 1
46
+ radius = radiusBump;
47
+ }
48
+ for (let i = 0; i < nlist.length; i++) {
49
+ const shell = nlist[i];
50
+ if (shell.length === 0)
51
+ continue;
52
+ if (shell.length === 1 && i === 0) {
53
+ // Already handled the case of a single center node
54
+ continue;
55
+ }
56
+ // Calculate positions on a circle
57
+ const theta = np.linspace(0, 2 * Math.PI, shell.length + 1).slice(0, -1);
58
+ shell.forEach((node, j) => {
59
+ const x = Math.cos(theta[j]) * radius + center[0];
60
+ const y = Math.sin(theta[j]) * radius + center[1];
61
+ pos[node] = [x, y];
62
+ });
63
+ radius += radiusBump;
64
+ }
65
+ return pos;
66
+ }
67
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../../../src/layouts/geometric/shell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Spiral layout algorithm
3
+ */
4
+ import { Graph, PositionMap } from '../../types';
5
+ /**
6
+ * Position nodes in a spiral layout.
7
+ *
8
+ * @param G - Graph or list of nodes
9
+ * @param scale - Scale factor for positions
10
+ * @param center - Coordinate pair around which to center the layout
11
+ * @param dim - Dimension of layout
12
+ * @param resolution - Controls the spacing between spiral elements
13
+ * @param equidistant - Whether to place nodes equidistant from each other
14
+ * @returns Positions dictionary keyed by node
15
+ */
16
+ export declare function spiralLayout(G: Graph, scale?: number, center?: number[] | null, dim?: number, resolution?: number, equidistant?: boolean): PositionMap;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Spiral layout algorithm
3
+ */
4
+ import { _processParams } from '../../utils/params';
5
+ import { getNodesFromGraph } from '../../utils/graph';
6
+ import { rescaleLayout } from '../../utils/rescale';
7
+ /**
8
+ * Position nodes in a spiral layout.
9
+ *
10
+ * @param G - Graph or list of nodes
11
+ * @param scale - Scale factor for positions
12
+ * @param center - Coordinate pair around which to center the layout
13
+ * @param dim - Dimension of layout
14
+ * @param resolution - Controls the spacing between spiral elements
15
+ * @param equidistant - Whether to place nodes equidistant from each other
16
+ * @returns Positions dictionary keyed by node
17
+ */
18
+ export function spiralLayout(G, scale = 1, center = null, dim = 2, resolution = 0.35, equidistant = false) {
19
+ if (dim !== 2) {
20
+ throw new Error("can only handle 2 dimensions");
21
+ }
22
+ const processed = _processParams(G, center || [0, 0], dim);
23
+ const nodes = getNodesFromGraph(processed.G);
24
+ center = processed.center;
25
+ const pos = {};
26
+ if (nodes.length === 0) {
27
+ return pos;
28
+ }
29
+ if (nodes.length === 1) {
30
+ pos[nodes[0]] = [...center];
31
+ return pos;
32
+ }
33
+ let positions = [];
34
+ if (equidistant) {
35
+ // Create equidistant points along the spiral
36
+ // This matches the Python implementation logic
37
+ const chord = 1;
38
+ const step = 0.5;
39
+ let theta = resolution;
40
+ theta += chord / (step * theta);
41
+ for (let i = 0; i < nodes.length; i++) {
42
+ const r = step * theta;
43
+ theta += chord / r;
44
+ positions.push([Math.cos(theta) * r, Math.sin(theta) * r]);
45
+ }
46
+ }
47
+ else {
48
+ // Create points with equal angle but increasing distance
49
+ const dist = Array.from({ length: nodes.length }, (_, i) => parseFloat(String(i)));
50
+ const angle = dist.map(d => resolution * d);
51
+ positions = dist.map((d, i) => [
52
+ Math.cos(angle[i]) * d,
53
+ Math.sin(angle[i]) * d
54
+ ]);
55
+ }
56
+ // Convert position array to position matrix for rescaling
57
+ const posArray = [];
58
+ for (let i = 0; i < positions.length; i++) {
59
+ posArray.push(positions[i]);
60
+ }
61
+ // Rescale positions and add center offset
62
+ const scaledPositions = rescaleLayout(posArray, scale);
63
+ for (let i = 0; i < scaledPositions.length; i++) {
64
+ scaledPositions[i][0] += center[0];
65
+ scaledPositions[i][1] += center[1];
66
+ }
67
+ // Create position dictionary
68
+ for (let i = 0; i < nodes.length; i++) {
69
+ pos[nodes[i]] = scaledPositions[i];
70
+ }
71
+ return pos;
72
+ }
73
+ //# sourceMappingURL=spiral.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spiral.js","sourceRoot":"","sources":["../../../../src/layouts/geometric/spiral.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Graph, Node, PositionMap } from '../../types';
2
+ /**
3
+ * Position nodes according to breadth-first search algorithm.
4
+ *
5
+ * @param G - Graph
6
+ * @param start - Starting node for bfs
7
+ * @param align - The alignment of layers: 'vertical' or 'horizontal'
8
+ * @param scale - Scale factor for positions
9
+ * @param center - Coordinate pair around which to center the layout
10
+ * @returns Positions dictionary keyed by node
11
+ */
12
+ export declare function bfsLayout(G: Graph, start: Node, align?: 'vertical' | 'horizontal', scale?: number, center?: number[] | null): PositionMap;
@@ -0,0 +1,62 @@
1
+ import { getNodesFromGraph, getNeighbors } from '../../utils/graph';
2
+ import { _processParams } from '../../utils/params';
3
+ import { multipartiteLayout } from './multipartite';
4
+ /**
5
+ * Position nodes according to breadth-first search algorithm.
6
+ *
7
+ * @param G - Graph
8
+ * @param start - Starting node for bfs
9
+ * @param align - The alignment of layers: 'vertical' or 'horizontal'
10
+ * @param scale - Scale factor for positions
11
+ * @param center - Coordinate pair around which to center the layout
12
+ * @returns Positions dictionary keyed by node
13
+ */
14
+ export function bfsLayout(G, start, align = 'vertical', scale = 1, center = null) {
15
+ const processed = _processParams(G, center || [0, 0], 2);
16
+ // BFS layout requires a proper Graph, not just a list of nodes
17
+ if (Array.isArray(processed.G)) {
18
+ throw new Error('BFS layout requires a Graph with edges, not just a list of nodes');
19
+ }
20
+ const graph = processed.G;
21
+ center = processed.center;
22
+ const allNodes = getNodesFromGraph(graph);
23
+ if (allNodes.length === 0) {
24
+ return {};
25
+ }
26
+ // Compute BFS layers
27
+ const layers = {};
28
+ const visited = new Set();
29
+ let currentLayer = 0;
30
+ // Starting layer
31
+ layers[currentLayer] = [start];
32
+ visited.add(start);
33
+ // BFS traversal
34
+ while (Object.values(layers).flat().length < allNodes.length) {
35
+ const nextLayer = [];
36
+ const currentNodes = layers[currentLayer];
37
+ for (const node of currentNodes) {
38
+ // Get neighbors - this is a simplified approach
39
+ // In a real implementation, we would get neighbors from the graph
40
+ const neighbors = getNeighbors(graph, node);
41
+ for (const neighbor of neighbors) {
42
+ if (!visited.has(neighbor)) {
43
+ nextLayer.push(neighbor);
44
+ visited.add(neighbor);
45
+ }
46
+ }
47
+ }
48
+ if (nextLayer.length === 0) {
49
+ // No more connected nodes
50
+ const unvisited = allNodes.filter((node) => !visited.has(node));
51
+ if (unvisited.length > 0) {
52
+ throw new Error("bfs_layout didn't include all nodes. Graph may be disconnected.");
53
+ }
54
+ break;
55
+ }
56
+ currentLayer++;
57
+ layers[currentLayer] = nextLayer;
58
+ }
59
+ // Use multipartite_layout to position the layers
60
+ return multipartiteLayout(graph, layers, align, scale, center);
61
+ }
62
+ //# sourceMappingURL=bfs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bfs.js","sourceRoot":"","sources":["../../../../src/layouts/hierarchical/bfs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CACvB,CAAQ,EACR,KAAW,EACX,QAAmC,UAAU,EAC7C,QAAgB,CAAC,EACjB,SAA0B,IAAI;IAE9B,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzD,+DAA+D;IAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC;IAC1B,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAQ,CAAC;IAChC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,iBAAiB;IACjB,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEnB,gBAAgB;IAChB,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAW,EAAE,CAAC;QAC7B,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QAE1C,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,gDAAgD;YAChD,kEAAkE;YAClE,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAE5C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC3B,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACzB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,0BAA0B;YAC1B,MAAM,SAAS,GAAW,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9E,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;YACrF,CAAC;YACD,MAAM;QACR,CAAC;QAED,YAAY,EAAE,CAAC;QACf,MAAM,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACnC,CAAC;IAED,iDAAiD;IACjD,OAAO,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Bipartite layout algorithm
3
+ */
4
+ import { Graph, Node, PositionMap } from '../../types';
5
+ /**
6
+ * Position nodes in two straight lines (bipartite layout).
7
+ *
8
+ * @param G - Graph or list of nodes
9
+ * @param nodes - Nodes in one node set of the graph
10
+ * @param align - The alignment of nodes: 'vertical' or 'horizontal'
11
+ * @param scale - Scale factor for positions
12
+ * @param center - Coordinate pair around which to center the layout
13
+ * @param aspectRatio - The ratio of the width to the height of the layout
14
+ * @returns Positions dictionary keyed by node
15
+ */
16
+ export declare function bipartiteLayout(G: Graph, nodes?: Node[] | null, align?: 'vertical' | 'horizontal', scale?: number, center?: number[] | null, aspectRatio?: number): PositionMap;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Bipartite layout algorithm
3
+ */
4
+ import { _processParams } from '../../utils/params';
5
+ import { getNodesFromGraph } from '../../utils/graph';
6
+ import { rescaleLayout } from '../../utils/rescale';
7
+ /**
8
+ * Position nodes in two straight lines (bipartite layout).
9
+ *
10
+ * @param G - Graph or list of nodes
11
+ * @param nodes - Nodes in one node set of the graph
12
+ * @param align - The alignment of nodes: 'vertical' or 'horizontal'
13
+ * @param scale - Scale factor for positions
14
+ * @param center - Coordinate pair around which to center the layout
15
+ * @param aspectRatio - The ratio of the width to the height of the layout
16
+ * @returns Positions dictionary keyed by node
17
+ */
18
+ export function bipartiteLayout(G, nodes = null, align = 'vertical', scale = 1, center = null, aspectRatio = 4 / 3) {
19
+ if (align !== 'vertical' && align !== 'horizontal') {
20
+ throw new Error("align must be either vertical or horizontal");
21
+ }
22
+ const processed = _processParams(G, center || [0, 0], 2);
23
+ const graph = processed.G;
24
+ center = processed.center;
25
+ const allNodes = getNodesFromGraph(graph);
26
+ if (allNodes.length === 0) {
27
+ return {};
28
+ }
29
+ // If nodes not provided, try to determine bipartite sets
30
+ if (!nodes) {
31
+ // A simple heuristic for bipartite detection: use nodes with even/odd indices
32
+ // This is a simplification, in Python NetworkX has bipartite.sets()
33
+ nodes = allNodes.filter((_, i) => i % 2 === 0);
34
+ }
35
+ const left = new Set(nodes);
36
+ const right = new Set(allNodes.filter((n) => !left.has(n)));
37
+ const height = 1;
38
+ const width = aspectRatio * height;
39
+ const offset = [width / 2, height / 2];
40
+ const pos = {};
41
+ // Position nodes in the left set
42
+ const leftNodes = [...left];
43
+ leftNodes.forEach((node, i) => {
44
+ const x = 0;
45
+ const y = i * height / (leftNodes.length || 1);
46
+ pos[node] = [x, y];
47
+ });
48
+ // Position nodes in the right set
49
+ const rightNodes = [...right];
50
+ rightNodes.forEach((node, i) => {
51
+ const x = width;
52
+ const y = i * height / (rightNodes.length || 1);
53
+ pos[node] = [x, y];
54
+ });
55
+ // Center positions around the origin and apply offset
56
+ for (const node in pos) {
57
+ pos[node][0] -= offset[0];
58
+ pos[node][1] -= offset[1];
59
+ }
60
+ // Rescale positions
61
+ const scaledPos = rescaleLayout(pos, scale, center);
62
+ // Handle horizontal alignment
63
+ if (align === 'horizontal') {
64
+ for (const node in scaledPos) {
65
+ const temp = scaledPos[node][0];
66
+ scaledPos[node][0] = scaledPos[node][1];
67
+ scaledPos[node][1] = temp;
68
+ }
69
+ }
70
+ return scaledPos;
71
+ }
72
+ //# sourceMappingURL=bipartite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bipartite.js","sourceRoot":"","sources":["../../../../src/layouts/hierarchical/bipartite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Hierarchical layout algorithms
3
+ */
4
+ export { bipartiteLayout } from './bipartite';
5
+ export { multipartiteLayout } from './multipartite';
6
+ export { bfsLayout } from './bfs';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Hierarchical layout algorithms
3
+ */
4
+ export { bipartiteLayout } from './bipartite';
5
+ export { multipartiteLayout } from './multipartite';
6
+ export { bfsLayout } from './bfs';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/layouts/hierarchical/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Graph, Node, PositionMap } from '../../types';
2
+ /**
3
+ * Position nodes in layers of straight lines (multipartite layout).
4
+ *
5
+ * @param G - Graph or list of nodes
6
+ * @param subsetKey - Object mapping layers to node sets, or node attribute name
7
+ * @param align - The alignment of nodes: 'vertical' or 'horizontal'
8
+ * @param scale - Scale factor for positions
9
+ * @param center - Coordinate pair around which to center the layout
10
+ * @returns Positions dictionary keyed by node
11
+ */
12
+ export declare function multipartiteLayout(G: Graph, subsetKey?: Record<number | string, Node | Node[]> | string, align?: 'vertical' | 'horizontal', scale?: number, center?: number[] | null): PositionMap;
@@ -0,0 +1,73 @@
1
+ import { getNodesFromGraph } from '../../utils/graph';
2
+ import { _processParams } from '../../utils/params';
3
+ import { rescaleLayout } from '../../utils/rescale';
4
+ /**
5
+ * Position nodes in layers of straight lines (multipartite layout).
6
+ *
7
+ * @param G - Graph or list of nodes
8
+ * @param subsetKey - Object mapping layers to node sets, or node attribute name
9
+ * @param align - The alignment of nodes: 'vertical' or 'horizontal'
10
+ * @param scale - Scale factor for positions
11
+ * @param center - Coordinate pair around which to center the layout
12
+ * @returns Positions dictionary keyed by node
13
+ */
14
+ export function multipartiteLayout(G, subsetKey = 'subset', align = 'vertical', scale = 1, center = null) {
15
+ if (align !== 'vertical' && align !== 'horizontal') {
16
+ throw new Error("align must be either vertical or horizontal");
17
+ }
18
+ const processed = _processParams(G, center || [0, 0], 2);
19
+ const graph = processed.G;
20
+ center = processed.center;
21
+ const allNodes = getNodesFromGraph(graph);
22
+ if (allNodes.length === 0) {
23
+ return {};
24
+ }
25
+ // Convert subsetKey to a layer mapping if it's a string
26
+ let layers = {};
27
+ if (typeof subsetKey === 'string') {
28
+ // In JS we don't have access to node attributes directly
29
+ // This is a simplification - in a real implementation we would need
30
+ // to access node attributes from the graph
31
+ console.warn("Using string subsetKey requires node attributes, using default partitioning");
32
+ // Create a simple partitioning as fallback
33
+ layers = { 0: allNodes };
34
+ }
35
+ else {
36
+ // subsetKey is already a mapping of layers to nodes
37
+ // Convert single nodes to arrays
38
+ for (const [key, value] of Object.entries(subsetKey)) {
39
+ if (Array.isArray(value)) {
40
+ layers[key] = value;
41
+ }
42
+ else {
43
+ layers[key] = [value];
44
+ }
45
+ }
46
+ }
47
+ const layerCount = Object.keys(layers).length;
48
+ let pos = {};
49
+ // Process each layer
50
+ Object.entries(layers).forEach(([layer, nodes], layerIdx) => {
51
+ const layerNodes = Array.isArray(nodes) ? nodes : [nodes];
52
+ const layerSize = layerNodes.length;
53
+ layerNodes.forEach((node, nodeIdx) => {
54
+ // Place nodes in a grid: layerIdx determines x-coordinate (column)
55
+ // nodeIdx determines y-coordinate (row position within column)
56
+ const x = layerIdx - (layerCount - 1) / 2;
57
+ const y = nodeIdx - (layerSize - 1) / 2;
58
+ pos[node] = [x, y];
59
+ });
60
+ });
61
+ // Rescale positions
62
+ pos = rescaleLayout(pos, scale, center);
63
+ // Handle horizontal alignment
64
+ if (align === 'horizontal') {
65
+ for (const node in pos) {
66
+ const temp = pos[node][0];
67
+ pos[node][0] = pos[node][1];
68
+ pos[node][1] = temp;
69
+ }
70
+ }
71
+ return pos;
72
+ }
73
+ //# sourceMappingURL=multipartite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipartite.js","sourceRoot":"","sources":["../../../../src/layouts/hierarchical/multipartite.ts"],"names":[],"mappings":"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"}