@skillpet/circuit 0.5.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 (332) hide show
  1. package/README.md +131 -0
  2. package/dist/circuit.bundle.js +31103 -0
  3. package/dist/circuit.bundle.js.map +7 -0
  4. package/dist/circuit.bundle.min.js +273 -0
  5. package/dist/circuit.bundle.min.js.map +7 -0
  6. package/dist/circuit.esm.js +31069 -0
  7. package/dist/circuit.esm.js.map +7 -0
  8. package/dist/config.d.ts +26 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +23 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/container.d.ts +32 -0
  13. package/dist/container.d.ts.map +1 -0
  14. package/dist/container.js +101 -0
  15. package/dist/container.js.map +1 -0
  16. package/dist/drawing-gradient.d.ts +13 -0
  17. package/dist/drawing-gradient.d.ts.map +1 -0
  18. package/dist/drawing-gradient.js +39 -0
  19. package/dist/drawing-gradient.js.map +1 -0
  20. package/dist/drawing-stack.d.ts +16 -0
  21. package/dist/drawing-stack.d.ts.map +1 -0
  22. package/dist/drawing-stack.js +32 -0
  23. package/dist/drawing-stack.js.map +1 -0
  24. package/dist/drawing-transition.d.ts +34 -0
  25. package/dist/drawing-transition.d.ts.map +1 -0
  26. package/dist/drawing-transition.js +181 -0
  27. package/dist/drawing-transition.js.map +1 -0
  28. package/dist/drawing.d.ts +117 -0
  29. package/dist/drawing.d.ts.map +1 -0
  30. package/dist/drawing.js +337 -0
  31. package/dist/drawing.js.map +1 -0
  32. package/dist/element-label.d.ts +54 -0
  33. package/dist/element-label.d.ts.map +1 -0
  34. package/dist/element-label.js +377 -0
  35. package/dist/element-label.js.map +1 -0
  36. package/dist/element-style.d.ts +34 -0
  37. package/dist/element-style.d.ts.map +1 -0
  38. package/dist/element-style.js +51 -0
  39. package/dist/element-style.js.map +1 -0
  40. package/dist/element.d.ts +114 -0
  41. package/dist/element.d.ts.map +1 -0
  42. package/dist/element.js +514 -0
  43. package/dist/element.js.map +1 -0
  44. package/dist/element2term.d.ts +25 -0
  45. package/dist/element2term.d.ts.map +1 -0
  46. package/dist/element2term.js +245 -0
  47. package/dist/element2term.js.map +1 -0
  48. package/dist/elements/cables.d.ts +22 -0
  49. package/dist/elements/cables.d.ts.map +1 -0
  50. package/dist/elements/cables.js +100 -0
  51. package/dist/elements/cables.js.map +1 -0
  52. package/dist/elements/capacitor.d.ts +23 -0
  53. package/dist/elements/capacitor.d.ts.map +1 -0
  54. package/dist/elements/capacitor.js +93 -0
  55. package/dist/elements/capacitor.js.map +1 -0
  56. package/dist/elements/compound.d.ts +41 -0
  57. package/dist/elements/compound.d.ts.map +1 -0
  58. package/dist/elements/compound.js +266 -0
  59. package/dist/elements/compound.js.map +1 -0
  60. package/dist/elements/connectors.d.ts +81 -0
  61. package/dist/elements/connectors.d.ts.map +1 -0
  62. package/dist/elements/connectors.js +578 -0
  63. package/dist/elements/connectors.js.map +1 -0
  64. package/dist/elements/crystal.d.ts +8 -0
  65. package/dist/elements/crystal.d.ts.map +1 -0
  66. package/dist/elements/crystal.js +31 -0
  67. package/dist/elements/crystal.js.map +1 -0
  68. package/dist/elements/diode-more.d.ts +36 -0
  69. package/dist/elements/diode-more.d.ts.map +1 -0
  70. package/dist/elements/diode-more.js +233 -0
  71. package/dist/elements/diode-more.js.map +1 -0
  72. package/dist/elements/diode.d.ts +14 -0
  73. package/dist/elements/diode.d.ts.map +1 -0
  74. package/dist/elements/diode.js +58 -0
  75. package/dist/elements/diode.js.map +1 -0
  76. package/dist/elements/element-compound.d.ts +16 -0
  77. package/dist/elements/element-compound.d.ts.map +1 -0
  78. package/dist/elements/element-compound.js +68 -0
  79. package/dist/elements/element-compound.js.map +1 -0
  80. package/dist/elements/element-drawing.d.ts +10 -0
  81. package/dist/elements/element-drawing.d.ts.map +1 -0
  82. package/dist/elements/element-drawing.js +16 -0
  83. package/dist/elements/element-drawing.js.map +1 -0
  84. package/dist/elements/ground.d.ts +6 -0
  85. package/dist/elements/ground.d.ts.map +1 -0
  86. package/dist/elements/ground.js +30 -0
  87. package/dist/elements/ground.js.map +1 -0
  88. package/dist/elements/ic.d.ts +169 -0
  89. package/dist/elements/ic.d.ts.map +1 -0
  90. package/dist/elements/ic.js +816 -0
  91. package/dist/elements/ic.js.map +1 -0
  92. package/dist/elements/image.d.ts +9 -0
  93. package/dist/elements/image.d.ts.map +1 -0
  94. package/dist/elements/image.js +27 -0
  95. package/dist/elements/image.js.map +1 -0
  96. package/dist/elements/inductor.d.ts +15 -0
  97. package/dist/elements/inductor.d.ts.map +1 -0
  98. package/dist/elements/inductor.js +111 -0
  99. package/dist/elements/inductor.js.map +1 -0
  100. package/dist/elements/line.d.ts +8 -0
  101. package/dist/elements/line.d.ts.map +1 -0
  102. package/dist/elements/line.js +14 -0
  103. package/dist/elements/line.js.map +1 -0
  104. package/dist/elements/lines-arc-labels.d.ts +223 -0
  105. package/dist/elements/lines-arc-labels.d.ts.map +1 -0
  106. package/dist/elements/lines-arc-labels.js +822 -0
  107. package/dist/elements/lines-arc-labels.js.map +1 -0
  108. package/dist/elements/lines-elements.d.ts +89 -0
  109. package/dist/elements/lines-elements.d.ts.map +1 -0
  110. package/dist/elements/lines-elements.js +271 -0
  111. package/dist/elements/lines-elements.js.map +1 -0
  112. package/dist/elements/misc-elements.d.ts +25 -0
  113. package/dist/elements/misc-elements.d.ts.map +1 -0
  114. package/dist/elements/misc-elements.js +160 -0
  115. package/dist/elements/misc-elements.js.map +1 -0
  116. package/dist/elements/oneterm.d.ts +29 -0
  117. package/dist/elements/oneterm.d.ts.map +1 -0
  118. package/dist/elements/oneterm.js +163 -0
  119. package/dist/elements/oneterm.js.map +1 -0
  120. package/dist/elements/opamp.d.ts +11 -0
  121. package/dist/elements/opamp.d.ts.map +1 -0
  122. package/dist/elements/opamp.js +72 -0
  123. package/dist/elements/opamp.js.map +1 -0
  124. package/dist/elements/outlets.d.ts +39 -0
  125. package/dist/elements/outlets.d.ts.map +1 -0
  126. package/dist/elements/outlets.js +285 -0
  127. package/dist/elements/outlets.js.map +1 -0
  128. package/dist/elements/resistor-more.d.ts +42 -0
  129. package/dist/elements/resistor-more.d.ts.map +1 -0
  130. package/dist/elements/resistor-more.js +171 -0
  131. package/dist/elements/resistor-more.js.map +1 -0
  132. package/dist/elements/resistor.d.ts +6 -0
  133. package/dist/elements/resistor.d.ts.map +1 -0
  134. package/dist/elements/resistor.js +22 -0
  135. package/dist/elements/resistor.js.map +1 -0
  136. package/dist/elements/source-v.d.ts +3 -0
  137. package/dist/elements/source-v.d.ts.map +1 -0
  138. package/dist/elements/source-v.js +3 -0
  139. package/dist/elements/source-v.js.map +1 -0
  140. package/dist/elements/sources.d.ts +111 -0
  141. package/dist/elements/sources.d.ts.map +1 -0
  142. package/dist/elements/sources.js +519 -0
  143. package/dist/elements/sources.js.map +1 -0
  144. package/dist/elements/switches.d.ts +66 -0
  145. package/dist/elements/switches.d.ts.map +1 -0
  146. package/dist/elements/switches.js +328 -0
  147. package/dist/elements/switches.js.map +1 -0
  148. package/dist/elements/transformer.d.ts +17 -0
  149. package/dist/elements/transformer.d.ts.map +1 -0
  150. package/dist/elements/transformer.js +184 -0
  151. package/dist/elements/transformer.js.map +1 -0
  152. package/dist/elements/transistors.d.ts +197 -0
  153. package/dist/elements/transistors.d.ts.map +1 -0
  154. package/dist/elements/transistors.js +1009 -0
  155. package/dist/elements/transistors.js.map +1 -0
  156. package/dist/elements/tubes.d.ts +70 -0
  157. package/dist/elements/tubes.d.ts.map +1 -0
  158. package/dist/elements/tubes.js +386 -0
  159. package/dist/elements/tubes.js.map +1 -0
  160. package/dist/elements/twoports.d.ts +47 -0
  161. package/dist/elements/twoports.d.ts.map +1 -0
  162. package/dist/elements/twoports.js +231 -0
  163. package/dist/elements/twoports.js.map +1 -0
  164. package/dist/elements/twoterm-extras.d.ts +50 -0
  165. package/dist/elements/twoterm-extras.d.ts.map +1 -0
  166. package/dist/elements/twoterm-extras.js +243 -0
  167. package/dist/elements/twoterm-extras.js.map +1 -0
  168. package/dist/elements/twoterm.d.ts +4 -0
  169. package/dist/elements/twoterm.d.ts.map +1 -0
  170. package/dist/elements/twoterm.js +4 -0
  171. package/dist/elements/twoterm.js.map +1 -0
  172. package/dist/geometry/point.d.ts +28 -0
  173. package/dist/geometry/point.d.ts.map +1 -0
  174. package/dist/geometry/point.js +99 -0
  175. package/dist/geometry/point.js.map +1 -0
  176. package/dist/geometry/roundcorners.d.ts +7 -0
  177. package/dist/geometry/roundcorners.d.ts.map +1 -0
  178. package/dist/geometry/roundcorners.js +64 -0
  179. package/dist/geometry/roundcorners.js.map +1 -0
  180. package/dist/geometry/transform.d.ts +14 -0
  181. package/dist/geometry/transform.d.ts.map +1 -0
  182. package/dist/geometry/transform.js +33 -0
  183. package/dist/geometry/transform.js.map +1 -0
  184. package/dist/geometry/util.d.ts +12 -0
  185. package/dist/geometry/util.d.ts.map +1 -0
  186. package/dist/geometry/util.js +36 -0
  187. package/dist/geometry/util.js.map +1 -0
  188. package/dist/index.cjs +31456 -0
  189. package/dist/index.cjs.map +7 -0
  190. package/dist/index.d.ts +77 -0
  191. package/dist/index.d.ts.map +1 -0
  192. package/dist/index.js +68 -0
  193. package/dist/index.js.map +1 -0
  194. package/dist/json/anchor-ref.d.ts +5 -0
  195. package/dist/json/anchor-ref.d.ts.map +1 -0
  196. package/dist/json/anchor-ref.js +35 -0
  197. package/dist/json/anchor-ref.js.map +1 -0
  198. package/dist/json/mount.d.ts +60 -0
  199. package/dist/json/mount.d.ts.map +1 -0
  200. package/dist/json/mount.js +369 -0
  201. package/dist/json/mount.js.map +1 -0
  202. package/dist/json/registry.d.ts +7 -0
  203. package/dist/json/registry.d.ts.map +1 -0
  204. package/dist/json/registry.js +323 -0
  205. package/dist/json/registry.js.map +1 -0
  206. package/dist/json/render.d.ts +59 -0
  207. package/dist/json/render.d.ts.map +1 -0
  208. package/dist/json/render.js +113 -0
  209. package/dist/json/render.js.map +1 -0
  210. package/dist/json/theme.d.ts +18 -0
  211. package/dist/json/theme.d.ts.map +1 -0
  212. package/dist/json/theme.js +57 -0
  213. package/dist/json/theme.js.map +1 -0
  214. package/dist/json/types.d.ts +42 -0
  215. package/dist/json/types.d.ts.map +1 -0
  216. package/dist/json/types.js +2 -0
  217. package/dist/json/types.js.map +1 -0
  218. package/dist/json/validate.d.ts +11 -0
  219. package/dist/json/validate.d.ts.map +1 -0
  220. package/dist/json/validate.js +77 -0
  221. package/dist/json/validate.js.map +1 -0
  222. package/dist/label-hint.d.ts +11 -0
  223. package/dist/label-hint.d.ts.map +1 -0
  224. package/dist/label-hint.js +2 -0
  225. package/dist/label-hint.js.map +1 -0
  226. package/dist/logic/and.d.ts +13 -0
  227. package/dist/logic/and.d.ts.map +1 -0
  228. package/dist/logic/and.js +63 -0
  229. package/dist/logic/and.js.map +1 -0
  230. package/dist/logic/bitfield.d.ts +32 -0
  231. package/dist/logic/bitfield.d.ts.map +1 -0
  232. package/dist/logic/bitfield.js +271 -0
  233. package/dist/logic/bitfield.js.map +1 -0
  234. package/dist/logic/buffer.d.ts +11 -0
  235. package/dist/logic/buffer.d.ts.map +1 -0
  236. package/dist/logic/buffer.js +46 -0
  237. package/dist/logic/buffer.js.map +1 -0
  238. package/dist/logic/extras.d.ts +36 -0
  239. package/dist/logic/extras.d.ts.map +1 -0
  240. package/dist/logic/extras.js +211 -0
  241. package/dist/logic/extras.js.map +1 -0
  242. package/dist/logic/kmap.d.ts +16 -0
  243. package/dist/logic/kmap.d.ts.map +1 -0
  244. package/dist/logic/kmap.js +163 -0
  245. package/dist/logic/kmap.js.map +1 -0
  246. package/dist/logic/or.d.ts +18 -0
  247. package/dist/logic/or.d.ts.map +1 -0
  248. package/dist/logic/or.js +117 -0
  249. package/dist/logic/or.js.map +1 -0
  250. package/dist/logic/timing.d.ts +44 -0
  251. package/dist/logic/timing.d.ts.map +1 -0
  252. package/dist/logic/timing.js +791 -0
  253. package/dist/logic/timing.js.map +1 -0
  254. package/dist/logic/tristate.d.ts +11 -0
  255. package/dist/logic/tristate.d.ts.map +1 -0
  256. package/dist/logic/tristate.js +48 -0
  257. package/dist/logic/tristate.js.map +1 -0
  258. package/dist/math-render.d.ts +9 -0
  259. package/dist/math-render.d.ts.map +1 -0
  260. package/dist/math-render.js +53 -0
  261. package/dist/math-render.js.map +1 -0
  262. package/dist/package-api.d.ts +20 -0
  263. package/dist/package-api.d.ts.map +1 -0
  264. package/dist/package-api.js +75 -0
  265. package/dist/package-api.js.map +1 -0
  266. package/dist/params.d.ts +6 -0
  267. package/dist/params.d.ts.map +1 -0
  268. package/dist/params.js +35 -0
  269. package/dist/params.js.map +1 -0
  270. package/dist/react/index.d.ts +22 -0
  271. package/dist/react/index.d.ts.map +1 -0
  272. package/dist/react/index.js +52 -0
  273. package/dist/react/index.js.map +1 -0
  274. package/dist/schemdraw-ts.bundle.js +30448 -0
  275. package/dist/schemdraw-ts.bundle.js.map +7 -0
  276. package/dist/segment.d.ts +267 -0
  277. package/dist/segment.d.ts.map +1 -0
  278. package/dist/segment.js +844 -0
  279. package/dist/segment.js.map +1 -0
  280. package/dist/style.d.ts +18 -0
  281. package/dist/style.d.ts.map +1 -0
  282. package/dist/style.js +230 -0
  283. package/dist/style.js.map +1 -0
  284. package/dist/subsystems/dsp.d.ts +65 -0
  285. package/dist/subsystems/dsp.d.ts.map +1 -0
  286. package/dist/subsystems/dsp.js +267 -0
  287. package/dist/subsystems/dsp.js.map +1 -0
  288. package/dist/subsystems/flow.d.ts +92 -0
  289. package/dist/subsystems/flow.d.ts.map +1 -0
  290. package/dist/subsystems/flow.js +315 -0
  291. package/dist/subsystems/flow.js.map +1 -0
  292. package/dist/subsystems/index.d.ts +22 -0
  293. package/dist/subsystems/index.d.ts.map +1 -0
  294. package/dist/subsystems/index.js +22 -0
  295. package/dist/subsystems/index.js.map +1 -0
  296. package/dist/subsystems/parsing.d.ts +41 -0
  297. package/dist/subsystems/parsing.d.ts.map +1 -0
  298. package/dist/subsystems/parsing.js +456 -0
  299. package/dist/subsystems/parsing.js.map +1 -0
  300. package/dist/subsystems/pictorial.d.ts +73 -0
  301. package/dist/subsystems/pictorial.d.ts.map +1 -0
  302. package/dist/subsystems/pictorial.js +469 -0
  303. package/dist/subsystems/pictorial.js.map +1 -0
  304. package/dist/svg/constants.d.ts +5 -0
  305. package/dist/svg/constants.d.ts.map +1 -0
  306. package/dist/svg/constants.js +5 -0
  307. package/dist/svg/constants.js.map +1 -0
  308. package/dist/svg/figure.d.ts +157 -0
  309. package/dist/svg/figure.d.ts.map +1 -0
  310. package/dist/svg/figure.js +634 -0
  311. package/dist/svg/figure.js.map +1 -0
  312. package/dist/svg/fmt.d.ts +2 -0
  313. package/dist/svg/fmt.d.ts.map +1 -0
  314. package/dist/svg/fmt.js +7 -0
  315. package/dist/svg/fmt.js.map +1 -0
  316. package/dist/svg/svg-style.d.ts +15 -0
  317. package/dist/svg/svg-style.d.ts.map +1 -0
  318. package/dist/svg/svg-style.js +46 -0
  319. package/dist/svg/svg-style.js.map +1 -0
  320. package/dist/types.d.ts +39 -0
  321. package/dist/types.d.ts.map +1 -0
  322. package/dist/types.js +21 -0
  323. package/dist/types.js.map +1 -0
  324. package/dist/version.d.ts +3 -0
  325. package/dist/version.d.ts.map +1 -0
  326. package/dist/version.js +3 -0
  327. package/dist/version.js.map +1 -0
  328. package/dist/vue/index.d.ts +43 -0
  329. package/dist/vue/index.d.ts.map +1 -0
  330. package/dist/vue/index.js +55 -0
  331. package/dist/vue/index.js.map +1 -0
  332. package/package.json +71 -0
@@ -0,0 +1,844 @@
1
+ import { bbox } from "./types.js";
2
+ import { flipXY, mirrorxXY } from "./geometry/util.js";
3
+ import { Point } from "./geometry/point.js";
4
+ import { roundCorners } from "./geometry/roundcorners.js";
5
+ import { textSize } from "./svg/figure.js";
6
+ import { PT_PER_IN } from "./svg/constants.js";
7
+ import { hasMath, isKatexAvailable, renderMathHtml, estimateMathSize } from "./math-render.js";
8
+ export const GAP = [Number.NaN, Number.NaN];
9
+ /** Resolve the special fill value `"bg"` to the drawing's background color (default white). */
10
+ function resolveBgFill(fill, style) {
11
+ if (typeof fill === "string" && fill.toLowerCase() === "bg") {
12
+ return style.bgcolor ?? "white";
13
+ }
14
+ return fill;
15
+ }
16
+ function isGap(p) {
17
+ if (Array.isArray(p)) {
18
+ return Number.isNaN(p[0]) && Number.isNaN(p[1]);
19
+ }
20
+ return false;
21
+ }
22
+ function pathPointToPair(p) {
23
+ if (isGap(p)) {
24
+ return [Number.NaN, Number.NaN];
25
+ }
26
+ return p instanceof Point ? [p.x, p.y] : [p[0], p[1]];
27
+ }
28
+ export class Segment {
29
+ path;
30
+ color;
31
+ lw;
32
+ ls;
33
+ capstyle;
34
+ joinstyle;
35
+ fill;
36
+ arrow;
37
+ arrowwidth = 0.15;
38
+ arrowlength = 0.25;
39
+ zorder;
40
+ visible = true;
41
+ clip;
42
+ role;
43
+ gradientStrokeId;
44
+ constructor(path, opts = {}) {
45
+ this.path = path.map(pathPointToPair);
46
+ Object.assign(this, opts);
47
+ }
48
+ xform(transform, style) {
49
+ const pts = transform.transformArray(this.path.map(([x, y]) => [x, y]));
50
+ const path = pts.map((pt) => [pt.x, pt.y]);
51
+ return new Segment(path, {
52
+ color: this.color ?? style.color,
53
+ lw: this.lw ?? style.lw,
54
+ ls: this.ls ?? style.ls,
55
+ capstyle: this.capstyle ?? style.capstyle,
56
+ joinstyle: this.joinstyle ?? style.joinstyle,
57
+ fill: this.fill ?? style.fill,
58
+ arrow: this.arrow,
59
+ arrowwidth: this.arrowwidth,
60
+ arrowlength: this.arrowlength,
61
+ zorder: this.zorder ?? style.zorder,
62
+ visible: this.visible,
63
+ clip: this.clip,
64
+ });
65
+ }
66
+ getBBox() {
67
+ const xs = this.path.map((p) => p[0]).filter((x) => !Number.isNaN(x));
68
+ const ys = this.path.map((p) => p[1]).filter((y) => !Number.isNaN(y));
69
+ const hw = this.arrow ? this.arrowwidth ?? 0 : 0;
70
+ return bbox(Math.min(...xs), Math.min(...ys) - hw, Math.max(...xs), Math.max(...ys) + hw);
71
+ }
72
+ /** Python `Segment.doreverse` — mirror path after reversing point order. */
73
+ doreverse(centerx) {
74
+ const rev = [...this.path].reverse();
75
+ this.path = rev.map(([x, y]) => {
76
+ if (Number.isNaN(x) && Number.isNaN(y)) {
77
+ return [x, y];
78
+ }
79
+ return mirrorxXY(x, y, centerx);
80
+ });
81
+ if (this.arrow) {
82
+ this.arrow = this.arrow
83
+ .split("")
84
+ .map((c) => (c === "<" ? ">" : c === ">" ? "<" : c))
85
+ .join("");
86
+ }
87
+ }
88
+ /** Python `Segment.doflip` — vertical flip of path points. */
89
+ doflip() {
90
+ this.path = this.path.map(([x, y]) => {
91
+ if (Number.isNaN(x) && Number.isNaN(y)) {
92
+ return [x, y];
93
+ }
94
+ return flipXY(x, y);
95
+ });
96
+ }
97
+ draw(fig, transform, style) {
98
+ if (!this.visible) {
99
+ return;
100
+ }
101
+ const path = transform.transformArray(this.path.map(([x, y]) => [x, y]));
102
+ let linepath = path.map((p) => new Point(p.x, p.y));
103
+ const color = (this.color ?? style.color ?? "black");
104
+ const ls = (this.ls ?? style.ls ?? "-");
105
+ const lw = (this.lw ?? style.lw ?? 2);
106
+ const capstyle = (this.capstyle ?? style.capstyle ?? "round");
107
+ const joinstyle = (this.joinstyle ?? style.joinstyle ?? "round");
108
+ let fill = resolveBgFill(this.fill ?? style.fill, style);
109
+ const zorder = this.zorder ?? style.zorder ?? 2;
110
+ const gid = style._svgGradientFillId;
111
+ if (fill) {
112
+ const tlist = linepath.map((p) => `${p.x},${p.y}`);
113
+ const uniq = new Set(tlist);
114
+ const dofill = tlist.length !== uniq.size;
115
+ if (!dofill) {
116
+ fill = undefined;
117
+ }
118
+ else if (fill === true) {
119
+ fill = color;
120
+ }
121
+ }
122
+ if (gid && fill) {
123
+ fill = `url(#${gid})`;
124
+ }
125
+ if (this.arrow?.includes("<")) {
126
+ const delta = linepath[1].sub(linepath[0]);
127
+ const th = Math.atan2(delta.y, delta.x);
128
+ linepath = [...linepath];
129
+ linepath[0] = new Point(linepath[0].x + this.arrowlength * Math.cos(th), linepath[0].y + this.arrowlength * Math.sin(th));
130
+ }
131
+ if (this.arrow?.includes(">")) {
132
+ const delta = linepath[linepath.length - 1].sub(linepath[linepath.length - 2]);
133
+ const th = Math.atan2(delta.y, delta.x);
134
+ linepath = [...linepath];
135
+ const last = linepath.length - 1;
136
+ linepath[last] = new Point(linepath[last].x - this.arrowlength * Math.cos(th), linepath[last].y - this.arrowlength * Math.sin(th));
137
+ }
138
+ const strokeColor = this.gradientStrokeId ? `url(#${this.gradientStrokeId})` : color;
139
+ const xs = linepath.map((p) => p.x);
140
+ const ys = linepath.map((p) => p.y);
141
+ fig.plot(xs, ys, {
142
+ color: strokeColor,
143
+ ls,
144
+ lw,
145
+ capstyle,
146
+ joinstyle,
147
+ fill: fill ?? "none",
148
+ zorder,
149
+ });
150
+ if (this.arrow) {
151
+ const pathPts = path.map((p) => new Point(p.x, p.y));
152
+ if (this.arrow.includes("<")) {
153
+ const theta = (Math.atan2(pathPts[0].y - pathPts[1].y, pathPts[0].x - pathPts[1].x) * 180) / Math.PI;
154
+ fig.arrow([pathPts[0].x, pathPts[0].y], theta, {
155
+ color,
156
+ zorder,
157
+ arrowlength: this.arrowlength,
158
+ arrowwidth: this.arrowwidth,
159
+ lw: 1,
160
+ });
161
+ }
162
+ if (this.arrow.includes(">")) {
163
+ const theta = (Math.atan2(pathPts[pathPts.length - 1].y - pathPts[pathPts.length - 2].y, pathPts[pathPts.length - 1].x - pathPts[pathPts.length - 2].x) *
164
+ 180) /
165
+ Math.PI;
166
+ fig.arrow([pathPts[pathPts.length - 1].x, pathPts[pathPts.length - 1].y], theta, {
167
+ color,
168
+ zorder,
169
+ arrowlength: this.arrowlength,
170
+ arrowwidth: this.arrowwidth,
171
+ lw: 1,
172
+ });
173
+ }
174
+ }
175
+ }
176
+ }
177
+ export class SegmentCircle {
178
+ center;
179
+ radius;
180
+ color;
181
+ lw;
182
+ ls;
183
+ fill;
184
+ zorder;
185
+ visible = true;
186
+ constructor(center, radius, opts = {}) {
187
+ this.center = center;
188
+ this.radius = radius;
189
+ Object.assign(this, opts);
190
+ }
191
+ xform(transform, style) {
192
+ const c = transform.transform(this.center);
193
+ const z = transform.zoom;
194
+ const uniform = z.x === z.y;
195
+ if (!uniform) {
196
+ throw new Error("SegmentCircle xform with non-uniform zoom not implemented in TS subset");
197
+ }
198
+ return new SegmentCircle([c.x, c.y], this.radius * z.x, {
199
+ color: this.color ?? style.color,
200
+ lw: this.lw ?? style.lw,
201
+ ls: (this.ls ?? style.ls),
202
+ fill: this.fill ?? style.fill,
203
+ zorder: this.zorder ?? style.zorder,
204
+ });
205
+ }
206
+ getBBox() {
207
+ const [cx, cy] = this.center;
208
+ const r = this.radius;
209
+ return bbox(cx - r, cy - r, cx + r, cy + r);
210
+ }
211
+ doreverse(centerx) {
212
+ this.center = mirrorxXY(this.center[0], this.center[1], centerx);
213
+ }
214
+ doflip() {
215
+ this.center = flipXY(this.center[0], this.center[1]);
216
+ }
217
+ draw(fig, transform, style) {
218
+ if (!this.visible) {
219
+ return;
220
+ }
221
+ const gid = style._svgGradientFillId;
222
+ const c = transform.transform(this.center);
223
+ const r = this.radius * transform.zoom.x;
224
+ const color = (this.color ?? style.color ?? "black");
225
+ const lw = (this.lw ?? style.lw ?? 2);
226
+ let fill = resolveBgFill(this.fill ?? style.fill, style);
227
+ if (gid) {
228
+ fill = `url(#${gid})`;
229
+ }
230
+ else if (fill === true) {
231
+ fill = color;
232
+ }
233
+ else if (fill === false) {
234
+ fill = "none";
235
+ }
236
+ if (fill === undefined || fill === null) {
237
+ fill = "none";
238
+ }
239
+ fig.circle(c.x, c.y, r, {
240
+ color,
241
+ lw,
242
+ ls: (this.ls ?? style.ls),
243
+ fill: fill,
244
+ zorder: this.zorder ?? style.zorder ?? 1,
245
+ });
246
+ }
247
+ }
248
+ /** Text label in element-local coordinates — aligned with Python `SegmentText` (subset). */
249
+ export class SegmentText {
250
+ xy;
251
+ text;
252
+ color;
253
+ fontsize;
254
+ fontfamily;
255
+ /** Math font (Python `SegmentText.mathfont`); used when text contains `$…$` (no Ziamath — SVG font-family only). */
256
+ mathfont;
257
+ zorder;
258
+ visible = true;
259
+ halign;
260
+ valign;
261
+ /** Hyperlink on label (Python `IcPin.href`). */
262
+ href;
263
+ /** `"underline"` / `"overline"` (Python `IcPin.decoration`). */
264
+ decoration;
265
+ /**
266
+ * Extra rotation in degrees (local), added to the element transform (Python `IcPin` name labels).
267
+ * If omitted, text is not rotated with the element (legacy behavior for unlabeled segments).
268
+ */
269
+ rotation;
270
+ constructor(xy, text, opts = {}) {
271
+ const p = xy instanceof Point ? xy : Point.fromXY(xy);
272
+ this.xy = [p.x, p.y];
273
+ this.text = text;
274
+ const al = opts.align;
275
+ if (al) {
276
+ this.halign = al[0];
277
+ this.valign = al[1];
278
+ }
279
+ Object.assign(this, opts);
280
+ }
281
+ xform(transform, style) {
282
+ const p = transform.transform(this.xy);
283
+ return new SegmentText([p.x, p.y], this.text, {
284
+ color: this.color ?? style.color,
285
+ fontsize: this.fontsize ?? style.fontsize,
286
+ fontfamily: this.fontfamily ?? style.font,
287
+ mathfont: this.mathfont ?? style.mathfont,
288
+ zorder: this.zorder ?? style.zorder,
289
+ visible: this.visible,
290
+ halign: this.halign,
291
+ valign: this.valign,
292
+ href: this.href,
293
+ decoration: this.decoration,
294
+ rotation: this.rotation,
295
+ });
296
+ }
297
+ getBBox() {
298
+ const fs = this.fontsize ?? 14;
299
+ const scale = PT_PER_IN * 0.5;
300
+ let w;
301
+ let h;
302
+ if (hasMath(this.text)) {
303
+ const sz = estimateMathSize(this.text, fs);
304
+ w = sz.width / scale;
305
+ h = sz.height / scale;
306
+ }
307
+ else {
308
+ const { width: wPt, height: hPt } = textSize(this.text, fs, this.fontfamily);
309
+ w = wPt / scale;
310
+ h = hPt / scale;
311
+ }
312
+ const ha = this.halign ?? "center";
313
+ let x0;
314
+ let x1;
315
+ if (ha === "left") {
316
+ x0 = this.xy[0];
317
+ x1 = this.xy[0] + w;
318
+ }
319
+ else if (ha === "right") {
320
+ x0 = this.xy[0] - w;
321
+ x1 = this.xy[0];
322
+ }
323
+ else {
324
+ x0 = this.xy[0] - w / 2;
325
+ x1 = this.xy[0] + w / 2;
326
+ }
327
+ const va = this.valign ?? "center";
328
+ let y = this.xy[1];
329
+ if (va === "center") {
330
+ y -= h / 2;
331
+ }
332
+ else if (va === "top") {
333
+ y -= h;
334
+ }
335
+ else if (va === "bottom") {
336
+ // y stays — bottom of text at anchor, text extends upward
337
+ }
338
+ else {
339
+ // base: approximate by treating like bottom
340
+ const nlines = this.text.split("\n").length;
341
+ y += fs * (2 / PT_PER_IN) * (nlines - 1);
342
+ }
343
+ return bbox(x0, y, x1, y + h);
344
+ }
345
+ doreverse(centerx) {
346
+ this.xy = mirrorxXY(this.xy[0], this.xy[1], centerx);
347
+ if (this.halign === "left") {
348
+ this.halign = "right";
349
+ }
350
+ else if (this.halign === "right") {
351
+ this.halign = "left";
352
+ }
353
+ }
354
+ doflip() {
355
+ this.xy = flipXY(this.xy[0], this.xy[1]);
356
+ if (this.valign === "top") {
357
+ this.valign = "bottom";
358
+ }
359
+ else if (this.valign === "bottom") {
360
+ this.valign = "top";
361
+ }
362
+ }
363
+ draw(fig, transform, style) {
364
+ if (!this.visible) {
365
+ return;
366
+ }
367
+ const p = transform.transform(this.xy);
368
+ const color = (this.color ?? style.color ?? "black");
369
+ const fontsize = (this.fontsize ?? style.fontsize ?? 14);
370
+ const baseFont = (this.fontfamily ?? style.font ?? "sans-serif");
371
+ const mathf = (this.mathfont ?? style.mathfont);
372
+ const t = this.text;
373
+ const baseDeg = (transform.theta * 180) / Math.PI;
374
+ const rotDeg = this.rotation !== undefined ? baseDeg + this.rotation : undefined;
375
+ if (hasMath(t) && isKatexAvailable()) {
376
+ const html = renderMathHtml(t, fontsize);
377
+ const { width, height } = estimateMathSize(t, fontsize);
378
+ fig.mathText(html, p.x, p.y, {
379
+ width,
380
+ height,
381
+ color,
382
+ fontsize,
383
+ halign: this.halign ?? "center",
384
+ valign: this.valign ?? "center",
385
+ zorder: this.zorder ?? style.zorder ?? 3,
386
+ rotation: rotDeg,
387
+ });
388
+ return;
389
+ }
390
+ const font = mathf !== undefined && mathf !== "" && t.includes("$") ? mathf : baseFont;
391
+ const dec = this.decoration?.toLowerCase();
392
+ const textDecoration = dec === "underline" || dec === "overline" ? dec : undefined;
393
+ fig.text(this.text, p.x, p.y, {
394
+ color,
395
+ fontsize,
396
+ fontfamily: font,
397
+ halign: this.halign ?? "center",
398
+ valign: this.valign ?? "center",
399
+ zorder: this.zorder ?? style.zorder ?? 3,
400
+ href: this.href ?? undefined,
401
+ textDecoration,
402
+ rotation: rotDeg,
403
+ });
404
+ }
405
+ }
406
+ export class SegmentPoly {
407
+ verts;
408
+ closed = true;
409
+ cornerradius = 0;
410
+ color;
411
+ fill;
412
+ lw;
413
+ ls;
414
+ hatch;
415
+ joinstyle;
416
+ capstyle;
417
+ zorder;
418
+ visible = true;
419
+ clip;
420
+ constructor(verts, opts = {}) {
421
+ this.verts = verts;
422
+ Object.assign(this, opts);
423
+ }
424
+ xform(transform, style) {
425
+ const pts = transform.transformArray(this.verts.map(([x, y]) => [x, y]));
426
+ const v = pts.map((p) => [p.x, p.y]);
427
+ return new SegmentPoly(v, {
428
+ closed: this.closed,
429
+ cornerradius: this.cornerradius,
430
+ color: this.color ?? style.color,
431
+ fill: this.fill ?? style.fill,
432
+ lw: this.lw ?? style.lw,
433
+ ls: this.ls ?? style.ls,
434
+ hatch: this.hatch,
435
+ joinstyle: this.joinstyle ?? style.joinstyle,
436
+ capstyle: this.capstyle ?? style.capstyle,
437
+ zorder: this.zorder ?? style.zorder,
438
+ visible: this.visible,
439
+ clip: this.clip,
440
+ });
441
+ }
442
+ getBBox() {
443
+ const x = this.verts.map((p) => p[0]);
444
+ const y = this.verts.map((p) => p[1]);
445
+ return bbox(Math.min(...x), Math.min(...y), Math.max(...x), Math.max(...y));
446
+ }
447
+ doreverse(centerx) {
448
+ this.verts = [...this.verts].reverse().map(([x, y]) => mirrorxXY(x, y, centerx));
449
+ }
450
+ doflip() {
451
+ this.verts = this.verts.map(([x, y]) => flipXY(x, y));
452
+ }
453
+ draw(fig, transform, style) {
454
+ if (!this.visible) {
455
+ return;
456
+ }
457
+ const gid = style._svgGradientFillId;
458
+ let rawFill = this.fill !== undefined ? this.fill : style.fill;
459
+ rawFill = resolveBgFill(rawFill, style);
460
+ let fill = rawFill === true
461
+ ? (style.color ?? "black")
462
+ : typeof rawFill === "string"
463
+ ? rawFill
464
+ : undefined;
465
+ if (gid && this.closed) {
466
+ fill = `url(#${gid})`;
467
+ }
468
+ const color = (this.color ?? style.color ?? "black");
469
+ const verts = transform.transformArray(this.verts.map(([x, y]) => [x, y]));
470
+ let vlist = verts.map((p) => ({ x: p.x, y: p.y }));
471
+ if (this.cornerradius > 0) {
472
+ const rc = roundCorners(this.verts.map(([x, y]) => [x, y]), this.cornerradius);
473
+ vlist = transform.transformArray(rc.map((p) => [p.x, p.y])).map((p) => ({ x: p.x, y: p.y }));
474
+ }
475
+ fig.poly(vlist, {
476
+ closed: this.closed,
477
+ color,
478
+ fill: fill === undefined ? "none" : fill,
479
+ lw: (this.lw ?? style.lw ?? 2),
480
+ ls: (this.ls ?? style.ls ?? "-"),
481
+ hatch: this.hatch,
482
+ capstyle: (this.capstyle ?? style.capstyle ?? "round"),
483
+ joinstyle: (this.joinstyle ?? style.joinstyle ?? "round"),
484
+ zorder: this.zorder ?? style.zorder ?? 1,
485
+ });
486
+ }
487
+ }
488
+ export class SegmentArc {
489
+ center;
490
+ width;
491
+ height;
492
+ theta1;
493
+ theta2;
494
+ arrow;
495
+ arrowwidth = 0.15;
496
+ arrowlength = 0.25;
497
+ angle = 0;
498
+ color;
499
+ lw;
500
+ ls;
501
+ fill;
502
+ zorder;
503
+ visible = true;
504
+ clip;
505
+ constructor(center, width, height, opts = {}) {
506
+ this.center = center;
507
+ this.width = width;
508
+ this.height = height;
509
+ this.theta1 = opts.theta1 ?? 35;
510
+ this.theta2 = opts.theta2 ?? -35;
511
+ this.arrow = opts.arrow;
512
+ if (opts.arrowwidth !== undefined) {
513
+ this.arrowwidth = opts.arrowwidth;
514
+ }
515
+ if (opts.arrowlength !== undefined) {
516
+ this.arrowlength = opts.arrowlength;
517
+ }
518
+ this.angle = opts.angle ?? 0;
519
+ this.color = opts.color;
520
+ this.lw = opts.lw;
521
+ this.ls = opts.ls;
522
+ this.fill = opts.fill;
523
+ this.zorder = opts.zorder;
524
+ this.visible = opts.visible ?? true;
525
+ this.clip = opts.clip;
526
+ }
527
+ xform(transform, style) {
528
+ const c = transform.transform(this.center);
529
+ const ang = this.angle + transform.theta;
530
+ return new SegmentArc([c.x, c.y], this.width * transform.zoom.x, this.height * transform.zoom.y, {
531
+ theta1: this.theta1,
532
+ theta2: this.theta2,
533
+ angle: ang,
534
+ arrow: this.arrow,
535
+ arrowwidth: this.arrowwidth,
536
+ arrowlength: this.arrowlength,
537
+ color: this.color ?? style.color,
538
+ lw: this.lw ?? style.lw,
539
+ ls: this.ls ?? style.ls,
540
+ fill: this.fill ?? style.fill,
541
+ zorder: this.zorder ?? style.zorder,
542
+ visible: this.visible,
543
+ clip: this.clip,
544
+ });
545
+ }
546
+ getBBox() {
547
+ const th1 = (this.theta1 * Math.PI) / 180;
548
+ const th2 = (this.theta2 * Math.PI) / 180;
549
+ let t1a = Math.atan2(this.width * Math.sin(th1), this.height * Math.cos(th1));
550
+ let t2a = Math.atan2(this.width * Math.sin(th2), this.height * Math.cos(th2));
551
+ while (t2a < t1a) {
552
+ t2a += 2 * Math.PI;
553
+ }
554
+ const phi = (this.angle * Math.PI) / 180;
555
+ const rx = this.width / 2;
556
+ const ry = this.height / 2;
557
+ const n = 50;
558
+ const xx = [];
559
+ const yy = [];
560
+ for (let i = 0; i <= n; i++) {
561
+ const t = t1a + ((t2a - t1a) * i) / n;
562
+ const st = Math.sin(t);
563
+ const ct = Math.cos(t);
564
+ xx.push(this.center[0] + rx * ct * Math.cos(phi) - ry * st * Math.sin(phi));
565
+ yy.push(this.center[1] + rx * ct * Math.sin(phi) + ry * st * Math.cos(phi));
566
+ }
567
+ return bbox(Math.min(...xx), Math.min(...yy), Math.max(...xx), Math.max(...yy));
568
+ }
569
+ doreverse(centerx) {
570
+ this.center = mirrorxXY(this.center[0], this.center[1], centerx);
571
+ const t1 = this.theta1;
572
+ const t2 = this.theta2;
573
+ this.theta1 = 180 - t2;
574
+ this.theta2 = 180 - t1;
575
+ if (this.arrow === "cw") {
576
+ this.arrow = "ccw";
577
+ }
578
+ else if (this.arrow === "ccw") {
579
+ this.arrow = "cw";
580
+ }
581
+ }
582
+ doflip() {
583
+ this.center = flipXY(this.center[0], this.center[1]);
584
+ const t1 = this.theta1;
585
+ const t2 = this.theta2;
586
+ this.theta1 = -t2;
587
+ this.theta2 = -t1;
588
+ if (this.arrow === "cw") {
589
+ this.arrow = "ccw";
590
+ }
591
+ else if (this.arrow === "ccw") {
592
+ this.arrow = "cw";
593
+ }
594
+ }
595
+ draw(fig, transform, style) {
596
+ if (!this.visible) {
597
+ return;
598
+ }
599
+ const c = transform.transform(this.center);
600
+ const w = this.width * transform.zoom.x;
601
+ const h = this.height * transform.zoom.y;
602
+ fig.arc([c.x, c.y], w, h, {
603
+ theta1: this.theta1,
604
+ theta2: this.theta2,
605
+ angle: this.angle + transform.theta,
606
+ color: (this.color ?? style.color ?? "black"),
607
+ lw: (this.lw ?? style.lw ?? 2),
608
+ ls: (this.ls ?? style.ls ?? "-"),
609
+ fill: resolveBgFill(this.fill ?? style.fill, style),
610
+ zorder: this.zorder ?? style.zorder ?? 1,
611
+ arrow: this.arrow ?? undefined,
612
+ arrowwidth: this.arrowwidth,
613
+ arrowlength: this.arrowlength,
614
+ });
615
+ }
616
+ }
617
+ export class SegmentBezier {
618
+ p;
619
+ color;
620
+ lw;
621
+ ls;
622
+ capstyle;
623
+ arrow;
624
+ arrowlength = 0.25;
625
+ arrowwidth = 0.15;
626
+ zorder;
627
+ visible = true;
628
+ clip;
629
+ constructor(pts, opts = {}) {
630
+ this.p = pts;
631
+ Object.assign(this, opts);
632
+ }
633
+ xform(transform, style) {
634
+ const pts = transform.transformArray(this.p.map(([x, y]) => [x, y]));
635
+ const pp = pts.map((pt) => [pt.x, pt.y]);
636
+ return new SegmentBezier(pp, {
637
+ color: this.color ?? style.color,
638
+ lw: this.lw ?? style.lw,
639
+ ls: this.ls ?? style.ls,
640
+ capstyle: this.capstyle ?? style.capstyle,
641
+ arrow: this.arrow,
642
+ arrowlength: this.arrowlength,
643
+ arrowwidth: this.arrowwidth,
644
+ zorder: this.zorder ?? style.zorder,
645
+ visible: this.visible,
646
+ clip: this.clip,
647
+ });
648
+ }
649
+ getBBox() {
650
+ const t = linspaceBezier(0, 1, 50);
651
+ const px = this.p.map((q) => q[0]);
652
+ const py = this.p.map((q) => q[1]);
653
+ let x;
654
+ let y;
655
+ if (this.p.length === 3) {
656
+ x = t.map((tt) => (1 - tt) ** 2 * px[0] + 2 * (1 - tt) * tt * px[1] + tt ** 2 * px[2]);
657
+ y = t.map((tt) => (1 - tt) ** 2 * py[0] + 2 * (1 - tt) * tt * py[1] + tt ** 2 * py[2]);
658
+ }
659
+ else {
660
+ x = t.map((tt) => (1 - tt) ** 3 * px[0] +
661
+ 3 * (1 - tt) ** 2 * tt * px[1] +
662
+ 3 * (1 - tt) * tt ** 2 * px[2] +
663
+ tt ** 3 * px[3]);
664
+ y = t.map((tt) => (1 - tt) ** 3 * py[0] +
665
+ 3 * (1 - tt) ** 2 * tt * py[1] +
666
+ 3 * (1 - tt) * tt ** 2 * py[2] +
667
+ tt ** 3 * py[3]);
668
+ }
669
+ return bbox(Math.min(...x), Math.min(...y), Math.max(...x), Math.max(...y));
670
+ }
671
+ doreverse(centerx) {
672
+ /** Python `SegmentBezier` mirrors each control point (no path reversal). */
673
+ this.p = this.p.map(([x, y]) => mirrorxXY(x, y, centerx));
674
+ if (this.arrow) {
675
+ const rev = [...this.arrow].reverse().join("");
676
+ this.arrow = rev
677
+ .split("")
678
+ .map((c) => (c === "<" ? ">" : c === ">" ? "<" : c))
679
+ .join("");
680
+ }
681
+ }
682
+ doflip() {
683
+ this.p = this.p.map(([x, y]) => flipXY(x, y));
684
+ }
685
+ draw(fig, transform, style) {
686
+ if (!this.visible) {
687
+ return;
688
+ }
689
+ const pts = transform.transformArray(this.p.map(([x, y]) => [x, y]));
690
+ const pp = pts.map((p) => ({ x: p.x, y: p.y }));
691
+ fig.bezier(pp, {
692
+ color: (this.color ?? style.color ?? "black"),
693
+ lw: (this.lw ?? style.lw ?? 2),
694
+ ls: (this.ls ?? style.ls ?? "-"),
695
+ capstyle: (this.capstyle ?? style.capstyle ?? "round"),
696
+ zorder: this.zorder ?? style.zorder ?? 1,
697
+ arrow: this.arrow,
698
+ arrowlength: this.arrowlength,
699
+ arrowwidth: this.arrowwidth,
700
+ });
701
+ }
702
+ }
703
+ function linspaceBezier(a, b, n) {
704
+ if (n < 2) {
705
+ return [a];
706
+ }
707
+ const step = (b - a) / (n - 1);
708
+ return Array.from({ length: n }, (_, i) => a + step * i);
709
+ }
710
+ export class SegmentPath {
711
+ path;
712
+ color;
713
+ lw;
714
+ ls;
715
+ capstyle;
716
+ joinstyle;
717
+ fill;
718
+ zorder;
719
+ visible = true;
720
+ clip;
721
+ constructor(path, opts = {}) {
722
+ this.path = path;
723
+ Object.assign(this, opts);
724
+ }
725
+ xform(transform, style) {
726
+ const next = [];
727
+ for (const item of this.path) {
728
+ if (typeof item === "string") {
729
+ next.push(item);
730
+ }
731
+ else {
732
+ const p = transform.transform(item);
733
+ next.push([p.x, p.y]);
734
+ }
735
+ }
736
+ return new SegmentPath(next, {
737
+ color: this.color ?? style.color,
738
+ lw: this.lw ?? style.lw,
739
+ ls: this.ls ?? style.ls,
740
+ capstyle: this.capstyle ?? style.capstyle,
741
+ joinstyle: this.joinstyle ?? style.joinstyle,
742
+ fill: this.fill ?? style.fill,
743
+ zorder: this.zorder ?? style.zorder,
744
+ visible: this.visible,
745
+ clip: this.clip,
746
+ });
747
+ }
748
+ getBBox() {
749
+ const xs = [];
750
+ const ys = [];
751
+ for (const item of this.path) {
752
+ if (typeof item !== "string") {
753
+ xs.push(item[0]);
754
+ ys.push(item[1]);
755
+ }
756
+ }
757
+ if (xs.length === 0) {
758
+ return bbox(0, 0, 0, 0);
759
+ }
760
+ return bbox(Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys));
761
+ }
762
+ /** SVG path commands are not transformed; matches Python stub. */
763
+ doreverse(_centerx) { }
764
+ doflip() { }
765
+ draw(fig, transform, style) {
766
+ if (!this.visible) {
767
+ return;
768
+ }
769
+ const parts = [];
770
+ for (const item of this.path) {
771
+ if (typeof item === "string") {
772
+ parts.push(item);
773
+ }
774
+ else {
775
+ const p = transform.transform(item);
776
+ parts.push({ x: p.x, y: p.y });
777
+ }
778
+ }
779
+ fig.path(parts, {
780
+ color: (this.color ?? style.color ?? "black"),
781
+ lw: (this.lw ?? style.lw ?? 2),
782
+ ls: (this.ls ?? style.ls ?? "-"),
783
+ capstyle: (this.capstyle ?? style.capstyle ?? "round"),
784
+ joinstyle: (this.joinstyle ?? style.joinstyle ?? "round"),
785
+ fill: (this.fill === true ? style.color : resolveBgFill(this.fill, style)),
786
+ zorder: this.zorder ?? style.zorder ?? 1,
787
+ });
788
+ }
789
+ }
790
+ export class SegmentImage {
791
+ image;
792
+ xy;
793
+ width;
794
+ height;
795
+ rotate;
796
+ imgfmt;
797
+ zorder;
798
+ visible = true;
799
+ constructor(image, opts = {}) {
800
+ this.image = image;
801
+ this.xy = opts.xy ?? [0, 0];
802
+ this.width = opts.width ?? 3;
803
+ this.height = opts.height ?? 1;
804
+ this.rotate = opts.rotate ?? 0;
805
+ this.imgfmt = opts.imgfmt;
806
+ this.zorder = opts.zorder;
807
+ }
808
+ getBBox() {
809
+ if (this.rotate % 360 === 0) {
810
+ return bbox(this.xy[0], this.xy[1], this.xy[0] + this.width, this.xy[1] + this.height);
811
+ }
812
+ const p1 = new Point(this.xy[0], this.xy[1]).rotate(this.rotate);
813
+ const p2 = new Point(this.xy[0] + this.width, this.xy[1]).rotate(this.rotate);
814
+ const p3 = new Point(this.xy[0] + this.width, this.xy[1] + this.height).rotate(this.rotate);
815
+ const p4 = new Point(this.xy[0], this.xy[1] + this.height).rotate(this.rotate);
816
+ const pts = [p1, p2, p3, p4];
817
+ return bbox(Math.min(...pts.map((p) => p.x)), Math.min(...pts.map((p) => p.y)), Math.max(...pts.map((p) => p.x)), Math.max(...pts.map((p) => p.y)));
818
+ }
819
+ xform(transform, style) {
820
+ const p = transform.transform(this.xy);
821
+ return new SegmentImage(this.image, {
822
+ xy: [p.x, p.y],
823
+ width: this.width * transform.zoom.x,
824
+ height: this.height * transform.zoom.y,
825
+ rotate: this.rotate + transform.theta,
826
+ imgfmt: this.imgfmt,
827
+ zorder: this.zorder ?? style.zorder,
828
+ });
829
+ }
830
+ doreverse(_centerx) { }
831
+ doflip() { }
832
+ draw(fig, transform, style) {
833
+ if (!this.visible) {
834
+ return;
835
+ }
836
+ const p = transform.transform(this.xy);
837
+ fig.image(this.image, [p.x, p.y], this.width * transform.zoom.x, this.height * transform.zoom.y, {
838
+ rotate: this.rotate + transform.theta,
839
+ zorder: this.zorder ?? style.zorder ?? 1,
840
+ imgfmt: this.imgfmt,
841
+ });
842
+ }
843
+ }
844
+ //# sourceMappingURL=segment.js.map