@antv/layout 0.2.0 → 0.2.3

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 (297) hide show
  1. package/dist/layout.min.js +1 -1
  2. package/dist/layout.min.js.LICENSE.txt +0 -9
  3. package/dist/layout.min.js.map +1 -1
  4. package/es/layout/circular.js.map +1 -1
  5. package/es/layout/comboCombined.js +3 -19
  6. package/es/layout/comboCombined.js.map +1 -1
  7. package/es/layout/concentric.js.map +1 -1
  8. package/es/layout/dagre/graph.d.ts +91 -0
  9. package/es/layout/dagre/graph.js +4 -0
  10. package/es/layout/dagre/graph.js.map +1 -0
  11. package/es/layout/dagre/index.d.ts +3 -4
  12. package/es/layout/dagre/index.js +0 -2
  13. package/es/layout/dagre/index.js.map +1 -1
  14. package/es/layout/dagre/src/acyclic.d.ts +1 -2
  15. package/es/layout/dagre/src/acyclic.js +7 -7
  16. package/es/layout/dagre/src/acyclic.js.map +1 -1
  17. package/es/layout/dagre/src/add-border-segments.d.ts +1 -2
  18. package/es/layout/dagre/src/add-border-segments.js +5 -5
  19. package/es/layout/dagre/src/add-border-segments.js.map +1 -1
  20. package/es/layout/dagre/src/coordinate-system.d.ts +1 -2
  21. package/es/layout/dagre/src/coordinate-system.js +15 -5
  22. package/es/layout/dagre/src/coordinate-system.js.map +1 -1
  23. package/es/layout/dagre/src/data/list.d.ts +9 -5
  24. package/es/layout/dagre/src/data/list.js +25 -27
  25. package/es/layout/dagre/src/data/list.js.map +1 -1
  26. package/es/layout/dagre/src/debug.d.ts +2 -3
  27. package/es/layout/dagre/src/debug.js +3 -5
  28. package/es/layout/dagre/src/debug.js.map +1 -1
  29. package/es/layout/dagre/src/greedy-fas.d.ts +2 -3
  30. package/es/layout/dagre/src/greedy-fas.js +16 -15
  31. package/es/layout/dagre/src/greedy-fas.js.map +1 -1
  32. package/es/layout/dagre/src/layout.d.ts +2 -3
  33. package/es/layout/dagre/src/layout.js +170 -91
  34. package/es/layout/dagre/src/layout.js.map +1 -1
  35. package/es/layout/dagre/src/nesting-graph.d.ts +1 -2
  36. package/es/layout/dagre/src/nesting-graph.js +15 -10
  37. package/es/layout/dagre/src/nesting-graph.js.map +1 -1
  38. package/es/layout/dagre/src/normalize.d.ts +1 -2
  39. package/es/layout/dagre/src/normalize.js +12 -11
  40. package/es/layout/dagre/src/normalize.js.map +1 -1
  41. package/es/layout/dagre/src/order/add-subgraph-constraints.d.ts +1 -2
  42. package/es/layout/dagre/src/order/add-subgraph-constraints.js.map +1 -1
  43. package/es/layout/dagre/src/order/barycenter.d.ts +1 -2
  44. package/es/layout/dagre/src/order/barycenter.js.map +1 -1
  45. package/es/layout/dagre/src/order/build-layer-graph.d.ts +2 -3
  46. package/es/layout/dagre/src/order/build-layer-graph.js +12 -8
  47. package/es/layout/dagre/src/order/build-layer-graph.js.map +1 -1
  48. package/es/layout/dagre/src/order/cross-count.d.ts +2 -3
  49. package/es/layout/dagre/src/order/cross-count.js +13 -12
  50. package/es/layout/dagre/src/order/cross-count.js.map +1 -1
  51. package/es/layout/dagre/src/order/index.d.ts +2 -3
  52. package/es/layout/dagre/src/order/index.js +17 -15
  53. package/es/layout/dagre/src/order/index.js.map +1 -1
  54. package/es/layout/dagre/src/order/init-data-order.d.ts +1 -2
  55. package/es/layout/dagre/src/order/init-data-order.js +3 -5
  56. package/es/layout/dagre/src/order/init-data-order.js.map +1 -1
  57. package/es/layout/dagre/src/order/init-order.d.ts +2 -3
  58. package/es/layout/dagre/src/order/init-order.js +1 -2
  59. package/es/layout/dagre/src/order/init-order.js.map +1 -1
  60. package/es/layout/dagre/src/order/resolve-conflicts.d.ts +18 -3
  61. package/es/layout/dagre/src/order/resolve-conflicts.js +9 -29
  62. package/es/layout/dagre/src/order/resolve-conflicts.js.map +1 -1
  63. package/es/layout/dagre/src/order/sort-subgraph.d.ts +6 -3
  64. package/es/layout/dagre/src/order/sort-subgraph.js +19 -14
  65. package/es/layout/dagre/src/order/sort-subgraph.js.map +1 -1
  66. package/es/layout/dagre/src/order/sort.d.ts +6 -1
  67. package/es/layout/dagre/src/order/sort.js +2 -2
  68. package/es/layout/dagre/src/order/sort.js.map +1 -1
  69. package/es/layout/dagre/src/parent-dummy-chains.d.ts +1 -2
  70. package/es/layout/dagre/src/parent-dummy-chains.js +47 -44
  71. package/es/layout/dagre/src/parent-dummy-chains.js.map +1 -1
  72. package/es/layout/dagre/src/position/bk.d.ts +22 -31
  73. package/es/layout/dagre/src/position/bk.js +49 -83
  74. package/es/layout/dagre/src/position/bk.js.map +1 -1
  75. package/es/layout/dagre/src/position/index.d.ts +1 -2
  76. package/es/layout/dagre/src/position/index.js +12 -14
  77. package/es/layout/dagre/src/position/index.js.map +1 -1
  78. package/es/layout/dagre/src/rank/feasible-tree.d.ts +5 -6
  79. package/es/layout/dagre/src/rank/feasible-tree.js +1 -2
  80. package/es/layout/dagre/src/rank/feasible-tree.js.map +1 -1
  81. package/es/layout/dagre/src/rank/index.d.ts +2 -3
  82. package/es/layout/dagre/src/rank/index.js.map +1 -1
  83. package/es/layout/dagre/src/rank/network-simplex.d.ts +8 -11
  84. package/es/layout/dagre/src/rank/network-simplex.js +18 -31
  85. package/es/layout/dagre/src/rank/network-simplex.js.map +1 -1
  86. package/es/layout/dagre/src/rank/util.d.ts +4 -5
  87. package/es/layout/dagre/src/rank/util.js +37 -20
  88. package/es/layout/dagre/src/rank/util.js.map +1 -1
  89. package/es/layout/dagre/src/util.d.ts +29 -48
  90. package/es/layout/dagre/src/util.js +91 -101
  91. package/es/layout/dagre/src/util.js.map +1 -1
  92. package/es/layout/dagre.d.ts +1 -1
  93. package/es/layout/dagre.js +28 -24
  94. package/es/layout/dagre.js.map +1 -1
  95. package/es/layout/fruchterman.js.map +1 -1
  96. package/es/layout/gForce.js +14 -6
  97. package/es/layout/gForce.js.map +1 -1
  98. package/lib/index.js +5 -1
  99. package/lib/index.js.map +1 -1
  100. package/lib/layout/circular.js.map +1 -1
  101. package/lib/layout/comboCombined.js +2 -18
  102. package/lib/layout/comboCombined.js.map +1 -1
  103. package/lib/layout/comboForce.js +5 -5
  104. package/lib/layout/comboForce.js.map +1 -1
  105. package/lib/layout/concentric.js.map +1 -1
  106. package/lib/layout/dagre/graph.d.ts +91 -0
  107. package/lib/layout/dagre/graph.js +28 -0
  108. package/lib/layout/dagre/graph.js.map +1 -0
  109. package/lib/layout/dagre/index.d.ts +3 -4
  110. package/lib/layout/dagre/index.js +0 -2
  111. package/lib/layout/dagre/index.js.map +1 -1
  112. package/lib/layout/dagre/src/acyclic.d.ts +1 -2
  113. package/lib/layout/dagre/src/acyclic.js +7 -7
  114. package/lib/layout/dagre/src/acyclic.js.map +1 -1
  115. package/lib/layout/dagre/src/add-border-segments.d.ts +1 -2
  116. package/lib/layout/dagre/src/add-border-segments.js +5 -8
  117. package/lib/layout/dagre/src/add-border-segments.js.map +1 -1
  118. package/lib/layout/dagre/src/coordinate-system.d.ts +1 -2
  119. package/lib/layout/dagre/src/coordinate-system.js +15 -5
  120. package/lib/layout/dagre/src/coordinate-system.js.map +1 -1
  121. package/lib/layout/dagre/src/data/list.d.ts +9 -5
  122. package/lib/layout/dagre/src/data/list.js +25 -26
  123. package/lib/layout/dagre/src/data/list.js.map +1 -1
  124. package/lib/layout/dagre/src/debug.d.ts +2 -3
  125. package/lib/layout/dagre/src/debug.js +6 -11
  126. package/lib/layout/dagre/src/debug.js.map +1 -1
  127. package/lib/layout/dagre/src/greedy-fas.d.ts +2 -3
  128. package/lib/layout/dagre/src/greedy-fas.js +41 -15
  129. package/lib/layout/dagre/src/greedy-fas.js.map +1 -1
  130. package/lib/layout/dagre/src/layout.d.ts +2 -3
  131. package/lib/layout/dagre/src/layout.js +171 -100
  132. package/lib/layout/dagre/src/layout.js.map +1 -1
  133. package/lib/layout/dagre/src/nesting-graph.d.ts +1 -2
  134. package/lib/layout/dagre/src/nesting-graph.js +15 -13
  135. package/lib/layout/dagre/src/nesting-graph.js.map +1 -1
  136. package/lib/layout/dagre/src/normalize.d.ts +1 -2
  137. package/lib/layout/dagre/src/normalize.js +12 -14
  138. package/lib/layout/dagre/src/normalize.js.map +1 -1
  139. package/lib/layout/dagre/src/order/add-subgraph-constraints.d.ts +1 -2
  140. package/lib/layout/dagre/src/order/add-subgraph-constraints.js.map +1 -1
  141. package/lib/layout/dagre/src/order/barycenter.d.ts +1 -2
  142. package/lib/layout/dagre/src/order/barycenter.js.map +1 -1
  143. package/lib/layout/dagre/src/order/build-layer-graph.d.ts +2 -3
  144. package/lib/layout/dagre/src/order/build-layer-graph.js +13 -12
  145. package/lib/layout/dagre/src/order/build-layer-graph.js.map +1 -1
  146. package/lib/layout/dagre/src/order/cross-count.d.ts +2 -3
  147. package/lib/layout/dagre/src/order/cross-count.js +14 -13
  148. package/lib/layout/dagre/src/order/cross-count.js.map +1 -1
  149. package/lib/layout/dagre/src/order/index.d.ts +2 -3
  150. package/lib/layout/dagre/src/order/index.js +15 -13
  151. package/lib/layout/dagre/src/order/index.js.map +1 -1
  152. package/lib/layout/dagre/src/order/init-data-order.d.ts +1 -2
  153. package/lib/layout/dagre/src/order/init-data-order.js +3 -5
  154. package/lib/layout/dagre/src/order/init-data-order.js.map +1 -1
  155. package/lib/layout/dagre/src/order/init-order.d.ts +2 -3
  156. package/lib/layout/dagre/src/order/init-order.js +1 -2
  157. package/lib/layout/dagre/src/order/init-order.js.map +1 -1
  158. package/lib/layout/dagre/src/order/resolve-conflicts.d.ts +18 -3
  159. package/lib/layout/dagre/src/order/resolve-conflicts.js +9 -29
  160. package/lib/layout/dagre/src/order/resolve-conflicts.js.map +1 -1
  161. package/lib/layout/dagre/src/order/sort-subgraph.d.ts +6 -3
  162. package/lib/layout/dagre/src/order/sort-subgraph.js +16 -11
  163. package/lib/layout/dagre/src/order/sort-subgraph.js.map +1 -1
  164. package/lib/layout/dagre/src/order/sort.d.ts +6 -1
  165. package/lib/layout/dagre/src/order/sort.js +2 -5
  166. package/lib/layout/dagre/src/order/sort.js.map +1 -1
  167. package/lib/layout/dagre/src/parent-dummy-chains.d.ts +1 -2
  168. package/lib/layout/dagre/src/parent-dummy-chains.js +47 -44
  169. package/lib/layout/dagre/src/parent-dummy-chains.js.map +1 -1
  170. package/lib/layout/dagre/src/position/bk.d.ts +22 -31
  171. package/lib/layout/dagre/src/position/bk.js +75 -85
  172. package/lib/layout/dagre/src/position/bk.js.map +1 -1
  173. package/lib/layout/dagre/src/position/index.d.ts +1 -2
  174. package/lib/layout/dagre/src/position/index.js +14 -17
  175. package/lib/layout/dagre/src/position/index.js.map +1 -1
  176. package/lib/layout/dagre/src/rank/feasible-tree.d.ts +5 -6
  177. package/lib/layout/dagre/src/rank/feasible-tree.js +3 -7
  178. package/lib/layout/dagre/src/rank/feasible-tree.js.map +1 -1
  179. package/lib/layout/dagre/src/rank/index.d.ts +2 -3
  180. package/lib/layout/dagre/src/rank/index.js.map +1 -1
  181. package/lib/layout/dagre/src/rank/network-simplex.d.ts +8 -11
  182. package/lib/layout/dagre/src/rank/network-simplex.js +27 -35
  183. package/lib/layout/dagre/src/rank/network-simplex.js.map +1 -1
  184. package/lib/layout/dagre/src/rank/util.d.ts +4 -5
  185. package/lib/layout/dagre/src/rank/util.js +36 -19
  186. package/lib/layout/dagre/src/rank/util.js.map +1 -1
  187. package/lib/layout/dagre/src/util.d.ts +29 -48
  188. package/lib/layout/dagre/src/util.js +80 -92
  189. package/lib/layout/dagre/src/util.js.map +1 -1
  190. package/lib/layout/dagre.d.ts +1 -1
  191. package/lib/layout/dagre.js +27 -23
  192. package/lib/layout/dagre.js.map +1 -1
  193. package/lib/layout/er/core.js +5 -1
  194. package/lib/layout/er/core.js.map +1 -1
  195. package/lib/layout/force/force-in-a-box.js +7 -3
  196. package/lib/layout/force/force-in-a-box.js.map +1 -1
  197. package/lib/layout/force/force.js +5 -1
  198. package/lib/layout/force/force.js.map +1 -1
  199. package/lib/layout/force/index.js +5 -1
  200. package/lib/layout/force/index.js.map +1 -1
  201. package/lib/layout/fruchterman.js.map +1 -1
  202. package/lib/layout/gForce.js +10 -2
  203. package/lib/layout/gForce.js.map +1 -1
  204. package/lib/layout/grid.js +2 -2
  205. package/lib/layout/grid.js.map +1 -1
  206. package/lib/layout/index.js +5 -1
  207. package/lib/layout/index.js.map +1 -1
  208. package/lib/layout/radial/index.js +5 -1
  209. package/lib/layout/radial/index.js.map +1 -1
  210. package/lib/registy/index.js +1 -1
  211. package/lib/registy/index.js.map +1 -1
  212. package/lib/util/index.js +5 -1
  213. package/lib/util/index.js.map +1 -1
  214. package/package.json +3 -2
  215. package/src/index.ts +7 -0
  216. package/src/layout/base.ts +54 -0
  217. package/src/layout/circular.ts +369 -0
  218. package/src/layout/comboCombined.ts +390 -0
  219. package/src/layout/comboForce.ts +873 -0
  220. package/src/layout/concentric.ts +289 -0
  221. package/src/layout/constants.ts +21 -0
  222. package/src/layout/dagre/graph.ts +104 -0
  223. package/src/layout/dagre/index.ts +31 -0
  224. package/src/layout/dagre/src/acyclic.ts +58 -0
  225. package/src/layout/dagre/src/add-border-segments.ts +47 -0
  226. package/src/layout/dagre/src/coordinate-system.ts +77 -0
  227. package/src/layout/dagre/src/data/list.ts +60 -0
  228. package/src/layout/dagre/src/debug.ts +30 -0
  229. package/src/layout/dagre/src/greedy-fas.ts +144 -0
  230. package/src/layout/dagre/src/layout.ts +580 -0
  231. package/src/layout/dagre/src/nesting-graph.ts +143 -0
  232. package/src/layout/dagre/src/normalize.ts +96 -0
  233. package/src/layout/dagre/src/order/add-subgraph-constraints.ts +29 -0
  234. package/src/layout/dagre/src/order/barycenter.ts +26 -0
  235. package/src/layout/dagre/src/order/build-layer-graph.ts +82 -0
  236. package/src/layout/dagre/src/order/cross-count.ts +77 -0
  237. package/src/layout/dagre/src/order/index.ts +105 -0
  238. package/src/layout/dagre/src/order/init-data-order.ts +27 -0
  239. package/src/layout/dagre/src/order/init-order.ts +56 -0
  240. package/src/layout/dagre/src/order/resolve-conflicts.ts +152 -0
  241. package/src/layout/dagre/src/order/sort-subgraph.ts +105 -0
  242. package/src/layout/dagre/src/order/sort.ts +76 -0
  243. package/src/layout/dagre/src/parent-dummy-chains.ts +102 -0
  244. package/src/layout/dagre/src/position/bk.ts +494 -0
  245. package/src/layout/dagre/src/position/index.ts +82 -0
  246. package/src/layout/dagre/src/rank/feasible-tree.ts +165 -0
  247. package/src/layout/dagre/src/rank/index.ts +54 -0
  248. package/src/layout/dagre/src/rank/network-simplex.ts +225 -0
  249. package/src/layout/dagre/src/rank/util.ts +157 -0
  250. package/src/layout/dagre/src/util.ts +308 -0
  251. package/src/layout/dagre.ts +423 -0
  252. package/src/layout/dagreCompound.ts +518 -0
  253. package/src/layout/er/core.ts +117 -0
  254. package/src/layout/er/forceGrid.ts +95 -0
  255. package/src/layout/er/grid.ts +185 -0
  256. package/src/layout/er/index.ts +68 -0
  257. package/src/layout/er/mysqlWorkbench.ts +345 -0
  258. package/src/layout/er/type.ts +39 -0
  259. package/src/layout/force/force-in-a-box.ts +400 -0
  260. package/src/layout/force/force.ts +391 -0
  261. package/src/layout/force/index.ts +1 -0
  262. package/src/layout/forceAtlas2/body.ts +115 -0
  263. package/src/layout/forceAtlas2/index.ts +556 -0
  264. package/src/layout/forceAtlas2/quad.ts +115 -0
  265. package/src/layout/forceAtlas2/quadTree.ts +107 -0
  266. package/src/layout/fruchterman.ts +361 -0
  267. package/src/layout/gForce.ts +487 -0
  268. package/src/layout/gpu/fruchterman.ts +314 -0
  269. package/src/layout/gpu/fruchtermanShader.ts +204 -0
  270. package/src/layout/gpu/gForce.ts +406 -0
  271. package/src/layout/gpu/gForceShader.ts +221 -0
  272. package/src/layout/grid.ts +391 -0
  273. package/src/layout/index.ts +45 -0
  274. package/src/layout/layout.ts +75 -0
  275. package/src/layout/mds.ts +140 -0
  276. package/src/layout/radial/index.ts +1 -0
  277. package/src/layout/radial/mds.ts +51 -0
  278. package/src/layout/radial/radial.ts +500 -0
  279. package/src/layout/radial/radialNonoverlapForce.ts +189 -0
  280. package/src/layout/random.ts +75 -0
  281. package/src/layout/types.ts +421 -0
  282. package/src/registy/index.ts +43 -0
  283. package/src/util/array.ts +1 -0
  284. package/src/util/function.ts +64 -0
  285. package/src/util/gpu.ts +254 -0
  286. package/src/util/index.ts +6 -0
  287. package/src/util/math.ts +158 -0
  288. package/src/util/number.ts +8 -0
  289. package/src/util/object.ts +28 -0
  290. package/src/util/string.ts +18 -0
  291. package/CHANGELOG.md +0 -78
  292. package/es/layout/dagre/src/graphlib.d.ts +0 -2
  293. package/es/layout/dagre/src/graphlib.js +0 -51
  294. package/es/layout/dagre/src/graphlib.js.map +0 -1
  295. package/lib/layout/dagre/src/graphlib.d.ts +0 -2
  296. package/lib/layout/dagre/src/graphlib.js +0 -56
  297. package/lib/layout/dagre/src/graphlib.js.map +0 -1
@@ -0,0 +1,391 @@
1
+ /**
2
+ * @fileOverview grid layout
3
+ * @author shiwu.wyy@antfin.com
4
+ * this algorithm refers to <cytoscape.js> - https://github.com/cytoscape/cytoscape.js/
5
+ */
6
+
7
+ import { isString, getDegree, isNaN, getFuncByUnknownType } from "../util";
8
+ import { Base } from "./base";
9
+ import {
10
+ OutNode,
11
+ Edge,
12
+ PointTuple,
13
+ Size,
14
+ IndexMap,
15
+ GridLayoutOptions
16
+ } from "./types";
17
+
18
+ type INode = OutNode & {
19
+ degree: number;
20
+ size: number | PointTuple | Size;
21
+ };
22
+
23
+ /**
24
+ * 网格布局
25
+ */
26
+ export class GridLayout extends Base {
27
+ /** 布局起始点 */
28
+ public begin: PointTuple = [0, 0];
29
+
30
+ /** prevents node overlap, may overflow boundingBox if not enough space */
31
+ public preventOverlap: boolean = true;
32
+
33
+ /** extra spacing around nodes when preventOverlap: true */
34
+ public preventOverlapPadding: number = 10;
35
+
36
+ /** uses all available space on false, uses minimal space on true */
37
+ public condense: boolean = false;
38
+
39
+ /** force num of rows in the grid */
40
+ public rows: number | undefined;
41
+
42
+ /** force num of columns in the grid */
43
+ public cols: number | undefined;
44
+
45
+ /** the spacing between two nodes */
46
+ public nodeSpacing: ((d?: unknown) => number) | number | undefined;
47
+
48
+ /** returns { row, col } for element */
49
+ public position:
50
+ | ((node: INode) => { row?: number; col?: number })
51
+ | undefined;
52
+
53
+ /** a sorting function to order the nodes; e.g. function(a, b){ return a.datapublic ('weight') - b.data('weight') } */
54
+ public sortBy: string = "degree";
55
+
56
+ public nodeSize: number | number[] | { width: number, height: number } | undefined;
57
+
58
+ public nodes: INode[] = [];
59
+
60
+ public edges: Edge[] = [];
61
+
62
+ public width: number = 300;
63
+
64
+ public height: number = 300;
65
+
66
+ private cells: number | undefined;
67
+
68
+ private row: number = 0;
69
+
70
+ private col: number = 0;
71
+
72
+ private splits: number | undefined;
73
+
74
+ private columns: number | undefined;
75
+
76
+ private cellWidth: number = 0;
77
+
78
+ private cellHeight: number = 0;
79
+
80
+ private cellUsed: {
81
+ [key: string]: boolean;
82
+ } = {};
83
+
84
+ private id2manPos: {
85
+ [key: string]: {
86
+ row: number;
87
+ col: number;
88
+ };
89
+ } = {};
90
+
91
+ /** 迭代结束的回调函数 */
92
+ public onLayoutEnd: () => void = () => {};
93
+
94
+ constructor(options?: GridLayoutOptions) {
95
+ super();
96
+ this.updateCfg(options);
97
+ }
98
+
99
+ public getDefaultCfg() {
100
+ return {
101
+ begin: [0, 0],
102
+ preventOverlap: true,
103
+ preventOverlapPadding: 10,
104
+ condense: false,
105
+ rows: undefined,
106
+ cols: undefined,
107
+ position: undefined,
108
+ sortBy: "degree",
109
+ nodeSize: 30
110
+ };
111
+ }
112
+
113
+ /**
114
+ * 执行布局
115
+ */
116
+ public execute() {
117
+ const self = this;
118
+ const { nodes, edges, begin } = self;
119
+ const n = nodes.length;
120
+ if (n === 0) {
121
+ if (self.onLayoutEnd) self.onLayoutEnd();
122
+ return {
123
+ nodes,
124
+ edges
125
+ };
126
+ }
127
+ if (n === 1) {
128
+ nodes[0].x = begin[0];
129
+ nodes[0].y = begin[1];
130
+ if (self.onLayoutEnd) self.onLayoutEnd();
131
+ return {
132
+ nodes,
133
+ edges,
134
+ };
135
+ }
136
+
137
+ let { sortBy, width, height } = self;
138
+ const { condense, preventOverlapPadding, preventOverlap, nodeSpacing: paramNodeSpacing, nodeSize: paramNodeSize } = self;
139
+
140
+ const layoutNodes: INode[] = [];
141
+ nodes.forEach((node) => {
142
+ layoutNodes.push(node);
143
+ });
144
+ const nodeIdxMap: IndexMap = {};
145
+ layoutNodes.forEach((node, i) => {
146
+ nodeIdxMap[node.id] = i;
147
+ });
148
+ if (
149
+ sortBy === "degree" ||
150
+ !isString(sortBy) ||
151
+ (layoutNodes[0] as any)[sortBy] === undefined
152
+ ) {
153
+ sortBy = "degree";
154
+ if (isNaN(nodes[0].degree)) {
155
+ const values = getDegree(layoutNodes.length, nodeIdxMap, edges);
156
+ layoutNodes.forEach((node, i) => {
157
+ node.degree = values[i];
158
+ });
159
+ }
160
+ }
161
+ // sort nodes by value
162
+ layoutNodes.sort(
163
+ (n1, n2) => (n2 as any)[sortBy] - (n1 as any)[sortBy]
164
+ );
165
+
166
+ if (!width && typeof window !== "undefined") {
167
+ width = window.innerWidth;
168
+ }
169
+ if (!height && typeof window !== "undefined") {
170
+ height = window.innerHeight;
171
+ }
172
+
173
+ const oRows = self.rows;
174
+ const oCols = self.cols != null ? self.cols : self.columns;
175
+ self.cells = n;
176
+
177
+ // if rows or columns were set in self, use those values
178
+ if (oRows != null && oCols != null) {
179
+ self.rows = oRows;
180
+ self.cols = oCols;
181
+ } else if (oRows != null && oCols == null) {
182
+ self.rows = oRows;
183
+ self.cols = Math.ceil(self.cells / self.rows);
184
+ } else if (oRows == null && oCols != null) {
185
+ self.cols = oCols;
186
+ self.rows = Math.ceil(self.cells / self.cols);
187
+ } else {
188
+ // otherwise use the automatic values and adjust accordingly // otherwise use the automatic values and adjust accordingly
189
+ // width/height * splits^2 = cells where splits is number of times to split width
190
+ self.splits = Math.sqrt((self.cells * self.height) / self.width);
191
+ self.rows = Math.round(self.splits);
192
+ self.cols = Math.round((self.width / self.height) * self.splits);
193
+ }
194
+ if (self.cols * self.rows > self.cells) {
195
+ // otherwise use the automatic values and adjust accordingly
196
+ // if rounding was up, see if we can reduce rows or columns
197
+ const sm = self.small() as number;
198
+ const lg = self.large() as number;
199
+
200
+ // reducing the small side takes away the most cells, so try it first
201
+ if ((sm - 1) * lg >= self.cells) {
202
+ self.small(sm - 1);
203
+ } else if ((lg - 1) * sm >= self.cells) {
204
+ self.large(lg - 1);
205
+ }
206
+ } else {
207
+ // if rounding was too low, add rows or columns
208
+ while (self.cols * self.rows < self.cells) {
209
+ const sm = self.small() as number;
210
+ const lg = self.large() as number;
211
+
212
+ // try to add to larger side first (adds less in multiplication)
213
+ if ((lg + 1) * sm >= self.cells) {
214
+ self.large(lg + 1);
215
+ } else {
216
+ self.small(sm + 1);
217
+ }
218
+ }
219
+ }
220
+
221
+ self.cellWidth = width / self.cols;
222
+ self.cellHeight = height / self.rows;
223
+
224
+ if (condense) {
225
+ self.cellWidth = 0;
226
+ self.cellHeight = 0;
227
+ }
228
+
229
+
230
+ if (preventOverlap || paramNodeSpacing) {
231
+ const nodeSpacing: Function = getFuncByUnknownType(10, paramNodeSpacing);
232
+ const nodeSize: Function = getFuncByUnknownType(30, paramNodeSize, false);
233
+ layoutNodes.forEach((node) => {
234
+ if (!node.x || !node.y) {
235
+ // for bb
236
+ node.x = 0;
237
+ node.y = 0;
238
+ }
239
+
240
+ const [nodew = 30, nodeh = 30] = nodeSize(node);
241
+
242
+ const p = nodeSpacing !== undefined ? nodeSpacing(node) : preventOverlapPadding;
243
+
244
+ const w = nodew + p;
245
+ const h = nodeh + p;
246
+
247
+ self.cellWidth = Math.max(self.cellWidth, w);
248
+ self.cellHeight = Math.max(self.cellHeight, h);
249
+ });
250
+ }
251
+
252
+ self.cellUsed = {}; // e.g. 'c-0-2' => true
253
+
254
+ // to keep track of current cell position
255
+ self.row = 0;
256
+ self.col = 0;
257
+
258
+ // get a cache of all the manual positions
259
+ self.id2manPos = {};
260
+ for (let i = 0; i < layoutNodes.length; i++) {
261
+ const node = layoutNodes[i];
262
+ let rcPos;
263
+ if (self.position) {
264
+ rcPos = self.position(node);
265
+ }
266
+
267
+ if (rcPos && (rcPos.row !== undefined || rcPos.col !== undefined)) {
268
+ // must have at least row or col def'd
269
+ const pos = {
270
+ row: rcPos.row,
271
+ col: rcPos.col
272
+ };
273
+
274
+ if (pos.col === undefined) {
275
+ // find unused col
276
+ pos.col = 0;
277
+
278
+ while (self.used(pos.row, pos.col)) {
279
+ pos.col++;
280
+ }
281
+ } else if (pos.row === undefined) {
282
+ // find unused row
283
+ pos.row = 0;
284
+
285
+ while (self.used(pos.row, pos.col)) {
286
+ pos.row++;
287
+ }
288
+ }
289
+
290
+ self.id2manPos[node.id] = pos as { row: number; col: number };
291
+ self.use(pos.row, pos.col);
292
+ }
293
+ self.getPos(node);
294
+ }
295
+
296
+ if (self.onLayoutEnd) self.onLayoutEnd();
297
+
298
+ return {
299
+ edges,
300
+ nodes: layoutNodes
301
+ };
302
+ }
303
+
304
+ private small(val?: number): number | undefined {
305
+ const self = this;
306
+ let res: number | undefined;
307
+ const rows = self.rows || 5;
308
+ const cols = self.cols || 5;
309
+ if (val == null) {
310
+ res = Math.min(rows, cols);
311
+ } else {
312
+ const min = Math.min(rows, cols);
313
+ if (min === self.rows) {
314
+ self.rows = val;
315
+ } else {
316
+ self.cols = val;
317
+ }
318
+ }
319
+ return res;
320
+ }
321
+
322
+ private large(val?: number): number | undefined {
323
+ const self = this;
324
+ let res: number | undefined;
325
+ const rows = self.rows || 5;
326
+ const cols = self.cols || 5;
327
+ if (val == null) {
328
+ res = Math.max(rows, cols);
329
+ } else {
330
+ const max = Math.max(rows, cols);
331
+ if (max === self.rows) {
332
+ self.rows = val;
333
+ } else {
334
+ self.cols = val;
335
+ }
336
+ }
337
+ return res;
338
+ }
339
+
340
+ private used(row: number | undefined, col: number | undefined) {
341
+ const self = this;
342
+ return self.cellUsed[`c-${row}-${col}`] || false;
343
+ }
344
+
345
+ private use(row: number | undefined, col: number | undefined) {
346
+ const self = this;
347
+ self.cellUsed[`c-${row}-${col}`] = true;
348
+ }
349
+
350
+ private moveToNextCell() {
351
+ const self = this;
352
+ const cols = self.cols || 5;
353
+ self.col++;
354
+ if (self.col >= cols) {
355
+ self.col = 0;
356
+ self.row++;
357
+ }
358
+ }
359
+
360
+ private getPos(node: INode) {
361
+ const self = this;
362
+ const { begin, cellWidth, cellHeight } = self;
363
+ let x: number;
364
+ let y: number;
365
+
366
+ // see if we have a manual position set
367
+ const rcPos = self.id2manPos[node.id];
368
+ if (rcPos) {
369
+ x = rcPos.col * cellWidth + cellWidth / 2 + begin[0];
370
+ y = rcPos.row * cellHeight + cellHeight / 2 + begin[1];
371
+ } else {
372
+ // otherwise set automatically
373
+
374
+ while (self.used(self.row, self.col)) {
375
+ self.moveToNextCell();
376
+ }
377
+
378
+ x = self.col * cellWidth + cellWidth / 2 + begin[0];
379
+ y = self.row * cellHeight + cellHeight / 2 + begin[1];
380
+ self.use(self.row, self.col);
381
+
382
+ self.moveToNextCell();
383
+ }
384
+ node.x = x;
385
+ node.y = y;
386
+ }
387
+
388
+ public getType() {
389
+ return "grid";
390
+ }
391
+ }
@@ -0,0 +1,45 @@
1
+ import { GridLayout } from "./grid";
2
+ import { RandomLayout } from "./random";
3
+ import { GForceLayout } from "./gForce";
4
+ import { ForceLayout } from "./force";
5
+ import { CircularLayout } from "./circular";
6
+ import { DagreLayout } from "./dagre";
7
+ import { DagreCompoundLayout } from "./dagreCompound";
8
+ import { RadialLayout } from "./radial";
9
+ import { ConcentricLayout } from "./concentric";
10
+ import { MDSLayout } from "./mds";
11
+ import { FruchtermanLayout } from "./fruchterman";
12
+ import { FruchtermanGPULayout } from "./gpu/fruchterman";
13
+ import { GForceGPULayout } from "./gpu/gForce";
14
+ import { ComboForceLayout } from "./comboForce";
15
+ import { ComboCombinedLayout } from "./comboCombined";
16
+ import { ForceAtlas2Layout } from "./forceAtlas2";
17
+ import { ERLayout } from './er';
18
+
19
+ import { Layout, Layouts } from "./layout";
20
+
21
+ export { Layout, Layouts };
22
+
23
+ // layout
24
+ export {
25
+ GridLayout,
26
+ RandomLayout,
27
+ GForceLayout,
28
+ ForceLayout,
29
+ CircularLayout,
30
+ DagreLayout,
31
+ DagreCompoundLayout,
32
+ RadialLayout,
33
+ ConcentricLayout,
34
+ MDSLayout,
35
+ FruchtermanLayout,
36
+ FruchtermanGPULayout,
37
+ GForceGPULayout,
38
+ ComboForceLayout,
39
+ ComboCombinedLayout,
40
+ ForceAtlas2Layout,
41
+ ERLayout
42
+ };
43
+
44
+ // types file
45
+ export * from "./types";
@@ -0,0 +1,75 @@
1
+ import { Base } from "./base";
2
+ import { Model, ILayout } from "./types";
3
+ import { getLayoutByName } from "../registy";
4
+ import { GridLayout } from "./grid";
5
+ import { RandomLayout } from "./random";
6
+ import { GForceLayout } from "./gForce";
7
+ import { ForceLayout } from "./force";
8
+ import { CircularLayout } from "./circular";
9
+ import { DagreLayout } from "./dagre";
10
+ import { RadialLayout } from "./radial";
11
+ import { ConcentricLayout } from "./concentric";
12
+ import { MDSLayout } from "./mds";
13
+ import { FruchtermanLayout } from "./fruchterman";
14
+ import { FruchtermanGPULayout } from "./gpu/fruchterman";
15
+ import { GForceGPULayout } from "./gpu/gForce";
16
+ import { ComboForceLayout } from "./comboForce";
17
+ import { ComboCombinedLayout } from "./comboCombined";
18
+ import { ForceAtlas2Layout } from "./forceAtlas2";
19
+ import { ERLayout } from "./er";
20
+ import { DagreCompoundLayout } from "./dagreCompound";
21
+ export class Layout {
22
+ public readonly layoutInstance: Base;
23
+
24
+ constructor(options: ILayout.LayoutOptions) {
25
+ const layoutClass = getLayoutByName(options.type as string);
26
+ this.layoutInstance = new layoutClass(options);
27
+ }
28
+
29
+ layout(data: Model) {
30
+ return this.layoutInstance.layout(data);
31
+ }
32
+
33
+ updateCfg(cfg: ILayout.LayoutOptions) {
34
+ this.layoutInstance.updateCfg(cfg);
35
+ }
36
+
37
+ init(data: Model) {
38
+ this.layoutInstance.init(data);
39
+ }
40
+
41
+ execute() {
42
+ this.layoutInstance.execute();
43
+ }
44
+
45
+ getDefaultCfg() {
46
+ return this.layoutInstance.getDefaultCfg();
47
+ }
48
+
49
+ destroy() {
50
+ return this.layoutInstance.destroy();
51
+ }
52
+ }
53
+
54
+ // FIXME
55
+ // FOR G6
56
+ // tslint:disable-next-line
57
+ export const Layouts: { [key: string]: any } = {
58
+ force: ForceLayout,
59
+ fruchterman: FruchtermanLayout,
60
+ forceAtlas2: ForceAtlas2Layout,
61
+ gForce: GForceLayout,
62
+ dagre: DagreLayout,
63
+ dagreCompound: DagreCompoundLayout,
64
+ circular: CircularLayout,
65
+ radial: RadialLayout,
66
+ concentric: ConcentricLayout,
67
+ grid: GridLayout,
68
+ mds: MDSLayout,
69
+ comboForce: ComboForceLayout,
70
+ comboCombined: ComboCombinedLayout,
71
+ random: RandomLayout,
72
+ 'gForce-gpu': GForceGPULayout,
73
+ 'fruchterman-gpu': FruchtermanGPULayout,
74
+ er: ERLayout,
75
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @fileOverview MDS layout
3
+ * @author shiwu.wyy@antfin.com
4
+ */
5
+
6
+ import { Matrix as MLMatrix, SingularValueDecomposition } from "ml-matrix";
7
+ import { PointTuple, OutNode, Edge, Matrix, MDSLayoutOptions } from "./types";
8
+ import { floydWarshall, getAdjMatrix, scaleMatrix } from "../util";
9
+ import { Base } from "./base";
10
+
11
+ /**
12
+ * mds 布局
13
+ */
14
+ export class MDSLayout extends Base {
15
+ /** 布局中心 */
16
+ public center: PointTuple = [0, 0];
17
+
18
+ /** 边长度 */
19
+ public linkDistance: number = 50;
20
+
21
+ private scaledDistances: Matrix[];
22
+
23
+ public nodes: OutNode[] = [];
24
+
25
+ public edges: Edge[] = [];
26
+
27
+ /** 迭代结束的回调函数 */
28
+ public onLayoutEnd: () => void = () => {};
29
+
30
+ constructor(options?: MDSLayoutOptions) {
31
+ super();
32
+ this.updateCfg(options);
33
+ }
34
+
35
+ public getDefaultCfg() {
36
+ return {
37
+ center: [0, 0],
38
+ linkDistance: 50
39
+ };
40
+ }
41
+
42
+ /**
43
+ * 执行布局
44
+ */
45
+ public execute() {
46
+ const self = this;
47
+ const { nodes, edges = [] } = self;
48
+ const center = self.center;
49
+ if (!nodes || nodes.length === 0) {
50
+ if (self.onLayoutEnd) self.onLayoutEnd();
51
+ return;
52
+ }
53
+ if (nodes.length === 1) {
54
+ nodes[0].x = center[0];
55
+ nodes[0].y = center[1];
56
+ if (self.onLayoutEnd) self.onLayoutEnd();
57
+ return;
58
+ }
59
+ const linkDistance = self.linkDistance;
60
+ // the graph-theoretic distance (shortest path distance) matrix
61
+ const adjMatrix = getAdjMatrix({ nodes, edges }, false);
62
+ const distances = floydWarshall(adjMatrix);
63
+ self.handleInfinity(distances);
64
+
65
+ // scale the ideal edge length acoording to linkDistance
66
+ const scaledD = scaleMatrix(distances, linkDistance);
67
+ self.scaledDistances = scaledD;
68
+
69
+ // get positions by MDS
70
+ const positions = self.runMDS();
71
+ self.positions = positions;
72
+ positions.forEach((p: number[], i: number) => {
73
+ nodes[i].x = p[0] + center[0];
74
+ nodes[i].y = p[1] + center[1];
75
+ });
76
+
77
+ if (self.onLayoutEnd) self.onLayoutEnd();
78
+
79
+ return {
80
+ nodes,
81
+ edges
82
+ };
83
+ }
84
+
85
+ /**
86
+ * mds 算法
87
+ * @return {array} positions 计算后的节点位置数组
88
+ */
89
+ public runMDS(): PointTuple[] {
90
+ const self = this;
91
+ const dimension = 2;
92
+ const distances = self.scaledDistances;
93
+
94
+ // square distances
95
+ const M = MLMatrix.mul(MLMatrix.pow(distances, 2), -0.5);
96
+
97
+ // double centre the rows/columns
98
+ const rowMeans = M.mean("row");
99
+ const colMeans = M.mean("column");
100
+ const totalMean = M.mean();
101
+ M.add(totalMean)
102
+ .subRowVector(rowMeans)
103
+ .subColumnVector(colMeans);
104
+
105
+ // take the SVD of the double centred matrix, and return the
106
+ // points from it
107
+ const ret = new SingularValueDecomposition(M);
108
+ const eigenValues = MLMatrix.sqrt(ret.diagonalMatrix).diagonal();
109
+ return ret.leftSingularVectors.toJSON().map((row: number[]) => {
110
+ return MLMatrix.mul([row], [eigenValues])
111
+ .toJSON()[0]
112
+ .splice(0, dimension) as PointTuple;
113
+ });
114
+ }
115
+
116
+ public handleInfinity(distances: Matrix[]) {
117
+ let maxDistance = -999999;
118
+ distances.forEach((row) => {
119
+ row.forEach((value) => {
120
+ if (value === Infinity) {
121
+ return;
122
+ }
123
+ if (maxDistance < value) {
124
+ maxDistance = value;
125
+ }
126
+ });
127
+ });
128
+ distances.forEach((row, i) => {
129
+ row.forEach((value, j) => {
130
+ if (value === Infinity) {
131
+ distances[i][j] = maxDistance;
132
+ }
133
+ });
134
+ });
135
+ }
136
+
137
+ public getType() {
138
+ return "mds";
139
+ }
140
+ }
@@ -0,0 +1 @@
1
+ export * from './radial';
@@ -0,0 +1,51 @@
1
+ import { PointTuple, Matrix } from '../types';
2
+ import { Matrix as MLMatrix, SingularValueDecomposition } from 'ml-matrix';
3
+
4
+ export default class MDS {
5
+ /** distance matrix */
6
+ public distances: Matrix[];
7
+
8
+ /** dimensions */
9
+ public dimension: number;
10
+
11
+ /** link distance */
12
+ public linkDistance: number;
13
+
14
+ constructor(params: { distances: Matrix[]; dimension?: number; linkDistance: number }) {
15
+ this.distances = params.distances;
16
+ this.dimension = params.dimension || 2;
17
+ this.linkDistance = params.linkDistance;
18
+ }
19
+
20
+ public layout(): PointTuple[] {
21
+ const self = this;
22
+ const { dimension, distances, linkDistance } = self;
23
+
24
+ try {
25
+ // square distances
26
+ const M = MLMatrix.mul(MLMatrix.pow(distances, 2), -0.5);
27
+
28
+ // double centre the rows/columns
29
+ const rowMeans = M.mean('row');
30
+ const colMeans = M.mean('column');
31
+ const totalMean = M.mean();
32
+ M.add(totalMean).subRowVector(rowMeans).subColumnVector(colMeans);
33
+
34
+ // take the SVD of the double centred matrix, and return the
35
+ // points from it
36
+ const ret = new SingularValueDecomposition(M);
37
+ const eigenValues = MLMatrix.sqrt(ret.diagonalMatrix).diagonal();
38
+ return ret.leftSingularVectors.toJSON().map((row: number[]) => {
39
+ return MLMatrix.mul([row], [eigenValues]).toJSON()[0].splice(0, dimension) as PointTuple;
40
+ });
41
+ } catch {
42
+ const res: PointTuple[] = [];
43
+ for (let i = 0; i < distances.length; i++) {
44
+ const x = Math.random() * linkDistance;
45
+ const y = Math.random() * linkDistance;
46
+ res.push([x, y]);
47
+ }
48
+ return res;
49
+ }
50
+ }
51
+ }