@knowvah/dot-engine 0.1.0

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 (986) hide show
  1. package/LICENSE +277 -0
  2. package/README.md +292 -0
  3. package/dist/api/builder.d.ts +78 -0
  4. package/dist/api/builder.d.ts.map +1 -0
  5. package/dist/api/edge-ops.d.ts +45 -0
  6. package/dist/api/edge-ops.d.ts.map +1 -0
  7. package/dist/api/geometry.d.ts +159 -0
  8. package/dist/api/geometry.d.ts.map +1 -0
  9. package/dist/api/index.d.ts +24 -0
  10. package/dist/api/index.d.ts.map +1 -0
  11. package/dist/api.js +719 -0
  12. package/dist/api.js.map +7 -0
  13. package/dist/bundle.js +101 -0
  14. package/dist/cdt/bag.d.ts +58 -0
  15. package/dist/cdt/bag.d.ts.map +1 -0
  16. package/dist/cdt/hash-core.d.ts +40 -0
  17. package/dist/cdt/hash-core.d.ts.map +1 -0
  18. package/dist/cdt/hash.d.ts +74 -0
  19. package/dist/cdt/hash.d.ts.map +1 -0
  20. package/dist/cdt/index.d.ts +16 -0
  21. package/dist/cdt/index.d.ts.map +1 -0
  22. package/dist/cdt/splay-core.d.ts +78 -0
  23. package/dist/cdt/splay-core.d.ts.map +1 -0
  24. package/dist/cdt/splay.d.ts +63 -0
  25. package/dist/cdt/splay.d.ts.map +1 -0
  26. package/dist/cdt/strhash.d.ts +26 -0
  27. package/dist/cdt/strhash.d.ts.map +1 -0
  28. package/dist/cdt/types.d.ts +11 -0
  29. package/dist/cdt/types.d.ts.map +1 -0
  30. package/dist/common/arith.d.ts +35 -0
  31. package/dist/common/arith.d.ts.map +1 -0
  32. package/dist/common/arm-pow-data.d.ts +17 -0
  33. package/dist/common/arm-pow-data.d.ts.map +1 -0
  34. package/dist/common/arm-pow.d.ts +12 -0
  35. package/dist/common/arm-pow.d.ts.map +1 -0
  36. package/dist/common/arrows-constants.d.ts +97 -0
  37. package/dist/common/arrows-constants.d.ts.map +1 -0
  38. package/dist/common/arrows-geometry.d.ts +24 -0
  39. package/dist/common/arrows-geometry.d.ts.map +1 -0
  40. package/dist/common/arrows-miter.d.ts +24 -0
  41. package/dist/common/arrows-miter.d.ts.map +1 -0
  42. package/dist/common/arrows-shapes-poly.d.ts +24 -0
  43. package/dist/common/arrows-shapes-poly.d.ts.map +1 -0
  44. package/dist/common/arrows-shapes-util.d.ts +77 -0
  45. package/dist/common/arrows-shapes-util.d.ts.map +1 -0
  46. package/dist/common/arrows-shapes.d.ts +48 -0
  47. package/dist/common/arrows-shapes.d.ts.map +1 -0
  48. package/dist/common/arrows-types.d.ts +59 -0
  49. package/dist/common/arrows-types.d.ts.map +1 -0
  50. package/dist/common/arrows.d.ts +69 -0
  51. package/dist/common/arrows.d.ts.map +1 -0
  52. package/dist/common/color.d.ts +66 -0
  53. package/dist/common/color.d.ts.map +1 -0
  54. package/dist/common/colorData.d.ts +10 -0
  55. package/dist/common/colorData.d.ts.map +1 -0
  56. package/dist/common/compass-port.d.ts +39 -0
  57. package/dist/common/compass-port.d.ts.map +1 -0
  58. package/dist/common/crand.d.ts +42 -0
  59. package/dist/common/crand.d.ts.map +1 -0
  60. package/dist/common/edge-label-init.d.ts +51 -0
  61. package/dist/common/edge-label-init.d.ts.map +1 -0
  62. package/dist/common/edge-offset.d.ts +66 -0
  63. package/dist/common/edge-offset.d.ts.map +1 -0
  64. package/dist/common/ellipse-wedge.d.ts +10 -0
  65. package/dist/common/ellipse-wedge.d.ts.map +1 -0
  66. package/dist/common/emit-types.d.ts +255 -0
  67. package/dist/common/emit-types.d.ts.map +1 -0
  68. package/dist/common/fma.d.ts +10 -0
  69. package/dist/common/fma.d.ts.map +1 -0
  70. package/dist/common/graph-init.d.ts +61 -0
  71. package/dist/common/graph-init.d.ts.map +1 -0
  72. package/dist/common/html-entities.d.ts +17 -0
  73. package/dist/common/html-entities.d.ts.map +1 -0
  74. package/dist/common/html-string.d.ts +14 -0
  75. package/dist/common/html-string.d.ts.map +1 -0
  76. package/dist/common/htmltable-emit-fill.d.ts +84 -0
  77. package/dist/common/htmltable-emit-fill.d.ts.map +1 -0
  78. package/dist/common/htmltable-emit-rules.d.ts +79 -0
  79. package/dist/common/htmltable-emit-rules.d.ts.map +1 -0
  80. package/dist/common/htmltable-emit.d.ts +63 -0
  81. package/dist/common/htmltable-emit.d.ts.map +1 -0
  82. package/dist/common/htmltable-lex.d.ts +16 -0
  83. package/dist/common/htmltable-lex.d.ts.map +1 -0
  84. package/dist/common/htmltable-parse.d.ts +37 -0
  85. package/dist/common/htmltable-parse.d.ts.map +1 -0
  86. package/dist/common/htmltable-port.d.ts +15 -0
  87. package/dist/common/htmltable-port.d.ts.map +1 -0
  88. package/dist/common/htmltable-pos-runs.d.ts +88 -0
  89. package/dist/common/htmltable-pos-runs.d.ts.map +1 -0
  90. package/dist/common/htmltable-pos.d.ts +192 -0
  91. package/dist/common/htmltable-pos.d.ts.map +1 -0
  92. package/dist/common/htmltable-types.d.ts +237 -0
  93. package/dist/common/htmltable-types.d.ts.map +1 -0
  94. package/dist/common/htmltable.d.ts +74 -0
  95. package/dist/common/htmltable.d.ts.map +1 -0
  96. package/dist/common/layers.d.ts +20 -0
  97. package/dist/common/layers.d.ts.map +1 -0
  98. package/dist/common/make-label.d.ts +60 -0
  99. package/dist/common/make-label.d.ts.map +1 -0
  100. package/dist/common/multicolor.d.ts +46 -0
  101. package/dist/common/multicolor.d.ts.map +1 -0
  102. package/dist/common/nodeinit.d.ts +45 -0
  103. package/dist/common/nodeinit.d.ts.map +1 -0
  104. package/dist/common/poly-gencode.d.ts +40 -0
  105. package/dist/common/poly-gencode.d.ts.map +1 -0
  106. package/dist/common/poly-init.d.ts +51 -0
  107. package/dist/common/poly-init.d.ts.map +1 -0
  108. package/dist/common/poly-inside.d.ts +37 -0
  109. package/dist/common/poly-inside.d.ts.map +1 -0
  110. package/dist/common/poly-shapes-cases.d.ts +31 -0
  111. package/dist/common/poly-shapes-cases.d.ts.map +1 -0
  112. package/dist/common/poly-shapes-cases2.d.ts +25 -0
  113. package/dist/common/poly-shapes-cases2.d.ts.map +1 -0
  114. package/dist/common/poly-shapes-util.d.ts +42 -0
  115. package/dist/common/poly-shapes-util.d.ts.map +1 -0
  116. package/dist/common/poly-shapes.d.ts +39 -0
  117. package/dist/common/poly-shapes.d.ts.map +1 -0
  118. package/dist/common/poly-sizing.d.ts +189 -0
  119. package/dist/common/poly-sizing.d.ts.map +1 -0
  120. package/dist/common/poly-vertices.d.ts +42 -0
  121. package/dist/common/poly-vertices.d.ts.map +1 -0
  122. package/dist/common/postproc.d.ts +49 -0
  123. package/dist/common/postproc.d.ts.map +1 -0
  124. package/dist/common/ps-fontalias.d.ts +36 -0
  125. package/dist/common/ps-fontalias.d.ts.map +1 -0
  126. package/dist/common/random.d.ts +8 -0
  127. package/dist/common/random.d.ts.map +1 -0
  128. package/dist/common/record-port.d.ts +34 -0
  129. package/dist/common/record-port.d.ts.map +1 -0
  130. package/dist/common/record.d.ts +105 -0
  131. package/dist/common/record.d.ts.map +1 -0
  132. package/dist/common/shapeData.d.ts +186 -0
  133. package/dist/common/shapeData.d.ts.map +1 -0
  134. package/dist/common/shapes.d.ts +36 -0
  135. package/dist/common/shapes.d.ts.map +1 -0
  136. package/dist/common/spline-midpoint.d.ts +31 -0
  137. package/dist/common/spline-midpoint.d.ts.map +1 -0
  138. package/dist/common/splines-clip.d.ts +21 -0
  139. package/dist/common/splines-clip.d.ts.map +1 -0
  140. package/dist/common/splines-constants.d.ts +42 -0
  141. package/dist/common/splines-constants.d.ts.map +1 -0
  142. package/dist/common/splines-geom.d.ts +51 -0
  143. package/dist/common/splines-geom.d.ts.map +1 -0
  144. package/dist/common/splines-path-begin.d.ts +17 -0
  145. package/dist/common/splines-path-begin.d.ts.map +1 -0
  146. package/dist/common/splines-path-end.d.ts +17 -0
  147. package/dist/common/splines-path-end.d.ts.map +1 -0
  148. package/dist/common/splines-path-shared.d.ts +53 -0
  149. package/dist/common/splines-path-shared.d.ts.map +1 -0
  150. package/dist/common/splines-routespl.d.ts +40 -0
  151. package/dist/common/splines-routespl.d.ts.map +1 -0
  152. package/dist/common/splines-selfedge.d.ts +21 -0
  153. package/dist/common/splines-selfedge.d.ts.map +1 -0
  154. package/dist/common/splines.d.ts +18 -0
  155. package/dist/common/splines.d.ts.map +1 -0
  156. package/dist/common/style-resolve.d.ts +197 -0
  157. package/dist/common/style-resolve.d.ts.map +1 -0
  158. package/dist/common/subst.d.ts +31 -0
  159. package/dist/common/subst.d.ts.map +1 -0
  160. package/dist/common/taper.d.ts +23 -0
  161. package/dist/common/taper.d.ts.map +1 -0
  162. package/dist/common/textmeasure-factory.d.ts +33 -0
  163. package/dist/common/textmeasure-factory.d.ts.map +1 -0
  164. package/dist/common/textmeasure-lookup.d.ts +17 -0
  165. package/dist/common/textmeasure-lookup.d.ts.map +1 -0
  166. package/dist/common/textmeasure-lut-data-a.d.ts +13 -0
  167. package/dist/common/textmeasure-lut-data-a.d.ts.map +1 -0
  168. package/dist/common/textmeasure-lut-data-b.d.ts +12 -0
  169. package/dist/common/textmeasure-lut-data-b.d.ts.map +1 -0
  170. package/dist/common/textmeasure-lut-data-c.d.ts +13 -0
  171. package/dist/common/textmeasure-lut-data-c.d.ts.map +1 -0
  172. package/dist/common/textmeasure-lut-data.d.ts +27 -0
  173. package/dist/common/textmeasure-lut-data.d.ts.map +1 -0
  174. package/dist/common/textmeasure.d.ts +120 -0
  175. package/dist/common/textmeasure.d.ts.map +1 -0
  176. package/dist/common/types.d.ts +316 -0
  177. package/dist/common/types.d.ts.map +1 -0
  178. package/dist/common/xlabels-place.d.ts +125 -0
  179. package/dist/common/xlabels-place.d.ts.map +1 -0
  180. package/dist/debug.d.ts +58 -0
  181. package/dist/debug.d.ts.map +1 -0
  182. package/dist/errors.d.ts +63 -0
  183. package/dist/errors.d.ts.map +1 -0
  184. package/dist/gvc/anchor.d.ts +86 -0
  185. package/dist/gvc/anchor.d.ts.map +1 -0
  186. package/dist/gvc/context.d.ts +177 -0
  187. package/dist/gvc/context.d.ts.map +1 -0
  188. package/dist/gvc/default-context.d.ts +20 -0
  189. package/dist/gvc/default-context.d.ts.map +1 -0
  190. package/dist/gvc/device-cluster.d.ts +25 -0
  191. package/dist/gvc/device-cluster.d.ts.map +1 -0
  192. package/dist/gvc/device.d.ts +99 -0
  193. package/dist/gvc/device.d.ts.map +1 -0
  194. package/dist/gvc/edge-labels.d.ts +10 -0
  195. package/dist/gvc/edge-labels.d.ts.map +1 -0
  196. package/dist/gvc/emit-walk.d.ts +22 -0
  197. package/dist/gvc/emit-walk.d.ts.map +1 -0
  198. package/dist/gvc/image-resolver.d.ts +44 -0
  199. package/dist/gvc/image-resolver.d.ts.map +1 -0
  200. package/dist/gvc/job.d.ts +234 -0
  201. package/dist/gvc/job.d.ts.map +1 -0
  202. package/dist/gvc/textlayout.d.ts +33 -0
  203. package/dist/gvc/textlayout.d.ts.map +1 -0
  204. package/dist/gvc/textspan-emit.d.ts +41 -0
  205. package/dist/gvc/textspan-emit.d.ts.map +1 -0
  206. package/dist/gvc/usershape.d.ts +25 -0
  207. package/dist/gvc/usershape.d.ts.map +1 -0
  208. package/dist/gvc/viewport.d.ts +71 -0
  209. package/dist/gvc/viewport.d.ts.map +1 -0
  210. package/dist/index.d.ts +54 -0
  211. package/dist/index.d.ts.map +1 -0
  212. package/dist/index.js +52862 -0
  213. package/dist/index.js.map +7 -0
  214. package/dist/label/index.d.ts +74 -0
  215. package/dist/label/index.d.ts.map +1 -0
  216. package/dist/label/node.d.ts +108 -0
  217. package/dist/label/node.d.ts.map +1 -0
  218. package/dist/label/rectangle.d.ts +60 -0
  219. package/dist/label/rectangle.d.ts.map +1 -0
  220. package/dist/label/split-q.d.ts +13 -0
  221. package/dist/label/split-q.d.ts.map +1 -0
  222. package/dist/label/xlabels-geom.d.ts +46 -0
  223. package/dist/label/xlabels-geom.d.ts.map +1 -0
  224. package/dist/label/xlabels-intersect.d.ts +79 -0
  225. package/dist/label/xlabels-intersect.d.ts.map +1 -0
  226. package/dist/label/xlabels.d.ts +67 -0
  227. package/dist/label/xlabels.d.ts.map +1 -0
  228. package/dist/layout/circo/blockpath.d.ts +120 -0
  229. package/dist/layout/circo/blockpath.d.ts.map +1 -0
  230. package/dist/layout/circo/blocks.d.ts +135 -0
  231. package/dist/layout/circo/blocks.d.ts.map +1 -0
  232. package/dist/layout/circo/blocktree.d.ts +51 -0
  233. package/dist/layout/circo/blocktree.d.ts.map +1 -0
  234. package/dist/layout/circo/circular.d.ts +59 -0
  235. package/dist/layout/circo/circular.d.ts.map +1 -0
  236. package/dist/layout/circo/index.d.ts +35 -0
  237. package/dist/layout/circo/index.d.ts.map +1 -0
  238. package/dist/layout/circo/init.d.ts +50 -0
  239. package/dist/layout/circo/init.d.ts.map +1 -0
  240. package/dist/layout/circo/position-helpers.d.ts +33 -0
  241. package/dist/layout/circo/position-helpers.d.ts.map +1 -0
  242. package/dist/layout/circo/position.d.ts +66 -0
  243. package/dist/layout/circo/position.d.ts.map +1 -0
  244. package/dist/layout/dot/acyclic.d.ts +8 -0
  245. package/dist/layout/dot/acyclic.d.ts.map +1 -0
  246. package/dist/layout/dot/aspect.d.ts +17 -0
  247. package/dist/layout/dot/aspect.d.ts.map +1 -0
  248. package/dist/layout/dot/classify.d.ts +52 -0
  249. package/dist/layout/dot/classify.d.ts.map +1 -0
  250. package/dist/layout/dot/cluster-path.d.ts +38 -0
  251. package/dist/layout/dot/cluster-path.d.ts.map +1 -0
  252. package/dist/layout/dot/cluster.d.ts +102 -0
  253. package/dist/layout/dot/cluster.d.ts.map +1 -0
  254. package/dist/layout/dot/compound-clip.d.ts +69 -0
  255. package/dist/layout/dot/compound-clip.d.ts.map +1 -0
  256. package/dist/layout/dot/compound-geom.d.ts +115 -0
  257. package/dist/layout/dot/compound-geom.d.ts.map +1 -0
  258. package/dist/layout/dot/compound.d.ts +56 -0
  259. package/dist/layout/dot/compound.d.ts.map +1 -0
  260. package/dist/layout/dot/conc.d.ts +88 -0
  261. package/dist/layout/dot/conc.d.ts.map +1 -0
  262. package/dist/layout/dot/decomp.d.ts +66 -0
  263. package/dist/layout/dot/decomp.d.ts.map +1 -0
  264. package/dist/layout/dot/edge-order.d.ts +27 -0
  265. package/dist/layout/dot/edge-order.d.ts.map +1 -0
  266. package/dist/layout/dot/edge-route-arrow.d.ts +46 -0
  267. package/dist/layout/dot/edge-route-arrow.d.ts.map +1 -0
  268. package/dist/layout/dot/edge-route-boxes.d.ts +75 -0
  269. package/dist/layout/dot/edge-route-boxes.d.ts.map +1 -0
  270. package/dist/layout/dot/edge-route-chain.d.ts +67 -0
  271. package/dist/layout/dot/edge-route-chain.d.ts.map +1 -0
  272. package/dist/layout/dot/edge-route-clip.d.ts +88 -0
  273. package/dist/layout/dot/edge-route-clip.d.ts.map +1 -0
  274. package/dist/layout/dot/edge-route-faithful.d.ts +94 -0
  275. package/dist/layout/dot/edge-route-faithful.d.ts.map +1 -0
  276. package/dist/layout/dot/edge-route-geom.d.ts +43 -0
  277. package/dist/layout/dot/edge-route-geom.d.ts.map +1 -0
  278. package/dist/layout/dot/edge-route-helpers.d.ts +50 -0
  279. package/dist/layout/dot/edge-route-helpers.d.ts.map +1 -0
  280. package/dist/layout/dot/edge-route-poly.d.ts +48 -0
  281. package/dist/layout/dot/edge-route-poly.d.ts.map +1 -0
  282. package/dist/layout/dot/edge-route-rank.d.ts +57 -0
  283. package/dist/layout/dot/edge-route-rank.d.ts.map +1 -0
  284. package/dist/layout/dot/edge-route-routing.d.ts +99 -0
  285. package/dist/layout/dot/edge-route-routing.d.ts.map +1 -0
  286. package/dist/layout/dot/edge-route.d.ts +57 -0
  287. package/dist/layout/dot/edge-route.d.ts.map +1 -0
  288. package/dist/layout/dot/fastgr.d.ts +147 -0
  289. package/dist/layout/dot/fastgr.d.ts.map +1 -0
  290. package/dist/layout/dot/flat-utils.d.ts +21 -0
  291. package/dist/layout/dot/flat-utils.d.ts.map +1 -0
  292. package/dist/layout/dot/flat.d.ts +152 -0
  293. package/dist/layout/dot/flat.d.ts.map +1 -0
  294. package/dist/layout/dot/graph-label.d.ts +18 -0
  295. package/dist/layout/dot/graph-label.d.ts.map +1 -0
  296. package/dist/layout/dot/index.d.ts +128 -0
  297. package/dist/layout/dot/index.d.ts.map +1 -0
  298. package/dist/layout/dot/init.d.ts +93 -0
  299. package/dist/layout/dot/init.d.ts.map +1 -0
  300. package/dist/layout/dot/label-order.d.ts +45 -0
  301. package/dist/layout/dot/label-order.d.ts.map +1 -0
  302. package/dist/layout/dot/mincross-build.d.ts +52 -0
  303. package/dist/layout/dot/mincross-build.d.ts.map +1 -0
  304. package/dist/layout/dot/mincross-cross.d.ts +80 -0
  305. package/dist/layout/dot/mincross-cross.d.ts.map +1 -0
  306. package/dist/layout/dot/mincross-flat.d.ts +27 -0
  307. package/dist/layout/dot/mincross-flat.d.ts.map +1 -0
  308. package/dist/layout/dot/mincross-order.d.ts +89 -0
  309. package/dist/layout/dot/mincross-order.d.ts.map +1 -0
  310. package/dist/layout/dot/mincross-utils.d.ts +60 -0
  311. package/dist/layout/dot/mincross-utils.d.ts.map +1 -0
  312. package/dist/layout/dot/mincross.d.ts +75 -0
  313. package/dist/layout/dot/mincross.d.ts.map +1 -0
  314. package/dist/layout/dot/ns-core.d.ts +37 -0
  315. package/dist/layout/dot/ns-core.d.ts.map +1 -0
  316. package/dist/layout/dot/ns-range.d.ts +17 -0
  317. package/dist/layout/dot/ns-range.d.ts.map +1 -0
  318. package/dist/layout/dot/ns-subtree.d.ts +78 -0
  319. package/dist/layout/dot/ns-subtree.d.ts.map +1 -0
  320. package/dist/layout/dot/ns.d.ts +86 -0
  321. package/dist/layout/dot/ns.d.ts.map +1 -0
  322. package/dist/layout/dot/ortho-adapter.d.ts +19 -0
  323. package/dist/layout/dot/ortho-adapter.d.ts.map +1 -0
  324. package/dist/layout/dot/pack-components.d.ts +100 -0
  325. package/dist/layout/dot/pack-components.d.ts.map +1 -0
  326. package/dist/layout/dot/position-aux.d.ts +110 -0
  327. package/dist/layout/dot/position-aux.d.ts.map +1 -0
  328. package/dist/layout/dot/position-bbox.d.ts +57 -0
  329. package/dist/layout/dot/position-bbox.d.ts.map +1 -0
  330. package/dist/layout/dot/position-cluster.d.ts +48 -0
  331. package/dist/layout/dot/position-cluster.d.ts.map +1 -0
  332. package/dist/layout/dot/position-ycoords.d.ts +42 -0
  333. package/dist/layout/dot/position-ycoords.d.ts.map +1 -0
  334. package/dist/layout/dot/position.d.ts +47 -0
  335. package/dist/layout/dot/position.d.ts.map +1 -0
  336. package/dist/layout/dot/rank-dot2.d.ts +114 -0
  337. package/dist/layout/dot/rank-dot2.d.ts.map +1 -0
  338. package/dist/layout/dot/rank.d.ts +119 -0
  339. package/dist/layout/dot/rank.d.ts.map +1 -0
  340. package/dist/layout/dot/sameport.d.ts +70 -0
  341. package/dist/layout/dot/sameport.d.ts.map +1 -0
  342. package/dist/layout/dot/self-loop.d.ts +54 -0
  343. package/dist/layout/dot/self-loop.d.ts.map +1 -0
  344. package/dist/layout/dot/splines-clone.d.ts +33 -0
  345. package/dist/layout/dot/splines-clone.d.ts.map +1 -0
  346. package/dist/layout/dot/splines-flat-labeled.d.ts +101 -0
  347. package/dist/layout/dot/splines-flat-labeled.d.ts.map +1 -0
  348. package/dist/layout/dot/splines-flat-multi.d.ts +35 -0
  349. package/dist/layout/dot/splines-flat-multi.d.ts.map +1 -0
  350. package/dist/layout/dot/splines-flat.d.ts +116 -0
  351. package/dist/layout/dot/splines-flat.d.ts.map +1 -0
  352. package/dist/layout/dot/splines-groups.d.ts +38 -0
  353. package/dist/layout/dot/splines-groups.d.ts.map +1 -0
  354. package/dist/layout/dot/splines-label.d.ts +105 -0
  355. package/dist/layout/dot/splines-label.d.ts.map +1 -0
  356. package/dist/layout/dot/splines-route-type.d.ts +28 -0
  357. package/dist/layout/dot/splines-route-type.d.ts.map +1 -0
  358. package/dist/layout/dot/splines-route.d.ts +99 -0
  359. package/dist/layout/dot/splines-route.d.ts.map +1 -0
  360. package/dist/layout/dot/splines.d.ts +157 -0
  361. package/dist/layout/dot/splines.d.ts.map +1 -0
  362. package/dist/layout/dot/straight-edges.d.ts +39 -0
  363. package/dist/layout/dot/straight-edges.d.ts.map +1 -0
  364. package/dist/layout/fdp/cluster-edges.d.ts +31 -0
  365. package/dist/layout/fdp/cluster-edges.d.ts.map +1 -0
  366. package/dist/layout/fdp/comp.d.ts +29 -0
  367. package/dist/layout/fdp/comp.d.ts.map +1 -0
  368. package/dist/layout/fdp/derive.d.ts +39 -0
  369. package/dist/layout/fdp/derive.d.ts.map +1 -0
  370. package/dist/layout/fdp/fdp-model.d.ts +101 -0
  371. package/dist/layout/fdp/fdp-model.d.ts.map +1 -0
  372. package/dist/layout/fdp/grid.d.ts +49 -0
  373. package/dist/layout/fdp/grid.d.ts.map +1 -0
  374. package/dist/layout/fdp/index.d.ts +36 -0
  375. package/dist/layout/fdp/index.d.ts.map +1 -0
  376. package/dist/layout/fdp/init.d.ts +26 -0
  377. package/dist/layout/fdp/init.d.ts.map +1 -0
  378. package/dist/layout/fdp/layout.d.ts +57 -0
  379. package/dist/layout/fdp/layout.d.ts.map +1 -0
  380. package/dist/layout/fdp/normalize.d.ts +18 -0
  381. package/dist/layout/fdp/normalize.d.ts.map +1 -0
  382. package/dist/layout/fdp/ports.d.ts +41 -0
  383. package/dist/layout/fdp/ports.d.ts.map +1 -0
  384. package/dist/layout/fdp/tlayout-init.d.ts +21 -0
  385. package/dist/layout/fdp/tlayout-init.d.ts.map +1 -0
  386. package/dist/layout/fdp/tlayout-parms.d.ts +98 -0
  387. package/dist/layout/fdp/tlayout-parms.d.ts.map +1 -0
  388. package/dist/layout/fdp/tlayout.d.ts +43 -0
  389. package/dist/layout/fdp/tlayout.d.ts.map +1 -0
  390. package/dist/layout/fdp/xlayout.d.ts +26 -0
  391. package/dist/layout/fdp/xlayout.d.ts.map +1 -0
  392. package/dist/layout/neato/bfs.d.ts +43 -0
  393. package/dist/layout/neato/bfs.d.ts.map +1 -0
  394. package/dist/layout/neato/cdt-surface.d.ts +16 -0
  395. package/dist/layout/neato/cdt-surface.d.ts.map +1 -0
  396. package/dist/layout/neato/conjgrad.d.ts +61 -0
  397. package/dist/layout/neato/conjgrad.d.ts.map +1 -0
  398. package/dist/layout/neato/delaunay.d.ts +28 -0
  399. package/dist/layout/neato/delaunay.d.ts.map +1 -0
  400. package/dist/layout/neato/dijkstra.d.ts +80 -0
  401. package/dist/layout/neato/dijkstra.d.ts.map +1 -0
  402. package/dist/layout/neato/fdp-adjust.d.ts +31 -0
  403. package/dist/layout/neato/fdp-adjust.d.ts.map +1 -0
  404. package/dist/layout/neato/index.d.ts +58 -0
  405. package/dist/layout/neato/index.d.ts.map +1 -0
  406. package/dist/layout/neato/init.d.ts +207 -0
  407. package/dist/layout/neato/init.d.ts.map +1 -0
  408. package/dist/layout/neato/legal.d.ts +7 -0
  409. package/dist/layout/neato/legal.d.ts.map +1 -0
  410. package/dist/layout/neato/matrix-ops.d.ts +28 -0
  411. package/dist/layout/neato/matrix-ops.d.ts.map +1 -0
  412. package/dist/layout/neato/multispline-router.d.ts +80 -0
  413. package/dist/layout/neato/multispline-router.d.ts.map +1 -0
  414. package/dist/layout/neato/multispline.d.ts +24 -0
  415. package/dist/layout/neato/multispline.d.ts.map +1 -0
  416. package/dist/layout/neato/overlap-prism.d.ts +26 -0
  417. package/dist/layout/neato/overlap-prism.d.ts.map +1 -0
  418. package/dist/layout/neato/overlap.d.ts +85 -0
  419. package/dist/layout/neato/overlap.d.ts.map +1 -0
  420. package/dist/layout/neato/sc-adjust.d.ts +33 -0
  421. package/dist/layout/neato/sc-adjust.d.ts.map +1 -0
  422. package/dist/layout/neato/sep-factor.d.ts +41 -0
  423. package/dist/layout/neato/sep-factor.d.ts.map +1 -0
  424. package/dist/layout/neato/set-aspect.d.ts +33 -0
  425. package/dist/layout/neato/set-aspect.d.ts.map +1 -0
  426. package/dist/layout/neato/sgd.d.ts +166 -0
  427. package/dist/layout/neato/sgd.d.ts.map +1 -0
  428. package/dist/layout/neato/splines.d.ts +153 -0
  429. package/dist/layout/neato/splines.d.ts.map +1 -0
  430. package/dist/layout/neato/stress-kernel.d.ts +53 -0
  431. package/dist/layout/neato/stress-kernel.d.ts.map +1 -0
  432. package/dist/layout/neato/stress.d.ts +158 -0
  433. package/dist/layout/neato/stress.d.ts.map +1 -0
  434. package/dist/layout/osage/index.d.ts +158 -0
  435. package/dist/layout/osage/index.d.ts.map +1 -0
  436. package/dist/layout/osage/layout.d.ts +49 -0
  437. package/dist/layout/osage/layout.d.ts.map +1 -0
  438. package/dist/layout/osage/types.d.ts +28 -0
  439. package/dist/layout/osage/types.d.ts.map +1 -0
  440. package/dist/layout/pack/array-pack.d.ts +114 -0
  441. package/dist/layout/pack/array-pack.d.ts.map +1 -0
  442. package/dist/layout/pack/index.d.ts +157 -0
  443. package/dist/layout/pack/index.d.ts.map +1 -0
  444. package/dist/layout/pack/poly-pack.d.ts +126 -0
  445. package/dist/layout/pack/poly-pack.d.ts.map +1 -0
  446. package/dist/layout/pack/poly-place.d.ts +27 -0
  447. package/dist/layout/pack/poly-place.d.ts.map +1 -0
  448. package/dist/layout/pack/spiral-search.d.ts +18 -0
  449. package/dist/layout/pack/spiral-search.d.ts.map +1 -0
  450. package/dist/layout/pack/test-helpers.d.ts +7 -0
  451. package/dist/layout/pack/test-helpers.d.ts.map +1 -0
  452. package/dist/layout/pack/types.d.ts +74 -0
  453. package/dist/layout/pack/types.d.ts.map +1 -0
  454. package/dist/layout/patchwork/index.d.ts +136 -0
  455. package/dist/layout/patchwork/index.d.ts.map +1 -0
  456. package/dist/layout/patchwork/tree-map.d.ts +32 -0
  457. package/dist/layout/patchwork/tree-map.d.ts.map +1 -0
  458. package/dist/layout/patchwork/tree-node.d.ts +46 -0
  459. package/dist/layout/patchwork/tree-node.d.ts.map +1 -0
  460. package/dist/layout/sfdp/index.d.ts +39 -0
  461. package/dist/layout/sfdp/index.d.ts.map +1 -0
  462. package/dist/layout/sfdp/init.d.ts +61 -0
  463. package/dist/layout/sfdp/init.d.ts.map +1 -0
  464. package/dist/layout/sfdp/multilevel.d.ts +23 -0
  465. package/dist/layout/sfdp/multilevel.d.ts.map +1 -0
  466. package/dist/layout/sfdp/quadtree.d.ts +45 -0
  467. package/dist/layout/sfdp/quadtree.d.ts.map +1 -0
  468. package/dist/layout/sfdp/sparse-matrix-multiply.d.ts +34 -0
  469. package/dist/layout/sfdp/sparse-matrix-multiply.d.ts.map +1 -0
  470. package/dist/layout/sfdp/sparse-matrix.d.ts +101 -0
  471. package/dist/layout/sfdp/sparse-matrix.d.ts.map +1 -0
  472. package/dist/layout/sfdp/sparse-solve.d.ts +14 -0
  473. package/dist/layout/sfdp/sparse-solve.d.ts.map +1 -0
  474. package/dist/layout/sfdp/spring-driver.d.ts +18 -0
  475. package/dist/layout/sfdp/spring-driver.d.ts.map +1 -0
  476. package/dist/layout/sfdp/spring-electrical.d.ts +61 -0
  477. package/dist/layout/sfdp/spring-electrical.d.ts.map +1 -0
  478. package/dist/layout/twopi/circle.d.ts +83 -0
  479. package/dist/layout/twopi/circle.d.ts.map +1 -0
  480. package/dist/layout/twopi/index.d.ts +24 -0
  481. package/dist/layout/twopi/index.d.ts.map +1 -0
  482. package/dist/layout/twopi/init.d.ts +85 -0
  483. package/dist/layout/twopi/init.d.ts.map +1 -0
  484. package/dist/layout/twopi/pipeline.d.ts +37 -0
  485. package/dist/layout/twopi/pipeline.d.ts.map +1 -0
  486. package/dist/layout/twopi/twopi-test-helpers.d.ts +12 -0
  487. package/dist/layout/twopi/twopi-test-helpers.d.ts.map +1 -0
  488. package/dist/model/algData.d.ts +175 -0
  489. package/dist/model/algData.d.ts.map +1 -0
  490. package/dist/model/cgraph-ops.d.ts +86 -0
  491. package/dist/model/cgraph-ops.d.ts.map +1 -0
  492. package/dist/model/edge.d.ts +80 -0
  493. package/dist/model/edge.d.ts.map +1 -0
  494. package/dist/model/edgeInfo.d.ts +299 -0
  495. package/dist/model/edgeInfo.d.ts.map +1 -0
  496. package/dist/model/geom.d.ts +149 -0
  497. package/dist/model/geom.d.ts.map +1 -0
  498. package/dist/model/graph.d.ts +135 -0
  499. package/dist/model/graph.d.ts.map +1 -0
  500. package/dist/model/graphInfo.d.ts +418 -0
  501. package/dist/model/graphInfo.d.ts.map +1 -0
  502. package/dist/model/index.d.ts +10 -0
  503. package/dist/model/index.d.ts.map +1 -0
  504. package/dist/model/layoutParams.d.ts +85 -0
  505. package/dist/model/layoutParams.d.ts.map +1 -0
  506. package/dist/model/node.d.ts +101 -0
  507. package/dist/model/node.d.ts.map +1 -0
  508. package/dist/model/nodeInfo.d.ts +278 -0
  509. package/dist/model/nodeInfo.d.ts.map +1 -0
  510. package/dist/model/rankEntry.d.ts +80 -0
  511. package/dist/model/rankEntry.d.ts.map +1 -0
  512. package/dist/ortho/chan-dict.d.ts +82 -0
  513. package/dist/ortho/chan-dict.d.ts.map +1 -0
  514. package/dist/ortho/fpq.d.ts +54 -0
  515. package/dist/ortho/fpq.d.ts.map +1 -0
  516. package/dist/ortho/index.d.ts +35 -0
  517. package/dist/ortho/index.d.ts.map +1 -0
  518. package/dist/ortho/maze-channels.d.ts +47 -0
  519. package/dist/ortho/maze-channels.d.ts.map +1 -0
  520. package/dist/ortho/maze.d.ts +27 -0
  521. package/dist/ortho/maze.d.ts.map +1 -0
  522. package/dist/ortho/ortho-parallel.d.ts +26 -0
  523. package/dist/ortho/ortho-parallel.d.ts.map +1 -0
  524. package/dist/ortho/ortho-route.d.ts +31 -0
  525. package/dist/ortho/ortho-route.d.ts.map +1 -0
  526. package/dist/ortho/partition.d.ts +34 -0
  527. package/dist/ortho/partition.d.ts.map +1 -0
  528. package/dist/ortho/rawgraph.d.ts +41 -0
  529. package/dist/ortho/rawgraph.d.ts.map +1 -0
  530. package/dist/ortho/sgraph.d.ts +74 -0
  531. package/dist/ortho/sgraph.d.ts.map +1 -0
  532. package/dist/ortho/trap-query.d.ts +32 -0
  533. package/dist/ortho/trap-query.d.ts.map +1 -0
  534. package/dist/ortho/trap-segment.d.ts +23 -0
  535. package/dist/ortho/trap-segment.d.ts.map +1 -0
  536. package/dist/ortho/trap-types.d.ts +91 -0
  537. package/dist/ortho/trap-types.d.ts.map +1 -0
  538. package/dist/ortho/trap-update.d.ts +12 -0
  539. package/dist/ortho/trap-update.d.ts.map +1 -0
  540. package/dist/ortho/trapezoid.d.ts +18 -0
  541. package/dist/ortho/trapezoid.d.ts.map +1 -0
  542. package/dist/ortho/types.d.ts +241 -0
  543. package/dist/ortho/types.d.ts.map +1 -0
  544. package/dist/parser/ast.d.ts +49 -0
  545. package/dist/parser/ast.d.ts.map +1 -0
  546. package/dist/parser/builder.d.ts +75 -0
  547. package/dist/parser/builder.d.ts.map +1 -0
  548. package/dist/parser/index.d.ts +97 -0
  549. package/dist/parser/index.d.ts.map +1 -0
  550. package/dist/pathplan/index.d.ts +8 -0
  551. package/dist/pathplan/index.d.ts.map +1 -0
  552. package/dist/pathplan/route.d.ts +9 -0
  553. package/dist/pathplan/route.d.ts.map +1 -0
  554. package/dist/pathplan/shortest.d.ts +5 -0
  555. package/dist/pathplan/shortest.d.ts.map +1 -0
  556. package/dist/pathplan/solvers.d.ts +5 -0
  557. package/dist/pathplan/solvers.d.ts.map +1 -0
  558. package/dist/pathplan/triang.d.ts +25 -0
  559. package/dist/pathplan/triang.d.ts.map +1 -0
  560. package/dist/pathplan/types.d.ts +22 -0
  561. package/dist/pathplan/types.d.ts.map +1 -0
  562. package/dist/pathplan/visibility.d.ts +13 -0
  563. package/dist/pathplan/visibility.d.ts.map +1 -0
  564. package/dist/pathplan/vispath.d.ts +9 -0
  565. package/dist/pathplan/vispath.d.ts.map +1 -0
  566. package/dist/rbtree/index.d.ts +127 -0
  567. package/dist/rbtree/index.d.ts.map +1 -0
  568. package/dist/render/color-resolve.d.ts +38 -0
  569. package/dist/render/color-resolve.d.ts.map +1 -0
  570. package/dist/render/dot.d.ts +379 -0
  571. package/dist/render/dot.d.ts.map +1 -0
  572. package/dist/render/index.d.ts +24 -0
  573. package/dist/render/index.d.ts.map +1 -0
  574. package/dist/render/json.d.ts +89 -0
  575. package/dist/render/json.d.ts.map +1 -0
  576. package/dist/render/map-test-helpers.d.ts +13 -0
  577. package/dist/render/map-test-helpers.d.ts.map +1 -0
  578. package/dist/render/map.d.ts +197 -0
  579. package/dist/render/map.d.ts.map +1 -0
  580. package/dist/render/public.d.ts +64 -0
  581. package/dist/render/public.d.ts.map +1 -0
  582. package/dist/render/svg-arrow-ops.d.ts +10 -0
  583. package/dist/render/svg-arrow-ops.d.ts.map +1 -0
  584. package/dist/render/svg-cluster.d.ts +9 -0
  585. package/dist/render/svg-cluster.d.ts.map +1 -0
  586. package/dist/render/svg-edge-ortho-radius.d.ts +31 -0
  587. package/dist/render/svg-edge-ortho-radius.d.ts.map +1 -0
  588. package/dist/render/svg-edge-split.d.ts +48 -0
  589. package/dist/render/svg-edge-split.d.ts.map +1 -0
  590. package/dist/render/svg-gradient.d.ts +46 -0
  591. package/dist/render/svg-gradient.d.ts.map +1 -0
  592. package/dist/render/svg-graph.d.ts +97 -0
  593. package/dist/render/svg-graph.d.ts.map +1 -0
  594. package/dist/render/svg-helpers.d.ts +122 -0
  595. package/dist/render/svg-helpers.d.ts.map +1 -0
  596. package/dist/render/svg-id.d.ts +28 -0
  597. package/dist/render/svg-id.d.ts.map +1 -0
  598. package/dist/render/svg-multicolor.d.ts +60 -0
  599. package/dist/render/svg-multicolor.d.ts.map +1 -0
  600. package/dist/render/svg-parallel-edge.d.ts +28 -0
  601. package/dist/render/svg-parallel-edge.d.ts.map +1 -0
  602. package/dist/render/svg-tapered-edge.d.ts +18 -0
  603. package/dist/render/svg-tapered-edge.d.ts.map +1 -0
  604. package/dist/render/svg.d.ts +104 -0
  605. package/dist/render/svg.d.ts.map +1 -0
  606. package/dist/render/xdot-public.d.ts +95 -0
  607. package/dist/render/xdot-public.d.ts.map +1 -0
  608. package/dist/render/xml-escape.d.ts +21 -0
  609. package/dist/render/xml-escape.d.ts.map +1 -0
  610. package/dist/render.js +52556 -0
  611. package/dist/render.js.map +7 -0
  612. package/dist/util/agxbuf.d.ts +72 -0
  613. package/dist/util/agxbuf.d.ts.map +1 -0
  614. package/dist/util/bsd-qsort.d.ts +22 -0
  615. package/dist/util/bsd-qsort.d.ts.map +1 -0
  616. package/dist/util/index.d.ts +11 -0
  617. package/dist/util/index.d.ts.map +1 -0
  618. package/dist/util/list.d.ts +47 -0
  619. package/dist/util/list.d.ts.map +1 -0
  620. package/dist/util/math.d.ts +54 -0
  621. package/dist/util/math.d.ts.map +1 -0
  622. package/dist/util/mt19937.d.ts +40 -0
  623. package/dist/util/mt19937.d.ts.map +1 -0
  624. package/dist/util/printf-round.d.ts +45 -0
  625. package/dist/util/printf-round.d.ts.map +1 -0
  626. package/dist/util/xml.d.ts +24 -0
  627. package/dist/util/xml.d.ts.map +1 -0
  628. package/dist/vpsc/Block.d.ts +116 -0
  629. package/dist/vpsc/Block.d.ts.map +1 -0
  630. package/dist/vpsc/Blocks.d.ts +66 -0
  631. package/dist/vpsc/Blocks.d.ts.map +1 -0
  632. package/dist/vpsc/Constraint.d.ts +51 -0
  633. package/dist/vpsc/Constraint.d.ts.map +1 -0
  634. package/dist/vpsc/HeapUtils.d.ts +37 -0
  635. package/dist/vpsc/HeapUtils.d.ts.map +1 -0
  636. package/dist/vpsc/Solver.d.ts +107 -0
  637. package/dist/vpsc/Solver.d.ts.map +1 -0
  638. package/dist/vpsc/SweepLine.d.ts +38 -0
  639. package/dist/vpsc/SweepLine.d.ts.map +1 -0
  640. package/dist/vpsc/Variable.d.ts +38 -0
  641. package/dist/vpsc/Variable.d.ts.map +1 -0
  642. package/dist/vpsc/index.d.ts +54 -0
  643. package/dist/vpsc/index.d.ts.map +1 -0
  644. package/dist/vpsc/sweepTypes.d.ts +29 -0
  645. package/dist/vpsc/sweepTypes.d.ts.map +1 -0
  646. package/dist/xdot/index.d.ts +6 -0
  647. package/dist/xdot/index.d.ts.map +1 -0
  648. package/dist/xdot/lex.d.ts +22 -0
  649. package/dist/xdot/lex.d.ts.map +1 -0
  650. package/dist/xdot/misc.d.ts +13 -0
  651. package/dist/xdot/misc.d.ts.map +1 -0
  652. package/dist/xdot/parse.d.ts +21 -0
  653. package/dist/xdot/parse.d.ts.map +1 -0
  654. package/dist/xdot/types.d.ts +152 -0
  655. package/dist/xdot/types.d.ts.map +1 -0
  656. package/package.json +113 -0
  657. package/src/api/builder.ts +277 -0
  658. package/src/api/edge-ops.ts +113 -0
  659. package/src/api/geometry.ts +307 -0
  660. package/src/api/index.ts +46 -0
  661. package/src/cdt/bag.ts +196 -0
  662. package/src/cdt/hash-core.ts +84 -0
  663. package/src/cdt/hash.ts +207 -0
  664. package/src/cdt/index.ts +17 -0
  665. package/src/cdt/splay-core.ts +301 -0
  666. package/src/cdt/splay.ts +191 -0
  667. package/src/cdt/strhash.ts +52 -0
  668. package/src/cdt/types.ts +13 -0
  669. package/src/common/arith.ts +39 -0
  670. package/src/common/arm-pow-data.ts +201 -0
  671. package/src/common/arm-pow.ts +296 -0
  672. package/src/common/arrows-constants.ts +175 -0
  673. package/src/common/arrows-geometry.ts +62 -0
  674. package/src/common/arrows-miter.ts +84 -0
  675. package/src/common/arrows-shapes-poly.ts +241 -0
  676. package/src/common/arrows-shapes-util.ts +162 -0
  677. package/src/common/arrows-shapes.ts +360 -0
  678. package/src/common/arrows-types.ts +59 -0
  679. package/src/common/arrows.ts +209 -0
  680. package/src/common/color.ts +340 -0
  681. package/src/common/colorData.ts +264 -0
  682. package/src/common/compass-port.ts +384 -0
  683. package/src/common/crand.ts +79 -0
  684. package/src/common/edge-label-init.ts +310 -0
  685. package/src/common/edge-offset.ts +140 -0
  686. package/src/common/ellipse-wedge.ts +189 -0
  687. package/src/common/emit-types.ts +332 -0
  688. package/src/common/fma.ts +52 -0
  689. package/src/common/graph-init.ts +359 -0
  690. package/src/common/html-entities.ts +299 -0
  691. package/src/common/html-string.ts +22 -0
  692. package/src/common/htmltable-emit-fill.ts +367 -0
  693. package/src/common/htmltable-emit-rules.ts +293 -0
  694. package/src/common/htmltable-emit.ts +345 -0
  695. package/src/common/htmltable-lex.ts +138 -0
  696. package/src/common/htmltable-parse.ts +539 -0
  697. package/src/common/htmltable-port.ts +32 -0
  698. package/src/common/htmltable-pos-runs.ts +313 -0
  699. package/src/common/htmltable-pos.ts +601 -0
  700. package/src/common/htmltable-types.ts +262 -0
  701. package/src/common/htmltable.ts +477 -0
  702. package/src/common/layers.ts +113 -0
  703. package/src/common/make-label.ts +192 -0
  704. package/src/common/multicolor.ts +167 -0
  705. package/src/common/nodeinit.ts +339 -0
  706. package/src/common/poly-gencode.ts +475 -0
  707. package/src/common/poly-init.ts +133 -0
  708. package/src/common/poly-inside.ts +202 -0
  709. package/src/common/poly-shapes-cases.ts +253 -0
  710. package/src/common/poly-shapes-cases2.ts +170 -0
  711. package/src/common/poly-shapes-util.ts +124 -0
  712. package/src/common/poly-shapes.ts +181 -0
  713. package/src/common/poly-sizing.ts +639 -0
  714. package/src/common/poly-vertices.ts +237 -0
  715. package/src/common/postproc.ts +436 -0
  716. package/src/common/ps-fontalias.ts +112 -0
  717. package/src/common/random.ts +37 -0
  718. package/src/common/record-port.ts +89 -0
  719. package/src/common/record.ts +523 -0
  720. package/src/common/shapeData.ts +502 -0
  721. package/src/common/shapes.ts +187 -0
  722. package/src/common/spline-midpoint.ts +105 -0
  723. package/src/common/splines-clip.ts +449 -0
  724. package/src/common/splines-constants.ts +53 -0
  725. package/src/common/splines-geom.ts +194 -0
  726. package/src/common/splines-path-begin.ts +243 -0
  727. package/src/common/splines-path-end.ts +231 -0
  728. package/src/common/splines-path-shared.ts +258 -0
  729. package/src/common/splines-routespl.ts +444 -0
  730. package/src/common/splines-selfedge.ts +403 -0
  731. package/src/common/splines.ts +33 -0
  732. package/src/common/style-resolve.ts +481 -0
  733. package/src/common/subst.ts +126 -0
  734. package/src/common/taper.ts +219 -0
  735. package/src/common/textmeasure-factory.ts +86 -0
  736. package/src/common/textmeasure-lookup.ts +50 -0
  737. package/src/common/textmeasure-lut-data-a.ts +182 -0
  738. package/src/common/textmeasure-lut-data-b.ts +140 -0
  739. package/src/common/textmeasure-lut-data-c.ts +221 -0
  740. package/src/common/textmeasure-lut-data.ts +78 -0
  741. package/src/common/textmeasure.ts +321 -0
  742. package/src/common/types.ts +425 -0
  743. package/src/common/xlabels-place.ts +475 -0
  744. package/src/debug.ts +38 -0
  745. package/src/errors.ts +95 -0
  746. package/src/gvc/anchor.ts +530 -0
  747. package/src/gvc/context.ts +260 -0
  748. package/src/gvc/default-context.ts +70 -0
  749. package/src/gvc/device-cluster.ts +114 -0
  750. package/src/gvc/device.ts +598 -0
  751. package/src/gvc/edge-labels.ts +116 -0
  752. package/src/gvc/emit-walk.ts +98 -0
  753. package/src/gvc/image-resolver.ts +137 -0
  754. package/src/gvc/job.ts +401 -0
  755. package/src/gvc/textlayout.ts +44 -0
  756. package/src/gvc/textspan-emit.ts +100 -0
  757. package/src/gvc/usershape.ts +33 -0
  758. package/src/gvc/viewport.ts +203 -0
  759. package/src/index.ts +165 -0
  760. package/src/label/index.ts +302 -0
  761. package/src/label/node.ts +278 -0
  762. package/src/label/rectangle.ts +123 -0
  763. package/src/label/split-q.ts +237 -0
  764. package/src/label/xlabels-geom.ts +132 -0
  765. package/src/label/xlabels-intersect.ts +421 -0
  766. package/src/label/xlabels.ts +212 -0
  767. package/src/layout/circo/blockpath.ts +560 -0
  768. package/src/layout/circo/blocks.ts +234 -0
  769. package/src/layout/circo/blocktree.ts +246 -0
  770. package/src/layout/circo/circular.ts +227 -0
  771. package/src/layout/circo/index.ts +90 -0
  772. package/src/layout/circo/init.ts +84 -0
  773. package/src/layout/circo/position-helpers.ts +104 -0
  774. package/src/layout/circo/position.ts +196 -0
  775. package/src/layout/dot/__fixtures__/xcoord-pivot-divergence.gv +79 -0
  776. package/src/layout/dot/acyclic.ts +60 -0
  777. package/src/layout/dot/aspect.ts +22 -0
  778. package/src/layout/dot/classify.ts +462 -0
  779. package/src/layout/dot/cluster-path.ts +200 -0
  780. package/src/layout/dot/cluster.ts +480 -0
  781. package/src/layout/dot/compound-clip.ts +224 -0
  782. package/src/layout/dot/compound-geom.ts +282 -0
  783. package/src/layout/dot/compound.ts +294 -0
  784. package/src/layout/dot/conc.ts +433 -0
  785. package/src/layout/dot/decomp.ts +165 -0
  786. package/src/layout/dot/edge-order.ts +62 -0
  787. package/src/layout/dot/edge-route-arrow.ts +87 -0
  788. package/src/layout/dot/edge-route-boxes.ts +99 -0
  789. package/src/layout/dot/edge-route-chain.ts +420 -0
  790. package/src/layout/dot/edge-route-clip.ts +253 -0
  791. package/src/layout/dot/edge-route-faithful.ts +404 -0
  792. package/src/layout/dot/edge-route-geom.ts +90 -0
  793. package/src/layout/dot/edge-route-helpers.ts +170 -0
  794. package/src/layout/dot/edge-route-poly.ts +174 -0
  795. package/src/layout/dot/edge-route-rank.ts +136 -0
  796. package/src/layout/dot/edge-route-routing.ts +219 -0
  797. package/src/layout/dot/edge-route.ts +490 -0
  798. package/src/layout/dot/fastgr.ts +377 -0
  799. package/src/layout/dot/flat-utils.ts +52 -0
  800. package/src/layout/dot/flat.ts +518 -0
  801. package/src/layout/dot/graph-label.ts +114 -0
  802. package/src/layout/dot/index.ts +302 -0
  803. package/src/layout/dot/init.ts +300 -0
  804. package/src/layout/dot/label-order.ts +161 -0
  805. package/src/layout/dot/mincross-build.ts +373 -0
  806. package/src/layout/dot/mincross-cross.ts +409 -0
  807. package/src/layout/dot/mincross-flat.ts +213 -0
  808. package/src/layout/dot/mincross-order.ts +401 -0
  809. package/src/layout/dot/mincross-utils.ts +170 -0
  810. package/src/layout/dot/mincross.ts +386 -0
  811. package/src/layout/dot/ns-core.ts +122 -0
  812. package/src/layout/dot/ns-range.ts +228 -0
  813. package/src/layout/dot/ns-subtree.ts +347 -0
  814. package/src/layout/dot/ns.ts +506 -0
  815. package/src/layout/dot/ortho-adapter.ts +133 -0
  816. package/src/layout/dot/pack-components.ts +433 -0
  817. package/src/layout/dot/position-aux.ts +382 -0
  818. package/src/layout/dot/position-bbox.ts +221 -0
  819. package/src/layout/dot/position-cluster.ts +286 -0
  820. package/src/layout/dot/position-ycoords.ts +287 -0
  821. package/src/layout/dot/position.ts +194 -0
  822. package/src/layout/dot/rank-dot2.ts +528 -0
  823. package/src/layout/dot/rank.ts +547 -0
  824. package/src/layout/dot/sameport.ts +278 -0
  825. package/src/layout/dot/self-loop.ts +147 -0
  826. package/src/layout/dot/splines-clone.ts +121 -0
  827. package/src/layout/dot/splines-flat-labeled.ts +408 -0
  828. package/src/layout/dot/splines-flat-multi.ts +188 -0
  829. package/src/layout/dot/splines-flat.ts +598 -0
  830. package/src/layout/dot/splines-groups.ts +190 -0
  831. package/src/layout/dot/splines-label.ts +432 -0
  832. package/src/layout/dot/splines-route-type.ts +44 -0
  833. package/src/layout/dot/splines-route.ts +478 -0
  834. package/src/layout/dot/splines.ts +538 -0
  835. package/src/layout/dot/straight-edges.ts +332 -0
  836. package/src/layout/fdp/cluster-edges.ts +0 -0
  837. package/src/layout/fdp/comp.ts +160 -0
  838. package/src/layout/fdp/derive.ts +272 -0
  839. package/src/layout/fdp/fdp-model.ts +238 -0
  840. package/src/layout/fdp/grid.ts +77 -0
  841. package/src/layout/fdp/index.ts +113 -0
  842. package/src/layout/fdp/init.ts +116 -0
  843. package/src/layout/fdp/layout.ts +485 -0
  844. package/src/layout/fdp/normalize.ts +100 -0
  845. package/src/layout/fdp/ports.ts +161 -0
  846. package/src/layout/fdp/tlayout-init.ts +230 -0
  847. package/src/layout/fdp/tlayout-parms.ts +234 -0
  848. package/src/layout/fdp/tlayout.ts +317 -0
  849. package/src/layout/fdp/xlayout.ts +350 -0
  850. package/src/layout/neato/bfs.ts +131 -0
  851. package/src/layout/neato/cdt-surface.ts +693 -0
  852. package/src/layout/neato/conjgrad.ts +159 -0
  853. package/src/layout/neato/delaunay.ts +259 -0
  854. package/src/layout/neato/dijkstra.ts +296 -0
  855. package/src/layout/neato/fdp-adjust.ts +124 -0
  856. package/src/layout/neato/index.ts +310 -0
  857. package/src/layout/neato/init.ts +505 -0
  858. package/src/layout/neato/legal.ts +316 -0
  859. package/src/layout/neato/matrix-ops.ts +112 -0
  860. package/src/layout/neato/multispline-router.ts +417 -0
  861. package/src/layout/neato/multispline.ts +427 -0
  862. package/src/layout/neato/overlap-prism.ts +503 -0
  863. package/src/layout/neato/overlap.ts +158 -0
  864. package/src/layout/neato/sc-adjust.ts +206 -0
  865. package/src/layout/neato/sep-factor.ts +118 -0
  866. package/src/layout/neato/set-aspect.ts +178 -0
  867. package/src/layout/neato/sgd.ts +461 -0
  868. package/src/layout/neato/splines.ts +1014 -0
  869. package/src/layout/neato/stress-kernel.ts +362 -0
  870. package/src/layout/neato/stress.ts +420 -0
  871. package/src/layout/osage/index.ts +548 -0
  872. package/src/layout/osage/layout.ts +254 -0
  873. package/src/layout/osage/types.ts +31 -0
  874. package/src/layout/pack/array-pack.ts +254 -0
  875. package/src/layout/pack/index.ts +570 -0
  876. package/src/layout/pack/poly-pack.ts +266 -0
  877. package/src/layout/pack/poly-place.ts +426 -0
  878. package/src/layout/pack/spiral-search.ts +106 -0
  879. package/src/layout/pack/test-helpers.ts +46 -0
  880. package/src/layout/pack/types.ts +85 -0
  881. package/src/layout/patchwork/index.ts +441 -0
  882. package/src/layout/patchwork/tree-map.ts +183 -0
  883. package/src/layout/patchwork/tree-node.ts +120 -0
  884. package/src/layout/sfdp/index.ts +231 -0
  885. package/src/layout/sfdp/init.ts +224 -0
  886. package/src/layout/sfdp/multilevel.ts +262 -0
  887. package/src/layout/sfdp/quadtree.ts +267 -0
  888. package/src/layout/sfdp/sparse-matrix-multiply.ts +160 -0
  889. package/src/layout/sfdp/sparse-matrix.ts +367 -0
  890. package/src/layout/sfdp/sparse-solve.ts +122 -0
  891. package/src/layout/sfdp/spring-driver.ts +209 -0
  892. package/src/layout/sfdp/spring-electrical.ts +431 -0
  893. package/src/layout/twopi/circle.ts +339 -0
  894. package/src/layout/twopi/index.ts +78 -0
  895. package/src/layout/twopi/init.ts +174 -0
  896. package/src/layout/twopi/pipeline.ts +98 -0
  897. package/src/layout/twopi/twopi-test-helpers.ts +44 -0
  898. package/src/model/algData.ts +194 -0
  899. package/src/model/cgraph-ops.ts +175 -0
  900. package/src/model/edge.ts +104 -0
  901. package/src/model/edgeInfo.ts +431 -0
  902. package/src/model/geom.ts +204 -0
  903. package/src/model/graph.ts +172 -0
  904. package/src/model/graphInfo.ts +528 -0
  905. package/src/model/index.ts +10 -0
  906. package/src/model/layoutParams.ts +127 -0
  907. package/src/model/node.ts +138 -0
  908. package/src/model/nodeInfo.ts +424 -0
  909. package/src/model/rankEntry.ts +95 -0
  910. package/src/ortho/chan-dict.ts +236 -0
  911. package/src/ortho/fpq.ts +149 -0
  912. package/src/ortho/index.ts +206 -0
  913. package/src/ortho/maze-channels.ts +196 -0
  914. package/src/ortho/maze.ts +311 -0
  915. package/src/ortho/ortho-parallel.ts +254 -0
  916. package/src/ortho/ortho-route.ts +349 -0
  917. package/src/ortho/partition.ts +303 -0
  918. package/src/ortho/rawgraph.ts +119 -0
  919. package/src/ortho/sgraph.ts +283 -0
  920. package/src/ortho/trap-query.ts +174 -0
  921. package/src/ortho/trap-segment.ts +303 -0
  922. package/src/ortho/trap-types.ts +171 -0
  923. package/src/ortho/trap-update.ts +89 -0
  924. package/src/ortho/trapezoid.ts +120 -0
  925. package/src/ortho/types.ts +286 -0
  926. package/src/parser/__fixtures__/directed.dot +10 -0
  927. package/src/parser/__fixtures__/simple.dot +7 -0
  928. package/src/parser/__fixtures__/subgraph.dot +17 -0
  929. package/src/parser/ast.ts +64 -0
  930. package/src/parser/builder.ts +401 -0
  931. package/src/parser/dot.d.ts +208 -0
  932. package/src/parser/dot.js +3321 -0
  933. package/src/parser/dot.pegjs +263 -0
  934. package/src/parser/index.ts +353 -0
  935. package/src/pathplan/index.ts +9 -0
  936. package/src/pathplan/route.ts +284 -0
  937. package/src/pathplan/shortest.ts +268 -0
  938. package/src/pathplan/solvers.ts +65 -0
  939. package/src/pathplan/triang.ts +221 -0
  940. package/src/pathplan/types.ts +16 -0
  941. package/src/pathplan/visibility.ts +170 -0
  942. package/src/pathplan/vispath.ts +118 -0
  943. package/src/rbtree/index.ts +418 -0
  944. package/src/render/color-resolve.ts +171 -0
  945. package/src/render/dot.ts +1514 -0
  946. package/src/render/index.ts +29 -0
  947. package/src/render/json.ts +734 -0
  948. package/src/render/map-test-helpers.ts +61 -0
  949. package/src/render/map.ts +528 -0
  950. package/src/render/public.ts +131 -0
  951. package/src/render/svg-arrow-ops.ts +113 -0
  952. package/src/render/svg-cluster.ts +24 -0
  953. package/src/render/svg-edge-ortho-radius.ts +228 -0
  954. package/src/render/svg-edge-split.ts +180 -0
  955. package/src/render/svg-gradient.ts +185 -0
  956. package/src/render/svg-graph.ts +415 -0
  957. package/src/render/svg-helpers.ts +623 -0
  958. package/src/render/svg-id.ts +76 -0
  959. package/src/render/svg-multicolor.ts +313 -0
  960. package/src/render/svg-parallel-edge.ts +123 -0
  961. package/src/render/svg-tapered-edge.ts +56 -0
  962. package/src/render/svg.ts +307 -0
  963. package/src/render/xdot-public.ts +164 -0
  964. package/src/render/xml-escape.ts +56 -0
  965. package/src/util/agxbuf.ts +138 -0
  966. package/src/util/bsd-qsort.ts +251 -0
  967. package/src/util/index.ts +25 -0
  968. package/src/util/list.ts +122 -0
  969. package/src/util/math.ts +104 -0
  970. package/src/util/mt19937.ts +143 -0
  971. package/src/util/printf-round.ts +163 -0
  972. package/src/util/xml.ts +184 -0
  973. package/src/vpsc/Block.ts +375 -0
  974. package/src/vpsc/Blocks.ts +164 -0
  975. package/src/vpsc/Constraint.ts +94 -0
  976. package/src/vpsc/HeapUtils.ts +88 -0
  977. package/src/vpsc/Solver.ts +274 -0
  978. package/src/vpsc/SweepLine.ts +214 -0
  979. package/src/vpsc/Variable.ts +54 -0
  980. package/src/vpsc/index.ts +122 -0
  981. package/src/vpsc/sweepTypes.ts +31 -0
  982. package/src/xdot/index.ts +7 -0
  983. package/src/xdot/lex.ts +151 -0
  984. package/src/xdot/misc.ts +226 -0
  985. package/src/xdot/parse.ts +349 -0
  986. package/src/xdot/types.ts +158 -0
@@ -0,0 +1,1014 @@
1
+ // SPDX-License-Identifier: EPL-2.0
2
+
3
+ /**
4
+ * Neato spline routing entry point.
5
+ *
6
+ * Faithful port of lib/neatogen/neatosplines.c — splineEdges dispatch,
7
+ * makeObstacle, makeSelfArcs, and supporting helpers.
8
+ *
9
+ * Full multispline.c routing is stubbed: when pathplan-based routing is
10
+ * attempted but would require multi-path resolution, the code falls back to
11
+ * straight-line edges. This covers the acceptance criteria surface area.
12
+ *
13
+ * @see lib/neatogen/neatosplines.c
14
+ */
15
+
16
+ import type { Graph } from '../../model/graph.js';
17
+ import type { Node } from '../../model/node.js';
18
+ import type { Edge } from '../../model/edge.js';
19
+ import type { Point } from '../../model/geom.js';
20
+ import type { SplineInfo, PolygonT, TextlabelT } from '../../common/types.js';
21
+ import { polygonOutlineRing } from '../../common/poly-sizing.js';
22
+ import { ShapeKind } from '../../common/types.js';
23
+ import type { ExpandT } from './sep-factor.js';
24
+ import { esepFactor } from './sep-factor.js';
25
+ import type { Poly, VConfig } from '../../pathplan/types.js';
26
+ import {
27
+ obsOpen, obsClose, obsPath,
28
+ routeSpline, polyBarriers,
29
+ POLYID_NONE, inPoly,
30
+ } from '../../pathplan/index.js';
31
+ import { makeSelfEdge } from '../../common/splines.js';
32
+ import { newSpline, clipAndInstall } from '../../common/splines-clip.js';
33
+ import { orthoEdges } from '../../ortho/index.js';
34
+ import type { OrthoGraph, OrthoEdge, OrthoPoint } from '../../ortho/index.js';
35
+ import {
36
+ EDGETYPE_NONE, EDGETYPE_LINE, EDGETYPE_ORTHO,
37
+ EDGETYPE_PLINE,
38
+ } from '../dot/splines.js';
39
+ import { shiftGraphBBs } from '../pack/index.js';
40
+ import { neatoSetAspect } from './init.js';
41
+ import { nodesInSeq } from '../dot/decomp.js';
42
+ import { mapbool } from '../dot/rank.js';
43
+ import { lateDouble } from '../../common/nodeinit.js';
44
+ import { makeStraightEdges, addEdgeLabels } from '../dot/straight-edges.js';
45
+ import { makeMultiSpline, mkRouter } from './multispline.js';
46
+ import { legalArrangement } from './legal.js';
47
+ import type { Router } from './multispline.js';
48
+ import { updateBB } from '../dot/splines-label.js';
49
+ import { resolvePort } from '../../common/splines-path-shared.js';
50
+ import { cround } from '../../common/arith.js';
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Re-export EDGETYPE constants for consumers of this module
54
+ // ---------------------------------------------------------------------------
55
+
56
+ export {
57
+ EDGETYPE_NONE, EDGETYPE_LINE, EDGETYPE_ORTHO,
58
+ EDGETYPE_PLINE, EDGETYPE_SPLINE,
59
+ } from '../dot/splines.js';
60
+ export const EDGETYPE_CURVED = 2;
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // Named type aliases — avoids inline generics/brackets that confuse lizard
64
+ // ---------------------------------------------------------------------------
65
+
66
+ /** Vertex array matching Poly.ps. */
67
+ type PolyPoints = Point[];
68
+
69
+ /** Node list matching OrthoGraph.nodes. */
70
+ type OrthoNodeList = OrthoGraph['nodes'];
71
+
72
+ /** Open visibility config produced by obsOpen(). */
73
+ type VisConfig = VConfig;
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // SplineInfo: neato always uses identity callbacks (no merge, no swap)
77
+ // @see lib/neatogen/neatosplines.c:sinfo
78
+ // ---------------------------------------------------------------------------
79
+
80
+ /** @see lib/neatogen/neatosplines.c:swap_ends_p */
81
+ export function swapEndsP(_e: unknown): boolean { return false; }
82
+
83
+ /** @see lib/neatogen/neatosplines.c:spline_merge */
84
+ export function splineMerge(_n: unknown): boolean { return false; }
85
+
86
+ /** @see lib/neatogen/neatosplines.c:sinfo */
87
+ export const SINFO: SplineInfo = {
88
+ swapEnds: swapEndsP,
89
+ splineMerge: splineMerge,
90
+ ignoreSwap: false,
91
+ isOrtho: false,
92
+ };
93
+
94
+ /** @see lib/ortho/ortho.c:1269 — {swap_ends_p, spline_merge, true, true} */
95
+ const ORTHO_SINFO: SplineInfo = {
96
+ ...SINFO,
97
+ ignoreSwap: true,
98
+ isOrtho: true,
99
+ };
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // ObstacleHelper — makeObstacle internals
103
+ // Class wrapper resets lizard's brace counter at each class boundary.
104
+ // ---------------------------------------------------------------------------
105
+
106
+ class ObstacleHelper {
107
+ static halfHeight(ht: number, sepY: number): number {
108
+ return ht / 2 + sepY;
109
+ }
110
+
111
+ static vertices(
112
+ cx: number, cy: number,
113
+ hw: number, rw: number, hh: number,
114
+ ): PolyPoints {
115
+ return [
116
+ { x: cx - hw, y: cy - hh },
117
+ { x: cx - hw, y: cy + hh },
118
+ { x: cx + rw, y: cy + hh },
119
+ { x: cx + rw, y: cy - hh },
120
+ ];
121
+ }
122
+ }
123
+
124
+ // ---------------------------------------------------------------------------
125
+ // makeObstacle
126
+ // ---------------------------------------------------------------------------
127
+
128
+ /** Slope of the ellipse tangent at p. @see neatosplines.c:ellipse_tangent_slope */
129
+ function ellipseTangentSlope(a: number, b: number, p: Point): number {
130
+ const signY = p.y >= 0 ? 1 : -1;
131
+ return (-signY * (b * p.x)) / (a * Math.sqrt(a * a - p.x * p.x));
132
+ }
133
+
134
+ /** Corner i of an nsides-gon circumscribed about the ellipse (a, b).
135
+ * @see neatosplines.c:circumscribed_polygon_corner_about_ellipse */
136
+ function circumscribedCorner(a: number, b: number, i: number, nsides: number): Point {
137
+ const angle0 = (2 * Math.PI * (i - 0.5)) / nsides;
138
+ const angle1 = (2 * Math.PI * (i + 0.5)) / nsides;
139
+ const p0 = { x: a * Math.cos(angle0), y: b * Math.sin(angle0) };
140
+ const p1 = { x: a * Math.cos(angle1), y: b * Math.sin(angle1) };
141
+ const m0 = ellipseTangentSlope(a, b, p0);
142
+ const m1 = ellipseTangentSlope(a, b, p1);
143
+ // line_intersection of the two tangents.
144
+ const x = (m0 * p0.x - p0.y - m1 * p1.x + p1.y) / (m0 - m1);
145
+ const y = p0.y + m0 * (x - p0.x);
146
+ return { x, y };
147
+ }
148
+
149
+ /** Margin displacement for corner j of a 4-sided polygon (CCW box order:
150
+ * LL, LR, UR, UL — C's case 0..3). @see makeObstacle (doAdd, sides==4) */
151
+ function boxCornerMargin(j: number, m: Point): Point {
152
+ if (j === 0) return { x: m.x, y: m.y };
153
+ if (j === 1) return { x: -m.x, y: m.y };
154
+ if (j === 2) return { x: -m.x, y: -m.y };
155
+ return { x: m.x, y: -m.y };
156
+ }
157
+
158
+ /** The poly-vertices (sides >= 3) branch of C makeObstacle. */
159
+ function polyObstacle(
160
+ n: Node, poly: PolygonT, pmargin: ExpandT,
161
+ ): Poly | null {
162
+ const sides = poly.sides;
163
+ const stored = poly.vertices;
164
+ if (stored == null) return null;
165
+ const penwidth = poly.penwidth ?? 1;
166
+ const extraPeripheries = poly.peripheries >= 1 && penwidth > 0 ? 1 : 0;
167
+ const outlinePeriphery = poly.peripheries + extraPeripheries;
168
+ const ringIdx = outlinePeriphery >= 1 ? outlinePeriphery - 1 : 0;
169
+ // C stores the half-penwidth OUTLINE ring in poly->vertices
170
+ // (shapes.c:poly_init outp); the port keeps only the periphery rings and
171
+ // derives the outline on demand, exactly like poly_inside does.
172
+ const storedRings = Math.max(poly.peripheries, 1);
173
+ let verts: Point[];
174
+ if (ringIdx < storedRings) {
175
+ verts = stored.slice(ringIdx * sides, (ringIdx + 1) * sides);
176
+ } else {
177
+ const outer = stored.slice((storedRings - 1) * sides, storedRings * sides);
178
+ verts = polygonOutlineRing(outer, sides, penwidth);
179
+ }
180
+ if (verts.length < sides) return null;
181
+ const ps: Point[] = new Array(sides);
182
+ for (let j = 0; j < sides; j++) {
183
+ const v = verts[j];
184
+ if (v === undefined) return null;
185
+ let polyp: Point;
186
+ if (pmargin.doAdd) {
187
+ if (sides === 4) {
188
+ // C's corner cases assume the CCW box vertex order LL,LR,UR,UL.
189
+ const m = boxCornerMargin(j, { x: pmargin.x, y: pmargin.y });
190
+ polyp = { x: v.x + m.x, y: v.y + m.y };
191
+ } else {
192
+ const h = Math.hypot(v.x, v.y);
193
+ polyp = { x: v.x * (1 + pmargin.x / h), y: v.y * (1 + pmargin.y / h) };
194
+ }
195
+ } else {
196
+ polyp = { x: v.x * pmargin.x, y: v.y * pmargin.y };
197
+ }
198
+ // CW output: ps[sides - j - 1].
199
+ ps[sides - j - 1] = { x: polyp.x + n.info.coord.x, y: polyp.y + n.info.coord.y };
200
+ }
201
+ return { ps };
202
+ }
203
+
204
+ /** The ellipse (sides < 3) branch: 8-gon circumscribed about the OUTLINE
205
+ * ellipse, margin added only when doAdd. */
206
+ function ellipseObstacle(n: Node, pmargin: ExpandT): Poly {
207
+ const sides = 8;
208
+ const width = (n.info.outline_width ?? 0) > 0 ? n.info.outline_width * 72 : n.info.lw + n.info.rw;
209
+ const height = (n.info.outline_height ?? 0) > 0 ? n.info.outline_height * 72 : n.info.ht;
210
+ const mx = pmargin.doAdd ? pmargin.x : 0;
211
+ const my = pmargin.doAdd ? pmargin.y : 0;
212
+ const a = (width + mx) / 2;
213
+ const b = (height + my) / 2;
214
+ const ps: Point[] = new Array(sides);
215
+ for (let j = 0; j < sides; j++) {
216
+ const polyp = circumscribedCorner(a, b, j, sides);
217
+ ps[sides - j - 1] = { x: polyp.x + n.info.coord.x, y: polyp.y + n.info.coord.y };
218
+ }
219
+ return { ps };
220
+ }
221
+
222
+ /** Rectangle obstacle around (llx,lly)-(urx,ury) relative to coord, with
223
+ * additive or multiplicative margins (C's genPt/recPt cases, CW order). */
224
+ function rectObstacle(
225
+ n: Node, llx: number, lly: number, urx: number, ury: number, pmargin: ExpandT,
226
+ ): Poly {
227
+ const pt = n.info.coord;
228
+ let x0: number; let y0: number; let x1: number; let y1: number;
229
+ if (pmargin.doAdd) {
230
+ x0 = llx - pmargin.x; y0 = lly - pmargin.y;
231
+ x1 = urx + pmargin.x; y1 = ury + pmargin.y;
232
+ } else {
233
+ x0 = llx * pmargin.x; y0 = lly * pmargin.y;
234
+ x1 = urx * pmargin.x; y1 = ury * pmargin.y;
235
+ }
236
+ // C order: LL, UL, UR, LR (CW).
237
+ return {
238
+ ps: [
239
+ { x: x0 + pt.x, y: y0 + pt.y },
240
+ { x: x0 + pt.x, y: y1 + pt.y },
241
+ { x: x1 + pt.x, y: y1 + pt.y },
242
+ { x: x1 + pt.x, y: y0 + pt.y },
243
+ ],
244
+ };
245
+ }
246
+
247
+ /**
248
+ * Obstacle polygon reflecting the node's geometry, vertices in CW order:
249
+ * the shape's own outline-periphery vertices (+margin) for polygons, an
250
+ * 8-gon circumscribed about the outline ellipse for ellipses, the field
251
+ * box for records, the node box for EPSF. Null = unsupported shape (the
252
+ * node is skipped as an obstacle, C returns NULL).
253
+ *
254
+ * @see lib/neatogen/neatosplines.c:makeObstacle
255
+ */
256
+ export function makeObstacle(n: Node, pmargin: ExpandT): Poly | null {
257
+ const shape = n.info.shape as { kind?: ShapeKind } | undefined;
258
+ const kind = shape?.kind;
259
+ if (kind === ShapeKind.SH_POLY || kind === ShapeKind.SH_POINT) {
260
+ const poly = n.info.shape_info as PolygonT | undefined;
261
+ if (poly !== undefined && poly.sides >= 3) return polyObstacle(n, poly, pmargin);
262
+ return ellipseObstacle(n, pmargin);
263
+ }
264
+ if (kind === ShapeKind.SH_RECORD) {
265
+ const fld = n.info.shape_info as { b?: { ll: Point; ur: Point } } | undefined;
266
+ const b = fld?.b;
267
+ if (b) return rectObstacle(n, b.ll.x, b.ll.y, b.ur.x, b.ur.y, pmargin);
268
+ return rectObstacle(n, -n.info.lw, -n.info.ht / 2, n.info.rw, n.info.ht / 2, pmargin);
269
+ }
270
+ // SH_EPSF and unbound shapes: the node box (C returns NULL only for
271
+ // SH_UNSET, which cannot occur post-init; unbound port-side shapes keep
272
+ // the legacy box so measurer-less runs still route).
273
+ return rectObstacle(n, -n.info.lw, -n.info.ht / 2, n.info.rw, n.info.ht / 2, pmargin);
274
+ }
275
+
276
+ /** bb of a polygon's vertex array. @see lib/common/utils.c:polyBB */
277
+ function polyVertexBB(vertices: Point[]): { ll: Point; ur: Point } {
278
+ const bb = { ll: { x: Infinity, y: Infinity }, ur: { x: -Infinity, y: -Infinity } };
279
+ for (const v of vertices) {
280
+ bb.ll.x = Math.min(bb.ll.x, v.x);
281
+ bb.ll.y = Math.min(bb.ll.y, v.y);
282
+ bb.ur.x = Math.max(bb.ur.x, v.x);
283
+ bb.ur.y = Math.max(bb.ur.y, v.y);
284
+ }
285
+ return bb;
286
+ }
287
+
288
+ /**
289
+ * The isOrtho branch of C makeObstacle for SH_POLY/SH_POINT nodes: the
290
+ * obstacle is the node's OUTLINE box (size + penwidth outline) with NO
291
+ * margin — margin stays {0,0}, so tightly packed layouts (osage's 4pt
292
+ * gutters) remain a legal arrangement and the maze routes them; the
293
+ * margined rectangle makes neighbours touch and forces the straight
294
+ * fallback. Records fall through to the margined box like C's SH_RECORD
295
+ * branch (no isOrtho special case there).
296
+ *
297
+ * @see lib/neatogen/neatosplines.c:makeObstacle (isOrtho, vs[0..3])
298
+ */
299
+ export function makeOrthoObstacle(n: Node, sep: ExpandT): Poly | null {
300
+ const info = n.info;
301
+ const shape = info.shape as { kind?: ShapeKind } | undefined;
302
+ const kind = shape?.kind;
303
+ if (kind !== undefined && kind !== ShapeKind.SH_POLY && kind !== ShapeKind.SH_POINT) {
304
+ return makeObstacle(n, sep); // SH_RECORD etc.: C applies pmargin as usual
305
+ }
306
+ const poly = info.shape_info as { option?: { fixedshape?: boolean }; vertices?: Point[] | null } | undefined;
307
+ let lw: number;
308
+ let rw: number;
309
+ let hh: number;
310
+ let cx = info.coord.x;
311
+ let cy = info.coord.y;
312
+ if (poly?.option?.fixedshape === true && poly.vertices != null) {
313
+ // C: b = polyBB(poly) — the actual shape, not the label-padded size.
314
+ const bb = polyVertexBB(poly.vertices);
315
+ lw = -bb.ll.x;
316
+ rw = bb.ur.x;
317
+ hh = (bb.ur.y - bb.ll.y) / 2;
318
+ cy += (bb.ur.y + bb.ll.y) / 2;
319
+ cx += 0;
320
+ } else {
321
+ const width = info.lw + info.rw;
322
+ const outlineW = (info.outline_width ?? 0) > 0 ? info.outline_width * 72 : width;
323
+ const outlineH = (info.outline_height ?? 0) > 0 ? info.outline_height * 72 : info.ht;
324
+ // C: outline_lw = ND_lw * outline_width / width, box spans ±outline_lw
325
+ // (SYMMETRIC — vs[0].x=-outline_lw, vs[1].x=+outline_lw).
326
+ const outlineLw = width > 0 ? (info.lw * outlineW) / width : outlineW / 2;
327
+ lw = outlineLw;
328
+ rw = outlineLw;
329
+ hh = outlineH / 2;
330
+ }
331
+ const ps = ObstacleHelper.vertices(cx, cy, lw, rw, hh);
332
+ return { ps };
333
+ }
334
+
335
+ // ---------------------------------------------------------------------------
336
+ // EdgeHelper — straight-edge and self-arc internals
337
+ // ---------------------------------------------------------------------------
338
+
339
+ class EdgeHelper {
340
+ static endpoint(coord: Point, port: Point): Point {
341
+ return { x: coord.x + port.x, y: coord.y + port.y };
342
+ }
343
+
344
+ static selfChain(e: Edge, cnt: number): Edge[] {
345
+ const edges: Edge[] = [];
346
+ let cur: Edge | undefined = e;
347
+ for (let i = 0; i < cnt && cur !== undefined; i++) {
348
+ edges.push(cur);
349
+ cur = cur.info.to_virt;
350
+ }
351
+ return edges;
352
+ }
353
+ }
354
+
355
+ // ---------------------------------------------------------------------------
356
+ // makeStraightEdge
357
+ // ---------------------------------------------------------------------------
358
+
359
+ /**
360
+ * Install a straight-line (two-point) spline on an edge.
361
+ *
362
+ * Used when pathplan routing is unavailable or edgetype == EDGETYPE_LINE.
363
+ *
364
+ * @see lib/neatogen/neatosplines.c (straight-line fallback in spline_edges_)
365
+ */
366
+ export function makeStraightEdge(e: Edge, sinfo: SplineInfo): void {
367
+ const tp = EdgeHelper.endpoint(e.tail.info.coord, e.info.tail_port.p);
368
+ const hp = EdgeHelper.endpoint(e.head.info.coord, e.info.head_port.p);
369
+ clipAndInstall(e, e.head, [tp, tp, hp, hp], 4, sinfo);
370
+ }
371
+
372
+
373
+ /**
374
+ * GD_nodesep for the neato-family routing sites. C parses nodesep
375
+ * engine-neutrally at graph_init (input.c:665-667: POINTS(late_double(g,
376
+ * "nodesep", 0.25, 0.02))); the port only did so in dot's init, so
377
+ * neato/circo/twopi self-loops and straight fans silently used the
378
+ * default 18 regardless of the attr (1949 sets nodesep=0.4 -> 29).
379
+ * Parses on demand and caches in root.info, mirroring C's assignment.
380
+ */
381
+ function graphNodesep(g: Graph): number {
382
+ const root = g.root;
383
+ if (root.info.nodesep === undefined) {
384
+ const inches = lateDouble(root.attrs.get('nodesep'), 0.25, 0.02);
385
+ // C POINTS(a) = ROUND(a*72), half away from zero. @see lib/common/geom.h:62
386
+ root.info.nodesep = cround(inches * 72);
387
+ }
388
+ return root.info.nodesep;
389
+ }
390
+
391
+ // ---------------------------------------------------------------------------
392
+ // makeSelfArcs
393
+ // ---------------------------------------------------------------------------
394
+
395
+ /**
396
+ * Route self-loop edges via makeSelfEdge, handling single and chained cases.
397
+ * Under concentrate only the representative is routed (C: cnt==1||Concentrate).
398
+ *
399
+ * @see lib/neatogen/neatosplines.c:makeSelfArcs
400
+ */
401
+ export function makeSelfArcs(e: Edge, stepx: number): void {
402
+ const cnt = e.info.count ?? 1;
403
+ const concentrate = e.tail.root.info.concentrate ?? false;
404
+ if (cnt <= 1 || concentrate) {
405
+ makeSelfEdge([e], 1, stepx, stepx, SINFO);
406
+ // C: the self-loop LABEL extends the graph bb (updateBB), and head/tail
407
+ // port labels are placed here. @see neatosplines.c:227-229
408
+ if (e.info.label) updateBB(e.tail.root, e.info.label as TextlabelT);
409
+ addEdgeLabels(e); // makePortLabels
410
+ return;
411
+ }
412
+ const edges = EdgeHelper.selfChain(e, cnt);
413
+ makeSelfEdge(edges, edges.length, stepx, stepx, SINFO);
414
+ for (const e0 of edges) {
415
+ if (e0.info.label) updateBB(e0.tail.root, e0.info.label as TextlabelT);
416
+ addEdgeLabels(e0);
417
+ }
418
+ }
419
+
420
+ // ---------------------------------------------------------------------------
421
+ // Equivalent-edge coalescing — the C splineEdges wrapper
422
+ // ---------------------------------------------------------------------------
423
+
424
+ /**
425
+ * Equivalence key mirroring equivEdge (neatosplines.c:equivEdge): edges with
426
+ * the same endpoint pair — UNORDERED, so A->B and B->A coalesce — and the same
427
+ * resolved port points belong to one class. C orders (n1,n2) by node pointer
428
+ * (allocation = creation order); node id is the port's stand-in. Self-loops
429
+ * normalize the two port points by x then y.
430
+ */
431
+ function equivKey(e: Edge): string {
432
+ const tp = e.info.tail_port?.p ?? { x: 0, y: 0 };
433
+ const hp = e.info.head_port?.p ?? { x: 0, y: 0 };
434
+ const t = e.tail.id;
435
+ const h = e.head.id;
436
+ let n1: number, n2: number, p1: Point, p2: Point;
437
+ if (t < h) {
438
+ n1 = t; p1 = tp; n2 = h; p2 = hp;
439
+ } else if (t > h) {
440
+ n2 = t; p2 = tp; n1 = h; p1 = hp;
441
+ } else {
442
+ if (tp.x < hp.x) { p1 = tp; p2 = hp; }
443
+ else if (tp.x > hp.x) { p1 = hp; p2 = tp; }
444
+ else if (tp.y < hp.y) { p1 = tp; p2 = hp; }
445
+ else if (tp.y > hp.y) { p1 = hp; p2 = tp; }
446
+ else { p1 = p2 = tp; }
447
+ n1 = n2 = t;
448
+ }
449
+ return `${n1}|${p1.x}|${p1.y}|${n2}|${p2.x}|${p2.y}`;
450
+ }
451
+
452
+ /**
453
+ * Coalesce equivalent edges, mirroring the C splineEdges wrapper
454
+ * (neatosplines.c:753-773): the FIRST edge of a class (agfstnode/agfstout
455
+ * order) becomes the leader with ED_count = 1 (set by newitem on dict
456
+ * insert); each later member increments the leader's count, gets count 0,
457
+ * and is prepended to the leader's ED_to_virt chain. The routing loop then
458
+ * skips count==0 members and routes the leader's whole chain (or only the
459
+ * representative under concentrate).
460
+ *
461
+ * @see lib/neatogen/neatosplines.c:splineEdges (find equivalent edges)
462
+ * @see lib/neatogen/neatosplines.c:newitem (ED_count(leader) = 1)
463
+ */
464
+ export function coalesceEdges(g: Graph): void {
465
+ const map = new Map<string, Edge>();
466
+ for (const n of nodesInSeq(g)) {
467
+ for (const e of n.outEdges(g)) {
468
+ const key = equivKey(e);
469
+ const leader = map.get(key);
470
+ if (leader === undefined) {
471
+ map.set(key, e);
472
+ e.info.count = 1;
473
+ e.info.to_virt = undefined;
474
+ } else {
475
+ leader.info.count = (leader.info.count ?? 1) + 1;
476
+ e.info.count = 0;
477
+ e.info.to_virt = leader.info.to_virt;
478
+ leader.info.to_virt = e;
479
+ }
480
+ }
481
+ }
482
+ }
483
+
484
+ // ---------------------------------------------------------------------------
485
+ // SplineHelper — pathplan routing internals
486
+ // ---------------------------------------------------------------------------
487
+
488
+ class SplineHelper {
489
+ static polylinePoints(pts: Point[]): Point[] {
490
+ if (pts.length === 0) return [];
491
+ const out: Point[] = [pts[0], pts[0]];
492
+ for (let i = 1; i + 1 < pts.length; i++) out.push(pts[i], pts[i], pts[i]);
493
+ out.push(pts[pts.length - 1], pts[pts.length - 1]);
494
+ return out;
495
+ }
496
+
497
+ static tryRouteSpline(
498
+ barriers: ReturnType<typeof polyBarriers>,
499
+ route: ReturnType<typeof obsPath>,
500
+ ): Point[] | null {
501
+ const slopes: [Point, Point] = [{ x: 0, y: 0 }, { x: 0, y: 0 }];
502
+ try {
503
+ const pts = routeSpline(barriers, route, slopes);
504
+ return pts.length >= 4 ? pts : null;
505
+ } catch {
506
+ return null;
507
+ }
508
+ }
509
+
510
+ static installPline(e: Edge, route: Point[]): void {
511
+ const pts = SplineHelper.polylinePoints(route);
512
+ clipAndInstall(e, e.head, pts, pts.length, SINFO);
513
+ addEdgeLabels(e); // C makePolyline. @see neatosplines.c:526
514
+ }
515
+
516
+ static installSpline(e: Edge, obstacles: Poly[], route: Point[]): void {
517
+ // C makeSpline re-derives the endpoint-containing polys from the PATH
518
+ // endpoints via in_poly (neatosplines.c:554-562) rather than reusing
519
+ // ND_lim: a boundary port point (e.g. a compass port) is NOT strictly
520
+ // inside its node's poly, so that poly stays a BARRIER and Proutespline
521
+ // subdivides the spline around it.
522
+ const p = route[0];
523
+ const q = route[route.length - 1];
524
+ let pp = POLYID_NONE;
525
+ let qp = POLYID_NONE;
526
+ for (let i = 0; i < obstacles.length; i++) {
527
+ if (pp === POLYID_NONE && inPoly(obstacles[i].ps, p)) pp = i;
528
+ if (qp === POLYID_NONE && inPoly(obstacles[i].ps, q)) qp = i;
529
+ }
530
+ const barrierPolys = obstacles.filter((_, i) => i !== pp && i !== qp);
531
+ const splinePts = SplineHelper.tryRouteSpline(polyBarriers(barrierPolys), route);
532
+ if (splinePts === null) { makeStraightEdge(e, SINFO); return; }
533
+ clipAndInstall(e, e.head, splinePts, splinePts.length, SINFO);
534
+ addEdgeLabels(e); // C makeSpline. @see neatosplines.c:585
535
+ }
536
+ }
537
+
538
+ // ---------------------------------------------------------------------------
539
+ // makeSplineEdge — single-edge pathplan routing
540
+ // ---------------------------------------------------------------------------
541
+
542
+ /**
543
+ * The pathfinding half of C's two passes: ED_path(e) = getPath(e, vconfig).
544
+ * @see lib/neatogen/neatosplines.c:getPath
545
+ */
546
+ export function edgePath(e: Edge, vconfig: VisConfig): Point[] {
547
+ const p = EdgeHelper.endpoint(e.tail.info.coord, e.info.tail_port.p);
548
+ const pp = e.tail.info.lim ?? POLYID_NONE;
549
+ const qp = e.head.info.lim ?? POLYID_NONE;
550
+ const q = EdgeHelper.endpoint(e.head.info.coord, e.info.head_port.p);
551
+ // C: Pobspath(vconfig, p, pp, q, qp, &line) — poly id comes before end-point
552
+ return obsPath(vconfig, p, pp, q, qp);
553
+ }
554
+
555
+ /** @see lib/neatogen/neatosplines.c:makeSpline */
556
+ export function makeSplineEdge(
557
+ e: Edge, obstacles: Poly[], vconfig: VisConfig, edgetype: number,
558
+ ): void {
559
+ const route = edgePath(e, vconfig);
560
+ if (edgetype === EDGETYPE_PLINE) { SplineHelper.installPline(e, route); return; }
561
+ SplineHelper.installSpline(e, obstacles, route);
562
+ }
563
+
564
+ // ---------------------------------------------------------------------------
565
+ // OrthoHelper — bridge between Graph model and ortho module
566
+ // ---------------------------------------------------------------------------
567
+
568
+ /** An OrthoEdge carrying the originating model Edge for result installation. */
569
+ interface TaggedOrthoEdge extends OrthoEdge {
570
+ _edge: Edge;
571
+ }
572
+
573
+ class OrthoHelper {
574
+ static buildNodes(nodeArr: Node[]): OrthoNodeList {
575
+ return nodeArr.map((n) => ({
576
+ bb: {
577
+ LL: { x: n.info.coord.x - n.info.lw, y: n.info.coord.y - n.info.ht / 2 },
578
+ UR: { x: n.info.coord.x + n.info.rw, y: n.info.coord.y + n.info.ht / 2 },
579
+ },
580
+ // C mkMaze reads ND_coord / ND_xsize (= lw+rw) / ND_ysize (= ht)
581
+ // directly; avoids the bb round-trip ULP loss (see OrthoNode).
582
+ coord: { x: n.info.coord.x, y: n.info.coord.y },
583
+ xsize: n.info.lw + n.info.rw,
584
+ ysize: n.info.ht,
585
+ }));
586
+ }
587
+
588
+ static buildEdges(
589
+ g: Graph, nodeArr: Node[], orthoNodes: OrthoNodeList,
590
+ ): TaggedOrthoEdge[] {
591
+ // C orthoEdges collects es[] via agfstnode/agfstout (ortho.c:1220) — the
592
+ // COLLECTION order matters: edgeLen ties keep qsort's permutation of the
593
+ // input, which decides seg_list order and therefore parallel-segment
594
+ // track assignment. Under concentrate, one edge per UNORDERED endpoint
595
+ // pair is routed (ortho.c:1223-1233). Self-loops are NOT filtered — the
596
+ // maze routes them via addLoop.
597
+ const concentrate = g.root.info.concentrate ?? false;
598
+ const seen = new Set<string>();
599
+ const edges: TaggedOrthoEdge[] = [];
600
+ for (const n of nodesInSeq(g)) {
601
+ for (const e of n.outEdges(g)) {
602
+ if (concentrate) {
603
+ const ti = e.tail.id;
604
+ const hi = e.head.id;
605
+ const key = ti <= hi ? `${ti}|${hi}` : `${hi}|${ti}`;
606
+ if (seen.has(key)) continue;
607
+ seen.add(key);
608
+ }
609
+ // C attachOrthoEdges endpoints: p1 = ND_coord(tail) + ED_tail_port.p,
610
+ // q1 = ND_coord(head) + ED_head_port.p (ortho.c:1075-1076). Plumb the
611
+ // port offset so compass/record ports (tailport=s, headport=n, …) exit
612
+ // on the correct node side; without it buildSpline falls back to the bb
613
+ // centre and every ported ortho edge starts/ends at the node centre.
614
+ const tc = e.tail.info.coord;
615
+ const hc = e.head.info.coord;
616
+ const tp = e.info.tail_port.p;
617
+ const hp = e.info.head_port.p;
618
+ edges.push({
619
+ tail: orthoNodes[nodeArr.indexOf(e.tail)],
620
+ head: orthoNodes[nodeArr.indexOf(e.head)],
621
+ tailPoint: { x: tc.x + tp.x, y: tc.y + tp.y },
622
+ headPoint: { x: hc.x + hp.x, y: hc.y + hp.y },
623
+ _edge: e,
624
+ } as TaggedOrthoEdge);
625
+ }
626
+ }
627
+ return edges;
628
+ }
629
+
630
+ static buildGraph(g: Graph): OrthoGraph {
631
+ const nodeArr = [...g.nodes.values()];
632
+ const orthoNodes = OrthoHelper.buildNodes(nodeArr);
633
+ return { nodes: orthoNodes, edges: OrthoHelper.buildEdges(g, nodeArr, orthoNodes) };
634
+ }
635
+
636
+ static installResult(oe: OrthoEdge, pts: OrthoPoint[]): void {
637
+ const origEdge = (oe as TaggedOrthoEdge)._edge;
638
+ if (!origEdge) return;
639
+ // C attachOrthoEdges installs with ortho.c's OWN sinfo {swap_ends_p,
640
+ // spline_merge, ignoreSwap=true, isOrtho=true} (ortho.c:1269) — its static
641
+ // callbacks return false, identical to neato's. isOrtho selects the
642
+ // segment-truncating ortho clip; the generic bezier clip reparameterizes
643
+ // the control points and diverges from native.
644
+ clipAndInstall(origEdge, origEdge.head, pts, pts.length, ORTHO_SINFO);
645
+ }
646
+ }
647
+
648
+ // ---------------------------------------------------------------------------
649
+ // RoutingHelper — splineEdgesImpl internals
650
+ // ---------------------------------------------------------------------------
651
+
652
+ class RoutingHelper {
653
+ static buildObstacles(g: Graph, pmargin: ExpandT, edgetype: number): Poly[] {
654
+ const obstacles: Poly[] = [];
655
+ let idx = 0;
656
+ for (const n of g.nodes.values()) {
657
+ if (edgetype >= EDGETYPE_PLINE) {
658
+ // C: makeObstacle(n, pmargin, edgetype == EDGETYPE_ORTHO) —
659
+ // ortho obstacles are the unmargined outline box. A null obstacle
660
+ // (unsupported shape) leaves the node out (ND_lim = POLYID_NONE).
661
+ const obp = edgetype === EDGETYPE_ORTHO
662
+ ? makeOrthoObstacle(n, pmargin)
663
+ : makeObstacle(n, pmargin);
664
+ if (obp !== null) {
665
+ n.info.lim = idx++;
666
+ obstacles.push(obp);
667
+ } else {
668
+ n.info.lim = POLYID_NONE;
669
+ }
670
+ } else {
671
+ n.info.lim = POLYID_NONE;
672
+ }
673
+ }
674
+ return obstacles;
675
+ }
676
+
677
+ static withVconfig(
678
+ g: Graph, obstacles: Poly[], vconfig: VisConfig, edgetype: number,
679
+ ): void {
680
+ const stepx = graphNodesep(g);
681
+ const concentrate = g.root.info.concentrate ?? false;
682
+ let rtr: Router | null = null;
683
+ for (const n of nodesInSeq(g)) {
684
+ for (const e of n.outEdges(g)) {
685
+ // C spline_edges_: ED_count==0 -> continue (only do representative).
686
+ if ((e.info.count ?? 0) === 0) continue;
687
+ if (e.tail === e.head) { makeSelfArcs(e, stepx); continue; }
688
+ // HAVE_GTS branch (neatosplines.c:681): multiplicity or a boundary
689
+ // port routes through the triangle router; a straight 2-point path
690
+ // without ports shortcuts to the perpendicular fan. Only on router
691
+ // FAILURE does the edge fall through to the plain pathplan loop.
692
+ const boundaryPort =
693
+ (e.info.tail_port.side | e.info.head_port.side) !== 0;
694
+ if ((e.info.count ?? 1) > 1 || boundaryPort) {
695
+ let fail = 0;
696
+ const route = edgePath(e, vconfig);
697
+ if (route.length === 2 && !boundaryPort) {
698
+ // if a straight line can connect the ends
699
+ const chain = RoutingHelper.chainList(e);
700
+ makeStraightEdges(g, chain, chain.length, edgetype, SINFO);
701
+ } else {
702
+ if (rtr === null) rtr = mkRouter(obstacles);
703
+ fail = makeMultiSpline(
704
+ g, e, rtr, route, edgetype === EDGETYPE_PLINE);
705
+ }
706
+ if (!fail) continue;
707
+ }
708
+ let cur: Edge | undefined = e;
709
+ let cnt = e.info.count ?? 1;
710
+ if (concentrate) cnt = 1; // only do representative
711
+ for (let i = 0; i < cnt && cur !== undefined; i++) {
712
+ makeSplineEdge(cur, obstacles, vconfig, edgetype);
713
+ cur = cur.info.to_virt;
714
+ }
715
+ }
716
+ }
717
+ }
718
+
719
+ /** Full ED_to_virt chain from a leader (C makeStraightEdge's walk). */
720
+ static chainList(e: Edge): Edge[] {
721
+ const list: Edge[] = [e];
722
+ let e0: Edge = e;
723
+ while (e0.info.to_virt !== undefined && e0.info.to_virt !== e0) {
724
+ e0 = e0.info.to_virt;
725
+ list.push(e0);
726
+ }
727
+ return list;
728
+ }
729
+
730
+ static straight(g: Graph, et: number): void {
731
+ const stepx = graphNodesep(g);
732
+ for (const n of nodesInSeq(g)) {
733
+ for (const e of n.outEdges(g)) {
734
+ // C spline_edges_: ED_count==0 -> continue (only do representative).
735
+ if ((e.info.count ?? 0) === 0) continue;
736
+ if (e.tail === e.head) { makeSelfArcs(e, stepx); continue; }
737
+ // C makeStraightEdge routes the WHOLE equivalence chain at once —
738
+ // makeStraightEdges fans parallels out perpendicular to the segment
739
+ // and handles the concentrate representative-only case internally.
740
+ // @see lib/common/routespl.c:956 makeStraightEdge
741
+ const chain = RoutingHelper.chainList(e);
742
+ makeStraightEdges(g, chain, chain.length, et, SINFO);
743
+ }
744
+ }
745
+ }
746
+
747
+ static ortho(g: Graph, et: number): void {
748
+ const og = OrthoHelper.buildGraph(g);
749
+ orthoEdges(og, false, (_og, oe, pts) => OrthoHelper.installResult(oe, pts));
750
+ // C spline_edges_ drawing loop: vconfig is NEVER built for ortho
751
+ // (neatosplines.c:618 gates Pobsopen on edgetype != ORTHO), so an edge the
752
+ // maze failed to route — attachOrthoEdges skips empty routes — has no
753
+ // ED_spl, fails the `useEdges && ED_spl(e)` test, and falls through to
754
+ // makeSelfArcs / makeStraightEdge with neato's NORMAL sinfo (generic
755
+ // bezier clip). Self-loops are never maze-routed and always land here.
756
+ const stepx = graphNodesep(g);
757
+ for (const n of nodesInSeq(g)) {
758
+ for (const e of n.outEdges(g)) {
759
+ if (e.info.spl != null) {
760
+ // C: `useEdges && ED_spl(e)` — maze-routed edges still get their
761
+ // head/tail port labels. @see neatosplines.c:655
762
+ addEdgeLabels(e);
763
+ continue;
764
+ }
765
+ if ((e.info.count ?? 0) === 0) continue; // only do representative
766
+ if (e.tail === e.head) { makeSelfArcs(e, stepx); continue; }
767
+ const chain = RoutingHelper.chainList(e);
768
+ makeStraightEdges(g, chain, chain.length, et, SINFO);
769
+ }
770
+ }
771
+ }
772
+
773
+ static routed(g: Graph, obstacles: Poly[], edgetype: number): void {
774
+ const vconfig = obsOpen(obstacles);
775
+ RoutingHelper.withVconfig(g, obstacles, vconfig, edgetype);
776
+ obsClose(vconfig);
777
+ }
778
+ }
779
+
780
+ // ---------------------------------------------------------------------------
781
+ // splineEdgesImpl — inner routing loop
782
+ // ---------------------------------------------------------------------------
783
+
784
+ /** @see lib/neatogen/neatosplines.c:spline_edges_ */
785
+ export function splineEdgesImpl(g: Graph, sep: ExpandT, edgetype: number): void {
786
+ const obstacles = RoutingHelper.buildObstacles(g, sep, edgetype);
787
+ // C: legal = Plegal_arrangement(obs, npoly) — sweep-line segment
788
+ // intersection + nesting, NOT a bbox test: circo octagon obstacles
789
+ // routinely overlap in bbox while the polygons are disjoint.
790
+ const legal = legalArrangement(obstacles);
791
+ if (legal && edgetype === EDGETYPE_ORTHO) { RoutingHelper.ortho(g, edgetype); return; }
792
+ if (obstacles.length > 0 && legal) { RoutingHelper.routed(g, obstacles, edgetype); return; }
793
+ RoutingHelper.straight(g, edgetype);
794
+ }
795
+
796
+ // ---------------------------------------------------------------------------
797
+ // splineEdges — public entry point
798
+ // ---------------------------------------------------------------------------
799
+
800
+ /**
801
+ * Main spline routing entry point for neato layout.
802
+ *
803
+ * Dispatch:
804
+ * 1. EDGETYPE_NONE → skip
805
+ * 2. EDGETYPE_LINE → straight lines for all edges
806
+ * 3. EDGETYPE_ORTHO → orthoEdges (if obstacles legal, else straight)
807
+ * 4. EDGETYPE_SPLINE / EDGETYPE_PLINE → pathplan routing with straight fallback
808
+ *
809
+ * @see lib/neatogen/neatosplines.c:spline_edges0, spline_edges1, splineEdges
810
+ */
811
+ export function splineEdges(g: Graph): void {
812
+ const edgetype = g.info.flags & 0xf;
813
+ if (edgetype === EDGETYPE_NONE) return;
814
+ // C graph_init caches Concentrate for every engine (input.c:708-709); the
815
+ // routing gates (spline_edges_, makeSelfArcs, makeStraightEdges) read it.
816
+ g.root.info.concentrate = mapbool(g.root.attrs.get('concentrate'));
817
+ // C splineEdges wrapper: resolve dynamic ports first (neatosplines.c:748) —
818
+ // a record/compass port stays .dyna until fixed against the OTHER endpoint;
819
+ // equivEdge then keys on the resolved port points.
820
+ for (const n of nodesInSeq(g)) {
821
+ for (const e of n.outEdges(g)) {
822
+ if (e.info.tail_port.dyna) e.info.tail_port = resolvePort(e.tail, e.head, e.info.tail_port);
823
+ if (e.info.head_port.dyna) e.info.head_port = resolvePort(e.head, e.tail, e.info.head_port);
824
+ }
825
+ }
826
+ // C splineEdges wrapper: coalesce equivalent edges before routing.
827
+ coalesceEdges(g);
828
+ if (edgetype === EDGETYPE_LINE) { RoutingHelper.straight(g, edgetype); return; }
829
+ // C: margin = esepFactor(g) — the edge separation, default {3.2, 3.2, add}.
830
+ // @see lib/neatogen/neatosplines.c:746
831
+ splineEdgesImpl(g, esepFactor(g), edgetype);
832
+ }
833
+
834
+ // ---------------------------------------------------------------------------
835
+ // splineEdgesShifted — the C spline_edges wrapper
836
+ // ---------------------------------------------------------------------------
837
+
838
+ /**
839
+ * Graph bounding box in points derived from node pos (inches) and node
840
+ * sizes, expanded by any existing edge splines. xlabels are not ported
841
+ * (no engine sets them yet).
842
+ * @see lib/common/utils.c:compute_bb
843
+ */
844
+ export function computeBBFromPos(g: Graph): { ll: Point; ur: Point } {
845
+ const bb = {
846
+ ll: { x: Infinity, y: Infinity },
847
+ ur: { x: -Infinity, y: -Infinity },
848
+ };
849
+ for (const n of g.nodes.values()) {
850
+ const px = (n.info.pos?.[0] ?? 0) * 72;
851
+ const py = (n.info.pos?.[1] ?? 0) * 72;
852
+ const sx = (n.info.lw + n.info.rw) / 2;
853
+ const sy = n.info.ht / 2;
854
+ bb.ll.x = Math.min(bb.ll.x, px - sx);
855
+ bb.ll.y = Math.min(bb.ll.y, py - sy);
856
+ bb.ur.x = Math.max(bb.ur.x, px + sx);
857
+ bb.ur.y = Math.max(bb.ur.y, py + sy);
858
+ }
859
+ // C compute_bb: an empty graph keeps bb = {0,0,0,0}. @see utils.c:641
860
+ if (!Number.isFinite(bb.ll.x)) {
861
+ return { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } };
862
+ }
863
+ return bb;
864
+ }
865
+
866
+ /**
867
+ * The C spline_edges wrapper: translate pos so the drawing's lower
868
+ * left corner is the origin, shift cluster bbs along, sync coord from
869
+ * pos (neato_set_aspect), then route edges by edge type.
870
+ * @see lib/neatogen/neatosplines.c:spline_edges
871
+ * @see lib/neatogen/neatosplines.c:spline_edges0
872
+ * @see lib/neatogen/neatosplines.c:shiftClusters
873
+ */
874
+ /** Shift every node pos (inches) by the given offset. */
875
+ function shiftAllPos(g: Graph, ox: number, oy: number): void {
876
+ for (const n of g.nodes.values()) {
877
+ if (!n.info.pos) n.info.pos = [0, 0];
878
+ n.info.pos[0] = (n.info.pos[0] ?? 0) - ox;
879
+ n.info.pos[1] = (n.info.pos[1] ?? 0) - oy;
880
+ }
881
+ }
882
+
883
+ /** Shift all top-level cluster bbs. @see lib/neatogen/neatosplines.c:shiftClusters */
884
+ function shiftClusters(g: Graph, dx: number, dy: number): void {
885
+ const nClust = g.info.n_cluster ?? 0;
886
+ for (let c = 1; c <= nClust; c++) {
887
+ const sub = g.info.clust?.[c - 1];
888
+ if (sub) shiftGraphBBs(sub, dx, dy);
889
+ }
890
+ }
891
+
892
+ /**
893
+ * T1 (iterative-parity-campaign, batch-1) injection hook: when
894
+ * `GVTS_POS_INJECT` names a dump file, overwrite `n.info.pos` for every
895
+ * matching node name before this module's own routing runs — mirroring the
896
+ * native `spline_edges` entry point where the session-local POS_DUMP patch
897
+ * captures oracle `ND_pos` (see
898
+ * `plans/iterative-parity-campaign/diagrams/injection-recipe.md`). This lets
899
+ * the attribution harness separate "port routing/emission is wrong" from
900
+ * "the port's own node placement is just a different (but internally
901
+ * consistent) FP-drift outcome" for the iterative engines (D1: pre-routing
902
+ * `ND_pos` stage only).
903
+ *
904
+ * Dump lines look like `GVTS_POS <name> <x> <y>` (any other line, e.g. dot's
905
+ * own stderr warnings mixed into the same capture, is ignored). Reads via
906
+ * `process.getBuiltinModule` rather than a static `node:fs` import so the
907
+ * browser bundle (esbuild, no `--platform=node`) never tries to resolve a
908
+ * Node builtin — this whole function is inert (returns immediately) unless
909
+ * `process` exists and `GVTS_POS_INJECT` is set, which is true only inside
910
+ * the Node test harness, never in a browser render.
911
+ *
912
+ * An optional `GVTS_BB <llx> <lly> <urx> <ury>` line (points) overwrites the
913
+ * graph bb as well. It is emitted only by the *fdp* dump site, and it is
914
+ * load-bearing there: neato/sfdp reach this hook at the top of `spline_edges`,
915
+ * one line ABOVE the `compute_bb` that derives GD_bb — so their bb is a pure
916
+ * function of the injected positions and needs no injection of its own. fdp is
917
+ * the exception: `GD_bb` is a product of `fdpLayout` itself (`finalCC` →
918
+ * `setBB`, layout.c:1030), which has already run and returned by the time the
919
+ * hook fires, so without this line the injected render keeps the port's OWN
920
+ * (drifted) bb while emitting the oracle's node positions — a bb that belongs
921
+ * to neither layout. That mismatch, not any defect in the port's bb code, is
922
+ * what made `graph/bb`+`graph/_draw_` the largest not-cleared fdp bucket (60
923
+ * ids, bb short on 24 and TALL on 18 — a sign-split no bb bug can produce).
924
+ * The bb is layout-stage state exactly like `ND_pos`; neutralizing it is what
925
+ * lets the comparison isolate routing/emission, which is all the harness
926
+ * claims to measure.
927
+ * @see lib/fdpgen/layout.c:1063 fdp_layout
928
+ */
929
+ export function injectOraclePositions(g: Graph): void {
930
+ if (typeof process === 'undefined') return;
931
+ const dumpPath = process.env?.['GVTS_POS_INJECT'];
932
+ if (!dumpPath || typeof process.getBuiltinModule !== 'function') return;
933
+ const fs = process.getBuiltinModule('node:fs');
934
+ if (!fs) return;
935
+ // fdp also emits GVTS_CLUST_BB per cluster: like GD_bb, cluster boxes are a
936
+ // product of fdpLayout's setBB (upstream of this hook) and are NOT re-derived
937
+ // from injected positions, so they must be carried across too — otherwise the
938
+ // injected render draws every cluster at the port's own (drifted) extent.
939
+ // Map cluster name → subgraph so a dump line can find its target.
940
+ const clustByName = new Map<string, Graph>();
941
+ const collectClusters = (sg: Graph): void => {
942
+ const n = sg.info.n_cluster ?? 0;
943
+ const cl = sg.info.clust;
944
+ if (!cl) return;
945
+ for (let i = 0; i < n; i++) {
946
+ const c = cl[i];
947
+ if (c) {
948
+ clustByName.set(c.name, c);
949
+ collectClusters(c);
950
+ }
951
+ }
952
+ };
953
+ collectClusters(g);
954
+ const text = fs.readFileSync(dumpPath, 'utf8');
955
+ for (const line of text.split('\n')) {
956
+ // Name is greedy: node names can contain spaces (and literal "\n" from
957
+ // multi-line labels used as ids), so x and y are the trailing two tokens
958
+ // and the name is everything between. `(.*)` (not `(.+)`) so a node with
959
+ // the EMPTY name "" also injects — `\S+` skipped space-named nodes (2193),
960
+ // `(.+)` still skipped empty-named nodes (2095's single "" node, which drags
961
+ // its two incident edges ~1000pt when left un-injected).
962
+ const m = /^GVTS_POS (.*) (\S+) (\S+)$/.exec(line);
963
+ if (m) {
964
+ const n = g.nodes.get(m[1]!);
965
+ if (n) n.info.pos = [Number(m[2]), Number(m[3])];
966
+ continue;
967
+ }
968
+ const cb = /^GVTS_CLUST_BB (\S+) (\S+) (\S+) (\S+) (\S+)/.exec(line);
969
+ if (cb) {
970
+ const c = clustByName.get(cb[1]!);
971
+ if (c) {
972
+ c.info.bb = {
973
+ ll: { x: Number(cb[2]), y: Number(cb[3]) },
974
+ ur: { x: Number(cb[4]), y: Number(cb[5]) },
975
+ };
976
+ }
977
+ continue;
978
+ }
979
+ const b = /^GVTS_BB (\S+) (\S+) (\S+) (\S+)/.exec(line);
980
+ if (b) {
981
+ g.info.bb = {
982
+ ll: { x: Number(b[1]), y: Number(b[2]) },
983
+ ur: { x: Number(b[3]), y: Number(b[4]) },
984
+ };
985
+ }
986
+ }
987
+ }
988
+
989
+ export function splineEdgesShifted(g: Graph): void {
990
+ injectOraclePositions(g);
991
+ const bb = computeBBFromPos(g);
992
+ if (typeof process !== 'undefined' && process.env['STRESS_DEBUG']) console.error('shiftBB', JSON.stringify(bb));
993
+ shiftAllPos(g, bb.ll.x / 72, bb.ll.y / 72);
994
+ shiftClusters(g, -bb.ll.x, -bb.ll.y);
995
+ // C spline_edges leaves GD_bb = the shifted node-extent box (LL at origin);
996
+ // _neato_set_aspect reads it for the fill/expand/value factors.
997
+ g.info.bb = {
998
+ ll: { x: 0, y: 0 },
999
+ ur: { x: bb.ur.x - bb.ll.x, y: bb.ur.y - bb.ll.y },
1000
+ };
1001
+ neatoSetAspect(g); // spline_edges0(g, true): aspect + pos -> coord
1002
+ // The bb was seeded above (and scaled by the aspect pass); C never
1003
+ // recomputes it here — clip_and_install only EXPANDS it during routing.
1004
+ // Recomputing from node extents would clobber the ratio=fill scale
1005
+ // (scaleBB sets bb to exactly size; node extents land short of it).
1006
+ splineEdges(g);
1007
+ }
1008
+
1009
+ // ---------------------------------------------------------------------------
1010
+ // Exports for testing
1011
+ // ---------------------------------------------------------------------------
1012
+
1013
+ export { newSpline };
1014
+ export type { Poly as NeatoPoly };