circuit-to-svg 0.0.1
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.
- package/README.md +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +322 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @tscircuit/soup-to-svg
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
pcbSoupToSvg: () => pcbSoupToSvg,
|
|
24
|
+
soupToSvg: () => soupToSvg
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// src/lib/pcb-soup-to-svg.ts
|
|
29
|
+
function pcbSoupToSvg(soup) {
|
|
30
|
+
const svgContent = [];
|
|
31
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
32
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
33
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
34
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
35
|
+
const board = soup.find((item) => item.type === "pcb_board");
|
|
36
|
+
if (board && "center" in board && "width" in board && "height" in board) {
|
|
37
|
+
updateBounds(board.center, board.width, board.height);
|
|
38
|
+
}
|
|
39
|
+
for (const component of soup.filter((item) => item.type === "pcb_component")) {
|
|
40
|
+
if ("center" in component && "width" in component && "height" in component) {
|
|
41
|
+
updateBounds(component.center, component.width, component.height);
|
|
42
|
+
svgContent.push(createPcbComponent(component));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const trace of soup.filter((item) => item.type === "pcb_trace")) {
|
|
46
|
+
svgContent.push(createPcbTrace(trace));
|
|
47
|
+
if ("route" in trace) {
|
|
48
|
+
updateTraceBounds(trace.route);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const item of soup.filter((i) => i.type === "pcb_plated_hole" || i.type === "pcb_smtpad")) {
|
|
52
|
+
if ("x" in item && "y" in item && ("outer_diameter" in item || "width" in item && "height" in item)) {
|
|
53
|
+
const diameter = "outer_diameter" in item ? item.outer_diameter : item.width;
|
|
54
|
+
const height2 = "outer_diameter" in item ? item.outer_diameter : item.height;
|
|
55
|
+
updateBounds({ x: item.x, y: item.y }, diameter, height2);
|
|
56
|
+
svgContent.push(createPcbHole(item));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const padding = 5;
|
|
60
|
+
const width = maxX - minX + 2 * padding;
|
|
61
|
+
const height = maxY - minY + 2 * padding;
|
|
62
|
+
const viewBox = `${minX - padding} ${-maxY - padding} ${width} ${height}`;
|
|
63
|
+
return `
|
|
64
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}" width="800" height="600">
|
|
65
|
+
<style>
|
|
66
|
+
.pcb-board { fill: #000; }
|
|
67
|
+
.pcb-trace { stroke: #CC0000; stroke-width: 0.1; fill: none; }
|
|
68
|
+
.pcb-hole { fill: #FF00FF; }
|
|
69
|
+
.pcb-pad { fill: #CC0000; }
|
|
70
|
+
.pcb-outline { fill: none; stroke: white; stroke-width: 0.1; }
|
|
71
|
+
</style>
|
|
72
|
+
<g transform="scale(1, -1)">
|
|
73
|
+
<rect class="pcb-board" x="${minX - padding}" y="${minY - padding}" width="${width}" height="${height}" />
|
|
74
|
+
${svgContent.join("\n")}
|
|
75
|
+
<rect class="pcb-outline" x="${minX}" y="${minY}" width="${maxX - minX}" height="${maxY - minY}" />
|
|
76
|
+
</g>
|
|
77
|
+
</svg>
|
|
78
|
+
`;
|
|
79
|
+
function updateBounds(center, width2, height2) {
|
|
80
|
+
const halfWidth = width2 / 2;
|
|
81
|
+
const halfHeight = height2 / 2;
|
|
82
|
+
minX = Math.min(minX, center.x - halfWidth);
|
|
83
|
+
minY = Math.min(minY, center.y - halfHeight);
|
|
84
|
+
maxX = Math.max(maxX, center.x + halfWidth);
|
|
85
|
+
maxY = Math.max(maxY, center.y + halfHeight);
|
|
86
|
+
}
|
|
87
|
+
function updateTraceBounds(route) {
|
|
88
|
+
for (const point of route) {
|
|
89
|
+
minX = Math.min(minX, point.x);
|
|
90
|
+
minY = Math.min(minY, point.y);
|
|
91
|
+
maxX = Math.max(maxX, point.x);
|
|
92
|
+
maxY = Math.max(maxY, point.y);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function createPcbComponent(component) {
|
|
97
|
+
const { center, width, height, rotation = 0 } = component;
|
|
98
|
+
const transform = `translate(${center.x}, ${center.y}) rotate(${-rotation})`;
|
|
99
|
+
return `
|
|
100
|
+
<g transform="${transform}">
|
|
101
|
+
<rect class="pcb-component" x="${-width / 2}" y="${-height / 2}" width="${width}" height="${height}" />
|
|
102
|
+
<rect class="pcb-component-outline" x="${-width / 2}" y="${-height / 2}" width="${width}" height="${height}" />
|
|
103
|
+
</g>
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
function createPcbTrace(trace) {
|
|
107
|
+
const path = trace.route.map((point, index) => {
|
|
108
|
+
return index === 0 ? `M ${point.x} ${point.y}` : `L ${point.x} ${point.y}`;
|
|
109
|
+
}).join(" ");
|
|
110
|
+
return `<path class="pcb-trace" d="${path}" />`;
|
|
111
|
+
}
|
|
112
|
+
function createPcbHole(hole) {
|
|
113
|
+
if (hole.type === "pcb_plated_hole") {
|
|
114
|
+
return `<circle class="pcb-hole" cx="${hole.x}" cy="${hole.y}" r="${hole.outer_diameter / 2}" />`;
|
|
115
|
+
}
|
|
116
|
+
return `<rect class="pcb-pad" x="${hole.x - hole.width / 2}" y="${hole.y - hole.height / 2}" width="${hole.width}" height="${hole.height}" />`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/lib/soup-to-svg.ts
|
|
120
|
+
function soupToSvg(soup) {
|
|
121
|
+
const svgContent = [];
|
|
122
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
123
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
124
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
125
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
126
|
+
for (const component of soup.filter(
|
|
127
|
+
(item) => item.type === "schematic_component"
|
|
128
|
+
)) {
|
|
129
|
+
const svg = createSchematicComponent(component);
|
|
130
|
+
svgContent.push(svg);
|
|
131
|
+
if ("center" in component && "size" in component && "rotation" in component) {
|
|
132
|
+
updateBounds(component.center, component.size, component.rotation);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const trace of soup.filter((item) => item.type === "schematic_trace")) {
|
|
136
|
+
const svg = createSchematicTrace(trace);
|
|
137
|
+
svgContent.push(svg);
|
|
138
|
+
updateTraceBounds(trace.edges);
|
|
139
|
+
}
|
|
140
|
+
for (const text of soup.filter((item) => item.type === "schematic_text")) {
|
|
141
|
+
const svg = createSchematicText(text);
|
|
142
|
+
svgContent.push(svg);
|
|
143
|
+
if ("position" in text) {
|
|
144
|
+
updateTextBounds(text.position);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (const label of soup.filter(
|
|
148
|
+
(item) => item.type === "schematic_net_label"
|
|
149
|
+
)) {
|
|
150
|
+
const svg = createSchematicNetLabel(label);
|
|
151
|
+
svgContent.push(svg);
|
|
152
|
+
const width2 = label.text.length * 0.15 + 0.3;
|
|
153
|
+
const height2 = 0.3;
|
|
154
|
+
minX = Math.min(minX, label.center.x);
|
|
155
|
+
minY = Math.min(minY, label.center.y - height2 / 2);
|
|
156
|
+
maxX = Math.max(maxX, label.center.x + width2);
|
|
157
|
+
maxY = Math.max(maxY, label.center.y + height2 / 2);
|
|
158
|
+
}
|
|
159
|
+
const padding = 1;
|
|
160
|
+
const width = maxX - minX + 2 * padding;
|
|
161
|
+
const height = maxY - minY + 2 * padding;
|
|
162
|
+
const viewBox = `${minX - padding} ${minY - padding} ${width} ${height}`;
|
|
163
|
+
return `
|
|
164
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}" width="1200" height="600">
|
|
165
|
+
<style>
|
|
166
|
+
.component { fill: none; stroke: red; stroke-width: 0.05; }
|
|
167
|
+
.component-pin { fill: none; stroke: blue; stroke-width: 0.05; }
|
|
168
|
+
.trace { stroke: green; stroke-width: 0.05; fill: none; }
|
|
169
|
+
.text { font-family: Arial, sans-serif; font-size: 0.2px; }
|
|
170
|
+
.net-label { font-family: Arial, sans-serif; font-size: 0.2px; fill: gray; }
|
|
171
|
+
</style>
|
|
172
|
+
${svgContent.join("\n")}
|
|
173
|
+
</svg>
|
|
174
|
+
`;
|
|
175
|
+
function updateBounds(center, size, rotation) {
|
|
176
|
+
const corners = [
|
|
177
|
+
{ x: -size.width / 2, y: -size.height / 2 },
|
|
178
|
+
{ x: size.width / 2, y: -size.height / 2 },
|
|
179
|
+
{ x: size.width / 2, y: size.height / 2 },
|
|
180
|
+
{ x: -size.width / 2, y: size.height / 2 }
|
|
181
|
+
];
|
|
182
|
+
for (const corner of corners) {
|
|
183
|
+
const rotatedX = corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x;
|
|
184
|
+
const rotatedY = corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y;
|
|
185
|
+
minX = Math.min(minX, rotatedX);
|
|
186
|
+
minY = Math.min(minY, rotatedY);
|
|
187
|
+
maxX = Math.max(maxX, rotatedX);
|
|
188
|
+
maxY = Math.max(maxY, rotatedY);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function updateTraceBounds(edges) {
|
|
192
|
+
for (const edge of edges) {
|
|
193
|
+
minX = Math.min(minX, edge.from.x, edge.to.x);
|
|
194
|
+
minY = Math.min(minY, edge.from.y, edge.to.y);
|
|
195
|
+
maxX = Math.max(maxX, edge.from.x, edge.to.x);
|
|
196
|
+
maxY = Math.max(maxY, edge.from.y, edge.to.y);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function updateTextBounds(position) {
|
|
200
|
+
minX = Math.min(minX, position.x);
|
|
201
|
+
minY = Math.min(minY, position.y);
|
|
202
|
+
maxX = Math.max(maxX, position.x);
|
|
203
|
+
maxY = Math.max(maxY, position.y);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function createSchematicComponent(component) {
|
|
207
|
+
const { center, size, rotation } = component;
|
|
208
|
+
const transform = `translate(${center.x}, ${center.y}) rotate(${rotation * 180 / Math.PI})`;
|
|
209
|
+
const pinSize = 0.2;
|
|
210
|
+
return `
|
|
211
|
+
<g transform="${transform}">
|
|
212
|
+
<rect
|
|
213
|
+
class="component"
|
|
214
|
+
x="${-size.width / 2}"
|
|
215
|
+
y="${-size.height / 2}"
|
|
216
|
+
width="${size.width}"
|
|
217
|
+
height="${size.height}"
|
|
218
|
+
/>
|
|
219
|
+
<rect
|
|
220
|
+
class="component-pin"
|
|
221
|
+
x="${-size.width / 2 - pinSize / 2}"
|
|
222
|
+
y="${-pinSize / 2}"
|
|
223
|
+
width="${pinSize}"
|
|
224
|
+
height="${pinSize}"
|
|
225
|
+
/>
|
|
226
|
+
<rect
|
|
227
|
+
class="component-pin"
|
|
228
|
+
x="${size.width / 2 - pinSize / 2}"
|
|
229
|
+
y="${-pinSize / 2}"
|
|
230
|
+
width="${pinSize}"
|
|
231
|
+
height="${pinSize}"
|
|
232
|
+
/>
|
|
233
|
+
</g>
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
function createSchematicTrace(trace) {
|
|
237
|
+
const path = trace.edges.map((edge, index) => {
|
|
238
|
+
const fromPoint = `${edge.from.x} ${edge.from.y}`;
|
|
239
|
+
const toPoint = `${edge.to.x} ${edge.to.y}`;
|
|
240
|
+
if (index === 0) {
|
|
241
|
+
return `M ${fromPoint} L ${toPoint}`;
|
|
242
|
+
}
|
|
243
|
+
const prevEdge = trace.edges[index - 1];
|
|
244
|
+
if (prevEdge.to.x === edge.from.x && prevEdge.to.y === edge.from.y) {
|
|
245
|
+
return `L ${toPoint}`;
|
|
246
|
+
}
|
|
247
|
+
return `M ${fromPoint} L ${toPoint}`;
|
|
248
|
+
}).join(" ");
|
|
249
|
+
return `<path class="trace" d="${path}" />`;
|
|
250
|
+
}
|
|
251
|
+
function createSchematicText(text) {
|
|
252
|
+
return `
|
|
253
|
+
<text
|
|
254
|
+
class="text"
|
|
255
|
+
x="${text.position.x}"
|
|
256
|
+
y="${text.position.y}"
|
|
257
|
+
text-anchor="${getTextAnchor(text.anchor)}"
|
|
258
|
+
>${text.text}</text>
|
|
259
|
+
`;
|
|
260
|
+
}
|
|
261
|
+
function createSchematicNetLabel(label) {
|
|
262
|
+
const width = label.text.length * 0.15 + 0.3;
|
|
263
|
+
const height = 0.3;
|
|
264
|
+
const arrowTip = 0.15;
|
|
265
|
+
const isLeftAnchor = label.anchor_side === "left";
|
|
266
|
+
const labelCenterX = isLeftAnchor ? label.center.x - width / 3 - 0.2 : label.center.x;
|
|
267
|
+
const path = isLeftAnchor ? `
|
|
268
|
+
M ${labelCenterX + width},${label.center.y - height / 2}
|
|
269
|
+
L ${labelCenterX + arrowTip},${label.center.y - height / 2}
|
|
270
|
+
L ${labelCenterX},${label.center.y}
|
|
271
|
+
L ${labelCenterX + arrowTip},${label.center.y + height / 2}
|
|
272
|
+
L ${labelCenterX + width},${label.center.y + height / 2}
|
|
273
|
+
Z
|
|
274
|
+
` : `
|
|
275
|
+
M ${labelCenterX},${label.center.y - height / 2}
|
|
276
|
+
L ${labelCenterX + width - arrowTip},${label.center.y - height / 2}
|
|
277
|
+
L ${labelCenterX + width},${label.center.y}
|
|
278
|
+
L ${labelCenterX + width - arrowTip},${label.center.y + height / 2}
|
|
279
|
+
L ${labelCenterX},${label.center.y + height / 2}
|
|
280
|
+
Z
|
|
281
|
+
`;
|
|
282
|
+
const textX = labelCenterX + width / 2;
|
|
283
|
+
const connectingLine = `
|
|
284
|
+
<line
|
|
285
|
+
x1="${labelCenterX + width}"
|
|
286
|
+
y1="${label.center.y}"
|
|
287
|
+
x2="${label.center.x}"
|
|
288
|
+
y2="${label.center.y}"
|
|
289
|
+
stroke="green"
|
|
290
|
+
stroke-width="0.05"
|
|
291
|
+
/>
|
|
292
|
+
`;
|
|
293
|
+
return `
|
|
294
|
+
<g class="net-label">
|
|
295
|
+
${connectingLine}
|
|
296
|
+
<path d="${path}" fill="white" stroke="black" stroke-width="0.02"/>
|
|
297
|
+
<text
|
|
298
|
+
x="${textX}"
|
|
299
|
+
y="${label.center.y}"
|
|
300
|
+
text-anchor="middle"
|
|
301
|
+
dominant-baseline="central"
|
|
302
|
+
fill="black"
|
|
303
|
+
>${label.text}</text>
|
|
304
|
+
</g>
|
|
305
|
+
`;
|
|
306
|
+
}
|
|
307
|
+
function getTextAnchor(anchor) {
|
|
308
|
+
switch (anchor) {
|
|
309
|
+
case "left":
|
|
310
|
+
return "start";
|
|
311
|
+
case "right":
|
|
312
|
+
return "end";
|
|
313
|
+
default:
|
|
314
|
+
return "middle";
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
318
|
+
0 && (module.exports = {
|
|
319
|
+
pcbSoupToSvg,
|
|
320
|
+
soupToSvg
|
|
321
|
+
});
|
|
322
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/pcb-soup-to-svg.ts","../src/lib/soup-to-svg.ts"],"sourcesContent":["export * from \"./lib\";\n\n","import type { AnySoupElement } from \"@tscircuit/soup\";\n\nfunction pcbSoupToSvg(soup: AnySoupElement[]): string {\n const svgContent: string[] = [];\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n \n // Process PCB board\n const board = soup.find((item) => item.type === \"pcb_board\");\n if (board && \"center\" in board && \"width\" in board && \"height\" in board) {\n updateBounds(board.center, board.width, board.height);\n }\n \n // Process PCB components\n for (const component of soup.filter((item) => item.type === \"pcb_component\")) {\n if (\"center\" in component && \"width\" in component && \"height\" in component) {\n updateBounds((component as { center: { x: number; y: number }; width: number; height: number }).center, component.width, component.height);\n svgContent.push(createPcbComponent(component));\n }\n }\n \n // Process PCB traces\n for (const trace of soup.filter((item) => item.type === \"pcb_trace\")) {\n svgContent.push(createPcbTrace(trace));\n if ('route' in trace) {\n updateTraceBounds(trace.route);\n }\n }\n \n // Process PCB plated holes and SMT pads\n for (const item of soup.filter((i) => i.type === \"pcb_plated_hole\" || i.type === \"pcb_smtpad\")) {\n if ('x' in item && 'y' in item && ('outer_diameter' in item || ('width' in item && 'height' in item))) {\n const diameter = 'outer_diameter' in item ? item.outer_diameter : item.width;\n const height = 'outer_diameter' in item ? item.outer_diameter : item.height;\n updateBounds({ x: item.x, y: item.y }, diameter, height);\n svgContent.push(createPcbHole(item));\n }\n }\n \n const padding = 5;\n const width = maxX - minX + 2 * padding;\n const height = maxY - minY + 2 * padding;\n const viewBox = `${minX - padding} ${-maxY - padding} ${width} ${height}`;\n \n return `\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" width=\"800\" height=\"600\">\n <style>\n .pcb-board { fill: #000; }\n .pcb-trace { stroke: #CC0000; stroke-width: 0.1; fill: none; }\n .pcb-hole { fill: #FF00FF; }\n .pcb-pad { fill: #CC0000; }\n .pcb-outline { fill: none; stroke: white; stroke-width: 0.1; }\n </style>\n <g transform=\"scale(1, -1)\">\n <rect class=\"pcb-board\" x=\"${minX - padding}\" y=\"${minY - padding}\" width=\"${width}\" height=\"${height}\" />\n ${svgContent.join(\"\\n\")}\n <rect class=\"pcb-outline\" x=\"${minX}\" y=\"${minY}\" width=\"${maxX - minX}\" height=\"${maxY - minY}\" />\n </g>\n </svg>\n `;\n \n function updateBounds(center: any, width: any, height: any) {\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n minX = Math.min(minX, center.x - halfWidth);\n minY = Math.min(minY, center.y - halfHeight);\n maxX = Math.max(maxX, center.x + halfWidth);\n maxY = Math.max(maxY, center.y + halfHeight);\n }\n \n function updateTraceBounds(route: any[]) {\n for (const point of route) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n }\n }\n \n function createPcbComponent(component: any): string {\n const { center, width, height, rotation = 0 } = component;\n const transform = `translate(${center.x}, ${center.y}) rotate(${-rotation})`;\n return `\n <g transform=\"${transform}\">\n <rect class=\"pcb-component\" x=\"${-width/2}\" y=\"${-height/2}\" width=\"${width}\" height=\"${height}\" />\n <rect class=\"pcb-component-outline\" x=\"${-width/2}\" y=\"${-height/2}\" width=\"${width}\" height=\"${height}\" />\n </g>\n `;\n }\n \n function createPcbTrace(trace: any): string {\n const path = trace.route.map((point: any, index: number) => {\n return index === 0 ? `M ${point.x} ${point.y}` : `L ${point.x} ${point.y}`;\n }).join(\" \");\n return `<path class=\"pcb-trace\" d=\"${path}\" />`;\n }\n \n function createPcbHole(hole: any): string {\n if (hole.type === \"pcb_plated_hole\") {\n return `<circle class=\"pcb-hole\" cx=\"${hole.x}\" cy=\"${hole.y}\" r=\"${hole.outer_diameter / 2}\" />`;\n }\n return `<rect class=\"pcb-pad\" x=\"${hole.x - hole.width/2}\" y=\"${hole.y - hole.height/2}\" width=\"${hole.width}\" height=\"${hole.height}\" />`;\n }\n\n\nexport { pcbSoupToSvg };\n\n","import type { AnySoupElement } from \"@tscircuit/soup\";\n\nfunction soupToSvg(soup: AnySoupElement[]): string {\n const svgContent: string[] = [];\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n // Process components\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\"\n )) {\n const svg = createSchematicComponent(component);\n svgContent.push(svg);\n if (\n \"center\" in component &&\n \"size\" in component &&\n \"rotation\" in component\n ) {\n updateBounds(component.center, component.size, component.rotation);\n }\n }\n\n // Process traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace);\n svgContent.push(svg);\n updateTraceBounds(trace.edges);\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const svg = createSchematicText(text);\n svgContent.push(svg);\n if (\"position\" in text) {\n updateTextBounds(text.position);\n }\n }\n\n // Process net labels\n for (const label of soup.filter(\n (item) => item.type === \"schematic_net_label\"\n )) {\n const svg = createSchematicNetLabel(label);\n svgContent.push(svg);\n const width = label.text.length * 0.15 + 0.3;\n const height = 0.3;\n minX = Math.min(minX, label.center.x);\n minY = Math.min(minY, label.center.y - height / 2);\n maxX = Math.max(maxX, label.center.x + width);\n maxY = Math.max(maxY, label.center.y + height / 2);\n }\n\n const padding = 1;\n const width = maxX - minX + 2 * padding;\n const height = maxY - minY + 2 * padding;\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height}`;\n\n return `\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" width=\"1200\" height=\"600\">\n <style>\n .component { fill: none; stroke: red; stroke-width: 0.05; }\n .component-pin { fill: none; stroke: blue; stroke-width: 0.05; }\n .trace { stroke: green; stroke-width: 0.05; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .net-label { font-family: Arial, sans-serif; font-size: 0.2px; fill: gray; }\n </style>\n ${svgContent.join(\"\\n\")}\n </svg>\n `;\n\n function updateBounds(center: any, size: any, rotation: number) {\n const corners = [\n { x: -size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: size.height / 2 },\n { x: -size.width / 2, y: size.height / 2 },\n ];\n\n for (const corner of corners) {\n const rotatedX =\n corner.x * Math.cos(rotation) -\n corner.y * Math.sin(rotation) +\n center.x;\n const rotatedY =\n corner.x * Math.sin(rotation) +\n corner.y * Math.cos(rotation) +\n center.y;\n minX = Math.min(minX, rotatedX);\n minY = Math.min(minY, rotatedY);\n maxX = Math.max(maxX, rotatedX);\n maxY = Math.max(maxY, rotatedY);\n }\n }\n\n function updateTraceBounds(edges: any[]) {\n for (const edge of edges) {\n minX = Math.min(minX, edge.from.x, edge.to.x);\n minY = Math.min(minY, edge.from.y, edge.to.y);\n maxX = Math.max(maxX, edge.from.x, edge.to.x);\n maxY = Math.max(maxY, edge.from.y, edge.to.y);\n }\n }\n\n function updateTextBounds(position: { x: number; y: number }) {\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n maxX = Math.max(maxX, position.x);\n maxY = Math.max(maxY, position.y);\n }\n}\n\nfunction createSchematicComponent(component: any): string {\n const { center, size, rotation } = component;\n const transform = `translate(${center.x}, ${center.y}) rotate(${\n (rotation * 180) / Math.PI\n })`;\n const pinSize = 0.2; // Size of the square pins\n\n return `\n <g transform=\"${transform}\">\n <rect \n class=\"component\" \n x=\"${-size.width / 2}\" \n y=\"${-size.height / 2}\" \n width=\"${size.width}\" \n height=\"${size.height}\" \n />\n <rect \n class=\"component-pin\"\n x=\"${-size.width / 2 - pinSize / 2}\" \n y=\"${-pinSize / 2}\" \n width=\"${pinSize}\" \n height=\"${pinSize}\" \n />\n <rect \n class=\"component-pin\"\n x=\"${size.width / 2 - pinSize / 2}\" \n y=\"${-pinSize / 2}\" \n width=\"${pinSize}\" \n height=\"${pinSize}\" \n />\n </g>\n `;\n}\n\nfunction createSchematicTrace(trace: any): string {\n const path = trace.edges.map((edge: any, index: number) => {\n const fromPoint = `${edge.from.x} ${edge.from.y}`;\n const toPoint = `${edge.to.x} ${edge.to.y}`;\n \n if (index === 0) {\n return `M ${fromPoint} L ${toPoint}`;\n }\n // Check if this is a 90-degree turn\n const prevEdge = trace.edges[index - 1];\n if (prevEdge.to.x === edge.from.x && prevEdge.to.y === edge.from.y) {\n return `L ${toPoint}`;\n }\n // Insert a move command for discontinuous segments\n return `M ${fromPoint} L ${toPoint}`;\n }).join(' ');\n\n return `<path class=\"trace\" d=\"${path}\" />`;\n}\n\nfunction createSchematicText(text: any): string {\n return `\n <text \n class=\"text\" \n x=\"${text.position.x}\" \n y=\"${text.position.y}\" \n text-anchor=\"${getTextAnchor(text.anchor)}\"\n >${text.text}</text>\n `;\n}\n\nfunction createSchematicNetLabel(label: any): string {\n const width = label.text.length * 0.15 + 0.3;\n const height = 0.3;\n const arrowTip = 0.15;\n const isLeftAnchor = label.anchor_side === \"left\";\n\n // Move the entire label to the left\n const labelCenterX = isLeftAnchor ? label.center.x - width / 3 - 0.2 : label.center.x;\n\n const path = isLeftAnchor\n ? `\n M ${labelCenterX + width},${label.center.y - height / 2}\n L ${labelCenterX + arrowTip},${label.center.y - height / 2}\n L ${labelCenterX},${label.center.y}\n L ${labelCenterX + arrowTip},${label.center.y + height / 2}\n L ${labelCenterX + width},${label.center.y + height / 2}\n Z\n `\n : `\n M ${labelCenterX},${label.center.y - height / 2}\n L ${labelCenterX + width - arrowTip},${label.center.y - height / 2}\n L ${labelCenterX + width},${label.center.y}\n L ${labelCenterX + width - arrowTip},${label.center.y + height / 2}\n L ${labelCenterX},${label.center.y + height / 2}\n Z\n `;\n\n // Keep text centered within the label\n const textX = labelCenterX + width / 2;\n\n // Add a line to connect the label to the resistor\n const connectingLine = `\n <line \n x1=\"${labelCenterX + width}\" \n y1=\"${label.center.y}\" \n x2=\"${label.center.x}\" \n y2=\"${label.center.y}\" \n stroke=\"green\" \n stroke-width=\"0.05\"\n />\n `;\n\n return `\n <g class=\"net-label\">\n ${connectingLine}\n <path d=\"${path}\" fill=\"white\" stroke=\"black\" stroke-width=\"0.02\"/>\n <text \n x=\"${textX}\" \n y=\"${label.center.y}\" \n text-anchor=\"middle\" \n dominant-baseline=\"central\"\n fill=\"black\"\n >${label.text}</text>\n </g>\n `;\n}\n\nfunction getTextAnchor(anchor: string): string {\n switch (anchor) {\n case \"left\":\n return \"start\";\n case \"right\":\n return \"end\";\n default:\n return \"middle\";\n }\n}\n\nexport { soupToSvg };\n"],"mappings":"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","names":["height","width","width","height"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "circuit-to-svg",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Convert Circuit JSON to SVG",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"prepublish": "npm run build",
|
|
11
|
+
"build": "tsup ./src/index.ts --dts --sourcemap",
|
|
12
|
+
"format": "biome format . --write",
|
|
13
|
+
"storybook": "storybook dev -p 6006",
|
|
14
|
+
"build-storybook": "storybook build"
|
|
15
|
+
},
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@biomejs/biome": "^1.8.3",
|
|
19
|
+
"@chromatic-com/storybook": "^1.6.1",
|
|
20
|
+
"@storybook/addon-essentials": "^8.2.5",
|
|
21
|
+
"@storybook/addon-interactions": "^8.2.5",
|
|
22
|
+
"@storybook/addon-links": "^8.2.5",
|
|
23
|
+
"@storybook/addon-onboarding": "^8.2.5",
|
|
24
|
+
"@storybook/blocks": "^8.2.5",
|
|
25
|
+
"@storybook/react": "^8.2.5",
|
|
26
|
+
"@storybook/react-vite": "^8.2.5",
|
|
27
|
+
"@storybook/test": "^8.2.5",
|
|
28
|
+
"@tscircuit/plop": "^0.0.10",
|
|
29
|
+
"esbuild": "^0.20.2",
|
|
30
|
+
"storybook": "^8.2.5",
|
|
31
|
+
"tsup": "^8.0.2",
|
|
32
|
+
"typescript": "^5.4.5"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@tscircuit/routing": "^1.3.5",
|
|
36
|
+
"@tscircuit/soup": "^0.0.39"
|
|
37
|
+
}
|
|
38
|
+
}
|