@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,423 @@
1
+ /**
2
+ * @fileOverview dagre layout
3
+ * @author shiwu.wyy@antfin.com
4
+ */
5
+
6
+ import { Edge, OutNode, DagreLayoutOptions, PointTuple, Point, Node } from "./types";
7
+ import dagre from "./dagre/index";
8
+ import { isArray, isNumber, isObject, getEdgeTerminal, getFunc, isString } from "../util";
9
+ import { Base } from "./base";
10
+ import { Graph as DagreGraph } from './dagre/graph';
11
+
12
+ /**
13
+ * 层次布局
14
+ */
15
+ export class DagreLayout extends Base {
16
+ /** layout 方向, 可选 TB, BT, LR, RL */
17
+ public rankdir: "TB" | "BT" | "LR" | "RL" = "TB";
18
+
19
+ /** 节点对齐方式,可选 UL, UR, DL, DR */
20
+ public align: undefined | "UL" | "UR" | "DL" | "DR";
21
+
22
+ /** 布局的起始(左上角)位置 */
23
+ public begin: PointTuple;
24
+
25
+ /** 节点大小 */
26
+ public nodeSize: number | number[] | undefined;
27
+
28
+ /** 节点水平间距(px) */
29
+ public nodesepFunc: ((d?: any) => number) | undefined;
30
+
31
+ /** 每一层节点之间间距 */
32
+ public ranksepFunc: ((d?: any) => number) | undefined;
33
+
34
+ /** 节点水平间距(px) */
35
+ public nodesep: number = 50;
36
+
37
+ /** 每一层节点之间间距 */
38
+ public ranksep: number = 50;
39
+
40
+ /** 是否保留布局连线的控制点 */
41
+ public controlPoints: boolean = false;
42
+
43
+ /** 每层节点是否根据节点数据中的 comboId 进行排序,以防止同层 combo 重叠 */
44
+ public sortByCombo: boolean = false;
45
+
46
+ /** 是否保留每条边上的dummy node */
47
+ public edgeLabelSpace: boolean = true;
48
+
49
+ /** 是否基于 dagre 进行辐射布局,若是,第一层节点将被放置在最内环上,其余层依次向外辐射 */
50
+ public radial: boolean = false;
51
+
52
+ /** radial 下生效,中心节点,被指定的节点及其同层节点将被放置在最内环上 */
53
+ public focusNode: string | Node | null;
54
+
55
+ /** 给定的节点顺序,配合keepNodeOrder使用 */
56
+ public nodeOrder: string[];
57
+
58
+ /** 上次的布局结果 */
59
+ public preset: {
60
+ nodes: OutNode[],
61
+ edges: any[],
62
+ };
63
+
64
+ public nodes: OutNode[] = [];
65
+
66
+ public edges: Edge[] = [];
67
+
68
+ /** 迭代结束的回调函数 */
69
+ public onLayoutEnd: () => void = () => {};
70
+
71
+ constructor(options?: DagreLayoutOptions) {
72
+ super();
73
+ this.updateCfg(options);
74
+ }
75
+
76
+ public getDefaultCfg() {
77
+ return {
78
+ rankdir: "TB", // layout 方向, 可选 TB, BT, LR, RL
79
+ align: undefined, // 节点对齐方式,可选 UL, UR, DL, DR
80
+ nodeSize: undefined, // 节点大小
81
+ nodesepFunc: undefined, // 节点水平间距(px)
82
+ ranksepFunc: undefined, // 每一层节点之间间距
83
+ nodesep: 50, // 节点水平间距(px)
84
+ ranksep: 50, // 每一层节点之间间距
85
+ controlPoints: false, // 是否保留布局连线的控制点
86
+ radial: false, // 是否基于 dagre 进行辐射布局
87
+ focusNode: null, // radial 为 true 时生效,关注的节点
88
+ };
89
+ }
90
+
91
+ public layoutNode = (nodeId: string) => {
92
+ const self = this;
93
+ const { nodes } = self;
94
+ const node = nodes.find((node) => node.id === nodeId);
95
+ if (node) {
96
+ const layout = node.layout !== false;
97
+ return layout;
98
+ }
99
+ return true;
100
+ }
101
+
102
+ /**
103
+ * 执行布局
104
+ */
105
+ public execute() {
106
+ const self = this;
107
+ const { nodes, nodeSize, rankdir, combos, begin, radial } = self;
108
+ if (!nodes) return;
109
+ const edges = (self.edges as any[]) || [];
110
+ const g = new DagreGraph({
111
+ multigraph: true,
112
+ compound: true,
113
+ });
114
+
115
+ let nodeSizeFunc: (d?: any) => number[];
116
+ if (!nodeSize) {
117
+ nodeSizeFunc = (d: any) => {
118
+ if (d.size) {
119
+ if (isArray(d.size)) {
120
+ return d.size;
121
+ } if (isObject(d.size)) {
122
+ return [d.size.width || 40, d.size.height || 40];
123
+ }
124
+ return [d.size, d.size];
125
+ }
126
+ return [40, 40];
127
+ };
128
+ } else if (isArray(nodeSize)) {
129
+ nodeSizeFunc = () => nodeSize;
130
+ } else {
131
+ nodeSizeFunc = () => [nodeSize, nodeSize];
132
+ }
133
+ const ranksepfunc = getFunc(self.ranksep, 50, self.ranksepFunc);
134
+ const nodesepfunc = getFunc(self.nodesep, 50, self.nodesepFunc);
135
+ let horisep: Function = nodesepfunc;
136
+ let vertisep: Function = ranksepfunc;
137
+
138
+ if (rankdir === "LR" || rankdir === "RL") {
139
+ horisep = ranksepfunc;
140
+ vertisep = nodesepfunc;
141
+ }
142
+ g.setDefaultEdgeLabel(() => ({}));
143
+ g.setGraph(self);
144
+
145
+ const comboMap: { [key: string]: boolean } = {};
146
+
147
+ if (this.sortByCombo && combos) {
148
+ combos.forEach((combo) => {
149
+ if (!combo.parentId) return;
150
+ if (!comboMap[combo.parentId]) {
151
+ comboMap[combo.parentId] = true;
152
+ g.setNode(combo.parentId, {});
153
+ }
154
+ g.setParent(combo.id, combo.parentId);
155
+ });
156
+ }
157
+
158
+ nodes.filter((node) => node.layout !== false).forEach((node) => {
159
+ const size = nodeSizeFunc(node);
160
+ const verti = vertisep(node);
161
+ const hori = horisep(node);
162
+ const width = size[0] + 2 * hori;
163
+ const height = size[1] + 2 * verti;
164
+ const layer = node.layer;
165
+ if (isNumber(layer)) {
166
+ // 如果有layer属性,加入到node的label中
167
+ g.setNode(node.id, { width, height, layer });
168
+ } else {
169
+ g.setNode(node.id, { width, height });
170
+ }
171
+
172
+ if (this.sortByCombo && node.comboId) {
173
+ if (!comboMap[node.comboId]) {
174
+ comboMap[node.comboId] = true;
175
+ g.setNode(node.comboId, {});
176
+ }
177
+ g.setParent(node.id, node.comboId);
178
+ }
179
+ });
180
+
181
+
182
+
183
+ edges.forEach((edge) => {
184
+ // dagrejs Wiki https://github.com/dagrejs/dagre/wiki#configuring-the-layout
185
+ const source = getEdgeTerminal(edge, 'source');
186
+ const target = getEdgeTerminal(edge, 'target');
187
+ if (this.layoutNode(source) && this.layoutNode(target)) {
188
+ g.setEdge(source, target, {
189
+ weight: edge.weight || 1,
190
+ });
191
+ }
192
+ });
193
+
194
+ // 考虑增量图中的原始图
195
+ let prevGraph: DagreGraph | undefined = undefined;
196
+ if (self.preset) {
197
+ prevGraph = new DagreGraph({
198
+ multigraph: true,
199
+ compound: true,
200
+ });
201
+ self.preset.nodes.forEach((node) => {
202
+ prevGraph?.setNode(node.id, node);
203
+ });
204
+ }
205
+
206
+ dagre.layout(g, {
207
+ prevGraph,
208
+ edgeLabelSpace: self.edgeLabelSpace,
209
+ keepNodeOrder: Boolean(!!self.nodeOrder),
210
+ nodeOrder: self.nodeOrder,
211
+ });
212
+
213
+ const dBegin = [0, 0];
214
+ if (begin) {
215
+ let minX = Infinity;
216
+ let minY = Infinity;
217
+ g.nodes().forEach((node) => {
218
+ const coord = g.node(node)!;
219
+ if (minX > coord.x!) minX = coord.x!;
220
+ if (minY > coord.y!) minY = coord.y!;
221
+ });
222
+ g.edges().forEach((edge) => {
223
+ const coord = g.edge(edge)!;
224
+ coord.points?.forEach((point: any) => {
225
+ if (minX > point.x) minX = point.x;
226
+ if (minY > point.y) minY = point.y;
227
+ });
228
+ });
229
+ dBegin[0] = begin[0] - minX;
230
+ dBegin[1] = begin[1] - minY;
231
+ }
232
+
233
+ // 变形为辐射
234
+ if (radial) {
235
+ const { focusNode, ranksep, getRadialPos } = this;
236
+ const focusId = isString(focusNode) ? focusNode: focusNode?.id;
237
+ const focusLayer = focusId ? g.node(focusId)?._rank : 0;
238
+ const layers: any[] = [];
239
+ const isHorizontal = rankdir === 'LR' || rankdir === 'RL';
240
+ const dim = isHorizontal ? 'y' : 'x';
241
+ const sizeDim = isHorizontal ? 'height' : 'width';
242
+ // 找到整个图作为环的坐标维度(dim)的最大、最小值,考虑节点宽度
243
+ let min = Infinity;
244
+ let max = -Infinity;
245
+ g.nodes().forEach((node: any) => {
246
+ const coord = g.node(node)! as any;
247
+ const i = nodes.findIndex((it) => it.id === node);
248
+ if (!nodes[i]) return;
249
+ const currentNodesep = nodesepfunc(nodes[i]);
250
+
251
+ if (focusLayer === 0) {
252
+ if (!layers[coord._rank]) layers[coord._rank] = { nodes: [], totalWidth: 0, maxSize: -Infinity };
253
+ layers[coord._rank].nodes.push(node);
254
+ layers[coord._rank].totalWidth += currentNodesep * 2 + coord[sizeDim];
255
+ if (layers[coord._rank].maxSize < Math.max(coord.width, coord.height)) layers[coord._rank].maxSize = Math.max(coord.width, coord.height);
256
+ } else {
257
+ const diffLayer = coord._rank - focusLayer!;
258
+ if (diffLayer === 0) {
259
+ if (!layers[diffLayer]) layers[diffLayer] = { nodes: [], totalWidth: 0, maxSize: -Infinity };
260
+ layers[diffLayer].nodes.push(node);
261
+ layers[diffLayer].totalWidth += currentNodesep * 2 + coord[sizeDim];
262
+ if (layers[diffLayer].maxSize < Math.max(coord.width, coord.height)) layers[diffLayer].maxSize = Math.max(coord.width, coord.height);
263
+ } else {
264
+ const diffLayerAbs = Math.abs(diffLayer);
265
+ if (!layers[diffLayerAbs]) layers[diffLayerAbs] = { left: [], right: [], totalWidth: 0, maxSize: -Infinity };
266
+ layers[diffLayerAbs].totalWidth += currentNodesep * 2 + coord[sizeDim];
267
+ if (layers[diffLayerAbs].maxSize < Math.max(coord.width, coord.height)) layers[diffLayerAbs].maxSize = Math.max(coord.width, coord.height);
268
+ if (diffLayer < 0) {
269
+ layers[diffLayerAbs].left.push(node);
270
+ } else {
271
+ layers[diffLayerAbs].right.push(node);
272
+ }
273
+ }
274
+ }
275
+ const leftPos = coord[dim] - coord[sizeDim] / 2 - currentNodesep;
276
+ const rightPos = coord[dim] + coord[sizeDim] / 2 + currentNodesep;
277
+ if (leftPos < min) min = leftPos;
278
+ if (rightPos > max) max = rightPos;
279
+ });
280
+ // const padding = (max - min) * 0.1; // TODO
281
+ // 初始化为第一圈的半径,后面根据每层 ranksep 叠加
282
+ let radius = ranksep || 50; // TODO;
283
+ const radiusMap: any = {};
284
+
285
+ // 扩大最大最小值范围,以便为环上留出接缝处的空隙
286
+ const rangeLength = (max - min) / 0.9;
287
+ const range = [ (min + max - rangeLength) * 0.5 , (min + max + rangeLength) * 0.5 ];
288
+
289
+ // 根据半径、分布比例,计算节点在环上的位置,并返回该组节点中最大的 ranksep 值
290
+ const processNodes = (layerNodes: any, radius: number, propsMaxRanksep = -Infinity, arcRange = [0, 1]) => {
291
+ let maxRanksep = propsMaxRanksep;
292
+ layerNodes.forEach((node: any) => {
293
+ const coord = g.node(node);
294
+ radiusMap[node] = radius;
295
+ // 获取变形为 radial 后的直角坐标系坐标
296
+ const { x: newX, y: newY } = getRadialPos(coord![dim]!, range, rangeLength, radius, arcRange);
297
+ // 将新坐标写入源数据
298
+ const i = nodes.findIndex((it) => it.id === node);
299
+ if (!nodes[i]) return;
300
+ nodes[i].x = newX + dBegin[0];
301
+ nodes[i].y = newY + dBegin[1];
302
+ // @ts-ignore: pass layer order to data for increment layout use
303
+ nodes[i]._order = coord._order;
304
+
305
+ // 找到本层最大的一个 ranksep,作为下一层与本层的间隙,叠加到下一层的半径上
306
+ const currentNodeRanksep = ranksepfunc(nodes[i]);
307
+ if (maxRanksep < currentNodeRanksep) maxRanksep = currentNodeRanksep;
308
+ });
309
+ return maxRanksep;
310
+ };
311
+
312
+ let isFirstLevel = true;
313
+ const lastLayerMaxNodeSize = 0;
314
+ layers.forEach((layerNodes) => {
315
+ if (!layerNodes?.nodes?.length && !layerNodes?.left?.length && !layerNodes?.right?.length) return;
316
+ // 第一层只有一个节点,直接放在圆心,初始半径设定为 0
317
+ if (isFirstLevel && layerNodes.nodes.length === 1) {
318
+ // 将新坐标写入源数据
319
+ const i = nodes.findIndex((it) => it.id === layerNodes.nodes[0]);
320
+ nodes[i].x = dBegin[0];
321
+ nodes[i].y = dBegin[1];
322
+ radiusMap[layerNodes.nodes[0]] = 0;
323
+ radius = ranksepfunc(nodes[i]);
324
+ isFirstLevel = false;
325
+ return;
326
+ }
327
+
328
+ // 为接缝留出空隙,半径也需要扩大
329
+ radius = Math.max(radius, layerNodes.totalWidth / (2 * Math.PI)); // / 0.9;
330
+
331
+ let maxRanksep = -Infinity;
332
+ if (focusLayer === 0 || layerNodes.nodes?.length) {
333
+ maxRanksep = processNodes(layerNodes.nodes, radius, maxRanksep, [0, 1]); // 0.8
334
+ } else {
335
+ const leftRatio = layerNodes.left?.length / (layerNodes.left?.length + layerNodes.right?.length);
336
+ maxRanksep= processNodes(layerNodes.left, radius, maxRanksep, [0, leftRatio]); // 接缝留出 0.05 的缝隙
337
+ maxRanksep = processNodes(layerNodes.right, radius, maxRanksep, [leftRatio + 0.05, 1]); // 接缝留出 0.05 的缝隙
338
+ }
339
+ radius += maxRanksep;
340
+ isFirstLevel = false;
341
+ lastLayerMaxNodeSize - layerNodes.maxSize;
342
+ });
343
+ g.edges().forEach((edge: any) => {
344
+ const coord = g.edge(edge);
345
+ const i = edges.findIndex((it) => {
346
+ const source = getEdgeTerminal(it, 'source');
347
+ const target = getEdgeTerminal(it, 'target');
348
+ return source === edge.v && target === edge.w;
349
+ });
350
+ if ((self.edgeLabelSpace) && self.controlPoints && edges[i].type !== "loop") {
351
+ const otherDim = dim === 'x' ? 'y' : 'x';
352
+ const controlPoints = coord?.points?.slice(1, coord.points.length - 1);
353
+ const newControlPoints: Point[] = [];
354
+ const sourceOtherDimValue = g.node(edge.v)?.[otherDim]!;
355
+ const otherDimDist = sourceOtherDimValue - g.node(edge.w)?.[otherDim]!;
356
+ const sourceRadius = radiusMap[edge.v];
357
+ const radiusDist = sourceRadius - radiusMap[edge.w];
358
+ controlPoints?.forEach((point: any) => {
359
+ // 根据该边的起点、终点半径,及起点、终点、控制点位置关系,确定该控制点的半径
360
+ const cRadius = (point[otherDim] - sourceOtherDimValue) / otherDimDist * radiusDist + sourceRadius;
361
+ // 获取变形为 radial 后的直角坐标系坐标
362
+ const newPos = getRadialPos(point[dim], range, rangeLength, cRadius);
363
+ newControlPoints.push({
364
+ x: newPos.x + dBegin[0],
365
+ y: newPos.y + dBegin[1]
366
+ });
367
+ });
368
+ edges[i].controlPoints = newControlPoints;
369
+ }
370
+ });
371
+ } else {
372
+ g.nodes().forEach((node: any) => {
373
+ const coord = g.node(node)!;
374
+ const i = nodes.findIndex((it) => it.id === node);
375
+ if (!nodes[i]) return;
376
+ nodes[i].x = coord.x! + dBegin[0];
377
+ nodes[i].y = coord.y! + dBegin[1];
378
+ // @ts-ignore: pass layer order to data for increment layout use
379
+ nodes[i]._order = coord._order;
380
+ });
381
+ g.edges().forEach((edge: any) => {
382
+ const coord = g.edge(edge);
383
+ const i = edges.findIndex((it) => {
384
+ const source = getEdgeTerminal(it, 'source');
385
+ const target = getEdgeTerminal(it, 'target');
386
+ return source === edge.v && target === edge.w;
387
+ });
388
+ if ((self.edgeLabelSpace) && self.controlPoints && edges[i].type !== "loop") {
389
+ edges[i].controlPoints = coord?.points?.slice(1, coord.points.length - 1); // 去掉头尾
390
+ edges[i].controlPoints.forEach((point: any) => {
391
+ point.x += dBegin[0];
392
+ point.y += dBegin[1];
393
+ });
394
+ }
395
+ });
396
+ }
397
+
398
+ if (self.onLayoutEnd) self.onLayoutEnd();
399
+
400
+ return {
401
+ nodes,
402
+ edges,
403
+ };
404
+ }
405
+
406
+ private getRadialPos(dimValue: number, range: number[], rangeLength: number, radius: number, arcRange: number[] = [0, 1]) {
407
+ // dimRatio 占圆弧的比例
408
+ let dimRatio = (dimValue - range[0]) / rangeLength;
409
+ // 再进一步归一化到指定的范围上
410
+ dimRatio = dimRatio * (arcRange[1] - arcRange[0]) + arcRange[0];
411
+ // 使用最终归一化后的范围计算角度
412
+ const angle = dimRatio * 2 * Math.PI; // 弧度
413
+ // 将极坐标系转换为直角坐标系
414
+ return {
415
+ x: Math.cos(angle) * radius,
416
+ y: Math.sin(angle) * radius
417
+ };
418
+ }
419
+
420
+ public getType() {
421
+ return "dagre";
422
+ }
423
+ }