@codefrydev/svg-engine 0.1.0 → 0.1.2

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.
@@ -1,2794 +0,0 @@
1
- // src/core/geometry.ts
2
- var GRID_SIZE = 20;
3
- var snap = (val, gridSize = GRID_SIZE) => Math.round(val / gridSize) * gridSize;
4
- var distance = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1);
5
- var angleDeg = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
6
- var getBounds = (x1, y1, x2, y2) => {
7
- const minX = Math.min(x1, x2);
8
- const minY = Math.min(y1, y2);
9
- const maxX = Math.max(x1, x2);
10
- const maxY = Math.max(y1, y2);
11
- return {
12
- minX,
13
- minY,
14
- maxX,
15
- maxY,
16
- width: Math.max(1, maxX - minX),
17
- height: Math.max(1, maxY - minY)
18
- };
19
- };
20
- var getMouseCoords = (svg, e) => {
21
- const ctm = svg.getScreenCTM();
22
- if (!ctm) return { x: 0, y: 0 };
23
- return {
24
- x: (e.clientX - ctm.e) / ctm.a,
25
- y: (e.clientY - ctm.f) / ctm.d
26
- };
27
- };
28
-
29
- // src/core/renderers/registry.ts
30
- var rendererMap = /* @__PURE__ */ new Map();
31
- var registerRenderer = (type, renderer) => {
32
- rendererMap.set(type, renderer);
33
- };
34
- var getRenderer = (type) => rendererMap.get(type);
35
- var hasRenderer = (type) => rendererMap.has(type);
36
-
37
- // src/core/Renderer.tsx
38
- import { useMemo } from "react";
39
-
40
- // src/core/renderers/primitives.tsx
41
- import { jsx, jsxs } from "react/jsx-runtime";
42
- var colorOf = (el) => el.color || "#0f172a";
43
- var strokeOf = (el) => el.strokeWidth || 2;
44
- var fontOf = (el) => el.fontSize || 16;
45
- registerRenderer("point", (el) => /* @__PURE__ */ jsxs("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
46
- /* @__PURE__ */ jsx("circle", { cx: "0", cy: "0", r: 3, fill: colorOf(el) }),
47
- el.label && /* @__PURE__ */ jsx("text", { x: "8", y: "-8", fontSize: fontOf(el), fill: colorOf(el), children: String(el.label) })
48
- ] }));
49
- registerRenderer("text", (el) => /* @__PURE__ */ jsx(
50
- "text",
51
- {
52
- x: el.x1,
53
- y: el.y1,
54
- dominantBaseline: "central",
55
- textAnchor: "middle",
56
- fill: colorOf(el),
57
- fontSize: fontOf(el),
58
- fontFamily: el.fontFamily || "serif",
59
- fontWeight: el.fontWeight || "normal",
60
- children: String(el.label || el.value || "")
61
- }
62
- ));
63
- var lineLike = (el, arrow = false) => {
64
- const d = distance(el.x1, el.y1, el.x2, el.y2);
65
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
66
- const dashed = el.lineStyle === "dashed" || el.type === "dashed" || el.type === "dashed_line" ? "6 6" : el.lineStyle === "dotted" ? "2 4" : void 0;
67
- return /* @__PURE__ */ jsxs("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
68
- /* @__PURE__ */ jsx("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: colorOf(el), strokeWidth: strokeOf(el), strokeDasharray: dashed, strokeLinecap: "round" }),
69
- arrow && /* @__PURE__ */ jsx("polygon", { points: `${d},0 ${d - 12},-6 ${d - 12},6`, fill: colorOf(el) }),
70
- el.label && /* @__PURE__ */ jsx("text", { x: d / 2, y: -10, fontSize: fontOf(el), fill: colorOf(el), textAnchor: "middle", children: String(el.label) })
71
- ] });
72
- };
73
- registerRenderer("line", (el) => lineLike(el));
74
- registerRenderer("dashed", (el) => lineLike({ ...el, lineStyle: "dashed" }));
75
- registerRenderer("dashed_line", (el) => lineLike({ ...el, lineStyle: "dashed" }));
76
- registerRenderer("vector", (el) => lineLike(el, true));
77
- registerRenderer("ray", (el) => lineLike(el, true));
78
- registerRenderer("wire", (el) => lineLike(el));
79
- registerRenderer("table_edge", (el) => {
80
- const minX = Math.min(el.x1, el.x2);
81
- const maxX = Math.max(el.x1, el.x2);
82
- const minY = Math.min(el.y1, el.y2);
83
- const maxY = Math.max(el.y1, el.y2);
84
- const w = Math.max(1, maxX - minX);
85
- const h = Math.max(1, maxY - minY);
86
- const hashes = [];
87
- const numH = Math.max(2, Math.floor(w / 12));
88
- const numV = Math.max(2, Math.floor(h / 12));
89
- for (let j = 0; j <= numH; j++) {
90
- const x = minX + j / numH * w;
91
- hashes.push(/* @__PURE__ */ jsx("line", { x1: x, y1: minY, x2: x - 8, y2: minY + 10, stroke: colorOf(el), strokeWidth: 1 }, `h-${j}`));
92
- }
93
- for (let j = 0; j <= numV; j++) {
94
- const y = minY + j / numV * h;
95
- hashes.push(/* @__PURE__ */ jsx("line", { x1: maxX, y1: y, x2: maxX - 10, y2: y + 8, stroke: colorOf(el), strokeWidth: 1 }, `v-${j}`));
96
- }
97
- return /* @__PURE__ */ jsxs("g", { children: [
98
- /* @__PURE__ */ jsx("polyline", { points: `${minX},${minY} ${maxX},${minY} ${maxX},${maxY}`, fill: "none", stroke: colorOf(el), strokeWidth: strokeOf(el) }),
99
- hashes,
100
- el.label && /* @__PURE__ */ jsx("text", { x: minX + w / 2, y: minY - 10, fill: colorOf(el), textAnchor: "middle", fontSize: fontOf(el), children: String(el.label) })
101
- ] });
102
- });
103
-
104
- // src/core/renderers/mechanics.tsx
105
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
106
- var c = (el) => el.color || "#0f172a";
107
- var sw = (el) => el.strokeWidth || 2;
108
- var fo = (el) => el.fillOpacity ?? 0.2;
109
- registerRenderer("slab", (el) => {
110
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
111
- const depth = el.curveHeight ?? 20;
112
- return /* @__PURE__ */ jsxs2("g", { children: [
113
- /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} L ${b.maxX} ${b.minY} L ${b.maxX} ${b.maxY} L ${b.minX} ${b.maxY} Z`, fill: c(el), fillOpacity: fo(el), stroke: c(el), strokeWidth: sw(el) }),
114
- /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} L ${b.minX + depth} ${b.minY - depth} L ${b.maxX + depth} ${b.minY - depth} L ${b.maxX} ${b.minY} Z`, fill: c(el), fillOpacity: Math.max(0, fo(el) - 0.1), stroke: c(el), strokeWidth: sw(el) }),
115
- /* @__PURE__ */ jsx2("path", { d: `M ${b.maxX} ${b.minY} L ${b.maxX + depth} ${b.minY - depth} L ${b.maxX + depth} ${b.maxY - depth} L ${b.maxX} ${b.maxY} Z`, fill: c(el), fillOpacity: Math.min(1, fo(el) + 0.1), stroke: c(el), strokeWidth: sw(el) })
116
- ] });
117
- });
118
- registerRenderer("sphere", (el) => {
119
- const r = Math.max(4, distance(el.x1, el.y1, el.x2, el.y2));
120
- return /* @__PURE__ */ jsx2("circle", { cx: el.x1, cy: el.y1, r, fill: c(el), fillOpacity: fo(el), stroke: c(el), strokeWidth: sw(el) });
121
- });
122
- registerRenderer("shell", (el) => {
123
- const r = Math.max(10, distance(el.x1, el.y1, el.x2, el.y2));
124
- const t = el.curveHeight ?? 10;
125
- const innerR = Math.max(1, r - t);
126
- return /* @__PURE__ */ jsx2(
127
- "path",
128
- {
129
- d: `M ${el.x1 - r} ${el.y1} A ${r} ${r} 0 1 0 ${el.x1 + r} ${el.y1} A ${r} ${r} 0 1 0 ${el.x1 - r} ${el.y1} Z M ${el.x1 - innerR} ${el.y1} A ${innerR} ${innerR} 0 1 1 ${el.x1 + innerR} ${el.y1} A ${innerR} ${innerR} 0 1 1 ${el.x1 - innerR} ${el.y1} Z`,
130
- fill: c(el),
131
- fillOpacity: fo(el),
132
- fillRule: "evenodd",
133
- stroke: c(el),
134
- strokeWidth: sw(el)
135
- }
136
- );
137
- });
138
- registerRenderer("cylinder", (el) => {
139
- const d = distance(el.x1, el.y1, el.x2, el.y2);
140
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
141
- const r = el.curveHeight ?? 20;
142
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
143
- /* @__PURE__ */ jsx2("path", { d: `M 0 ${-r} L ${d} ${-r} A 10 ${r} 0 0 1 ${d} ${r} L 0 ${r} Z`, fill: c(el), fillOpacity: fo(el) }),
144
- /* @__PURE__ */ jsx2("path", { d: `M 0 ${-r} L ${d} ${-r} M 0 ${r} L ${d} ${r}`, fill: "none", stroke: c(el), strokeWidth: sw(el) }),
145
- /* @__PURE__ */ jsx2("ellipse", { cx: d, cy: 0, rx: 10, ry: r, fill: c(el), fillOpacity: fo(el), stroke: c(el), strokeWidth: sw(el) }),
146
- /* @__PURE__ */ jsx2("ellipse", { cx: 0, cy: 0, rx: 10, ry: r, fill: "none", stroke: c(el), strokeWidth: sw(el), strokeDasharray: "2 4" })
147
- ] });
148
- });
149
- registerRenderer("ladder", (el) => {
150
- const d = distance(el.x1, el.y1, el.x2, el.y2);
151
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
152
- const hw = el.curveHeight ?? 10;
153
- const rungs = [];
154
- for (let i = 15; i < d - 10; i += 15) {
155
- rungs.push(/* @__PURE__ */ jsx2("line", { x1: i, y1: -hw, x2: i, y2: hw, stroke: c(el), strokeWidth: Math.max(1, sw(el) - 1) }, i));
156
- }
157
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
158
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: -hw, x2: d, y2: -hw, stroke: c(el), strokeWidth: sw(el) }),
159
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: hw, x2: d, y2: hw, stroke: c(el), strokeWidth: sw(el) }),
160
- rungs
161
- ] });
162
- });
163
- registerRenderer("spring", (el) => {
164
- const d = distance(el.x1, el.y1, el.x2, el.y2);
165
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
166
- const zigCount = Math.max(0, Math.floor(d / 12));
167
- let path = "M 0 0";
168
- for (let i = 0; i < zigCount; i++) {
169
- path += ` L ${i * 12 + 3} 8 L ${i * 12 + 9} -8`;
170
- }
171
- path += ` L ${d} 0`;
172
- return /* @__PURE__ */ jsx2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: /* @__PURE__ */ jsx2("path", { d: path, fill: "none", stroke: c(el), strokeWidth: sw(el), strokeLinejoin: "round" }) });
173
- });
174
- registerRenderer("rod", (el) => {
175
- const d = distance(el.x1, el.y1, el.x2, el.y2);
176
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
177
- return /* @__PURE__ */ jsx2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c(el), strokeWidth: Math.max(4, sw(el)), strokeLinecap: "round" }) });
178
- });
179
- registerRenderer("arc_arrow", (el) => {
180
- const r = Math.max(8, distance(el.x1, el.y1, el.x2, el.y2));
181
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
182
- /* @__PURE__ */ jsx2("path", { d: `M ${r} 0 A ${r} ${r} 0 0 0 ${-r} 0`, fill: "none", stroke: c(el), strokeWidth: sw(el) }),
183
- /* @__PURE__ */ jsx2("polygon", { points: `${-r},2 ${-r - 6},-10 ${-r + 6},-10`, fill: c(el) })
184
- ] });
185
- });
186
- registerRenderer("lens_convex", (el) => {
187
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
188
- const cx = b.minX + b.width / 2;
189
- return /* @__PURE__ */ jsx2("ellipse", { cx, cy: b.minY + b.height / 2, rx: Math.max(6, b.width / 2), ry: b.height / 2, fill: c(el), fillOpacity: Math.max(0.15, fo(el)), stroke: c(el), strokeWidth: sw(el) });
190
- });
191
- registerRenderer("lens_concave", (el) => {
192
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
193
- const cx = b.minX + b.width / 2;
194
- const rx = Math.max(6, b.width / 2);
195
- const ry = b.height / 2;
196
- return /* @__PURE__ */ jsx2(
197
- "path",
198
- {
199
- d: `M ${cx - rx} ${b.minY} Q ${cx - rx * 0.2} ${b.minY + ry} ${cx - rx} ${b.maxY} M ${cx + rx} ${b.minY} Q ${cx + rx * 0.2} ${b.minY + ry} ${cx + rx} ${b.maxY}`,
200
- fill: "none",
201
- stroke: c(el),
202
- strokeWidth: sw(el)
203
- }
204
- );
205
- });
206
- registerRenderer("mirror_concave", (el) => {
207
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
208
- const ch = el.curveHeight ?? 40;
209
- return /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} Q ${b.maxX + ch} ${b.minY + b.height / 2} ${b.minX} ${b.maxY}`, fill: "none", stroke: c(el), strokeWidth: sw(el) });
210
- });
211
- registerRenderer("mirror_convex", (el) => {
212
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
213
- const ch = el.curveHeight ?? 40;
214
- const midY = b.minY + b.height / 2;
215
- return /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} Q ${b.minX - ch} ${midY} ${b.minX} ${b.maxY}`, fill: "none", stroke: c(el), strokeWidth: sw(el) });
216
- });
217
- registerRenderer("prism", (el) => {
218
- const d = distance(el.x1, el.y1, el.x2, el.y2);
219
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
220
- const py = -d * 0.866;
221
- const fs = el.fontSize || 16;
222
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
223
- /* @__PURE__ */ jsx2("polygon", { points: `0,0 ${d},0 ${d / 2},${py}`, fill: c(el), fillOpacity: Math.max(0.15, fo(el)), stroke: c(el), strokeWidth: sw(el), strokeLinejoin: "round" }),
224
- el.label && /* @__PURE__ */ jsx2("text", { x: d / 2, y: py - 10, fontSize: fs, fill: c(el), textAnchor: "middle", children: String(el.label) })
225
- ] });
226
- });
227
- registerRenderer("slit_single", (el) => {
228
- const d = distance(el.x1, el.y1, el.x2, el.y2);
229
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
230
- const gap = 16;
231
- const thick = Math.max(4, sw(el));
232
- const fs = el.fontSize || 16;
233
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
234
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: d / 2 - gap / 2, y2: 0, stroke: c(el), strokeWidth: thick, strokeLinecap: "square" }),
235
- /* @__PURE__ */ jsx2("line", { x1: d / 2 + gap / 2, y1: 0, x2: d, y2: 0, stroke: c(el), strokeWidth: thick, strokeLinecap: "square" }),
236
- el.label && /* @__PURE__ */ jsx2("text", { x: d / 2, y: -14, fontSize: fs, fill: c(el), textAnchor: "middle", children: String(el.label) })
237
- ] });
238
- });
239
- registerRenderer("slit_double", (el) => {
240
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
241
- const cx = b.minX + b.width / 2;
242
- return /* @__PURE__ */ jsxs2("g", { children: [
243
- /* @__PURE__ */ jsx2("line", { x1: cx - 6, y1: b.minY, x2: cx - 6, y2: b.maxY, stroke: c(el), strokeWidth: sw(el) }),
244
- /* @__PURE__ */ jsx2("line", { x1: cx + 6, y1: b.minY, x2: cx + 6, y2: b.maxY, stroke: c(el), strokeWidth: sw(el) })
245
- ] });
246
- });
247
- registerRenderer("photon", (el) => {
248
- const d = distance(el.x1, el.y1, el.x2, el.y2);
249
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
250
- const amp = 6;
251
- const waves = Math.max(3, Math.floor(d / 24));
252
- const step = d / (waves * 2);
253
- let path = "M 0 0 ";
254
- for (let i = 0; i < waves * 2; i++) {
255
- const x = (i + 1) * step;
256
- const y = i % 2 === 0 ? -amp : amp;
257
- path += `L ${x} ${y} `;
258
- }
259
- path += `L ${d} 0`;
260
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
261
- /* @__PURE__ */ jsx2("path", { d: path, fill: "none", stroke: c(el), strokeWidth: sw(el) }),
262
- el.label && /* @__PURE__ */ jsx2("text", { x: d / 2, y: -12, textAnchor: "middle", fill: c(el), children: String(el.label) })
263
- ] });
264
- });
265
- registerRenderer("glass_slab", (el) => {
266
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
267
- return /* @__PURE__ */ jsx2("rect", { x: b.minX, y: b.minY, width: b.width, height: b.height, fill: c(el), fillOpacity: Math.max(0.1, fo(el)), stroke: c(el), strokeWidth: sw(el) });
268
- });
269
- registerRenderer("pipe", (el) => {
270
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
271
- const neck = el.curveHeight ?? b.height * 0.35;
272
- return /* @__PURE__ */ jsx2(
273
- "path",
274
- {
275
- d: `M ${b.minX} ${b.minY} C ${b.minX + b.width * 0.3} ${b.minY}, ${b.minX + b.width * 0.3} ${b.minY + neck}, ${b.minX + b.width * 0.5} ${b.minY + neck} C ${b.minX + b.width * 0.7} ${b.minY + neck}, ${b.minX + b.width * 0.7} ${b.minY}, ${b.maxX} ${b.minY} L ${b.maxX} ${b.maxY} C ${b.minX + b.width * 0.7} ${b.maxY}, ${b.minX + b.width * 0.7} ${b.maxY - neck}, ${b.minX + b.width * 0.5} ${b.maxY - neck} C ${b.minX + b.width * 0.3} ${b.maxY - neck}, ${b.minX + b.width * 0.3} ${b.maxY}, ${b.minX} ${b.maxY} Z`,
276
- fill: c(el),
277
- fillOpacity: fo(el),
278
- stroke: c(el),
279
- strokeWidth: sw(el)
280
- }
281
- );
282
- });
283
- registerRenderer("liquid", (el) => {
284
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
285
- return /* @__PURE__ */ jsxs2("g", { children: [
286
- /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} Q ${b.minX + b.width / 2} ${b.minY + 10} ${b.maxX} ${b.minY} L ${b.maxX} ${b.maxY} L ${b.minX} ${b.maxY} Z`, fill: c(el), fillOpacity: Math.max(0.2, fo(el)) }),
287
- /* @__PURE__ */ jsx2("path", { d: `M ${b.minX} ${b.minY} Q ${b.minX + b.width / 2} ${b.minY + 10} ${b.maxX} ${b.minY}`, fill: "none", stroke: c(el), strokeWidth: 2 })
288
- ] });
289
- });
290
- registerRenderer("orbit", (el) => {
291
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
292
- return /* @__PURE__ */ jsx2("ellipse", { cx: b.minX + b.width / 2, cy: b.minY + b.height / 2, rx: b.width / 2, ry: b.height / 2, fill: "none", stroke: c(el), strokeWidth: sw(el), strokeDasharray: "3 3" });
293
- });
294
- registerRenderer("pole_piece", (el) => {
295
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
296
- const poleLabel = String(el.label || "N");
297
- const isNorth = poleLabel.toUpperCase().includes("N");
298
- const blockFill = isNorth ? "#ef4444" : "#3b82f6";
299
- const labelFs = Math.min(b.width, b.height) * 0.5 + 10;
300
- return /* @__PURE__ */ jsxs2("g", { children: [
301
- /* @__PURE__ */ jsx2("rect", { x: b.minX, y: b.minY, width: b.width, height: b.height, fill: blockFill, fillOpacity: 0.2, stroke: c(el), strokeWidth: sw(el), rx: "4" }),
302
- /* @__PURE__ */ jsx2("text", { x: b.minX + b.width / 2, y: b.minY + b.height / 2, textAnchor: "middle", dominantBaseline: "central", fill: c(el), fontWeight: "bold", fontSize: labelFs, children: poleLabel })
303
- ] });
304
- });
305
- registerRenderer("b_field_line", (el) => {
306
- const d = distance(el.x1, el.y1, el.x2, el.y2);
307
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
308
- const fs = el.fontSize || 18;
309
- const mid = d / 2;
310
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
311
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c(el), strokeWidth: sw(el), strokeLinecap: "round" }),
312
- /* @__PURE__ */ jsx2("polygon", { points: `${mid + 6},0 ${mid - 6},-5 ${mid - 6},5`, fill: c(el) }),
313
- el.label ? /* @__PURE__ */ jsx2("text", { x: mid, y: -10, textAnchor: "middle", fill: c(el), fontSize: fs, children: String(el.label) }) : null
314
- ] });
315
- });
316
- registerRenderer("b_field_curve", (el) => {
317
- const d = distance(el.x1, el.y1, el.x2, el.y2);
318
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
319
- const curveHeight = el.curveHeight !== void 0 ? el.curveHeight : d * 0.4;
320
- const fs = el.fontSize || 18;
321
- const apexY = -curveHeight;
322
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
323
- /* @__PURE__ */ jsx2(
324
- "path",
325
- {
326
- d: `M 0 0 Q ${d / 2} ${-curveHeight * 2} ${d} 0`,
327
- fill: "none",
328
- stroke: c(el),
329
- strokeWidth: sw(el),
330
- strokeLinecap: "round"
331
- }
332
- ),
333
- /* @__PURE__ */ jsx2("polygon", { points: `${d / 2 + 6},${apexY} ${d / 2 - 6},${apexY - 5} ${d / 2 - 6},${apexY + 5}`, fill: c(el) }),
334
- el.label ? /* @__PURE__ */ jsx2("text", { x: d / 2, y: apexY - 15, textAnchor: "middle", fill: c(el), fontSize: fs, children: String(el.label) }) : null
335
- ] });
336
- });
337
- registerRenderer("axes_3d", (el) => /* @__PURE__ */ jsxs2("g", { children: [
338
- /* @__PURE__ */ jsx2("line", { x1: el.x1, y1: el.y1, x2: el.x1 + 100, y2: el.y1, stroke: c(el), strokeWidth: sw(el) }),
339
- /* @__PURE__ */ jsx2("line", { x1: el.x1, y1: el.y1, x2: el.x1, y2: el.y1 - 100, stroke: c(el), strokeWidth: sw(el) }),
340
- /* @__PURE__ */ jsx2("line", { x1: el.x1, y1: el.y1, x2: el.x1 + 70, y2: el.y1 + 50, stroke: c(el), strokeWidth: sw(el) })
341
- ] }));
342
- registerRenderer("wedge", (el) => {
343
- const dx = el.x2 - el.x1;
344
- const dy = el.y2 - el.y1;
345
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
346
- /* @__PURE__ */ jsx2("polygon", { points: `0,0 ${dx},0 ${dx},${dy}`, fill: "#f1f5f9", stroke: c(el), strokeWidth: sw(el), strokeLinejoin: "round" }),
347
- el.label ? /* @__PURE__ */ jsx2(
348
- "text",
349
- {
350
- x: dx * 0.6,
351
- y: dy * 0.3,
352
- dominantBaseline: "central",
353
- textAnchor: "middle",
354
- fill: c(el),
355
- fontSize: 20,
356
- fontFamily: "serif",
357
- fontWeight: "bold",
358
- children: String(el.label)
359
- }
360
- ) : null
361
- ] });
362
- });
363
- registerRenderer("dimension", (el) => {
364
- const d = distance(el.x1, el.y1, el.x2, el.y2);
365
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
366
- const w = Math.max(1, sw(el) - 0.5);
367
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
368
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c(el), strokeWidth: w, strokeDasharray: "4 4" }),
369
- /* @__PURE__ */ jsx2("polygon", { points: `0,0 10,-5 10,5`, fill: c(el) }),
370
- /* @__PURE__ */ jsx2("polygon", { points: `${d},0 ${d - 10},-5 ${d - 10},5`, fill: c(el) }),
371
- el.label ? /* @__PURE__ */ jsx2("text", { x: d / 2, y: -10, textAnchor: "middle", fill: c(el), fontSize: 18, fontFamily: "serif", fontStyle: "italic", fontWeight: "bold", children: String(el.label) }) : null
372
- ] });
373
- });
374
- registerRenderer("arc", (el) => {
375
- const dx = el.x2 - el.x1;
376
- const dy = el.y2 - el.y1;
377
- const d = Math.hypot(dx, dy);
378
- const angleDegVal = Math.atan2(dy, dx) * 180 / Math.PI;
379
- const R = Math.min(d, 40);
380
- const sweepFlag = dy > 0 ? 1 : 0;
381
- const startX = R;
382
- const startY = 0;
383
- const endX = R * Math.cos(angleDegVal * Math.PI / 180);
384
- const endY = R * Math.sin(angleDegVal * Math.PI / 180);
385
- const midAngle = angleDegVal / 2;
386
- const textDist = R + 15;
387
- const tx = textDist * Math.cos(midAngle * Math.PI / 180);
388
- const ty = textDist * Math.sin(midAngle * Math.PI / 180);
389
- const refLen = Math.max(d, 50);
390
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
391
- /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: refLen, y2: 0, stroke: c(el), strokeWidth: 1.5, strokeDasharray: "4 4" }),
392
- /* @__PURE__ */ jsx2("path", { d: `M ${startX} ${startY} A ${R} ${R} 0 0 ${sweepFlag} ${endX} ${endY}`, fill: "none", stroke: c(el), strokeWidth: sw(el) }),
393
- el.label ? /* @__PURE__ */ jsx2(
394
- "text",
395
- {
396
- x: tx,
397
- y: ty,
398
- dominantBaseline: "central",
399
- textAnchor: "middle",
400
- fill: c(el),
401
- fontSize: 16,
402
- fontFamily: "serif",
403
- fontStyle: "italic",
404
- fontWeight: "bold",
405
- children: String(el.label)
406
- }
407
- ) : null
408
- ] });
409
- });
410
- registerRenderer("nucleus", (el) => {
411
- const fs = el.fontSize || 18;
412
- const stroke2 = c(el);
413
- const w = sw(el);
414
- return /* @__PURE__ */ jsxs2("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
415
- /* @__PURE__ */ jsx2("ellipse", { cx: 0, cy: 0, rx: 24, ry: 8, fill: "none", stroke: stroke2, strokeWidth: w, transform: "rotate(30)" }),
416
- /* @__PURE__ */ jsx2("ellipse", { cx: 0, cy: 0, rx: 24, ry: 8, fill: "none", stroke: stroke2, strokeWidth: w, transform: "rotate(-30)" }),
417
- /* @__PURE__ */ jsx2("ellipse", { cx: 0, cy: 0, rx: 24, ry: 8, fill: "none", stroke: stroke2, strokeWidth: w, transform: "rotate(90)" }),
418
- /* @__PURE__ */ jsx2("circle", { cx: 0, cy: 0, r: 6, fill: "#ef4444" }),
419
- el.label && /* @__PURE__ */ jsx2("text", { x: 0, y: 36, fontSize: fs, fill: stroke2, textAnchor: "middle", children: String(el.label) })
420
- ] });
421
- });
422
- ["cone", "curved_wedge", "incline", "container", "hinge"].forEach(
423
- (t) => registerRenderer(t, (el) => {
424
- const d = distance(el.x1, el.y1, el.x2, el.y2);
425
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
426
- return /* @__PURE__ */ jsx2("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: /* @__PURE__ */ jsx2("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c(el), strokeWidth: sw(el) }) });
427
- })
428
- );
429
- ["semicircle", "quarter_circle", "axes"].forEach(
430
- (t) => registerRenderer(t, (el) => {
431
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
432
- return /* @__PURE__ */ jsx2("rect", { x: b.minX, y: b.minY, width: b.width, height: b.height, fill: "none", stroke: c(el), strokeWidth: sw(el) });
433
- })
434
- );
435
-
436
- // src/core/renderers/magnetism.tsx
437
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
438
- var c2 = (el) => el.color || "#0f172a";
439
- var sw2 = (el) => el.strokeWidth || 2;
440
- var fontSizeOf = (el) => el.fontSize || 18;
441
- var dashOf = (el) => el.lineStyle === "dashed" || el.type === "dashed_line" ? "6 6" : el.lineStyle === "dotted" ? "2 4" : void 0;
442
- registerRenderer("b_region_in", (el) => {
443
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
444
- const minX = b.minX;
445
- const maxX = b.maxX;
446
- const minY = b.minY;
447
- const maxY = b.maxY;
448
- const midX = (minX + maxX) / 2;
449
- const spacing = 40;
450
- const markR = 6;
451
- const marks = [];
452
- for (let px = minX + spacing / 2; px <= maxX; px += spacing) {
453
- for (let py = minY + spacing / 2; py <= maxY; py += spacing) {
454
- marks.push(
455
- /* @__PURE__ */ jsxs3("g", { transform: `translate(${px}, ${py})`, children: [
456
- /* @__PURE__ */ jsx3("circle", { cx: 0, cy: 0, r: markR, fill: "none", stroke: c2(el), strokeWidth: sw2(el) * 0.75 }),
457
- /* @__PURE__ */ jsx3("line", { x1: -markR * 0.7, y1: -markR * 0.7, x2: markR * 0.7, y2: markR * 0.7, stroke: c2(el), strokeWidth: sw2(el) * 0.75 }),
458
- /* @__PURE__ */ jsx3("line", { x1: markR * 0.7, y1: -markR * 0.7, x2: -markR * 0.7, y2: markR * 0.7, stroke: c2(el), strokeWidth: sw2(el) * 0.75 })
459
- ] }, `${px}-${py}`)
460
- );
461
- }
462
- }
463
- return /* @__PURE__ */ jsxs3("g", { children: [
464
- /* @__PURE__ */ jsx3("rect", { x: minX, y: minY, width: b.width, height: b.height, fill: c2(el), stroke: c2(el), strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.1 }),
465
- marks,
466
- el.label ? /* @__PURE__ */ jsx3("text", { x: midX, y: minY - 10, fontSize: fontSizeOf(el), fill: c2(el), textAnchor: "middle", fontWeight: "bold", children: String(el.label) }) : null
467
- ] });
468
- });
469
- registerRenderer("b_region_out", (el) => {
470
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
471
- const minX = b.minX;
472
- const maxX = b.maxX;
473
- const minY = b.minY;
474
- const maxY = b.maxY;
475
- const midX = (minX + maxX) / 2;
476
- const spacing = 40;
477
- const markR = 6;
478
- const marks = [];
479
- for (let px = minX + spacing / 2; px <= maxX; px += spacing) {
480
- for (let py = minY + spacing / 2; py <= maxY; py += spacing) {
481
- marks.push(
482
- /* @__PURE__ */ jsxs3("g", { transform: `translate(${px}, ${py})`, children: [
483
- /* @__PURE__ */ jsx3("circle", { cx: 0, cy: 0, r: markR, fill: "none", stroke: c2(el), strokeWidth: sw2(el) * 0.75 }),
484
- /* @__PURE__ */ jsx3("circle", { cx: 0, cy: 0, r: 2, fill: c2(el) })
485
- ] }, `${px}-${py}`)
486
- );
487
- }
488
- }
489
- return /* @__PURE__ */ jsxs3("g", { children: [
490
- /* @__PURE__ */ jsx3("rect", { x: minX, y: minY, width: b.width, height: b.height, fill: c2(el), stroke: c2(el), strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.1 }),
491
- marks,
492
- el.label ? /* @__PURE__ */ jsx3("text", { x: midX, y: minY - 10, fontSize: fontSizeOf(el), fill: c2(el), textAnchor: "middle", fontWeight: "bold", children: String(el.label) }) : null
493
- ] });
494
- });
495
- registerRenderer("current_wire", (el) => {
496
- const d = distance(el.x1, el.y1, el.x2, el.y2);
497
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
498
- const mid = d / 2;
499
- const flip = angle > 90 || angle <= -90;
500
- return /* @__PURE__ */ jsxs3("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
501
- /* @__PURE__ */ jsx3("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c2(el), strokeWidth: sw2(el), strokeDasharray: dashOf(el), strokeLinecap: "round" }),
502
- /* @__PURE__ */ jsx3("polygon", { points: `${mid + 8},0 ${mid - 6},-7 ${mid - 6},7`, fill: c2(el) }),
503
- el.label ? /* @__PURE__ */ jsx3(
504
- "text",
505
- {
506
- x: mid,
507
- y: -15,
508
- fontSize: fontSizeOf(el),
509
- fill: c2(el),
510
- textAnchor: "middle",
511
- fontStyle: "italic",
512
- transform: flip ? `rotate(180, ${mid}, -15)` : void 0,
513
- children: String(el.label)
514
- }
515
- ) : null
516
- ] });
517
- });
518
- registerRenderer("bar_magnet", (el) => {
519
- const d = distance(el.x1, el.y1, el.x2, el.y2);
520
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
521
- const magW = Math.max(20, sw2(el) * 10);
522
- const flipLabel = angle > 90 || angle <= -90;
523
- return /* @__PURE__ */ jsxs3("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
524
- /* @__PURE__ */ jsx3("rect", { x: 0, y: -magW / 2, width: d / 2, height: magW, fill: "#ef4444", stroke: c2(el), strokeWidth: 1 }),
525
- /* @__PURE__ */ jsx3("rect", { x: d / 2, y: -magW / 2, width: d / 2, height: magW, fill: "#3b82f6", stroke: c2(el), strokeWidth: 1 }),
526
- /* @__PURE__ */ jsx3(
527
- "text",
528
- {
529
- x: d / 4,
530
- y: 0,
531
- fill: "white",
532
- fontSize: magW * 0.6,
533
- fontWeight: "bold",
534
- textAnchor: "middle",
535
- dominantBaseline: "central",
536
- transform: flipLabel ? `rotate(180, ${d / 4}, 0)` : void 0,
537
- children: "N"
538
- }
539
- ),
540
- /* @__PURE__ */ jsx3(
541
- "text",
542
- {
543
- x: d * 0.75,
544
- y: 0,
545
- fill: "white",
546
- fontSize: magW * 0.6,
547
- fontWeight: "bold",
548
- textAnchor: "middle",
549
- dominantBaseline: "central",
550
- transform: flipLabel ? `rotate(180, ${d * 0.75}, 0)` : void 0,
551
- children: "S"
552
- }
553
- ),
554
- el.label ? /* @__PURE__ */ jsx3(
555
- "text",
556
- {
557
- x: d / 2,
558
- y: -magW / 2 - 10,
559
- fill: c2(el),
560
- fontSize: fontSizeOf(el),
561
- textAnchor: "middle",
562
- transform: flipLabel ? `rotate(180, ${d / 2}, ${-magW / 2 - 10})` : void 0,
563
- children: String(el.label)
564
- }
565
- ) : null
566
- ] });
567
- });
568
- registerRenderer("coil", (el) => {
569
- const d = distance(el.x1, el.y1, el.x2, el.y2);
570
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
571
- const coils = Math.max(Math.floor(d / 15), 1);
572
- let dPath = "M 0 0 ";
573
- for (let i = 1; i <= coils; i++) {
574
- dPath += `C ${i * (d / coils) - d / (coils * 2)} -15, ${i * (d / coils)} 20, ${i * (d / coils)} 0 `;
575
- }
576
- const flip = angle > 90 || angle <= -90;
577
- return /* @__PURE__ */ jsxs3("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
578
- /* @__PURE__ */ jsx3("path", { d: dPath, fill: "none", stroke: c2(el), strokeWidth: sw2(el), strokeLinejoin: "round" }),
579
- el.label ? /* @__PURE__ */ jsx3(
580
- "text",
581
- {
582
- x: d / 2,
583
- y: -20,
584
- fontSize: fontSizeOf(el),
585
- fill: c2(el),
586
- textAnchor: "middle",
587
- transform: flip ? `rotate(180, ${d / 2}, -20)` : void 0,
588
- children: String(el.label)
589
- }
590
- ) : null
591
- ] });
592
- });
593
- registerRenderer("meter", (el) => {
594
- const r = Math.max(16, sw2(el) * 5);
595
- const label = String(el.label || "G");
596
- return /* @__PURE__ */ jsxs3("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
597
- /* @__PURE__ */ jsx3("circle", { cx: 0, cy: 0, r, fill: "white", stroke: c2(el), strokeWidth: sw2(el) }),
598
- /* @__PURE__ */ jsx3("text", { x: 0, y: 0, fontSize: fontSizeOf(el), fill: c2(el), fontWeight: "bold", textAnchor: "middle", dominantBaseline: "central", children: label })
599
- ] });
600
- });
601
- registerRenderer("ac_source", (el) => {
602
- const r = Math.max(16, sw2(el) * 5);
603
- return /* @__PURE__ */ jsxs3("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
604
- /* @__PURE__ */ jsx3("circle", { cx: 0, cy: 0, r, fill: "white", stroke: c2(el), strokeWidth: sw2(el) }),
605
- /* @__PURE__ */ jsx3(
606
- "path",
607
- {
608
- d: `M ${-r * 0.6} 0 Q ${-r * 0.3} ${-r * 0.6} 0 0 T ${r * 0.6} 0`,
609
- fill: "none",
610
- stroke: c2(el),
611
- strokeWidth: sw2(el) * 0.8
612
- }
613
- ),
614
- el.label ? /* @__PURE__ */ jsx3("text", { x: 0, y: r + 18, fontSize: fontSizeOf(el), fill: c2(el), textAnchor: "middle", children: String(el.label) }) : null
615
- ] });
616
- });
617
- registerRenderer("bezier", (el) => {
618
- const { x1, y1, x2, y2 } = el;
619
- const cps = el.cps?.length ? el.cps : [{ x: (x1 + x2) / 2, y: Math.min(y1, y2) - 50 }];
620
- const cp0 = cps[0];
621
- const dPath = `M ${x1} ${y1} Q ${cp0.x} ${cp0.y} ${x2} ${y2}`;
622
- const labelX = 0.25 * x1 + 0.5 * cp0.x + 0.25 * x2;
623
- const labelY = 0.25 * y1 + 0.5 * cp0.y + 0.25 * y2;
624
- const angleRad = Math.atan2(y2 - y1, x2 - x1);
625
- const showArrow = Boolean(el.showArrow);
626
- return /* @__PURE__ */ jsxs3("g", { children: [
627
- /* @__PURE__ */ jsx3("path", { d: dPath, fill: "none", stroke: "transparent", strokeWidth: 24, strokeLinecap: "round", strokeLinejoin: "round" }),
628
- /* @__PURE__ */ jsx3("path", { d: dPath, fill: "none", stroke: c2(el), strokeWidth: sw2(el), strokeDasharray: dashOf(el), strokeLinecap: "round", strokeLinejoin: "round" }),
629
- showArrow ? /* @__PURE__ */ jsx3("g", { transform: `translate(${labelX}, ${labelY}) rotate(${angleRad * 180 / Math.PI})`, children: /* @__PURE__ */ jsx3("polygon", { points: "6,0 -6,-5 -6,5", fill: c2(el) }) }) : null,
630
- el.label ? /* @__PURE__ */ jsx3("text", { x: labelX, y: labelY - 14, fontSize: fontSizeOf(el), fill: c2(el), textAnchor: "middle", children: String(el.label) }) : null
631
- ] });
632
- });
633
-
634
- // src/core/renderers/graph.tsx
635
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
636
- var colorOf2 = (el) => el.color || "#0f172a";
637
- var strokeOf2 = (el) => el.strokeWidth || 2;
638
- var fontOf2 = (el) => el.fontSize || 16;
639
- var dashOf2 = (el) => {
640
- if (el.lineStyle === "dashed" || el.type === "dashed_line" || el.type === "dashed") return "6 6";
641
- if (el.lineStyle === "dotted") return "2 4";
642
- return void 0;
643
- };
644
- var op = (ctx) => ctx?.isGhost ? 0.5 : 1;
645
- registerRenderer("axes", (el, ctx) => {
646
- const minX = Math.min(el.x1, el.x2);
647
- const maxX = Math.max(el.x1, el.x2);
648
- const minY = Math.min(el.y1, el.y2);
649
- const maxY = Math.max(el.y1, el.y2);
650
- const midX = (minX + maxX) / 2;
651
- const midY = (minY + maxY) / 2;
652
- const w = Math.max(1, maxX - minX);
653
- const h = Math.max(1, maxY - minY);
654
- const c7 = colorOf2(el);
655
- const sw7 = strokeOf2(el);
656
- const dash = dashOf2(el);
657
- if (maxX - minX <= 1 && maxY - minY <= 1) {
658
- const cx = el.x1;
659
- const cy = el.y1;
660
- const arm = 40;
661
- const fs = fontOf2(el);
662
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
663
- /* @__PURE__ */ jsx4("line", { x1: cx, y1: cy, x2: cx + arm, y2: cy, stroke: c7, strokeWidth: sw7 }),
664
- /* @__PURE__ */ jsx4("polygon", { points: `${cx + arm},${cy} ${cx + arm - 8},${cy - 5} ${cx + arm - 8},${cy + 5}`, fill: c7 }),
665
- /* @__PURE__ */ jsx4(
666
- "text",
667
- {
668
- x: cx + arm + 10,
669
- y: cy,
670
- dominantBaseline: "central",
671
- textAnchor: "middle",
672
- fill: c7,
673
- fontSize: fs,
674
- fontFamily: "serif",
675
- fontStyle: "italic",
676
- children: "x"
677
- }
678
- ),
679
- /* @__PURE__ */ jsx4("line", { x1: cx, y1: cy, x2: cx, y2: cy - arm, stroke: c7, strokeWidth: sw7 }),
680
- /* @__PURE__ */ jsx4("polygon", { points: `${cx},${cy - arm} ${cx - 5},${cy - arm + 8} ${cx + 5},${cy - arm + 8}`, fill: c7 }),
681
- /* @__PURE__ */ jsx4(
682
- "text",
683
- {
684
- x: cx,
685
- y: cy - arm - 12,
686
- dominantBaseline: "central",
687
- textAnchor: "middle",
688
- fill: c7,
689
- fontSize: fs,
690
- fontFamily: "serif",
691
- fontStyle: "italic",
692
- children: "y"
693
- }
694
- ),
695
- /* @__PURE__ */ jsx4("circle", { cx, cy, r: 2, fill: c7 })
696
- ] });
697
- }
698
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
699
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
700
- /* @__PURE__ */ jsxs4("g", { pointerEvents: "none", children: [
701
- /* @__PURE__ */ jsx4("line", { x1: midX, y1: minY, x2: midX, y2: maxY, stroke: c7, strokeWidth: sw7, strokeDasharray: dash, opacity: 0.8 }),
702
- /* @__PURE__ */ jsx4("line", { x1: minX, y1: midY, x2: maxX, y2: midY, stroke: c7, strokeWidth: sw7, strokeDasharray: dash, opacity: 0.8 }),
703
- /* @__PURE__ */ jsx4("polygon", { points: `${maxX},${midY} ${maxX - 10},${midY - 5} ${maxX - 10},${midY + 5}`, fill: c7, opacity: 0.8 }),
704
- /* @__PURE__ */ jsx4("polygon", { points: `${midX},${minY} ${midX - 5},${minY + 10} ${midX + 5},${minY + 10}`, fill: c7, opacity: 0.8 })
705
- ] })
706
- ] });
707
- });
708
- registerRenderer("circle", (el, ctx) => {
709
- const r = distance(el.x1, el.y1, el.x2, el.y2);
710
- const c7 = colorOf2(el);
711
- const sw7 = strokeOf2(el);
712
- const dash = dashOf2(el);
713
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
714
- /* @__PURE__ */ jsx4("circle", { cx: el.x1, cy: el.y1, r, fill: "none", stroke: c7, strokeWidth: sw7, strokeDasharray: dash, pointerEvents: "none" }),
715
- /* @__PURE__ */ jsx4("circle", { cx: el.x1, cy: el.y1, r, fill: "transparent", stroke: "transparent", strokeWidth: 20 })
716
- ] });
717
- });
718
- registerRenderer("ellipse", (el, ctx) => {
719
- const minX = Math.min(el.x1, el.x2);
720
- const maxX = Math.max(el.x1, el.x2);
721
- const minY = Math.min(el.y1, el.y2);
722
- const maxY = Math.max(el.y1, el.y2);
723
- const midX = (minX + maxX) / 2;
724
- const midY = (minY + maxY) / 2;
725
- const w = Math.max(1, maxX - minX);
726
- const h = Math.max(1, maxY - minY);
727
- const c7 = colorOf2(el);
728
- const sw7 = strokeOf2(el);
729
- const dash = dashOf2(el);
730
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
731
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
732
- /* @__PURE__ */ jsx4("ellipse", { cx: midX, cy: midY, rx: w / 2, ry: h / 2, fill: "none", stroke: c7, strokeWidth: sw7, strokeDasharray: dash, pointerEvents: "none" })
733
- ] });
734
- });
735
- registerRenderer("rectangle", (el, ctx) => {
736
- const b = getBounds(el.x1, el.y1, el.x2, el.y2);
737
- const c7 = colorOf2(el);
738
- const sw7 = strokeOf2(el);
739
- const dash = dashOf2(el);
740
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
741
- /* @__PURE__ */ jsx4("rect", { x: b.minX, y: b.minY, width: b.width, height: b.height, fill: "transparent" }),
742
- /* @__PURE__ */ jsx4(
743
- "rect",
744
- {
745
- x: b.minX,
746
- y: b.minY,
747
- width: b.width,
748
- height: b.height,
749
- fill: "none",
750
- stroke: c7,
751
- strokeWidth: sw7,
752
- strokeDasharray: dash,
753
- strokeLinejoin: "round",
754
- pointerEvents: "none"
755
- }
756
- )
757
- ] });
758
- });
759
- registerRenderer("angle", (el, ctx) => {
760
- const { x1, y1, x2, y2 } = el;
761
- const dx = x2 - x1;
762
- const dy = y2 - y1;
763
- const dist = Math.hypot(dx, dy);
764
- const minX = Math.min(x1, x2);
765
- const maxX = Math.max(x1, x2);
766
- const minY = Math.min(y1, y2);
767
- const maxY = Math.max(y1, y2);
768
- const w = Math.max(1, maxX - minX);
769
- const h = Math.max(1, maxY - minY);
770
- const c7 = colorOf2(el);
771
- const sw7 = strokeOf2(el);
772
- const dash = dashOf2(el);
773
- const fs = fontOf2(el);
774
- const angleRad = Math.atan2(dy, dx);
775
- const r = dist;
776
- const arcR = Math.min(r * 0.4, 40);
777
- const hDir = dx >= 0 ? 1 : -1;
778
- const baseA = hDir === 1 ? 0 : Math.PI;
779
- let diff = angleRad - baseA;
780
- diff = Math.atan2(Math.sin(diff), Math.cos(diff));
781
- const midA = baseA + diff / 2;
782
- const sweepFlag = diff > 0 ? 1 : 0;
783
- const arcStartX = x1 + arcR * Math.cos(baseA);
784
- const arcStartY = y1 + arcR * Math.sin(baseA);
785
- const arcEndX = x1 + arcR * Math.cos(angleRad);
786
- const arcEndY = y1 + arcR * Math.sin(angleRad);
787
- const deg = angleRad * 180 / Math.PI;
788
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
789
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
790
- /* @__PURE__ */ jsxs4("g", { pointerEvents: "none", children: [
791
- /* @__PURE__ */ jsx4("line", { x1, y1, x2: x1 + dx, y2: y1, stroke: c7, strokeWidth: sw7, strokeDasharray: "4 4", opacity: 0.6 }),
792
- /* @__PURE__ */ jsx4("line", { x1, y1, x2, y2, stroke: c7, strokeWidth: sw7, strokeLinecap: "round", strokeDasharray: dash }),
793
- /* @__PURE__ */ jsx4("g", { transform: `translate(${x2}, ${y2}) rotate(${deg})`, children: /* @__PURE__ */ jsx4("polygon", { points: "0,0 -12,-6 -12,6", fill: c7 }) }),
794
- dist > 20 && /* @__PURE__ */ jsx4(
795
- "path",
796
- {
797
- d: `M ${arcStartX} ${arcStartY} A ${arcR} ${arcR} 0 0 ${sweepFlag} ${arcEndX} ${arcEndY}`,
798
- fill: "none",
799
- stroke: c7,
800
- strokeWidth: sw7
801
- }
802
- ),
803
- el.label && /* @__PURE__ */ jsx4(
804
- "text",
805
- {
806
- x: x1 + (arcR + 16) * Math.cos(midA),
807
- y: y1 + (arcR + 16) * Math.sin(midA),
808
- fontSize: fs,
809
- fill: c7,
810
- fontFamily: "serif",
811
- fontStyle: "italic",
812
- dominantBaseline: "central",
813
- textAnchor: "middle",
814
- children: String(el.label)
815
- }
816
- )
817
- ] })
818
- ] });
819
- });
820
- registerRenderer("parabola_v", (el, ctx) => {
821
- const minX = Math.min(el.x1, el.x2);
822
- const maxX = Math.max(el.x1, el.x2);
823
- const minY = Math.min(el.y1, el.y2);
824
- const maxY = Math.max(el.y1, el.y2);
825
- const midX = (minX + maxX) / 2;
826
- const w = Math.max(1, maxX - minX);
827
- const h = Math.max(1, maxY - minY);
828
- const cpY = 2 * el.y1 - el.y2;
829
- const c7 = colorOf2(el);
830
- const sw7 = strokeOf2(el);
831
- const dash = dashOf2(el);
832
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
833
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
834
- /* @__PURE__ */ jsx4(
835
- "path",
836
- {
837
- d: `M ${minX} ${el.y2} Q ${midX} ${cpY} ${maxX} ${el.y2}`,
838
- fill: "none",
839
- stroke: c7,
840
- strokeWidth: sw7,
841
- strokeDasharray: dash,
842
- pointerEvents: "none"
843
- }
844
- )
845
- ] });
846
- });
847
- registerRenderer("parabola_h", (el, ctx) => {
848
- const minX = Math.min(el.x1, el.x2);
849
- const maxX = Math.max(el.x1, el.x2);
850
- const minY = Math.min(el.y1, el.y2);
851
- const maxY = Math.max(el.y1, el.y2);
852
- const midY = (minY + maxY) / 2;
853
- const w = Math.max(1, maxX - minX);
854
- const h = Math.max(1, maxY - minY);
855
- const cpX = 2 * el.x1 - el.x2;
856
- const c7 = colorOf2(el);
857
- const sw7 = strokeOf2(el);
858
- const dash = dashOf2(el);
859
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
860
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
861
- /* @__PURE__ */ jsx4(
862
- "path",
863
- {
864
- d: `M ${el.x2} ${minY} Q ${cpX} ${midY} ${el.x2} ${maxY}`,
865
- fill: "none",
866
- stroke: c7,
867
- strokeWidth: sw7,
868
- strokeDasharray: dash,
869
- pointerEvents: "none"
870
- }
871
- )
872
- ] });
873
- });
874
- registerRenderer("hyperbola", (el, ctx) => {
875
- const minX = Math.min(el.x1, el.x2);
876
- const maxX = Math.max(el.x1, el.x2);
877
- const minY = Math.min(el.y1, el.y2);
878
- const maxY = Math.max(el.y1, el.y2);
879
- const midX = (minX + maxX) / 2;
880
- const midY = (minY + maxY) / 2;
881
- const w = Math.max(1, maxX - minX);
882
- const h = Math.max(1, maxY - minY);
883
- const c7 = colorOf2(el);
884
- const sw7 = strokeOf2(el);
885
- const dash = dashOf2(el);
886
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
887
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
888
- /* @__PURE__ */ jsxs4("g", { pointerEvents: "none", children: [
889
- /* @__PURE__ */ jsx4("path", { d: `M ${minX} ${minY} Q ${midX} ${midY} ${minX} ${maxY}`, fill: "none", stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
890
- /* @__PURE__ */ jsx4("path", { d: `M ${maxX} ${minY} Q ${midX} ${midY} ${maxX} ${maxY}`, fill: "none", stroke: c7, strokeWidth: sw7, strokeDasharray: dash })
891
- ] })
892
- ] });
893
- });
894
- registerRenderer("modulus", (el, ctx) => {
895
- const minX = Math.min(el.x1, el.x2);
896
- const maxX = Math.max(el.x1, el.x2);
897
- const minY = Math.min(el.y1, el.y2);
898
- const maxY = Math.max(el.y1, el.y2);
899
- const midX = (minX + maxX) / 2;
900
- const w = Math.max(1, maxX - minX);
901
- const h = Math.max(1, maxY - minY);
902
- const c7 = colorOf2(el);
903
- const sw7 = strokeOf2(el);
904
- const dash = dashOf2(el);
905
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
906
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
907
- /* @__PURE__ */ jsx4(
908
- "polyline",
909
- {
910
- points: `${minX},${minY} ${midX},${maxY} ${maxX},${minY}`,
911
- fill: "none",
912
- stroke: c7,
913
- strokeWidth: sw7,
914
- strokeLinecap: "round",
915
- strokeLinejoin: "round",
916
- strokeDasharray: dash,
917
- pointerEvents: "none"
918
- }
919
- )
920
- ] });
921
- });
922
- registerRenderer("exponential", (el, ctx) => {
923
- const minX = Math.min(el.x1, el.x2);
924
- const maxX = Math.max(el.x1, el.x2);
925
- const minY = Math.min(el.y1, el.y2);
926
- const maxY = Math.max(el.y1, el.y2);
927
- const midX = (minX + maxX) / 2;
928
- const w = Math.max(1, maxX - minX);
929
- const h = Math.max(1, maxY - minY);
930
- const c7 = colorOf2(el);
931
- const sw7 = strokeOf2(el);
932
- const dash = dashOf2(el);
933
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
934
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
935
- /* @__PURE__ */ jsx4(
936
- "path",
937
- {
938
- d: `M ${minX} ${maxY} Q ${midX + w * 0.2} ${maxY} ${maxX} ${minY}`,
939
- fill: "none",
940
- stroke: c7,
941
- strokeWidth: sw7,
942
- strokeDasharray: dash,
943
- pointerEvents: "none"
944
- }
945
- )
946
- ] });
947
- });
948
- registerRenderer("logarithmic", (el, ctx) => {
949
- const minX = Math.min(el.x1, el.x2);
950
- const maxX = Math.max(el.x1, el.x2);
951
- const minY = Math.min(el.y1, el.y2);
952
- const maxY = Math.max(el.y1, el.y2);
953
- const midY = (minY + maxY) / 2;
954
- const w = Math.max(1, maxX - minX);
955
- const h = Math.max(1, maxY - minY);
956
- const c7 = colorOf2(el);
957
- const sw7 = strokeOf2(el);
958
- const dash = dashOf2(el);
959
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
960
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
961
- /* @__PURE__ */ jsx4(
962
- "path",
963
- {
964
- d: `M ${minX} ${maxY} Q ${minX} ${midY - h * 0.2} ${maxX} ${minY}`,
965
- fill: "none",
966
- stroke: c7,
967
- strokeWidth: sw7,
968
- strokeDasharray: dash,
969
- pointerEvents: "none"
970
- }
971
- )
972
- ] });
973
- });
974
- registerRenderer("sine_wave", (el, ctx) => {
975
- const minX = Math.min(el.x1, el.x2);
976
- const maxX = Math.max(el.x1, el.x2);
977
- const minY = Math.min(el.y1, el.y2);
978
- const maxY = Math.max(el.y1, el.y2);
979
- const midX = (minX + maxX) / 2;
980
- const midY = (minY + maxY) / 2;
981
- const w = Math.max(1, maxX - minX);
982
- const h = Math.max(1, maxY - minY);
983
- const s = w / 4;
984
- const c7 = colorOf2(el);
985
- const sw7 = strokeOf2(el);
986
- const dash = dashOf2(el);
987
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
988
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
989
- /* @__PURE__ */ jsx4(
990
- "path",
991
- {
992
- d: `M ${minX} ${midY} Q ${minX + s / 2} ${minY}, ${minX + s} ${midY} T ${minX + 2 * s} ${midY} T ${minX + 3 * s} ${midY} T ${maxX} ${midY}`,
993
- fill: "none",
994
- stroke: c7,
995
- strokeWidth: sw7,
996
- strokeLinecap: "round",
997
- strokeLinejoin: "round",
998
- strokeDasharray: dash,
999
- pointerEvents: "none"
1000
- }
1001
- )
1002
- ] });
1003
- });
1004
- registerRenderer("step_function", (el, ctx) => {
1005
- const minX = Math.min(el.x1, el.x2);
1006
- const maxX = Math.max(el.x1, el.x2);
1007
- const minY = Math.min(el.y1, el.y2);
1008
- const maxY = Math.max(el.y1, el.y2);
1009
- const w = Math.max(1, maxX - minX);
1010
- const h = Math.max(1, maxY - minY);
1011
- const c7 = colorOf2(el);
1012
- const sw7 = strokeOf2(el);
1013
- const dash = dashOf2(el);
1014
- const stepsCount = 4;
1015
- const stepW = w / stepsCount;
1016
- const stepH = h / stepsCount;
1017
- const steps = [];
1018
- for (let i = 0; i < stepsCount; i++) {
1019
- const curX = minX + i * stepW;
1020
- const curY = maxY - i * stepH;
1021
- const nextX = curX + stepW;
1022
- steps.push(
1023
- /* @__PURE__ */ jsxs4("g", { children: [
1024
- /* @__PURE__ */ jsx4("line", { x1: curX, y1: curY, x2: nextX, y2: curY, stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
1025
- /* @__PURE__ */ jsx4("circle", { cx: curX, cy: curY, r: sw7 * 1.5, fill: c7 }),
1026
- /* @__PURE__ */ jsx4("circle", { cx: nextX, cy: curY, r: sw7 * 1.5, fill: "white", stroke: c7, strokeWidth: sw7 * 0.75 })
1027
- ] }, i)
1028
- );
1029
- }
1030
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
1031
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
1032
- /* @__PURE__ */ jsx4("g", { pointerEvents: "none", children: steps })
1033
- ] });
1034
- });
1035
- registerRenderer("shaded_area", (el, ctx) => {
1036
- const minX = Math.min(el.x1, el.x2);
1037
- const maxX = Math.max(el.x1, el.x2);
1038
- const minY = Math.min(el.y1, el.y2);
1039
- const maxY = Math.max(el.y1, el.y2);
1040
- const midX = (minX + maxX) / 2;
1041
- const w = Math.max(1, maxX - minX);
1042
- const h = Math.max(1, maxY - minY);
1043
- const c7 = colorOf2(el);
1044
- const sw7 = strokeOf2(el);
1045
- const dash = dashOf2(el);
1046
- return /* @__PURE__ */ jsxs4("g", { opacity: op(ctx), children: [
1047
- /* @__PURE__ */ jsx4("rect", { x: minX, y: minY, width: w, height: h, fill: "transparent" }),
1048
- /* @__PURE__ */ jsxs4("g", { pointerEvents: "none", children: [
1049
- /* @__PURE__ */ jsx4(
1050
- "path",
1051
- {
1052
- d: `M ${minX} ${maxY} L ${minX} ${minY + h * 0.3} Q ${midX} ${minY} ${maxX} ${minY + h * 0.3} L ${maxX} ${maxY} Z`,
1053
- fill: c7,
1054
- opacity: 0.2
1055
- }
1056
- ),
1057
- /* @__PURE__ */ jsx4("path", { d: `M ${minX} ${minY + h * 0.3} Q ${midX} ${minY} ${maxX} ${minY + h * 0.3}`, fill: "none", stroke: c7, strokeWidth: sw7, strokeDasharray: dash })
1058
- ] })
1059
- ] });
1060
- });
1061
-
1062
- // src/core/renderers/waveOscillation.tsx
1063
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1064
- var c3 = (el) => el.color || "#0f172a";
1065
- var sw3 = (el) => el.strokeWidth || 2;
1066
- var font = (el) => el.fontSize || 18;
1067
- registerRenderer("mass_box", (el) => {
1068
- const size = el.size || 30;
1069
- const color = c3(el);
1070
- const strokeWidth = sw3(el);
1071
- const fontSize = font(el);
1072
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1073
- /* @__PURE__ */ jsx5(
1074
- "rect",
1075
- {
1076
- x: -size / 2,
1077
- y: -size / 2,
1078
- width: size,
1079
- height: size,
1080
- fill: color,
1081
- fillOpacity: 0.2,
1082
- stroke: color,
1083
- strokeWidth,
1084
- rx: 4
1085
- }
1086
- ),
1087
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: 0, dominantBaseline: "central", textAnchor: "middle", fontSize, fill: color, fontWeight: "bold", children: String(el.label) }) : null
1088
- ] });
1089
- });
1090
- registerRenderer("tuning_fork", (el) => {
1091
- const color = c3(el);
1092
- const strokeWidth = sw3(el);
1093
- const fontSize = font(el);
1094
- const w = Math.max(3, strokeWidth);
1095
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1096
- /* @__PURE__ */ jsx5(
1097
- "path",
1098
- {
1099
- d: "M -10 -20 L -10 0 Q -10 10 0 10 Q 10 10 10 0 L 10 -20",
1100
- fill: "none",
1101
- stroke: color,
1102
- strokeWidth: w,
1103
- strokeLinecap: "round"
1104
- }
1105
- ),
1106
- /* @__PURE__ */ jsx5("line", { x1: "0", y1: "10", x2: "0", y2: "30", stroke: color, strokeWidth: Math.max(4, strokeWidth), strokeLinecap: "round" }),
1107
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: 45, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1108
- ] });
1109
- });
1110
- registerRenderer("speaker", (el) => {
1111
- const color = c3(el);
1112
- const fontSize = font(el);
1113
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1114
- /* @__PURE__ */ jsx5("polygon", { points: "-10,-15 5,-25 5,25 -10,15", fill: color }),
1115
- /* @__PURE__ */ jsx5("rect", { x: "-20", y: "-15", width: "10", height: "30", fill: color }),
1116
- /* @__PURE__ */ jsx5("path", { d: "M 12 -10 Q 18 0 12 10 M 18 -20 Q 28 0 18 20", fill: "none", stroke: color, strokeWidth: 2, strokeLinecap: "round" }),
1117
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: 40, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1118
- ] });
1119
- });
1120
- registerRenderer("wavefronts", (el) => {
1121
- const rings = el.rings || 5;
1122
- const vRatio = el.velocityRatio ?? 0;
1123
- const color = c3(el);
1124
- const strokeWidth = sw3(el);
1125
- const fontSize = font(el);
1126
- const circles = [];
1127
- for (let i = 1; i <= rings; i++) {
1128
- const r = i * 20;
1129
- const cx = vRatio * r;
1130
- circles.push(
1131
- /* @__PURE__ */ jsx5(
1132
- "circle",
1133
- {
1134
- cx,
1135
- cy: 0,
1136
- r,
1137
- fill: "none",
1138
- stroke: color,
1139
- strokeWidth,
1140
- opacity: 1 - i / rings * 0.5
1141
- },
1142
- i
1143
- )
1144
- );
1145
- }
1146
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1147
- /* @__PURE__ */ jsx5("circle", { cx: 0, cy: 0, r: 4, fill: color }),
1148
- circles,
1149
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: rings * 20 + 20, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1150
- ] });
1151
- });
1152
- registerRenderer("pendulum", (el) => {
1153
- const size = el.size || 15;
1154
- const color = c3(el);
1155
- const strokeWidth = sw3(el);
1156
- const fontSize = font(el);
1157
- const theta = Math.atan2(el.x2 - el.x1, el.y2 - el.y1);
1158
- const thetaDeg = theta * (180 / Math.PI);
1159
- const l = Math.hypot(el.x2 - el.x1, el.y2 - el.y1);
1160
- const arcR = Math.min(40, l * 0.5);
1161
- const arcX = Math.sin(theta) * arcR;
1162
- const arcY = Math.cos(theta) * arcR;
1163
- const arcFlag = theta > 0 ? 0 : 1;
1164
- const showF = el.showForces;
1165
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1166
- /* @__PURE__ */ jsx5("line", { x1: -20, y1: 0, x2: 20, y2: 0, stroke: color, strokeWidth: 2 }),
1167
- /* @__PURE__ */ jsx5("line", { x1: -15, y1: 0, x2: -10, y2: -5, stroke: color }),
1168
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 5, y2: -5, stroke: color }),
1169
- /* @__PURE__ */ jsx5("line", { x1: 15, y1: 0, x2: 20, y2: -5, stroke: color }),
1170
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: l + 20, stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1171
- Math.abs(theta) > 0.05 ? /* @__PURE__ */ jsx5(
1172
- "path",
1173
- {
1174
- d: `M 0 ${arcR} A ${arcR} ${arcR} 0 0 ${arcFlag} ${arcX} ${arcY}`,
1175
- fill: "none",
1176
- stroke: color,
1177
- strokeWidth: 1.5
1178
- }
1179
- ) : null,
1180
- /* @__PURE__ */ jsxs5("g", { transform: `rotate(${-thetaDeg})`, children: [
1181
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: l, stroke: color, strokeWidth }),
1182
- /* @__PURE__ */ jsx5("circle", { cx: 0, cy: l, r: size, fill: color, stroke: "#fff", strokeWidth: 2 }),
1183
- showF ? /* @__PURE__ */ jsxs5("g", { transform: `translate(0, ${l})`, children: [
1184
- /* @__PURE__ */ jsxs5("g", { transform: `rotate(${thetaDeg})`, children: [
1185
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: 40, stroke: "#ef4444", strokeWidth: 2 }),
1186
- /* @__PURE__ */ jsx5("polygon", { points: "0,45 -4,37 4,37", fill: "#ef4444" }),
1187
- /* @__PURE__ */ jsx5("text", { x: 10, y: 40, fontSize: 12, fill: "#ef4444", children: "F_g" })
1188
- ] }),
1189
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: -40, stroke: "#3b82f6", strokeWidth: 2 }),
1190
- /* @__PURE__ */ jsx5("polygon", { points: "0,-45 -4,-37 4,-37", fill: "#3b82f6" }),
1191
- /* @__PURE__ */ jsx5("text", { x: 10, y: -35, fontSize: 12, fill: "#3b82f6", children: "T" }),
1192
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: -35 * Math.sin(theta), y2: 0, stroke: "#10b981", strokeWidth: 2 }),
1193
- /* @__PURE__ */ jsx5(
1194
- "polygon",
1195
- {
1196
- points: `${-40 * Math.sin(theta)},0 ${-32 * Math.sin(theta)},-4 ${-32 * Math.sin(theta)},4`,
1197
- fill: "#10b981"
1198
- }
1199
- ),
1200
- /* @__PURE__ */ jsx5("text", { x: -45 * Math.sin(theta), y: -10, fontSize: 12, fill: "#10b981", children: "F_g sin(\u03B8)" })
1201
- ] }) : null,
1202
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: l + size + 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1203
- ] })
1204
- ] });
1205
- });
1206
- registerRenderer("phasor", (el) => {
1207
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1208
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1209
- const dx = el.x2 - el.x1;
1210
- const dy = el.y2 - el.y1;
1211
- const color = c3(el);
1212
- const strokeWidth = sw3(el);
1213
- const fontSize = font(el);
1214
- const showProj = el.showProjection;
1215
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1216
- /* @__PURE__ */ jsx5("circle", { cx: 0, cy: 0, r: dist, fill: "none", stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1217
- /* @__PURE__ */ jsx5("line", { x1: -dist - 10, y1: 0, x2: dist + 10, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.3 }),
1218
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: -dist - 10, x2: 0, y2: dist + 10, stroke: color, strokeWidth: 1, opacity: 0.3 }),
1219
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth }),
1220
- /* @__PURE__ */ jsx5("polygon", { points: `${dist},0 ${dist - 12},-6 ${dist - 12},6`, fill: color }),
1221
- showProj ? /* @__PURE__ */ jsxs5("g", { transform: `rotate(${-angle})`, children: [
1222
- /* @__PURE__ */ jsx5("line", { x1: dx, y1: dy, x2: dx, y2: 0, stroke: "#ef4444", strokeWidth: 1, strokeDasharray: "4 4" }),
1223
- /* @__PURE__ */ jsx5("line", { x1: dx, y1: dy, x2: 0, y2: dy, stroke: "#3b82f6", strokeWidth: 1, strokeDasharray: "4 4" }),
1224
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dx, y2: 0, stroke: "#ef4444", strokeWidth: 2 }),
1225
- /* @__PURE__ */ jsx5("polygon", { points: `${dx},0 ${dx > 0 ? dx - 8 : dx + 8},-4 ${dx > 0 ? dx - 8 : dx + 8},4`, fill: "#ef4444" }),
1226
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: dy, stroke: "#3b82f6", strokeWidth: 2 }),
1227
- /* @__PURE__ */ jsx5("polygon", { points: `0,${dy} -4,${dy > 0 ? dy - 8 : dy + 8} 4,${dy > 0 ? dy - 8 : dy + 8}`, fill: "#3b82f6" })
1228
- ] }) : null,
1229
- /* @__PURE__ */ jsx5(
1230
- "path",
1231
- {
1232
- d: `M ${dist * 0.3} 0 A ${dist * 0.3} ${dist * 0.3} 0 0 0 ${dist * 0.3 * Math.cos(-angle * Math.PI / 180)} ${dist * 0.3 * Math.sin(-angle * Math.PI / 180)}`,
1233
- fill: "none",
1234
- stroke: color,
1235
- strokeWidth: 1.5,
1236
- transform: `rotate(${-angle})`
1237
- }
1238
- ),
1239
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1240
- ] });
1241
- });
1242
- registerRenderer("sine_wave", (el) => {
1243
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1244
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1245
- const amp = el.amplitude || 40;
1246
- const loops = el.loops || 2;
1247
- const wl = dist / (loops / 2);
1248
- const color = c3(el);
1249
- const strokeWidth = sw3(el);
1250
- const fontSize = font(el);
1251
- let d = "M 0 0";
1252
- const step = Math.max(1, dist / 100);
1253
- for (let i = 0; i <= dist; i += step) {
1254
- d += ` L ${i} ${-amp * Math.sin(i / wl * 2 * Math.PI)}`;
1255
- }
1256
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1257
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1258
- /* @__PURE__ */ jsx5("path", { d, fill: "none", stroke: color, strokeWidth, strokeLinejoin: "round" }),
1259
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1260
- ] });
1261
- });
1262
- registerRenderer("standing_wave", (el) => {
1263
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1264
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1265
- const amp = el.amplitude || 40;
1266
- const loops = el.loops || 3;
1267
- const wl = dist / (loops / 2);
1268
- const color = c3(el);
1269
- const strokeWidth = sw3(el);
1270
- const fontSize = font(el);
1271
- let d1 = "M 0 0";
1272
- let d2 = "M 0 0";
1273
- const step = Math.max(1, dist / 100);
1274
- for (let i = 0; i <= dist; i += step) {
1275
- const y = amp * Math.sin(i / wl * 2 * Math.PI);
1276
- d1 += ` L ${i} ${-y}`;
1277
- d2 += ` L ${i} ${y}`;
1278
- }
1279
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1280
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.5 }),
1281
- /* @__PURE__ */ jsx5("path", { d: d1, fill: color, fillOpacity: 0.1, stroke: color, strokeWidth, strokeLinejoin: "round" }),
1282
- /* @__PURE__ */ jsx5("path", { d: d2, fill: "none", stroke: color, strokeWidth, strokeDasharray: "4 4", strokeLinejoin: "round" }),
1283
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1284
- ] });
1285
- });
1286
- registerRenderer("shm_graph", (el) => {
1287
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1288
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1289
- const amp = el.amplitude || 40;
1290
- const loops = el.loops || 1;
1291
- const wl = dist / loops;
1292
- const gType = el.graphType || "x";
1293
- const color = c3(el);
1294
- const strokeWidth = sw3(el);
1295
- const fontSize = font(el);
1296
- let dX = `M 0 ${-amp}`;
1297
- let dV = "M 0 0";
1298
- let dA = `M 0 ${amp}`;
1299
- const step = Math.max(1, dist / 100);
1300
- for (let i = 0; i <= dist; i += step) {
1301
- const phase = i / wl * 2 * Math.PI;
1302
- dX += ` L ${i} ${-amp * Math.cos(phase)}`;
1303
- dV += ` L ${i} ${-amp * 0.8 * -Math.sin(phase)}`;
1304
- dA += ` L ${i} ${-amp * 0.6 * -Math.cos(phase)}`;
1305
- }
1306
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1307
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.5 }),
1308
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: -amp * 1.2, x2: 0, y2: amp * 1.2, stroke: color, strokeWidth: 1, opacity: 0.5 }),
1309
- (gType === "x" || gType === "all") && /* @__PURE__ */ jsx5("path", { d: dX, fill: "none", stroke: "#3b82f6", strokeWidth, strokeLinejoin: "round" }),
1310
- (gType === "v" || gType === "all") && /* @__PURE__ */ jsx5("path", { d: dV, fill: "none", stroke: "#ef4444", strokeWidth, strokeLinejoin: "round" }),
1311
- (gType === "a" || gType === "all") && /* @__PURE__ */ jsx5("path", { d: dA, fill: "none", stroke: "#10b981", strokeWidth, strokeLinejoin: "round" }),
1312
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1313
- ] });
1314
- });
1315
- registerRenderer("energy_graph", (el) => {
1316
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1317
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1318
- const amp = el.amplitude || 50;
1319
- const loops = el.loops || 1;
1320
- const wl = dist / loops;
1321
- const dom = el.domain || "time";
1322
- const color = c3(el);
1323
- const strokeWidth = sw3(el);
1324
- const fontSize = font(el);
1325
- let dU = "M 0 0";
1326
- let dK = `M 0 ${-amp}`;
1327
- const step = Math.max(1, dist / 100);
1328
- if (dom === "time") {
1329
- dU = `M 0 ${-amp}`;
1330
- dK = "M 0 0";
1331
- for (let i = 0; i <= dist; i += step) {
1332
- const phase = i / wl * 2 * Math.PI;
1333
- dU += ` L ${i} ${-amp * Math.pow(Math.cos(phase), 2)}`;
1334
- dK += ` L ${i} ${-amp * Math.pow(Math.sin(phase), 2)}`;
1335
- }
1336
- } else {
1337
- for (let i = 0; i <= dist; i += step) {
1338
- const xNorm = 2 * (i / dist) - 1;
1339
- const uVal = amp * xNorm * xNorm;
1340
- dU += ` L ${i} ${-uVal}`;
1341
- dK += ` L ${i} ${-(amp - uVal)}`;
1342
- }
1343
- }
1344
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1345
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.5 }),
1346
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: -amp, x2: dist, y2: -amp, stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1347
- /* @__PURE__ */ jsx5("path", { d: dU, fill: "none", stroke: "#10b981", strokeWidth, strokeLinejoin: "round" }),
1348
- /* @__PURE__ */ jsx5("path", { d: dK, fill: "none", stroke: "#ef4444", strokeWidth, strokeLinejoin: "round" }),
1349
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1350
- ] });
1351
- });
1352
- registerRenderer("strobe_shm", (el) => {
1353
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1354
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1355
- const amp = el.amplitude || 40;
1356
- const loops = el.loops || 1;
1357
- const color = c3(el);
1358
- const strokeWidth = sw3(el);
1359
- const fontSize = font(el);
1360
- const rows = 10;
1361
- const pts = [];
1362
- const circles = [];
1363
- const lines = [];
1364
- for (let i = 0; i <= rows; i++) {
1365
- const t = i / rows;
1366
- const cx = amp * Math.cos(t * 2 * Math.PI * loops);
1367
- const cy = t * dist;
1368
- pts.push(`${cx},${cy}`);
1369
- circles.push(/* @__PURE__ */ jsx5("circle", { cx, cy, r: strokeWidth * 2, fill: color }, `c${i}`));
1370
- lines.push(
1371
- /* @__PURE__ */ jsx5("line", { x1: -amp - 20, y1: cy, x2: amp + 20, y2: cy, stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.3 }, `l${i}`)
1372
- );
1373
- }
1374
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1375
- lines,
1376
- /* @__PURE__ */ jsx5("polyline", { points: pts.join(" "), fill: "none", stroke: color, strokeWidth: 1, opacity: 0.4 }),
1377
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: 0, y2: dist, stroke: color, strokeWidth: 1, opacity: 0.5 }),
1378
- circles,
1379
- el.label ? /* @__PURE__ */ jsx5("text", { x: 0, y: -15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1380
- ] });
1381
- });
1382
- registerRenderer("torsion_pendulum", (el) => {
1383
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1384
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1385
- const color = c3(el);
1386
- const strokeWidth = sw3(el);
1387
- const fontSize = font(el);
1388
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1389
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth }),
1390
- /* @__PURE__ */ jsx5("ellipse", { cx: dist, cy: 0, rx: 40, ry: 15, fill: color, fillOpacity: 0.2, stroke: color, strokeWidth }),
1391
- /* @__PURE__ */ jsx5("line", { x1: dist, y1: 0, x2: dist + 40, y2: 0, stroke: color, strokeWidth, strokeDasharray: "2 2" }),
1392
- /* @__PURE__ */ jsx5("line", { x1: dist, y1: 0, x2: dist + 30, y2: 20, stroke: "#ef4444", strokeWidth }),
1393
- /* @__PURE__ */ jsx5("path", { d: `M ${dist + 20} 0 A 20 7.5 0 0 1 ${dist + 15} 10`, fill: "none", stroke: "#ef4444", strokeWidth: 1.5 }),
1394
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1395
- ] });
1396
- });
1397
- registerRenderer("vane_liquid", (el) => {
1398
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1399
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1400
- const color = c3(el);
1401
- const strokeWidth = sw3(el);
1402
- const fontSize = font(el);
1403
- const beakerW = Math.max(40, dist * 0.4);
1404
- const beakerH = Math.max(40, dist * 0.5);
1405
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1406
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth }),
1407
- /* @__PURE__ */ jsx5("line", { x1: dist, y1: -beakerW * 0.3, x2: dist, y2: beakerW * 0.3, stroke: color, strokeWidth: strokeWidth * 1.5, strokeLinecap: "round" }),
1408
- /* @__PURE__ */ jsx5(
1409
- "path",
1410
- {
1411
- d: `M ${dist - beakerH} ${-beakerW / 2} L ${dist + 10} ${-beakerW / 2} L ${dist + 10} ${beakerW / 2} L ${dist - beakerH} ${beakerW / 2}`,
1412
- fill: "none",
1413
- stroke: color,
1414
- strokeWidth: 2,
1415
- strokeLinecap: "round",
1416
- strokeLinejoin: "round"
1417
- }
1418
- ),
1419
- /* @__PURE__ */ jsx5(
1420
- "rect",
1421
- {
1422
- x: dist - beakerH + 2,
1423
- y: -beakerW / 2 + 2,
1424
- width: beakerH + 8,
1425
- height: beakerW - 4,
1426
- fill: "#38bdf8",
1427
- fillOpacity: 0.3
1428
- }
1429
- ),
1430
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -beakerW / 2 - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1431
- ] });
1432
- });
1433
- registerRenderer("wave_pulse", (el) => {
1434
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1435
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1436
- const amp = el.amplitude || 50;
1437
- const color = c3(el);
1438
- const strokeWidth = sw3(el);
1439
- const fontSize = font(el);
1440
- const mid = dist / 2;
1441
- const spread = dist / 6;
1442
- let d = "M 0 0";
1443
- const step = Math.max(1, dist / 50);
1444
- for (let i = 0; i <= dist; i += step) {
1445
- const y = amp * Math.exp(-Math.pow(i - mid, 2) / (2 * spread * spread));
1446
- d += ` L ${i} ${-y}`;
1447
- }
1448
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1449
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth, strokeLinecap: "round" }),
1450
- /* @__PURE__ */ jsx5("path", { d, fill: color, fillOpacity: 0.1, stroke: color, strokeWidth, strokeLinejoin: "round" }),
1451
- el.label ? /* @__PURE__ */ jsx5("text", { x: mid, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1452
- ] });
1453
- });
1454
- registerRenderer("damped_wave", (el) => {
1455
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1456
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1457
- const amp = el.amplitude || 50;
1458
- const damp = el.damping || 0.015;
1459
- const freq = el.frequency || 10;
1460
- const color = c3(el);
1461
- const strokeWidth = sw3(el);
1462
- const fontSize = font(el);
1463
- let d = `M 0 ${-amp}`;
1464
- let env1 = `M 0 ${-amp}`;
1465
- let env2 = `M 0 ${amp}`;
1466
- const step = Math.max(1, dist / 200);
1467
- for (let i = 0; i <= dist; i += step) {
1468
- const envY = amp * Math.exp(-damp * i);
1469
- const y = envY * Math.cos(i / dist * freq * 2 * Math.PI);
1470
- d += ` L ${i} ${-y}`;
1471
- env1 += ` L ${i} ${-envY}`;
1472
- env2 += ` L ${i} ${envY}`;
1473
- }
1474
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1475
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.3 }),
1476
- /* @__PURE__ */ jsx5("path", { d: env1, fill: "none", stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1477
- /* @__PURE__ */ jsx5("path", { d: env2, fill: "none", stroke: color, strokeWidth: 1, strokeDasharray: "4 4", opacity: 0.5 }),
1478
- /* @__PURE__ */ jsx5("path", { d, fill: "none", stroke: color, strokeWidth, strokeLinejoin: "round" }),
1479
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1480
- ] });
1481
- });
1482
- registerRenderer("beats_graph", (el) => {
1483
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1484
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1485
- const amp = el.amplitude || 30;
1486
- const freq = el.frequency || 20;
1487
- const beatF = el.beatFreq || 2;
1488
- const color = c3(el);
1489
- const strokeWidth = sw3(el);
1490
- const fontSize = font(el);
1491
- let d = "M 0 0";
1492
- let env1 = "M 0 0";
1493
- let env2 = "M 0 0";
1494
- const step = Math.max(1, dist / 200);
1495
- for (let i = 0; i <= dist; i += step) {
1496
- const env = amp * Math.cos(i / dist * beatF * Math.PI);
1497
- const y = env * Math.sin(i / dist * freq * 2 * Math.PI);
1498
- d += ` L ${i} ${-y}`;
1499
- env1 += ` L ${i} ${-Math.abs(env)}`;
1500
- env2 += ` L ${i} ${Math.abs(env)}`;
1501
- }
1502
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1503
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth: 1, opacity: 0.3 }),
1504
- /* @__PURE__ */ jsx5("path", { d: env1, fill: "none", stroke: color, strokeWidth: 1, strokeDasharray: "2 4", opacity: 0.5 }),
1505
- /* @__PURE__ */ jsx5("path", { d: env2, fill: "none", stroke: color, strokeWidth: 1, strokeDasharray: "2 4", opacity: 0.5 }),
1506
- /* @__PURE__ */ jsx5("path", { d, fill: "none", stroke: color, strokeWidth, strokeLinejoin: "round" }),
1507
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: -amp - 20, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1508
- ] });
1509
- });
1510
- registerRenderer("mach_cone", (el) => {
1511
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1512
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1513
- const M = el.machNumber || 2;
1514
- const coneAngle = Math.asin(1 / Math.max(1.01, M));
1515
- const h = dist;
1516
- const r = h * Math.tan(coneAngle);
1517
- const color = c3(el);
1518
- const strokeWidth = sw3(el);
1519
- const fontSize = font(el);
1520
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1521
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: h, y2: 0, stroke: color, strokeWidth: 1, strokeDasharray: "4 4" }),
1522
- /* @__PURE__ */ jsx5("line", { x1: h, y1: 0, x2: 0, y2: -r, stroke: color, strokeWidth }),
1523
- /* @__PURE__ */ jsx5("line", { x1: h, y1: 0, x2: 0, y2: r, stroke: color, strokeWidth }),
1524
- /* @__PURE__ */ jsx5("circle", { cx: h, cy: 0, r: 4, fill: color }),
1525
- [0.2, 0.5, 0.8].map((t) => /* @__PURE__ */ jsx5("circle", { cx: h * t, cy: 0, r: (1 - t) * r, fill: "none", stroke: color, strokeWidth: 1, opacity: 0.6 }, t)),
1526
- el.label ? /* @__PURE__ */ jsx5("text", { x: h / 2, y: r + 20, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1527
- ] });
1528
- });
1529
- registerRenderer("wall", (el) => {
1530
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1531
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1532
- const color = c3(el);
1533
- const strokeWidth = sw3(el);
1534
- const fontSize = font(el);
1535
- const hashes = [];
1536
- const numHashes = Math.max(2, Math.floor(dist / 10));
1537
- for (let j = 0; j <= numHashes; j++) {
1538
- const i = j / numHashes * dist;
1539
- hashes.push(/* @__PURE__ */ jsx5("line", { x1: i, y1: 0, x2: i - 8, y2: -12, stroke: color, strokeWidth: 1 }, j));
1540
- }
1541
- return /* @__PURE__ */ jsxs5("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1542
- /* @__PURE__ */ jsx5("line", { x1: 0, y1: 0, x2: dist, y2: 0, stroke: color, strokeWidth }),
1543
- hashes,
1544
- el.label ? /* @__PURE__ */ jsx5("text", { x: dist / 2, y: 20, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
1545
- ] });
1546
- });
1547
-
1548
- // src/core/renderers/mechanical.tsx
1549
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1550
- var c4 = (el) => el.color || "#0f172a";
1551
- var sw4 = (el) => el.strokeWidth || 2;
1552
- var font2 = (el) => el.fontSize || 18;
1553
- registerRenderer("string", (el) => {
1554
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1555
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1556
- return /* @__PURE__ */ jsx6("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: /* @__PURE__ */ jsx6("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c4(el), strokeWidth: sw4(el), strokeLinecap: "round" }) });
1557
- });
1558
- registerRenderer("surface", (el) => {
1559
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1560
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1561
- const hatchCount = Math.max(0, Math.floor(d / 12));
1562
- const hatches = [];
1563
- for (let i = 0; i <= hatchCount; i++) {
1564
- hatches.push(/* @__PURE__ */ jsx6("line", { x1: i * 12, y1: 0, x2: i * 12 - 8, y2: 12, stroke: c4(el), strokeWidth: 1.5 }, i));
1565
- }
1566
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1567
- /* @__PURE__ */ jsx6("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c4(el), strokeWidth: sw4(el) + 0.5, strokeLinecap: "round" }),
1568
- hatches
1569
- ] });
1570
- });
1571
- var rotOf = (el) => el.rotation || 0;
1572
- registerRenderer("block", (el) => {
1573
- const w = Math.abs(el.x2 - el.x1);
1574
- const h = Math.abs(el.y2 - el.y1);
1575
- const cx = (el.x1 + el.x2) / 2;
1576
- const cy = (el.y1 + el.y2) / 2;
1577
- const rot = rotOf(el);
1578
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${cx}, ${cy}) rotate(${rot})`, children: [
1579
- /* @__PURE__ */ jsx6("rect", { x: -w / 2, y: -h / 2, width: w, height: h, fill: "#f1f5f9", stroke: c4(el), strokeWidth: sw4(el) }),
1580
- el.label ? /* @__PURE__ */ jsx6(
1581
- "text",
1582
- {
1583
- x: 0,
1584
- y: el.value ? -6 : 0,
1585
- dominantBaseline: "central",
1586
- textAnchor: "middle",
1587
- fill: c4(el),
1588
- fontSize: 18,
1589
- fontFamily: "serif",
1590
- fontWeight: "bold",
1591
- children: String(el.label)
1592
- }
1593
- ) : null,
1594
- el.value ? /* @__PURE__ */ jsx6(
1595
- "text",
1596
- {
1597
- x: 0,
1598
- y: el.label ? 10 : 0,
1599
- dominantBaseline: "central",
1600
- textAnchor: "middle",
1601
- fill: "#4b5563",
1602
- fontSize: 14,
1603
- fontFamily: "sans-serif",
1604
- children: String(el.value)
1605
- }
1606
- ) : null
1607
- ] });
1608
- });
1609
- registerRenderer("cart", (el) => {
1610
- const w = Math.abs(el.x2 - el.x1);
1611
- const h = Math.abs(el.y2 - el.y1);
1612
- const cx = (el.x1 + el.x2) / 2;
1613
- const cy = (el.y1 + el.y2) / 2;
1614
- const rot = rotOf(el);
1615
- const wheelR = Math.min(w * 0.15, h * 0.25, 12);
1616
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${cx}, ${cy}) rotate(${rot})`, children: [
1617
- /* @__PURE__ */ jsx6("rect", { x: -w / 2, y: -h / 2, width: w, height: h - wheelR, fill: "#f1f5f9", stroke: c4(el), strokeWidth: sw4(el) }),
1618
- /* @__PURE__ */ jsx6("circle", { cx: -w / 2 + wheelR * 1.5, cy: h / 2 - wheelR, r: wheelR, fill: "#cbd5e1", stroke: c4(el), strokeWidth: sw4(el) }),
1619
- /* @__PURE__ */ jsx6("circle", { cx: w / 2 - wheelR * 1.5, cy: h / 2 - wheelR, r: wheelR, fill: "#cbd5e1", stroke: c4(el), strokeWidth: sw4(el) }),
1620
- el.label ? /* @__PURE__ */ jsx6(
1621
- "text",
1622
- {
1623
- x: 0,
1624
- y: el.value ? -8 : -2,
1625
- dominantBaseline: "central",
1626
- textAnchor: "middle",
1627
- fill: c4(el),
1628
- fontSize: 18,
1629
- fontFamily: "serif",
1630
- fontWeight: "bold",
1631
- children: String(el.label)
1632
- }
1633
- ) : null,
1634
- el.value ? /* @__PURE__ */ jsx6(
1635
- "text",
1636
- {
1637
- x: 0,
1638
- y: el.label ? 8 : -2,
1639
- dominantBaseline: "central",
1640
- textAnchor: "middle",
1641
- fill: "#4b5563",
1642
- fontSize: 14,
1643
- fontFamily: "sans-serif",
1644
- children: String(el.value)
1645
- }
1646
- ) : null
1647
- ] });
1648
- });
1649
- registerRenderer("particle", (el) => {
1650
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1651
- const r = Math.max(5, d);
1652
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1653
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r, fill: c4(el) }),
1654
- el.label ? /* @__PURE__ */ jsx6("text", { x: 0, y: -r - 12, dominantBaseline: "central", textAnchor: "middle", fill: c4(el), fontSize: font2(el), fontFamily: "serif", fontWeight: "bold", children: String(el.label) }) : null,
1655
- el.value ? /* @__PURE__ */ jsx6("text", { x: 0, y: r + 12, dominantBaseline: "central", textAnchor: "middle", fill: "#4b5563", fontSize: 14, fontFamily: "sans-serif", children: String(el.value) }) : null
1656
- ] });
1657
- });
1658
- registerRenderer("disk", (el) => {
1659
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1660
- const r = Math.max(10, d);
1661
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1662
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r, fill: "#e2e8f0", stroke: c4(el), strokeWidth: sw4(el) }),
1663
- /* @__PURE__ */ jsx6("line", { x1: 0, y1: 0, x2: r, y2: 0, stroke: c4(el), strokeWidth: sw4(el) }),
1664
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r: 3, fill: c4(el) }),
1665
- el.label ? /* @__PURE__ */ jsx6("text", { x: 0, y: -r - 12, dominantBaseline: "central", textAnchor: "middle", fill: c4(el), fontSize: font2(el), fontFamily: "serif", fontWeight: "bold", children: String(el.label) }) : null,
1666
- el.value ? /* @__PURE__ */ jsx6("text", { x: 0, y: r + 12, dominantBaseline: "central", textAnchor: "middle", fill: "#4b5563", fontSize: 14, fontFamily: "sans-serif", children: String(el.value) }) : null
1667
- ] });
1668
- });
1669
- registerRenderer("com", (el) => /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1670
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r: 10, fill: "none", stroke: c4(el), strokeWidth: sw4(el) }),
1671
- /* @__PURE__ */ jsx6("path", { d: "M 0 -10 A 10 10 0 0 1 10 0 L 0 0 Z", fill: c4(el) }),
1672
- /* @__PURE__ */ jsx6("path", { d: "M 0 10 A 10 10 0 0 1 -10 0 L 0 0 Z", fill: c4(el) })
1673
- ] }));
1674
- registerRenderer("pivot", (el) => /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1675
- /* @__PURE__ */ jsx6("polygon", { points: "0,0 -12,20 12,20", fill: "#f8fafc", stroke: c4(el), strokeWidth: sw4(el), strokeLinejoin: "round" }),
1676
- /* @__PURE__ */ jsx6("line", { x1: -20, y1: 20, x2: 20, y2: 20, stroke: c4(el), strokeWidth: sw4(el), strokeLinecap: "round" }),
1677
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r: 3, fill: c4(el) })
1678
- ] }));
1679
- registerRenderer("pulley", (el) => {
1680
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1681
- const r = Math.max(10, d);
1682
- return /* @__PURE__ */ jsxs6("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1683
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r, fill: "#f8fafc", stroke: c4(el), strokeWidth: sw4(el) }),
1684
- /* @__PURE__ */ jsx6("circle", { cx: 0, cy: 0, r: 4, fill: c4(el) }),
1685
- el.label ? /* @__PURE__ */ jsx6("text", { x: 0, y: -r - 12, dominantBaseline: "central", textAnchor: "middle", fill: c4(el), fontSize: font2(el), fontFamily: "serif", fontWeight: "bold", children: String(el.label) }) : null
1686
- ] });
1687
- });
1688
-
1689
- // src/core/renderers/rotation.tsx
1690
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1691
- var c5 = (el) => el.color || "#0f172a";
1692
- var sw5 = (el) => el.strokeWidth || 2;
1693
- var font3 = (el) => el.fontSize || 18;
1694
- function generateSpringPath(dist, coils, width2 = 20) {
1695
- const ccount = Math.max(3, coils ?? Math.floor(dist / 20));
1696
- const step = dist / ccount;
1697
- let d = `M 0 0 L ${step * 0.2} 0 `;
1698
- for (let i = 0; i < ccount; i++) {
1699
- const startX = i * step;
1700
- if (i === ccount - 1) {
1701
- d += `L ${startX + step * 0.25} ${-width2 / 2} L ${startX + step * 0.75} ${width2 / 2} L ${dist} 0 `;
1702
- } else {
1703
- d += `L ${startX + step * 0.25} ${-width2 / 2} L ${startX + step * 0.75} ${width2 / 2} L ${startX + step} 0 `;
1704
- }
1705
- }
1706
- return d;
1707
- }
1708
- registerRenderer("point_mass", (el) => {
1709
- const size = el.size ?? 15;
1710
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1711
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: size, fill: c5(el), fillOpacity: 0.8, stroke: c5(el), strokeWidth: 2 }),
1712
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: size * 0.3, fill: "#fff", fillOpacity: 0.5 }),
1713
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: size + 15, fontSize: font3(el), fill: c5(el), textAnchor: "middle", fontWeight: "bold", children: String(el.label) }) : null
1714
- ] });
1715
- });
1716
- registerRenderer("com_indicator", (el) => {
1717
- const size = el.size ?? 15;
1718
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1719
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: size, fill: "none", stroke: c5(el), strokeWidth: sw5(el) }),
1720
- /* @__PURE__ */ jsx7("line", { x1: -size * 1.3, y1: 0, x2: size * 1.3, y2: 0, stroke: c5(el), strokeWidth: sw5(el) }),
1721
- /* @__PURE__ */ jsx7("line", { x1: 0, y1: -size * 1.3, x2: 0, y2: size * 1.3, stroke: c5(el), strokeWidth: sw5(el) }),
1722
- /* @__PURE__ */ jsx7("path", { d: `M 0 0 L ${size} 0 A ${size} ${size} 0 0 0 0 ${-size} Z`, fill: c5(el), fillOpacity: 0.5 }),
1723
- /* @__PURE__ */ jsx7("path", { d: `M 0 0 L ${-size} 0 A ${size} ${size} 0 0 0 0 ${size} Z`, fill: c5(el), fillOpacity: 0.5 }),
1724
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: size + 15, fontSize: font3(el), fill: c5(el), textAnchor: "middle", fontWeight: "bold", children: String(el.label) }) : null
1725
- ] });
1726
- });
1727
- registerRenderer("pivot", (el) => {
1728
- const size = el.size ?? 20;
1729
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1730
- /* @__PURE__ */ jsx7(
1731
- "polygon",
1732
- {
1733
- points: `0,0 ${-size},${size * 1.5} ${size},${size * 1.5}`,
1734
- fill: "none",
1735
- stroke: c5(el),
1736
- strokeWidth: sw5(el)
1737
- }
1738
- ),
1739
- /* @__PURE__ */ jsx7(
1740
- "line",
1741
- {
1742
- x1: -size * 1.5,
1743
- y1: size * 1.5,
1744
- x2: size * 1.5,
1745
- y2: size * 1.5,
1746
- stroke: c5(el),
1747
- strokeWidth: sw5(el) + 1,
1748
- strokeLinecap: "round"
1749
- }
1750
- ),
1751
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: sw5(el) * 1.5, fill: c5(el) }),
1752
- Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx7(
1753
- "line",
1754
- {
1755
- x1: -size + i * size * 0.5,
1756
- y1: size * 1.5,
1757
- x2: -size + i * size * 0.5 - 5,
1758
- y2: size * 1.5 + 8,
1759
- stroke: c5(el),
1760
- strokeWidth: 1
1761
- },
1762
- i
1763
- )),
1764
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: size * 1.5 + 20, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1765
- ] });
1766
- });
1767
- registerRenderer("block_mass", (el) => {
1768
- const minX = Math.min(el.x1, el.x2);
1769
- const minY = Math.min(el.y1, el.y2);
1770
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
1771
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
1772
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${minX}, ${minY})`, children: [
1773
- /* @__PURE__ */ jsx7("rect", { x: 0, y: 0, width: w, height: h, fill: c5(el), fillOpacity: 0.2, stroke: c5(el), strokeWidth: sw5(el), rx: 2 }),
1774
- el.label ? /* @__PURE__ */ jsx7("text", { x: w / 2, y: h / 2, dominantBaseline: "central", textAnchor: "middle", fontSize: font3(el), fill: c5(el), fontWeight: "bold", children: String(el.label) }) : null
1775
- ] });
1776
- });
1777
- registerRenderer("system_boundary", (el) => {
1778
- const minX = Math.min(el.x1, el.x2);
1779
- const minY = Math.min(el.y1, el.y2);
1780
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
1781
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
1782
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${minX}, ${minY})`, children: [
1783
- /* @__PURE__ */ jsx7("rect", { x: 0, y: 0, width: w, height: h, fill: "none", stroke: c5(el), strokeWidth: sw5(el), strokeDasharray: "8 6", rx: 15 }),
1784
- el.label ? /* @__PURE__ */ jsx7("text", { x: w / 2, y: -10, fontSize: font3(el), fill: c5(el), textAnchor: "middle", fontStyle: "italic", children: String(el.label) }) : null
1785
- ] });
1786
- });
1787
- registerRenderer("rocket", (el) => {
1788
- const dx = el.x2 - el.x1;
1789
- const dy = el.y2 - el.y1;
1790
- const dist = Math.hypot(dx, dy);
1791
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1792
- const minX = Math.min(el.x1, el.x2);
1793
- const maxX = Math.max(el.x1, el.x2);
1794
- const minY = Math.min(el.y1, el.y2);
1795
- const maxY = Math.max(el.y1, el.y2);
1796
- const w = Math.max(1, maxX - minX);
1797
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1798
- /* @__PURE__ */ jsx7(
1799
- "path",
1800
- {
1801
- d: `M 0 ${-w / 4} L ${dist * 0.7} ${-w / 4} L ${dist} 0 L ${dist * 0.7} ${w / 4} L 0 ${w / 4} Z`,
1802
- fill: "none",
1803
- stroke: c5(el),
1804
- strokeWidth: sw5(el)
1805
- }
1806
- ),
1807
- /* @__PURE__ */ jsx7("polygon", { points: `0,${-w / 4} ${dist * 0.2},${-w / 4} 0,${-w / 2}`, fill: c5(el), fillOpacity: 0.8 }),
1808
- /* @__PURE__ */ jsx7("polygon", { points: `0,${w / 4} ${dist * 0.2},${w / 4} 0,${w / 2}`, fill: c5(el), fillOpacity: 0.8 }),
1809
- /* @__PURE__ */ jsx7("path", { d: `M 0 ${-w / 6} Q ${-dist * 0.3} 0 0 ${w / 6}`, fill: "#f97316", fillOpacity: 0.8 }),
1810
- /* @__PURE__ */ jsx7("path", { d: `M 0 ${-w / 8} Q ${-dist * 0.5} 0 0 ${w / 8}`, fill: "#ef4444", fillOpacity: 0.6 }),
1811
- el.label ? /* @__PURE__ */ jsx7("text", { x: dist / 2, y: -w / 2 - 10, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1812
- ] });
1813
- });
1814
- registerRenderer("dashed_path", (el) => {
1815
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1816
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1817
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1818
- /* @__PURE__ */ jsx7("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c5(el), strokeWidth: sw5(el), strokeLinecap: "round", strokeDasharray: "8 6" }),
1819
- el.label ? /* @__PURE__ */ jsx7("text", { x: d / 2, y: -10, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1820
- ] });
1821
- });
1822
- registerRenderer("uniform_rod", (el) => {
1823
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1824
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1825
- const strokeWidth = sw5(el);
1826
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1827
- /* @__PURE__ */ jsx7("rect", { x: 0, y: -strokeWidth / 2, width: dist, height: strokeWidth, fill: c5(el), rx: strokeWidth / 4 }),
1828
- /* @__PURE__ */ jsx7("circle", { cx: dist / 2, cy: 0, r: Math.max(2, strokeWidth / 4), fill: "#fff" }),
1829
- el.label ? /* @__PURE__ */ jsx7("text", { x: dist / 2, y: -strokeWidth / 2 - 10, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1830
- ] });
1831
- });
1832
- registerRenderer("solid_disk", (el) => {
1833
- const dx = el.x2 - el.x1;
1834
- const dy = el.y2 - el.y1;
1835
- const radius = Math.hypot(dx, dy);
1836
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1837
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: radius, fill: c5(el), fillOpacity: 0.4, stroke: c5(el), strokeWidth: sw5(el) }),
1838
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: radius + 20, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1839
- ] });
1840
- });
1841
- registerRenderer("hoop_ring", (el) => {
1842
- const dx = el.x2 - el.x1;
1843
- const dy = el.y2 - el.y1;
1844
- const radius = Math.hypot(dx, dy);
1845
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1846
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: radius, fill: "none", stroke: c5(el), strokeWidth: Math.max(4, sw5(el) * 2) }),
1847
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: radius + 20, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1848
- ] });
1849
- });
1850
- registerRenderer("rolling_body", (el) => {
1851
- const dx = el.x2 - el.x1;
1852
- const dy = el.y2 - el.y1;
1853
- const radius = Math.hypot(dx, dy);
1854
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1855
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: radius, fill: c5(el), fillOpacity: 0.1, stroke: c5(el), strokeWidth: sw5(el) }),
1856
- /* @__PURE__ */ jsx7("line", { x1: -radius, y1: 0, x2: radius, y2: 0, stroke: c5(el), strokeWidth: 1, strokeDasharray: "4 4" }),
1857
- /* @__PURE__ */ jsx7("line", { x1: 0, y1: -radius, x2: 0, y2: radius, stroke: c5(el), strokeWidth: 1, strokeDasharray: "4 4" }),
1858
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: 3, fill: c5(el) }),
1859
- el.showVelocity ? /* @__PURE__ */ jsxs7("g", { children: [
1860
- /* @__PURE__ */ jsx7("line", { x1: 0, y1: 0, x2: radius * 1.5, y2: 0, stroke: "#ef4444", strokeWidth: 2 }),
1861
- /* @__PURE__ */ jsx7("polygon", { points: `${radius * 1.5},0 ${radius * 1.5 - 8},-4 ${radius * 1.5 - 8},4`, fill: "#ef4444" }),
1862
- /* @__PURE__ */ jsx7("text", { x: radius * 1.5 + 10, y: 5, fill: "#ef4444", fontSize: 14, fontStyle: "italic", children: "v" })
1863
- ] }) : null,
1864
- el.showOmega ? /* @__PURE__ */ jsxs7("g", { transform: `translate(0, ${-radius * 1.2})`, children: [
1865
- /* @__PURE__ */ jsx7("path", { d: `M ${-radius * 0.4} 0 A ${radius * 0.4} ${radius * 0.4} 0 0 1 ${radius * 0.4} 0`, fill: "none", stroke: "#10b981", strokeWidth: 2 }),
1866
- /* @__PURE__ */ jsx7("polygon", { points: `${radius * 0.4},0 ${radius * 0.4 - 4},-6 ${radius * 0.4 + 4},-6`, fill: "#10b981" }),
1867
- /* @__PURE__ */ jsx7("text", { x: 0, y: -10, fill: "#10b981", fontSize: 14, fontStyle: "italic", textAnchor: "middle", children: "\u03C9" })
1868
- ] }) : null,
1869
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: radius + 20, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1870
- ] });
1871
- });
1872
- registerRenderer("inclined_wedge", (el) => {
1873
- const { x1, y1, x2, y2 } = el;
1874
- const dx = x2 - x1;
1875
- const dy = y2 - y1;
1876
- const angle = Math.atan2(dy, dx) * (180 / Math.PI);
1877
- return /* @__PURE__ */ jsxs7("g", { children: [
1878
- /* @__PURE__ */ jsx7(
1879
- "polygon",
1880
- {
1881
- points: `${x1},${y1} ${x1},${y2} ${x2},${y2}`,
1882
- fill: c5(el),
1883
- fillOpacity: 0.1,
1884
- stroke: c5(el),
1885
- strokeWidth: sw5(el),
1886
- strokeLinejoin: "round"
1887
- }
1888
- ),
1889
- el.label ? /* @__PURE__ */ jsx7("text", { x: (x1 + x2) / 2, y: y2 - 10, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null,
1890
- Math.abs(x2 - x1) > 20 && Math.abs(y2 - y1) > 20 ? /* @__PURE__ */ jsx7(
1891
- "path",
1892
- {
1893
- d: `M ${x2 > x1 ? x2 - 20 : x2 + 20} ${y2} A 20 20 0 0 ${x2 > x1 ? 0 : 1} ${x2 > x1 ? x2 - 20 * Math.cos(angle * Math.PI / 180) : x2 + 20 * Math.cos(angle * Math.PI / 180)} ${y2 - 20 * Math.sin(Math.abs(angle) * Math.PI / 180)}`,
1894
- fill: "none",
1895
- stroke: c5(el),
1896
- strokeWidth: 1
1897
- }
1898
- ) : null
1899
- ] });
1900
- });
1901
- registerRenderer("pulley", (el) => {
1902
- const dx = el.x2 - el.x1;
1903
- const dy = el.y2 - el.y1;
1904
- const radius = Math.hypot(dx, dy);
1905
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
1906
- /* @__PURE__ */ jsx7("path", { d: `M 0 0 L 0 ${-radius * 1.5}`, fill: "none", stroke: c5(el), strokeWidth: sw5(el) }),
1907
- /* @__PURE__ */ jsx7("line", { x1: -radius * 0.8, y1: -radius * 1.5, x2: radius * 0.8, y2: -radius * 1.5, stroke: c5(el), strokeWidth: sw5(el) }),
1908
- Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx7(
1909
- "line",
1910
- {
1911
- x1: -radius * 0.8 + i * radius * 0.4,
1912
- y1: -radius * 1.5,
1913
- x2: -radius * 0.8 + i * radius * 0.4 + 5,
1914
- y2: -radius * 1.5 - 5,
1915
- stroke: c5(el),
1916
- strokeWidth: 1
1917
- },
1918
- i
1919
- )),
1920
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: radius, fill: "#fff", stroke: c5(el), strokeWidth: sw5(el) }),
1921
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: radius * 0.8, fill: "none", stroke: c5(el), strokeWidth: 1, opacity: 0.3 }),
1922
- /* @__PURE__ */ jsx7("circle", { cx: 0, cy: 0, r: 3, fill: c5(el) }),
1923
- el.label ? /* @__PURE__ */ jsx7("text", { x: 0, y: -radius * 1.5 - 15, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1924
- ] });
1925
- });
1926
- registerRenderer("curve_arrow", (el) => {
1927
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1928
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1929
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1930
- /* @__PURE__ */ jsx7("path", { d: `M 0 0 Q ${dist / 2} ${-dist * 0.5} ${dist} 0`, fill: "none", stroke: c5(el), strokeWidth: sw5(el), strokeLinecap: "round" }),
1931
- /* @__PURE__ */ jsx7("polygon", { points: `${dist},0 ${dist - 8},-6 ${dist - 4},-1`, fill: c5(el), transform: `rotate(20 ${dist} 0)` }),
1932
- el.label ? /* @__PURE__ */ jsx7("text", { x: dist / 2, y: -dist * 0.3, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1933
- ] });
1934
- });
1935
- registerRenderer("spring", (el) => {
1936
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
1937
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
1938
- return /* @__PURE__ */ jsxs7("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
1939
- /* @__PURE__ */ jsx7(
1940
- "path",
1941
- {
1942
- d: generateSpringPath(dist, el.coils),
1943
- fill: "none",
1944
- stroke: c5(el),
1945
- strokeWidth: sw5(el),
1946
- strokeLinecap: "round",
1947
- strokeLinejoin: "round"
1948
- }
1949
- ),
1950
- el.label ? /* @__PURE__ */ jsx7("text", { x: dist / 2, y: -20, fontSize: font3(el), fill: c5(el), textAnchor: "middle", children: String(el.label) }) : null
1951
- ] });
1952
- });
1953
-
1954
- // src/core/renderers/circuit.tsx
1955
- import { Fragment, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1956
- var drawColor = (el, ctx) => ctx?.isSelected ? "#2563eb" : el.color || "#111827";
1957
- var drawStroke = (el, ctx) => ctx?.isSelected ? 2.5 : el.strokeWidth || 2;
1958
- registerRenderer("wire", (el, ctx) => /* @__PURE__ */ jsxs8("g", { opacity: ctx?.isGhost ? 0.5 : 1, children: [
1959
- /* @__PURE__ */ jsx8(
1960
- "line",
1961
- {
1962
- x1: el.x1,
1963
- y1: el.y1,
1964
- x2: el.x2,
1965
- y2: el.y2,
1966
- stroke: "transparent",
1967
- strokeWidth: 20,
1968
- strokeLinecap: "round"
1969
- }
1970
- ),
1971
- /* @__PURE__ */ jsx8(
1972
- "line",
1973
- {
1974
- x1: el.x1,
1975
- y1: el.y1,
1976
- x2: el.x2,
1977
- y2: el.y2,
1978
- stroke: drawColor(el, ctx),
1979
- strokeWidth: drawStroke(el, ctx),
1980
- strokeLinecap: "round",
1981
- pointerEvents: "none"
1982
- }
1983
- )
1984
- ] }));
1985
- var rotated = (el, inner, ctx) => {
1986
- const d = distance(el.x1, el.y1, el.x2, el.y2);
1987
- const a = angleDeg(el.x1, el.y1, el.x2, el.y2);
1988
- const dx = el.x2 - el.x1;
1989
- const dy = el.y2 - el.y1;
1990
- const mx = (el.x1 + el.x2) / 2;
1991
- const my = (el.y1 + el.y2) / 2;
1992
- let nx = -dy / (d || 1);
1993
- let ny = dx / (d || 1);
1994
- if (ny > 0) {
1995
- nx = -nx;
1996
- ny = -ny;
1997
- }
1998
- const labelDist = 20;
1999
- return /* @__PURE__ */ jsxs8("g", { opacity: ctx?.isGhost ? 0.5 : 1, children: [
2000
- /* @__PURE__ */ jsx8("line", { x1: el.x1, y1: el.y1, x2: el.x2, y2: el.y2, stroke: "transparent", strokeWidth: 20 }),
2001
- /* @__PURE__ */ jsx8("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${a})`, children: /* @__PURE__ */ jsx8("g", { children: inner }) }),
2002
- el.label && /* @__PURE__ */ jsx8("text", { x: mx + nx * labelDist, y: my + ny * labelDist, dominantBaseline: "central", textAnchor: "middle", fill: drawColor(el, ctx), fontSize: "16", fontFamily: "serif", fontWeight: "bold", children: String(el.label) }),
2003
- el.value && /* @__PURE__ */ jsx8("text", { x: mx - nx * labelDist, y: my - ny * labelDist, dominantBaseline: "central", textAnchor: "middle", fill: "#4b5563", fontSize: "14", fontFamily: "sans-serif", children: String(el.value) })
2004
- ] });
2005
- };
2006
- registerRenderer("resistor", (el, ctx) => {
2007
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2008
- const start = d / 2 - 15;
2009
- return rotated(el, /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${start} 0 l 2.5 -8 l 5 16 l 5 -16 l 5 16 l 5 -16 l 5 16 l 2.5 -8 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx), strokeLinejoin: "bevel" }), ctx);
2010
- });
2011
- registerRenderer("capacitor", (el, ctx) => {
2012
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2013
- const cx = d / 2;
2014
- return rotated(el, /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${cx - 4} 0 M ${cx - 4} -12 L ${cx - 4} 12 M ${cx + 4} -12 L ${cx + 4} 12 M ${cx + 4} 0 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }), ctx);
2015
- });
2016
- registerRenderer("inductor", (el, ctx) => {
2017
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2018
- const s = d / 2 - 15;
2019
- return rotated(el, /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${s} 0 A 5 5 0 0 0 ${s + 10} 0 A 5 5 0 0 0 ${s + 20} 0 A 5 5 0 0 0 ${s + 30} 0 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }), ctx);
2020
- });
2021
- registerRenderer("diode", (el, ctx) => {
2022
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2023
- const cx = d / 2;
2024
- return rotated(el, /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${cx - 8} 0 M ${cx - 8} -8 L ${cx - 8} 8 L ${cx + 8} 0 Z M ${cx + 8} -8 L ${cx + 8} 8 M ${cx + 8} 0 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }), ctx);
2025
- });
2026
- registerRenderer("battery", (el, ctx) => {
2027
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2028
- const cx = d / 2;
2029
- return rotated(el, /* @__PURE__ */ jsxs8(Fragment, { children: [
2030
- /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${cx - 4} 0 M ${cx - 4} -16 L ${cx - 4} 16 M ${cx + 4} -8 L ${cx + 4} 8 M ${cx + 4} 0 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }),
2031
- /* @__PURE__ */ jsx8("line", { x1: cx + 4, y1: -8, x2: cx + 4, y2: 8, stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) + 2 }),
2032
- /* @__PURE__ */ jsx8("text", { x: cx - 12, y: -12, fontSize: "12", fill: drawColor(el, ctx), textAnchor: "middle", children: "+" })
2033
- ] }), ctx);
2034
- });
2035
- ["meter_v", "meter_a"].forEach(
2036
- (t) => registerRenderer(t, (el, ctx) => {
2037
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2038
- const cx = d / 2;
2039
- const letter = t === "meter_v" ? "V" : "A";
2040
- return rotated(el, /* @__PURE__ */ jsxs8(Fragment, { children: [
2041
- /* @__PURE__ */ jsx8("path", { d: `M 0 0 L ${cx - 14} 0 M ${cx + 14} 0 L ${d} 0`, fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }),
2042
- /* @__PURE__ */ jsx8("circle", { cx, cy: 0, r: 14, fill: "#f8f9fa", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }),
2043
- /* @__PURE__ */ jsx8("text", { x: cx, y: 0, textAnchor: "middle", dominantBaseline: "central", fill: drawColor(el, ctx), fontSize: "14", fontWeight: "bold", children: letter })
2044
- ] }), ctx);
2045
- })
2046
- );
2047
- registerRenderer("ground", (el, ctx) => /* @__PURE__ */ jsx8("g", { transform: `translate(${el.x1}, ${el.y1})`, opacity: ctx?.isGhost ? 0.5 : 1, children: /* @__PURE__ */ jsx8("path", { d: "M 0 0 L 0 15 M -12 15 L 12 15 M -8 20 L 8 20 M -4 25 L 4 25", fill: "none", stroke: drawColor(el, ctx), strokeWidth: drawStroke(el, ctx) }) }));
2048
-
2049
- // src/core/renderers/circuitAutoNodes.ts
2050
- var getCircuitAutoNodes = (elements) => {
2051
- const pointMap = {};
2052
- elements.forEach((el) => {
2053
- if (el.type !== "wire") return;
2054
- const p1 = `${el.x1},${el.y1}`;
2055
- const p2 = `${el.x2},${el.y2}`;
2056
- pointMap[p1] = (pointMap[p1] || 0) + 1;
2057
- pointMap[p2] = (pointMap[p2] || 0) + 1;
2058
- });
2059
- return Object.entries(pointMap).filter(([, count]) => count > 2).map(([pt]) => pt.split(",").map(Number));
2060
- };
2061
-
2062
- // src/core/renderers/thermo.tsx
2063
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2064
- var c6 = (el) => el.color || "#0f172a";
2065
- var sw6 = (el) => el.strokeWidth || 2;
2066
- var font4 = (el) => el.fontSize || 18;
2067
- var seededRandom = (seed) => {
2068
- const x = Math.sin(seed) * 1e4;
2069
- return x - Math.floor(x);
2070
- };
2071
- var strokeDashFromLineStyle = (el) => {
2072
- if (el.lineStyle === "dashed") return "6 6";
2073
- if (el.lineStyle === "dotted") return "2 4";
2074
- return void 0;
2075
- };
2076
- registerRenderer("pv_axes", (el) => {
2077
- const minX = Math.min(el.x1, el.x2);
2078
- const minY = Math.min(el.y1, el.y2);
2079
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
2080
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
2081
- const yLabel = String(el.yLabel ?? "P");
2082
- const xLabel = String(el.xLabel ?? "V");
2083
- const color = c6(el);
2084
- const strokeWidth = sw6(el);
2085
- const fontSize = font4(el);
2086
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${minX}, ${minY})`, children: [
2087
- /* @__PURE__ */ jsx9("line", { x1: 0, y1: 0, x2: 0, y2: h, stroke: color, strokeWidth }),
2088
- /* @__PURE__ */ jsx9("polygon", { points: "0,0 -5,10 5,10", fill: color }),
2089
- /* @__PURE__ */ jsx9("text", { x: -15, y: 10, fontSize, fill: color, fontWeight: "bold", children: yLabel }),
2090
- /* @__PURE__ */ jsx9("line", { x1: 0, y1: h, x2: w, y2: h, stroke: color, strokeWidth }),
2091
- /* @__PURE__ */ jsx9("polygon", { points: `${w},${h} ${w - 10},${h - 5} ${w - 10},${h + 5}`, fill: color }),
2092
- /* @__PURE__ */ jsx9("text", { x: w - 10, y: h + 20, fontSize, fill: color, fontWeight: "bold", children: xLabel }),
2093
- /* @__PURE__ */ jsx9("text", { x: -10, y: h + 15, fontSize: 12, fill: color, children: "0" }),
2094
- el.label ? /* @__PURE__ */ jsx9("text", { x: w / 2, y: -10, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2095
- ] });
2096
- });
2097
- registerRenderer("piston_cylinder", (el) => {
2098
- const minX = Math.min(el.x1, el.x2);
2099
- const minY = Math.min(el.y1, el.y2);
2100
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
2101
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
2102
- const compression = el.compression ?? 0.5;
2103
- const pistonY = h * compression;
2104
- const color = c6(el);
2105
- const strokeWidth = sw6(el);
2106
- const particles = [];
2107
- const numParticles = 40;
2108
- for (let i = 0; i < numParticles; i++) {
2109
- const px = seededRandom(Number(el.id) + i) * (w - 10) + 5;
2110
- const py = pistonY + 10 + seededRandom(Number(el.id) + i * 100) * (h - pistonY - 15);
2111
- particles.push(/* @__PURE__ */ jsx9("circle", { cx: px, cy: py, r: "2", fill: "#94a3b8" }, i));
2112
- }
2113
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${minX}, ${minY})`, children: [
2114
- /* @__PURE__ */ jsx9(
2115
- "polyline",
2116
- {
2117
- points: `0,0 0,${h} ${w},${h} ${w},0`,
2118
- fill: "#f8fafc",
2119
- stroke: color,
2120
- strokeWidth,
2121
- strokeLinecap: "square",
2122
- strokeLinejoin: "miter"
2123
- }
2124
- ),
2125
- particles,
2126
- /* @__PURE__ */ jsxs9("g", { transform: `translate(0, ${pistonY})`, children: [
2127
- /* @__PURE__ */ jsx9("rect", { x: "2", y: "0", width: w - 4, height: "12", fill: "#64748b", rx: "2" }),
2128
- /* @__PURE__ */ jsx9("line", { x1: w / 2, y1: "0", x2: w / 2, y2: "-40", stroke: "#64748b", strokeWidth: "4" }),
2129
- /* @__PURE__ */ jsx9("line", { x1: w / 2 - 15, y1: "-40", x2: w / 2 + 15, y2: "-40", stroke: "#64748b", strokeWidth: "6", strokeLinecap: "round" }),
2130
- /* @__PURE__ */ jsx9("line", { x1: w / 2, y1: "-50", x2: w / 2, y2: "-42", stroke: "#ef4444", strokeWidth: "2" }),
2131
- /* @__PURE__ */ jsx9("polygon", { points: `${w / 2},-42 ${w / 2 - 4},-46 ${w / 2 + 4},-46`, fill: "#ef4444" })
2132
- ] }),
2133
- el.showHeat ? /* @__PURE__ */ jsxs9("g", { transform: `translate(${w / 2}, ${h + 15})`, children: [
2134
- /* @__PURE__ */ jsx9("path", { d: "M-10,0 Q-15,-10 -5,-20 Q0,-10 10,-15 Q5,-5 10,0 Z", fill: "#ef4444", opacity: "0.8" }),
2135
- /* @__PURE__ */ jsx9("path", { d: "M-5,0 Q-8,-6 0,-12 Q2,-5 5,0 Z", fill: "#f59e0b" }),
2136
- /* @__PURE__ */ jsx9("text", { x: "25", y: "-5", fontSize: "14", fill: "#ef4444", fontWeight: "bold", children: "Q" })
2137
- ] }) : null,
2138
- el.label ? /* @__PURE__ */ jsx9("text", { x: w / 2, y: h + (el.showHeat ? 35 : 20), textAnchor: "middle", fill: color, fontSize: font4(el), children: String(el.label) }) : null
2139
- ] });
2140
- });
2141
- registerRenderer("heat_engine", (el) => {
2142
- const minX = Math.min(el.x1, el.x2);
2143
- const minY = Math.min(el.y1, el.y2);
2144
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
2145
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
2146
- const isEngine = el.engineType !== "refrigerator";
2147
- const r = Math.min(w * 0.3, h * 0.2);
2148
- const color = c6(el);
2149
- const strokeWidth = sw6(el);
2150
- const fontSize = font4(el);
2151
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${minX}, ${minY})`, children: [
2152
- /* @__PURE__ */ jsx9("rect", { x: 0, y: 0, width: w, height: h * 0.2, fill: "#ef4444", rx: "4" }),
2153
- /* @__PURE__ */ jsx9("text", { x: w / 2, y: h * 0.1, fontSize, fill: "#fff", textAnchor: "middle", dominantBaseline: "central", children: "T_H" }),
2154
- /* @__PURE__ */ jsx9("rect", { x: 0, y: h * 0.8, width: w, height: h * 0.2, fill: "#3b82f6", rx: "4" }),
2155
- /* @__PURE__ */ jsx9("text", { x: w / 2, y: h * 0.9, fontSize, fill: "#fff", textAnchor: "middle", dominantBaseline: "central", children: "T_C" }),
2156
- /* @__PURE__ */ jsx9("circle", { cx: w / 2, cy: h / 2, r, fill: "#fff", stroke: color, strokeWidth }),
2157
- /* @__PURE__ */ jsx9(
2158
- "text",
2159
- {
2160
- x: w / 2,
2161
- y: h / 2,
2162
- fontSize: fontSize * 1.2,
2163
- fill: color,
2164
- textAnchor: "middle",
2165
- dominantBaseline: "central",
2166
- fontWeight: "bold",
2167
- children: isEngine ? "E" : "R"
2168
- }
2169
- ),
2170
- /* @__PURE__ */ jsxs9("g", { strokeWidth: 2, stroke: color, children: [
2171
- /* @__PURE__ */ jsx9("line", { x1: w / 2, y1: h * 0.2, x2: w / 2, y2: h * 0.5 - r - 5 }),
2172
- /* @__PURE__ */ jsx9(
2173
- "polygon",
2174
- {
2175
- points: isEngine ? `${w / 2},${h * 0.5 - r - 2} ${w / 2 - 5},${h * 0.5 - r - 10} ${w / 2 + 5},${h * 0.5 - r - 10}` : `${w / 2},${h * 0.2 + 2} ${w / 2 - 5},${h * 0.2 + 10} ${w / 2 + 5},${h * 0.2 + 10}`,
2176
- fill: color
2177
- }
2178
- ),
2179
- /* @__PURE__ */ jsx9("text", { x: w / 2 + 10, y: h * 0.35, fontSize: 14, fill: color, dominantBaseline: "central", children: "Q_H" }),
2180
- /* @__PURE__ */ jsx9("line", { x1: w / 2, y1: h * 0.5 + r + 5, x2: w / 2, y2: h * 0.8 }),
2181
- /* @__PURE__ */ jsx9(
2182
- "polygon",
2183
- {
2184
- points: isEngine ? `${w / 2},${h * 0.8 - 2} ${w / 2 - 5},${h * 0.8 - 10} ${w / 2 + 5},${h * 0.8 - 10}` : `${w / 2},${h * 0.5 + r + 2} ${w / 2 - 5},${h * 0.5 + r + 10} ${w / 2 + 5},${h * 0.5 + r + 10}`,
2185
- fill: color
2186
- }
2187
- ),
2188
- /* @__PURE__ */ jsx9("text", { x: w / 2 + 10, y: h * 0.65, fontSize: 14, fill: color, dominantBaseline: "central", children: "Q_C" }),
2189
- /* @__PURE__ */ jsx9(
2190
- "line",
2191
- {
2192
- x1: isEngine ? w / 2 + r + 5 : w,
2193
- y1: h / 2,
2194
- x2: isEngine ? w : w / 2 + r + 5,
2195
- y2: h / 2
2196
- }
2197
- ),
2198
- /* @__PURE__ */ jsx9(
2199
- "polygon",
2200
- {
2201
- points: isEngine ? `${w},${h / 2} ${w - 8},${h / 2 - 5} ${w - 8},${h / 2 + 5}` : `${w / 2 + r + 5},${h / 2} ${w / 2 + r + 13},${h / 2 - 5} ${w / 2 + r + 13},${h / 2 + 5}`,
2202
- fill: color
2203
- }
2204
- ),
2205
- /* @__PURE__ */ jsx9("text", { x: w * 0.8, y: h / 2 - 15, fontSize: 14, fill: color, textAnchor: "middle", children: "W" })
2206
- ] }),
2207
- el.label ? /* @__PURE__ */ jsx9("text", { x: w / 2, y: h + 20, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2208
- ] });
2209
- });
2210
- registerRenderer("conduction_rod", (el) => {
2211
- const dist = distance(el.x1, el.y1, el.x2, el.y2);
2212
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2213
- const gradId = `grad-rod-${el.id}`;
2214
- const color = c6(el);
2215
- const strokeWidth = sw6(el);
2216
- const fontSize = font4(el);
2217
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2218
- /* @__PURE__ */ jsx9("defs", { children: /* @__PURE__ */ jsxs9("linearGradient", { id: gradId, x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
2219
- /* @__PURE__ */ jsx9("stop", { offset: "0%", stopColor: "#ef4444" }),
2220
- /* @__PURE__ */ jsx9("stop", { offset: "100%", stopColor: "#3b82f6" })
2221
- ] }) }),
2222
- /* @__PURE__ */ jsx9("rect", { x: 0, y: -20, width: dist, height: 40, fill: `url(#${gradId})`, stroke: color, strokeWidth, rx: "4" }),
2223
- /* @__PURE__ */ jsxs9("g", { stroke: "#fff", strokeWidth: "2", opacity: 0.6, children: [
2224
- /* @__PURE__ */ jsx9("line", { x1: dist * 0.2, y1: 0, x2: dist * 0.4, y2: 0 }),
2225
- /* @__PURE__ */ jsx9("polygon", { points: `${dist * 0.4},0 ${dist * 0.4 - 6},-4 ${dist * 0.4 - 6},4`, fill: "#fff" }),
2226
- /* @__PURE__ */ jsx9("line", { x1: dist * 0.6, y1: 0, x2: dist * 0.8, y2: 0 }),
2227
- /* @__PURE__ */ jsx9("polygon", { points: `${dist * 0.8},0 ${dist * 0.8 - 6},-4 ${dist * 0.8 - 6},4`, fill: "#fff" })
2228
- ] }),
2229
- /* @__PURE__ */ jsx9("text", { x: 0, y: -30, fontSize, fill: "#ef4444", textAnchor: "middle", fontWeight: "bold", children: "T_H" }),
2230
- /* @__PURE__ */ jsx9("text", { x: dist, y: -30, fontSize, fill: "#3b82f6", textAnchor: "middle", fontWeight: "bold", children: "T_C" }),
2231
- el.label ? /* @__PURE__ */ jsx9("text", { x: dist / 2, y: 35, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2232
- ] });
2233
- });
2234
- registerRenderer("thermo_process", (el) => {
2235
- const pType = el.processType || "isotherm";
2236
- const dx = el.x2 - el.x1;
2237
- const dy = el.y2 - el.y1;
2238
- let pathD = "";
2239
- if (pType === "isobaric") pathD = `M 0 0 L ${dx} 0`;
2240
- else if (pType === "isochoric") pathD = `M 0 0 L 0 ${dy}`;
2241
- else if (pType === "adiabatic") pathD = `M 0 0 Q ${dx * 0.1} ${dy * 0.9} ${dx} ${dy}`;
2242
- else pathD = `M 0 0 Q ${dx * 0.2} ${dy * 0.8} ${dx} ${dy}`;
2243
- let midX = dx / 2;
2244
- let midY = dy / 2;
2245
- if (pType === "isotherm" || pType === "adiabatic") {
2246
- const cx = dx * (pType === "adiabatic" ? 0.1 : 0.2);
2247
- const cy = dy * (pType === "adiabatic" ? 0.9 : 0.8);
2248
- midX = 0.25 * 0 + 0.5 * cx + 0.25 * dx;
2249
- midY = 0.25 * 0 + 0.5 * cy + 0.25 * dy;
2250
- }
2251
- const arrowAngle = Math.atan2(dy, dx) * 180 / Math.PI;
2252
- const dash = strokeDashFromLineStyle(el);
2253
- const color = c6(el);
2254
- const strokeWidth = sw6(el);
2255
- const fontSize = font4(el);
2256
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2257
- /* @__PURE__ */ jsx9("path", { d: pathD, fill: "none", stroke: color, strokeWidth, strokeDasharray: dash }),
2258
- /* @__PURE__ */ jsx9("g", { transform: `translate(${midX}, ${midY}) rotate(${arrowAngle})`, children: /* @__PURE__ */ jsx9("polygon", { points: "0,0 -8,-5 -8,5", fill: color }) }),
2259
- el.label ? /* @__PURE__ */ jsx9("text", { x: midX + 15, y: midY - 10, fontSize, fill: color, children: String(el.label) }) : null
2260
- ] });
2261
- });
2262
- registerRenderer("carnot_cycle", (el) => {
2263
- const minX = Math.min(el.x1, el.x2);
2264
- const minY = Math.min(el.y1, el.y2);
2265
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
2266
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
2267
- const p1 = { x: w * 0.1, y: h * 0.1 };
2268
- const p2 = { x: w * 0.6, y: h * 0.3 };
2269
- const p3 = { x: w * 0.9, y: h * 0.9 };
2270
- const p4 = { x: w * 0.4, y: h * 0.7 };
2271
- const iso1 = `M ${p1.x} ${p1.y} Q ${w * 0.3} ${h * 0.15} ${p2.x} ${p2.y}`;
2272
- const ad1 = `Q ${w * 0.7} ${h * 0.6} ${p3.x} ${p3.y}`;
2273
- const iso2 = `Q ${w * 0.6} ${h * 0.85} ${p4.x} ${p4.y}`;
2274
- const ad2 = `Q ${w * 0.2} ${h * 0.4} ${p1.x} ${p1.y}`;
2275
- const color = c6(el);
2276
- const strokeWidth = sw6(el);
2277
- const fontSize = font4(el);
2278
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${minX}, ${minY})`, children: [
2279
- /* @__PURE__ */ jsx9("path", { d: `${iso1} ${ad1} ${iso2} ${ad2} Z`, fill: color, fillOpacity: 0.1 }),
2280
- /* @__PURE__ */ jsx9("path", { d: iso1, fill: "none", stroke: "#ef4444", strokeWidth }),
2281
- /* @__PURE__ */ jsx9("path", { d: `M ${p2.x} ${p2.y} ${ad1}`, fill: "none", stroke: "#64748b", strokeWidth, strokeDasharray: "4 4" }),
2282
- /* @__PURE__ */ jsx9("path", { d: `M ${p3.x} ${p3.y} ${iso2}`, fill: "none", stroke: "#3b82f6", strokeWidth }),
2283
- /* @__PURE__ */ jsx9("path", { d: `M ${p4.x} ${p4.y} ${ad2}`, fill: "none", stroke: "#64748b", strokeWidth, strokeDasharray: "4 4" }),
2284
- /* @__PURE__ */ jsx9("circle", { cx: p1.x, cy: p1.y, r: "3", fill: "#1e293b" }),
2285
- /* @__PURE__ */ jsx9("circle", { cx: p2.x, cy: p2.y, r: "3", fill: "#1e293b" }),
2286
- /* @__PURE__ */ jsx9("circle", { cx: p3.x, cy: p3.y, r: "3", fill: "#1e293b" }),
2287
- /* @__PURE__ */ jsx9("circle", { cx: p4.x, cy: p4.y, r: "3", fill: "#1e293b" }),
2288
- /* @__PURE__ */ jsx9("text", { x: w * 0.4, y: h * 0.15, fontSize: "14", fill: "#ef4444", fontWeight: "bold", children: "T_H" }),
2289
- /* @__PURE__ */ jsx9("text", { x: w * 0.6, y: h * 0.95, fontSize: "14", fill: "#3b82f6", fontWeight: "bold", children: "T_C" }),
2290
- /* @__PURE__ */ jsx9("text", { x: w / 2, y: h / 2 + 5, fontSize: 16, fill: color, textAnchor: "middle", fontWeight: "bold", children: "W" }),
2291
- el.label ? /* @__PURE__ */ jsx9("text", { x: w / 2, y: -15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2292
- ] });
2293
- });
2294
- registerRenderer("maxwell_boltzmann", (el) => {
2295
- const minX = Math.min(el.x1, el.x2);
2296
- const minY = Math.min(el.y1, el.y2);
2297
- const w = Math.max(1, Math.abs(el.x2 - el.x1));
2298
- const h = Math.max(1, Math.abs(el.y2 - el.y1));
2299
- const t1 = el.t1 || 300;
2300
- const t2 = el.t2 || 600;
2301
- const strokeWidth = sw6(el);
2302
- const fontSize = font4(el);
2303
- const color = c6(el);
2304
- const buildCurve = (temp, peakHeight, strokeCol, dash) => {
2305
- let d = `M 0 ${h}`;
2306
- const k = 1 / temp;
2307
- const vmp = Math.sqrt(2 / k);
2308
- const xMax = vmp * 3.5;
2309
- for (let x = 0; x <= w; x += 2) {
2310
- const v = x / w * xMax;
2311
- const rawVal = v * v * Math.exp(-k * v * v);
2312
- const maxRawVal = vmp * vmp * Math.exp(-1);
2313
- const y = h - rawVal / maxRawVal * peakHeight;
2314
- d += ` L ${x} ${y}`;
2315
- }
2316
- return /* @__PURE__ */ jsx9("path", { d, fill: "none", stroke: strokeCol, strokeWidth, strokeDasharray: dash, strokeLinejoin: "round" });
2317
- };
2318
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${minX}, ${minY})`, children: [
2319
- /* @__PURE__ */ jsx9("line", { x1: 0, y1: 0, x2: 0, y2: h, stroke: "#1e293b", strokeWidth: "2" }),
2320
- /* @__PURE__ */ jsx9("line", { x1: 0, y1: h, x2: w, y2: h, stroke: "#1e293b", strokeWidth: "2" }),
2321
- /* @__PURE__ */ jsx9("text", { x: -25, y: h / 2, fontSize: 14, fill: "#1e293b", transform: `rotate(-90, -25, ${h / 2})`, textAnchor: "middle", children: "N(v)" }),
2322
- /* @__PURE__ */ jsx9("text", { x: w / 2, y: h + 20, fontSize: 14, fill: "#1e293b", textAnchor: "middle", children: "Speed (v)" }),
2323
- buildCurve(t1, h * 0.8, "#ef4444"),
2324
- buildCurve(t2, h * 0.5, "#3b82f6", "4 4"),
2325
- /* @__PURE__ */ jsx9("rect", { x: w - 70, y: 10, width: 10, height: 10, fill: "#ef4444" }),
2326
- /* @__PURE__ */ jsxs9("text", { x: w - 55, y: 20, fontSize: 12, fill: "#1e293b", children: [
2327
- "T\u2081 = ",
2328
- t1,
2329
- "K"
2330
- ] }),
2331
- /* @__PURE__ */ jsx9("rect", { x: w - 70, y: 30, width: 10, height: 10, fill: "#3b82f6" }),
2332
- /* @__PURE__ */ jsxs9("text", { x: w - 55, y: 40, fontSize: 12, fill: "#1e293b", children: [
2333
- "T\u2082 = ",
2334
- t2,
2335
- "K"
2336
- ] }),
2337
- el.label ? /* @__PURE__ */ jsx9("text", { x: w / 2, y: -15, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2338
- ] });
2339
- });
2340
- registerRenderer("diatomic_gas", (el) => {
2341
- const color = c6(el);
2342
- const strokeWidth = sw6(el);
2343
- const fontSize = font4(el);
2344
- const showRot = el.showRotations !== false;
2345
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2346
- /* @__PURE__ */ jsx9("circle", { cx: -15, cy: 0, r: 8, fill: color, stroke: "#fff", strokeWidth: 2 }),
2347
- /* @__PURE__ */ jsx9("circle", { cx: 15, cy: 0, r: 8, fill: color, stroke: "#fff", strokeWidth: 2 }),
2348
- /* @__PURE__ */ jsx9("line", { x1: -10, y1: 0, x2: 10, y2: 0, stroke: color, strokeWidth: 4 }),
2349
- showRot ? /* @__PURE__ */ jsxs9("g", { stroke: "#94a3b8", strokeWidth: 1.5, fill: "none", children: [
2350
- /* @__PURE__ */ jsx9("path", { d: "M -10 -15 A 15 15 0 0 1 10 -15", strokeDasharray: "2 2" }),
2351
- /* @__PURE__ */ jsx9("polygon", { points: "10,-15 6,-18 6,-12", fill: "#94a3b8" }),
2352
- /* @__PURE__ */ jsx9("path", { d: "M -25 0 A 25 10 0 0 1 0 10 A 25 10 0 0 1 25 0", strokeDasharray: "2 2" })
2353
- ] }) : null,
2354
- el.label ? /* @__PURE__ */ jsx9("text", { x: 0, y: 25, fontSize, fill: color, textAnchor: "middle", children: String(el.label) }) : null
2355
- ] });
2356
- });
2357
- registerRenderer("random_walk", (el) => {
2358
- const steps = el.steps || 5;
2359
- const dist = Math.hypot(el.x2 - el.x1, el.y2 - el.y1);
2360
- let d = "M 0 0";
2361
- let curX = 0;
2362
- let curY = 0;
2363
- const points = [/* @__PURE__ */ jsx9("circle", { cx: "0", cy: "0", r: "4", fill: "#22c55e" }, "start")];
2364
- for (let i = 1; i <= steps; i++) {
2365
- const angle = seededRandom(Number(el.id) + i * 7) * Math.PI * 2;
2366
- const stepDist = dist / steps * (0.5 + seededRandom(Number(el.id) + i * 13));
2367
- curX += Math.cos(angle) * stepDist;
2368
- curY += Math.sin(angle) * stepDist;
2369
- d += ` L ${curX} ${curY}`;
2370
- points.push(/* @__PURE__ */ jsx9("circle", { cx: curX, cy: curY, r: i === steps ? 4 : 2, fill: i === steps ? "#ef4444" : c6(el) }, i));
2371
- }
2372
- return /* @__PURE__ */ jsxs9("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2373
- /* @__PURE__ */ jsx9("path", { d, fill: "none", stroke: c6(el), strokeWidth: sw6(el), strokeLinejoin: "round" }),
2374
- points,
2375
- el.label ? /* @__PURE__ */ jsx9("text", { x: dist / 2, y: dist / 2, fontSize: font4(el), fill: c6(el), textAnchor: "middle", children: String(el.label) }) : null
2376
- ] });
2377
- });
2378
-
2379
- // src/core/renderers/chemistry.tsx
2380
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2381
- var colorOf3 = (el, isSelected) => {
2382
- if (isSelected) return "#0d9488";
2383
- return el.color || "#111827";
2384
- };
2385
- var strokeOf3 = (el, isSelected) => {
2386
- const base = el.strokeWidth || 2;
2387
- return isSelected ? Math.max(3, base) : base;
2388
- };
2389
- var fontOf3 = (el) => el.fontSize || 16;
2390
- var ringPolygonPoints = (sides, radius, startDeg) => Array.from({ length: sides }).map((_, i) => {
2391
- const angle = (i * 360 / sides + startDeg) * (Math.PI / 180);
2392
- return `${radius * Math.cos(angle)},${radius * Math.sin(angle)}`;
2393
- }).join(" ");
2394
- registerRenderer("atom", (el, ctx) => /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2395
- /* @__PURE__ */ jsx10("rect", { x: "-20", y: "-15", width: "40", height: "30", fill: "white", rx: "6" }),
2396
- /* @__PURE__ */ jsx10(
2397
- "text",
2398
- {
2399
- x: "0",
2400
- y: "0",
2401
- dominantBaseline: "central",
2402
- textAnchor: "middle",
2403
- fill: colorOf3(el, ctx.isSelected),
2404
- fontSize: Math.max(18, fontOf3(el)),
2405
- fontFamily: "sans-serif",
2406
- fontWeight: "bold",
2407
- children: String(el.label || "C")
2408
- }
2409
- )
2410
- ] }));
2411
- registerRenderer("charge_plus", (el, ctx) => {
2412
- const stroke2 = colorOf3(el, ctx.isSelected);
2413
- const sw7 = strokeOf3(el, ctx.isSelected);
2414
- const baseSw = el.strokeWidth || 2;
2415
- const r = Math.max(12, baseSw * 4);
2416
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2417
- /* @__PURE__ */ jsx10("circle", { cx: "0", cy: "0", r, fill: "white", stroke: stroke2, strokeWidth: sw7 }),
2418
- /* @__PURE__ */ jsx10("line", { x1: -r / 2, y1: "0", x2: r / 2, y2: "0", stroke: stroke2, strokeWidth: sw7 }),
2419
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: -r / 2, x2: "0", y2: r / 2, stroke: stroke2, strokeWidth: sw7 }),
2420
- el.label && /* @__PURE__ */ jsx10(
2421
- "text",
2422
- {
2423
- x: "0",
2424
- y: r + 18,
2425
- fontSize: fontOf3(el),
2426
- fill: stroke2,
2427
- fontFamily: "sans-serif",
2428
- fontWeight: "bold",
2429
- textAnchor: "middle",
2430
- children: String(el.label)
2431
- }
2432
- )
2433
- ] });
2434
- });
2435
- registerRenderer("charge_minus", (el, ctx) => {
2436
- const stroke2 = colorOf3(el, ctx.isSelected);
2437
- const sw7 = strokeOf3(el, ctx.isSelected);
2438
- const baseSw = el.strokeWidth || 2;
2439
- const r = Math.max(12, baseSw * 4);
2440
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2441
- /* @__PURE__ */ jsx10("circle", { cx: "0", cy: "0", r, fill: "white", stroke: stroke2, strokeWidth: sw7 }),
2442
- /* @__PURE__ */ jsx10("line", { x1: -r / 2, y1: "0", x2: r / 2, y2: "0", stroke: stroke2, strokeWidth: sw7 }),
2443
- el.label && /* @__PURE__ */ jsx10(
2444
- "text",
2445
- {
2446
- x: "0",
2447
- y: r + 18,
2448
- fontSize: fontOf3(el),
2449
- fill: stroke2,
2450
- fontFamily: "sans-serif",
2451
- fontWeight: "bold",
2452
- textAnchor: "middle",
2453
- children: String(el.label)
2454
- }
2455
- )
2456
- ] });
2457
- });
2458
- registerRenderer("radical", (el, ctx) => /* @__PURE__ */ jsx10("circle", { cx: el.x1, cy: el.y1, r: "3.5", fill: colorOf3(el, ctx.isSelected) }));
2459
- registerRenderer("lone_pair", (el, ctx) => /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2460
- /* @__PURE__ */ jsx10("circle", { cx: "-4", cy: "0", r: "2.5", fill: colorOf3(el, ctx.isSelected) }),
2461
- /* @__PURE__ */ jsx10("circle", { cx: "4", cy: "0", r: "2.5", fill: colorOf3(el, ctx.isSelected) })
2462
- ] }));
2463
- registerRenderer("benzene", (el, ctx) => {
2464
- const r = 30;
2465
- const stroke2 = colorOf3(el, ctx.isSelected);
2466
- const sw7 = strokeOf3(el, ctx.isSelected);
2467
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: [
2468
- /* @__PURE__ */ jsx10("polygon", { points: ringPolygonPoints(6, r, -30), fill: "white", stroke: stroke2, strokeWidth: sw7, strokeLinejoin: "round" }),
2469
- /* @__PURE__ */ jsx10("circle", { cx: "0", cy: "0", r: r - 10, fill: "none", stroke: stroke2, strokeWidth: sw7 })
2470
- ] });
2471
- });
2472
- registerRenderer("cyclohexane", (el, ctx) => /* @__PURE__ */ jsx10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: /* @__PURE__ */ jsx10(
2473
- "polygon",
2474
- {
2475
- points: ringPolygonPoints(6, 30, -30),
2476
- fill: "white",
2477
- stroke: colorOf3(el, ctx.isSelected),
2478
- strokeWidth: strokeOf3(el, ctx.isSelected),
2479
- strokeLinejoin: "round"
2480
- }
2481
- ) }));
2482
- registerRenderer("cyclopentane", (el, ctx) => /* @__PURE__ */ jsx10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: /* @__PURE__ */ jsx10(
2483
- "polygon",
2484
- {
2485
- points: ringPolygonPoints(5, 30, -90),
2486
- fill: "white",
2487
- stroke: colorOf3(el, ctx.isSelected),
2488
- strokeWidth: strokeOf3(el, ctx.isSelected),
2489
- strokeLinejoin: "round"
2490
- }
2491
- ) }));
2492
- registerRenderer("cyclobutane", (el, ctx) => /* @__PURE__ */ jsx10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: /* @__PURE__ */ jsx10(
2493
- "polygon",
2494
- {
2495
- points: ringPolygonPoints(4, 30, -45),
2496
- fill: "white",
2497
- stroke: colorOf3(el, ctx.isSelected),
2498
- strokeWidth: strokeOf3(el, ctx.isSelected),
2499
- strokeLinejoin: "round"
2500
- }
2501
- ) }));
2502
- registerRenderer("cyclopropane", (el, ctx) => /* @__PURE__ */ jsx10("g", { transform: `translate(${el.x1}, ${el.y1})`, children: /* @__PURE__ */ jsx10(
2503
- "polygon",
2504
- {
2505
- points: ringPolygonPoints(3, 30, -90),
2506
- fill: "white",
2507
- stroke: colorOf3(el, ctx.isSelected),
2508
- strokeWidth: strokeOf3(el, ctx.isSelected),
2509
- strokeLinejoin: "round"
2510
- }
2511
- ) }));
2512
- var drawBond = (el, style, isSelected) => {
2513
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2514
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2515
- const stroke2 = colorOf3(el, isSelected);
2516
- const sw7 = strokeOf3(el, isSelected);
2517
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2518
- style === "single" && /* @__PURE__ */ jsx10("line", { x1: "0", y1: "0", x2: d, y2: "0", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" }),
2519
- style === "double" && /* @__PURE__ */ jsxs10(Fragment2, { children: [
2520
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "-3.5", x2: d, y2: "-3.5", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" }),
2521
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "3.5", x2: d, y2: "3.5", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" })
2522
- ] }),
2523
- style === "triple" && /* @__PURE__ */ jsxs10(Fragment2, { children: [
2524
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "-6", x2: d, y2: "-6", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" }),
2525
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "0", x2: d, y2: "0", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" }),
2526
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "6", x2: d, y2: "6", stroke: stroke2, strokeWidth: sw7, strokeLinecap: "round" })
2527
- ] }),
2528
- style === "wedge" && /* @__PURE__ */ jsx10("polygon", { points: `0,0 ${d},-5 ${d},5`, fill: stroke2 }),
2529
- style === "dash" && /* @__PURE__ */ jsx10("line", { x1: "0", y1: "0", x2: d, y2: "0", stroke: stroke2, strokeWidth: sw7 + 1, strokeDasharray: "5 5", strokeLinecap: "square" })
2530
- ] });
2531
- };
2532
- registerRenderer("single_bond", (el, ctx) => drawBond(el, "single", ctx.isSelected));
2533
- registerRenderer("double_bond", (el, ctx) => drawBond(el, "double", ctx.isSelected));
2534
- registerRenderer("triple_bond", (el, ctx) => drawBond(el, "triple", ctx.isSelected));
2535
- registerRenderer("wedge_bond", (el, ctx) => drawBond(el, "wedge", ctx.isSelected));
2536
- registerRenderer("dash_bond", (el, ctx) => drawBond(el, "dash", ctx.isSelected));
2537
- var lineMid = (el) => ({ x: (el.x1 + el.x2) / 2, y: (el.y1 + el.y2) / 2 });
2538
- registerRenderer("reaction_arrow", (el, ctx) => {
2539
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2540
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2541
- const stroke2 = colorOf3(el, ctx.isSelected);
2542
- const sw7 = strokeOf3(el, ctx.isSelected);
2543
- const mid = lineMid(el);
2544
- return /* @__PURE__ */ jsxs10("g", { children: [
2545
- /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2546
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "0", x2: d, y2: "0", stroke: stroke2, strokeWidth: sw7 }),
2547
- /* @__PURE__ */ jsx10("polygon", { points: `${d},0 ${d - 12},-6 ${d - 12},6`, fill: stroke2 })
2548
- ] }),
2549
- el.label && /* @__PURE__ */ jsx10("text", { x: mid.x, y: mid.y - 18, textAnchor: "middle", fill: "#0f766e", fontSize: "14", fontFamily: "sans-serif", fontWeight: "bold", children: String(el.label) }),
2550
- el.value && /* @__PURE__ */ jsx10("text", { x: mid.x, y: mid.y + 18, textAnchor: "middle", fill: "#4b5563", fontSize: "13", fontFamily: "sans-serif", children: String(el.value) })
2551
- ] });
2552
- });
2553
- registerRenderer("equilibrium_arrow", (el, ctx) => {
2554
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2555
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2556
- const stroke2 = colorOf3(el, ctx.isSelected);
2557
- const sw7 = strokeOf3(el, ctx.isSelected);
2558
- const mid = lineMid(el);
2559
- return /* @__PURE__ */ jsxs10("g", { children: [
2560
- /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2561
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "-4", x2: d, y2: "-4", stroke: stroke2, strokeWidth: sw7 }),
2562
- /* @__PURE__ */ jsx10("polygon", { points: `${d},-4 ${d - 10},-10 ${d - 10},-4`, fill: stroke2 }),
2563
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "4", x2: d, y2: "4", stroke: stroke2, strokeWidth: sw7 }),
2564
- /* @__PURE__ */ jsx10("polygon", { points: `0,4 10,4 10,10`, fill: stroke2 })
2565
- ] }),
2566
- el.label && /* @__PURE__ */ jsx10("text", { x: mid.x, y: mid.y - 18, textAnchor: "middle", fill: "#0f766e", fontSize: "14", fontFamily: "sans-serif", fontWeight: "bold", children: String(el.label) }),
2567
- el.value && /* @__PURE__ */ jsx10("text", { x: mid.x, y: mid.y + 18, textAnchor: "middle", fill: "#4b5563", fontSize: "13", fontFamily: "sans-serif", children: String(el.value) })
2568
- ] });
2569
- });
2570
- registerRenderer("resonance_arrow", (el, ctx) => {
2571
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2572
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2573
- const stroke2 = colorOf3(el, ctx.isSelected);
2574
- const sw7 = strokeOf3(el, ctx.isSelected);
2575
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2576
- /* @__PURE__ */ jsx10("line", { x1: "0", y1: "0", x2: d, y2: "0", stroke: stroke2, strokeWidth: sw7 }),
2577
- /* @__PURE__ */ jsx10("polygon", { points: `0,0 12,-6 12,6`, fill: stroke2 }),
2578
- /* @__PURE__ */ jsx10("polygon", { points: `${d},0 ${d - 12},-6 ${d - 12},6`, fill: stroke2 })
2579
- ] });
2580
- });
2581
- registerRenderer("curved_arrow", (el, ctx) => {
2582
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2583
- const angle = angleDeg(el.x1, el.y1, el.x2, el.y2);
2584
- const h = d / 3;
2585
- const arrowAngle = Math.atan2(h, d / 2) * (180 / Math.PI);
2586
- const stroke2 = colorOf3(el, ctx.isSelected);
2587
- const sw7 = strokeOf3(el, ctx.isSelected);
2588
- return /* @__PURE__ */ jsxs10("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${angle})`, children: [
2589
- /* @__PURE__ */ jsx10("path", { d: `M 0 0 Q ${d / 2} ${-h} ${d} 0`, fill: "none", stroke: stroke2, strokeWidth: sw7 }),
2590
- /* @__PURE__ */ jsx10("g", { transform: `translate(${d}, 0) rotate(${arrowAngle})`, children: /* @__PURE__ */ jsx10("polygon", { points: "0,0 -12,-6 -12,6", fill: stroke2 }) })
2591
- ] });
2592
- });
2593
-
2594
- // src/core/renderers/electrostatics.tsx
2595
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2596
- var stroke = (el, selected) => selected ? "#2563eb" : el.color || "#0f172a";
2597
- var width = (el, selected) => selected ? 2.5 : el.strokeWidth || 2;
2598
- var rotated2 = (el, content, selected) => {
2599
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2600
- const a = angleDeg(el.x1, el.y1, el.x2, el.y2);
2601
- const dx = el.x2 - el.x1;
2602
- const dy = el.y2 - el.y1;
2603
- const mx = (el.x1 + el.x2) / 2;
2604
- const my = (el.y1 + el.y2) / 2;
2605
- let nx = -dy / (d || 1);
2606
- let ny = dx / (d || 1);
2607
- if (ny > 0) {
2608
- nx = -nx;
2609
- ny = -ny;
2610
- }
2611
- const labelDist = 18;
2612
- const c7 = stroke(el, selected);
2613
- return /* @__PURE__ */ jsxs11("g", { children: [
2614
- /* @__PURE__ */ jsx11("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${a})`, children: content }),
2615
- el.label && /* @__PURE__ */ jsx11("text", { x: mx + nx * labelDist, y: my + ny * labelDist, dominantBaseline: "central", textAnchor: "middle", fill: c7, fontSize: 14, fontFamily: "sans-serif", children: String(el.label) })
2616
- ] });
2617
- };
2618
- registerRenderer("charge_pos", (el, ctx) => {
2619
- const c7 = ctx.isSelected ? "#2563eb" : "#ef4444";
2620
- return /* @__PURE__ */ jsxs11("g", { transform: `translate(${el.x1}, ${el.y1})`, opacity: ctx?.isGhost ? 0.5 : 1, children: [
2621
- /* @__PURE__ */ jsx11("circle", { cx: "0", cy: "0", r: "10", fill: "#fecaca", stroke: c7, strokeWidth: width(el, ctx.isSelected) }),
2622
- /* @__PURE__ */ jsx11("line", { x1: "0", y1: "-4", x2: "0", y2: "4", stroke: c7, strokeWidth: 2 }),
2623
- /* @__PURE__ */ jsx11("line", { x1: "-4", y1: "0", x2: "4", y2: "0", stroke: c7, strokeWidth: 2 }),
2624
- el.label && /* @__PURE__ */ jsx11("text", { x: 0, y: -16, textAnchor: "middle", fill: c7, fontSize: el.fontSize || 14, children: String(el.label) })
2625
- ] });
2626
- });
2627
- registerRenderer("charge_neg", (el, ctx) => {
2628
- const c7 = ctx.isSelected ? "#2563eb" : "#3b82f6";
2629
- return /* @__PURE__ */ jsxs11("g", { transform: `translate(${el.x1}, ${el.y1})`, opacity: ctx?.isGhost ? 0.5 : 1, children: [
2630
- /* @__PURE__ */ jsx11("circle", { cx: "0", cy: "0", r: "10", fill: "#bfdbfe", stroke: c7, strokeWidth: width(el, ctx.isSelected) }),
2631
- /* @__PURE__ */ jsx11("line", { x1: "-4", y1: "0", x2: "4", y2: "0", stroke: c7, strokeWidth: 2 }),
2632
- el.label && /* @__PURE__ */ jsx11("text", { x: 0, y: -16, textAnchor: "middle", fill: c7, fontSize: el.fontSize || 14, children: String(el.label) })
2633
- ] });
2634
- });
2635
- registerRenderer("dipole", (el, ctx) => {
2636
- const w = width(el, ctx.isSelected);
2637
- return /* @__PURE__ */ jsxs11("g", { opacity: ctx?.isGhost ? 0.5 : 1, children: [
2638
- /* @__PURE__ */ jsx11("line", { x1: el.x1, y1: el.y1, x2: el.x2, y2: el.y2, stroke: "#64748b", strokeWidth: w, strokeDasharray: "4 4" }),
2639
- /* @__PURE__ */ jsx11("circle", { cx: el.x1, cy: el.y1, r: "8", fill: "#fecaca", stroke: ctx.isSelected ? "#2563eb" : "#ef4444", strokeWidth: w }),
2640
- /* @__PURE__ */ jsx11("circle", { cx: el.x2, cy: el.y2, r: "8", fill: "#bfdbfe", stroke: ctx.isSelected ? "#2563eb" : "#3b82f6", strokeWidth: w }),
2641
- el.label && /* @__PURE__ */ jsx11("text", { x: (el.x1 + el.x2) / 2, y: el.y1 - 16, textAnchor: "middle", fill: "#475569", fontSize: 14, children: String(el.label) })
2642
- ] });
2643
- });
2644
- var plateGlyphs = (d, isPos) => {
2645
- const n = Math.max(2, Math.floor(d / 25));
2646
- const glyphs = [];
2647
- for (let i = 0; i <= n; i++) {
2648
- const pos = i / n * d;
2649
- glyphs.push(
2650
- /* @__PURE__ */ jsx11("g", { transform: `translate(${pos}, 0)`, children: isPos ? /* @__PURE__ */ jsx11(Fragment3, { children: /* @__PURE__ */ jsx11("path", { d: "M-4 0 h8 M0 -4 v8", stroke: "#ffffff", strokeWidth: "2", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx11("path", { d: "M-4 0 h8", stroke: "#ffffff", strokeWidth: "2", strokeLinecap: "round" }) }, i)
2651
- );
2652
- }
2653
- return glyphs;
2654
- };
2655
- registerRenderer("charged_plate_pos", (el, ctx) => {
2656
- const c7 = ctx.isSelected ? "#2563eb" : "#ef4444";
2657
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2658
- const a = angleDeg(el.x1, el.y1, el.x2, el.y2);
2659
- const sw7 = Math.max(12, el.strokeWidth * 4 || 8);
2660
- return /* @__PURE__ */ jsxs11("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${a})`, opacity: ctx?.isGhost ? 0.5 : 1, children: [
2661
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c7, strokeWidth: sw7, strokeLinecap: "round" }),
2662
- plateGlyphs(d, true)
2663
- ] });
2664
- });
2665
- registerRenderer("charged_plate_neg", (el, ctx) => {
2666
- const c7 = ctx.isSelected ? "#2563eb" : "#3b82f6";
2667
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2668
- const a = angleDeg(el.x1, el.y1, el.x2, el.y2);
2669
- const sw7 = Math.max(12, el.strokeWidth * 4 || 8);
2670
- return /* @__PURE__ */ jsxs11("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${a})`, opacity: ctx?.isGhost ? 0.5 : 1, children: [
2671
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: 0, x2: d, y2: 0, stroke: c7, strokeWidth: sw7, strokeLinecap: "round" }),
2672
- plateGlyphs(d, false)
2673
- ] });
2674
- });
2675
- registerRenderer("gaussian_sphere", (el, ctx) => {
2676
- const r = Math.max(10, distance(el.x1, el.y1, el.x2, el.y2));
2677
- const c7 = ctx.isSelected ? "#2563eb" : "#10b981";
2678
- return /* @__PURE__ */ jsxs11("g", { opacity: ctx?.isGhost ? 0.5 : 1, children: [
2679
- /* @__PURE__ */ jsx11("circle", { cx: el.x1, cy: el.y1, r, fill: "#d1fae5", fillOpacity: 0.35, stroke: c7, strokeWidth: width(el, ctx.isSelected), strokeDasharray: "5 5" }),
2680
- el.label && /* @__PURE__ */ jsx11("text", { x: el.x1, y: el.y1 - r - 12, textAnchor: "middle", fill: c7, fontSize: 13, children: String(el.label) })
2681
- ] });
2682
- });
2683
- registerRenderer("gaussian_cylinder", (el, ctx) => {
2684
- const d = distance(el.x1, el.y1, el.x2, el.y2);
2685
- const a = angleDeg(el.x1, el.y1, el.x2, el.y2);
2686
- const r = el.curveHeight ?? 40;
2687
- const capRx = 15;
2688
- const c7 = ctx.isSelected ? "#2563eb" : "#10b981";
2689
- const sw7 = width(el, ctx.isSelected);
2690
- const dash = "6 6";
2691
- return /* @__PURE__ */ jsxs11("g", { opacity: ctx?.isGhost ? 0.5 : 1, children: [
2692
- /* @__PURE__ */ jsx11("line", { x1: el.x1, y1: el.y1, x2: el.x2, y2: el.y2, stroke: "transparent", strokeWidth: Math.max(24, r * 2), strokeLinecap: "round" }),
2693
- /* @__PURE__ */ jsxs11("g", { transform: `translate(${el.x1}, ${el.y1}) rotate(${a})`, children: [
2694
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: -r, x2: d, y2: -r, stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
2695
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: r, x2: d, y2: r, stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
2696
- /* @__PURE__ */ jsx11("ellipse", { cx: 0, cy: 0, rx: capRx, ry: r, fill: c7, fillOpacity: 0.05, stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
2697
- /* @__PURE__ */ jsx11("ellipse", { cx: d, cy: 0, rx: capRx, ry: r, fill: c7, fillOpacity: 0.05, stroke: c7, strokeWidth: sw7, strokeDasharray: dash }),
2698
- el.label && /* @__PURE__ */ jsx11("text", { x: d / 2, y: -r - 10, textAnchor: "middle", fill: c7, fontSize: el.fontSize || 14, children: String(el.label) })
2699
- ] })
2700
- ] });
2701
- });
2702
- registerRenderer(
2703
- "mirror_plane",
2704
- (el, ctx) => rotated2(
2705
- el,
2706
- /* @__PURE__ */ jsxs11(Fragment3, { children: [
2707
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: -24, x2: 0, y2: 24, stroke: stroke(el, ctx.isSelected), strokeWidth: width(el, ctx.isSelected) }),
2708
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: -18, x2: -8, y2: -12, stroke: stroke(el, ctx.isSelected), strokeWidth: 1.5 }),
2709
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: -6, x2: -8, y2: 0, stroke: stroke(el, ctx.isSelected), strokeWidth: 1.5 }),
2710
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: 6, x2: -8, y2: 12, stroke: stroke(el, ctx.isSelected), strokeWidth: 1.5 }),
2711
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: 18, x2: -8, y2: 24, stroke: stroke(el, ctx.isSelected), strokeWidth: 1.5 })
2712
- ] }),
2713
- ctx.isSelected
2714
- )
2715
- );
2716
- registerRenderer("energy_level", (el, ctx) => {
2717
- const d = Math.max(24, distance(el.x1, el.y1, el.x2, el.y2));
2718
- const c7 = stroke(el, ctx.isSelected);
2719
- const energyText = el.energy != null ? String(el.energy) : "";
2720
- return rotated2(
2721
- el,
2722
- /* @__PURE__ */ jsxs11(Fragment3, { children: [
2723
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: -8, x2: d, y2: -8, stroke: c7, strokeWidth: width(el, ctx.isSelected) }),
2724
- /* @__PURE__ */ jsx11("line", { x1: 0, y1: 8, x2: d, y2: 8, stroke: c7, strokeWidth: width(el, ctx.isSelected) }),
2725
- energyText && /* @__PURE__ */ jsx11("text", { x: d / 2, y: 22, textAnchor: "middle", fontSize: 10, fill: "#4b5563", children: energyText })
2726
- ] }),
2727
- ctx.isSelected
2728
- );
2729
- });
2730
-
2731
- // src/core/Renderer.tsx
2732
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2733
- var UnknownElement = ({ x, y, type }) => /* @__PURE__ */ jsxs12("g", { children: [
2734
- /* @__PURE__ */ jsx12("rect", { x: x - 20, y: y - 12, width: 40, height: 24, fill: "#fee2e2", stroke: "#ef4444" }),
2735
- /* @__PURE__ */ jsx12("text", { x, y, textAnchor: "middle", dominantBaseline: "central", fontSize: 10, fill: "#991b1b", children: type })
2736
- ] });
2737
- var Renderer = ({
2738
- elements,
2739
- selectedId,
2740
- drawing,
2741
- viewMode = false,
2742
- showGrid = true,
2743
- gridSize = GRID_SIZE,
2744
- className,
2745
- svgRef,
2746
- onBackgroundMouseDown,
2747
- onBackgroundMouseMove,
2748
- onBackgroundMouseUp,
2749
- onBackgroundMouseLeave,
2750
- onElementMouseDown
2751
- }) => {
2752
- const autoNodes = useMemo(() => getCircuitAutoNodes(elements), [elements]);
2753
- return /* @__PURE__ */ jsxs12(
2754
- "svg",
2755
- {
2756
- ref: svgRef,
2757
- className,
2758
- onMouseDown: onBackgroundMouseDown,
2759
- onMouseMove: onBackgroundMouseMove,
2760
- onMouseUp: onBackgroundMouseUp,
2761
- onMouseLeave: onBackgroundMouseLeave,
2762
- children: [
2763
- !viewMode && showGrid && /* @__PURE__ */ jsxs12(Fragment4, { children: [
2764
- /* @__PURE__ */ jsx12("defs", { children: /* @__PURE__ */ jsx12("pattern", { id: "svg-engine-grid", width: gridSize, height: gridSize, patternUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx12("path", { d: `M ${gridSize} 0 L 0 0 0 ${gridSize}`, fill: "none", stroke: "#e2e8f0", strokeWidth: "1" }) }) }),
2765
- /* @__PURE__ */ jsx12("rect", { width: "100%", height: "100%", fill: "url(#svg-engine-grid)", pointerEvents: "none" })
2766
- ] }),
2767
- elements.map((el) => {
2768
- const renderer = getRenderer(String(el.type));
2769
- const content = renderer ? renderer(el, { isSelected: selectedId === el.id, viewMode }) : /* @__PURE__ */ jsx12(UnknownElement, { x: el.x1, y: el.y1, type: String(el.type) });
2770
- return /* @__PURE__ */ jsx12("g", { onMouseDown: (e) => onElementMouseDown?.(e, el), cursor: viewMode ? "default" : "move", children: content }, String(el.id));
2771
- }),
2772
- autoNodes.map(([nx, ny], idx) => /* @__PURE__ */ jsx12("circle", { cx: nx, cy: ny, r: 4, fill: "#111827", pointerEvents: "none" }, `junction-${idx}`)),
2773
- drawing && (() => {
2774
- const renderer = getRenderer(String(drawing.type));
2775
- if (!renderer) return null;
2776
- return /* @__PURE__ */ jsx12("g", { opacity: 0.5, children: renderer(drawing, { isGhost: true, viewMode }) });
2777
- })()
2778
- ]
2779
- }
2780
- );
2781
- };
2782
-
2783
- export {
2784
- GRID_SIZE,
2785
- snap,
2786
- distance,
2787
- angleDeg,
2788
- getBounds,
2789
- getMouseCoords,
2790
- registerRenderer,
2791
- getRenderer,
2792
- hasRenderer,
2793
- Renderer
2794
- };