circuit-to-svg 0.0.19 → 0.0.21

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/dist/index.js CHANGED
@@ -1,33 +1,64 @@
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 });
1
+ // src/lib/circuit-to-pcb-svg.ts
2
+ import { stringify as stringify2 } from "svgson";
3
+ import {
4
+ applyToPoint as applyToPoint2,
5
+ compose,
6
+ scale,
7
+ translate
8
+ } from "transformation-matrix";
9
+
10
+ // src/utils/pairs.ts
11
+ function pairs(arr) {
12
+ const result = [];
13
+ for (let i = 0; i < arr.length - 1; i++) {
14
+ result.push([arr[i], arr[i + 1]]);
15
15
  }
16
- return to;
16
+ return result;
17
+ }
18
+
19
+ // src/lib/svg-object-fns/create-svg-object-from-pcb-trace.ts
20
+ import "svgson";
21
+ import { applyToPoint } from "transformation-matrix";
22
+
23
+ // src/lib/layer-name-to-color.ts
24
+ var LAYER_NAME_TO_COLOR = {
25
+ top: "rgb(200, 52, 52)",
26
+ bottom: "rgb(77, 127, 196)"
17
27
  };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
28
 
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- circuitJsonToPcbSvg: () => circuitJsonToPcbSvg,
24
- circuitJsonToSchematicSvg: () => circuitJsonToSchematicSvg
25
- });
26
- module.exports = __toCommonJS(src_exports);
29
+ // src/lib/svg-object-fns/create-svg-object-from-pcb-trace.ts
30
+ function createSvgObjectsFromPcbTrace(trace, transform) {
31
+ if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)
32
+ return [];
33
+ const segments = pairs(trace.route);
34
+ const svgObjects = [];
35
+ for (const [start, end] of segments) {
36
+ const startPoint = applyToPoint(transform, [start.x, start.y]);
37
+ const endPoint = applyToPoint(transform, [end.x, end.y]);
38
+ const layer = "layer" in start ? start.layer : "layer" in end ? end.layer : null;
39
+ if (!layer) continue;
40
+ const layerColor = LAYER_NAME_TO_COLOR[layer] ?? "white";
41
+ const traceWidth = "width" in start ? start.width : "width" in end ? end.width : null;
42
+ svgObjects.push({
43
+ name: "path",
44
+ type: "element",
45
+ value: "",
46
+ children: [],
47
+ attributes: {
48
+ class: "pcb-trace",
49
+ stroke: layerColor,
50
+ d: `M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,
51
+ "stroke-width": traceWidth ? (traceWidth * Math.abs(transform.a)).toString() : "0.3",
52
+ "stroke-linecap": "round",
53
+ "stroke-linejoin": "round",
54
+ "shape-rendering": "crispEdges"
55
+ }
56
+ });
57
+ }
58
+ return svgObjects;
59
+ }
27
60
 
28
61
  // src/lib/circuit-to-pcb-svg.ts
29
- var import_svgson = require("svgson");
30
- var import_transformation_matrix = require("transformation-matrix");
31
62
  function circuitJsonToPcbSvg(soup) {
32
63
  let minX = Number.POSITIVE_INFINITY;
33
64
  let minY = Number.POSITIVE_INFINITY;
@@ -58,22 +89,22 @@ function circuitJsonToPcbSvg(soup) {
58
89
  const scaleFactor = Math.min(scaleX, scaleY);
59
90
  const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
60
91
  const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
61
- const transform = (0, import_transformation_matrix.compose)(
62
- (0, import_transformation_matrix.translate)(
92
+ const transform = compose(
93
+ translate(
63
94
  offsetX - minX * scaleFactor + padding * scaleFactor,
64
95
  svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
65
96
  ),
66
- (0, import_transformation_matrix.scale)(scaleFactor, -scaleFactor)
97
+ scale(scaleFactor, -scaleFactor)
67
98
  // Flip in y-direction
68
99
  );
69
- const traceElements = soup.filter((item) => item.type === "pcb_trace").map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
70
- const holeElements = soup.filter((item) => item.type === "pcb_plated_hole").map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
71
- const silkscreenElements = soup.filter((item) => item.type === "pcb_silkscreen_path").map((item) => createPcbSilkscreenPath(item, transform)).filter((element) => element !== null);
100
+ const traceElements = soup.filter((item) => item.type === "pcb_trace").flatMap((item) => createSvgObjects(item, transform));
101
+ const holeElements = soup.filter((item) => item.type === "pcb_plated_hole").flatMap((item) => createSvgObjects(item, transform));
102
+ const silkscreenElements = soup.filter((item) => item.type === "pcb_silkscreen_path").flatMap((item) => createPcbSilkscreenPath(item, transform));
72
103
  const otherElements = soup.filter(
73
104
  (item) => !["pcb_trace", "pcb_plated_hole", "pcb_silkscreen_path"].includes(
74
105
  item.type
75
106
  )
76
- ).map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
107
+ ).flatMap((item) => createSvgObjects(item, transform));
77
108
  let strokeWidth = String(0.05 * scaleFactor);
78
109
  for (const element of soup) {
79
110
  if ("stroke_width" in element) {
@@ -89,6 +120,7 @@ function circuitJsonToPcbSvg(soup) {
89
120
  width: svgWidth.toString(),
90
121
  height: svgHeight.toString()
91
122
  },
123
+ value: "",
92
124
  children: [
93
125
  {
94
126
  name: "style",
@@ -98,7 +130,7 @@ function circuitJsonToPcbSvg(soup) {
98
130
  type: "text",
99
131
  value: `
100
132
  .pcb-board { fill: #000; }
101
- .pcb-trace { stroke: rgb(200, 52, 52); stroke-width: ${strokeWidth}; fill: none; }
133
+ .pcb-trace { fill: none; }
102
134
  .pcb-hole-outer { fill: rgb(200, 52, 52); }
103
135
  .pcb-hole-inner { fill: rgb(255, 38, 226); }
104
136
  .pcb-pad { fill: rgb(200, 52, 52); }
@@ -121,7 +153,7 @@ function circuitJsonToPcbSvg(soup) {
121
153
  height: svgHeight.toString()
122
154
  }
123
155
  },
124
- createPcbBoundary(transform, minX, minY, maxX, maxY),
156
+ createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY),
125
157
  {
126
158
  name: "g",
127
159
  type: "element",
@@ -149,7 +181,7 @@ function circuitJsonToPcbSvg(soup) {
149
181
  ].filter((child) => child !== null)
150
182
  };
151
183
  try {
152
- return (0, import_svgson.stringify)(svgObject);
184
+ return stringify2(svgObject);
153
185
  } catch (error) {
154
186
  console.error("Error stringifying SVG object:", error);
155
187
  throw error;
@@ -171,23 +203,23 @@ function circuitJsonToPcbSvg(soup) {
171
203
  }
172
204
  }
173
205
  }
174
- function createSvgElement(item, transform) {
175
- switch (item.type) {
206
+ function createSvgObjects(elm, transform) {
207
+ switch (elm.type) {
176
208
  case "pcb_component":
177
- return createPcbComponent(item, transform);
209
+ return [createSvgObjectsFromPcbComponent(elm, transform)].filter(Boolean);
178
210
  case "pcb_trace":
179
- return createPcbTrace(item, transform);
211
+ return createSvgObjectsFromPcbTrace(elm, transform);
180
212
  case "pcb_plated_hole":
181
- return createPcbHole(item, transform);
213
+ return [createSvgObjectsFromPcbHole(elm, transform)].filter(Boolean);
182
214
  case "pcb_smtpad":
183
- return createPcbSMTPad(item, transform);
215
+ return [createSvgObjectsFromSmtPad(elm, transform)].filter(Boolean);
184
216
  default:
185
- return null;
217
+ return [];
186
218
  }
187
219
  }
188
- function createPcbComponent(component, transform) {
220
+ function createSvgObjectsFromPcbComponent(component, transform) {
189
221
  const { center, width, height, rotation = 0 } = component;
190
- const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [center.x, center.y]);
222
+ const [x, y] = applyToPoint2(transform, [center.x, center.y]);
191
223
  const scaledWidth = width * Math.abs(transform.a);
192
224
  const scaledHeight = height * Math.abs(transform.d);
193
225
  const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`;
@@ -221,8 +253,8 @@ function createPcbComponent(component, transform) {
221
253
  ]
222
254
  };
223
255
  }
224
- function createPcbHole(hole, transform) {
225
- const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [hole.x, hole.y]);
256
+ function createSvgObjectsFromPcbHole(hole, transform) {
257
+ const [x, y] = applyToPoint2(transform, [hole.x, hole.y]);
226
258
  const scaledOuterRadius = hole.outer_diameter / 2 * Math.abs(transform.a);
227
259
  const scaledInnerRadius = hole.hole_diameter / 2 * Math.abs(transform.a);
228
260
  return {
@@ -252,8 +284,8 @@ function createPcbHole(hole, transform) {
252
284
  ]
253
285
  };
254
286
  }
255
- function createPcbSMTPad(pad, transform) {
256
- const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [pad.x, pad.y]);
287
+ function createSvgObjectsFromSmtPad(pad, transform) {
288
+ const [x, y] = applyToPoint2(transform, [pad.x, pad.y]);
257
289
  const width = pad.width * Math.abs(transform.a);
258
290
  const height = pad.height * Math.abs(transform.d);
259
291
  return {
@@ -268,55 +300,10 @@ function createPcbSMTPad(pad, transform) {
268
300
  }
269
301
  };
270
302
  }
271
- function createPcbTrace(trace, transform) {
272
- if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)
273
- return null;
274
- const cornerRadius = 0.2;
275
- const pathCommands = [];
276
- const transformedPoints = trace.route.map(
277
- (point) => (0, import_transformation_matrix.applyToPoint)(transform, [point.x, point.y])
278
- );
279
- pathCommands.push(`M ${transformedPoints[0][0]} ${transformedPoints[0][1]}`);
280
- for (let i = 1; i < transformedPoints.length - 1; i++) {
281
- const prev = transformedPoints[i - 1];
282
- const curr = transformedPoints[i];
283
- const next = transformedPoints[i + 1];
284
- const v1 = curr && prev ? [curr[0] - prev[0], curr[1] - prev[1]] : [0, 0];
285
- const v2 = next && curr ? [next[0] - curr[0], next[1] - curr[1]] : [0, 0];
286
- const l1 = Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1]);
287
- const l2 = Math.sqrt(v2[0] * v2[0] + v2[1] * v2[1]);
288
- if (l1 !== 0) {
289
- v1[0] /= l1;
290
- v1[1] /= l1;
291
- }
292
- if (l2 !== 0) {
293
- v2[0] /= l2;
294
- v2[1] /= l2;
295
- }
296
- const radius = Math.min(cornerRadius, Math.min(l1, l2) / 2);
297
- const p1 = [curr[0] - v1[0] * radius, curr[1] - v1[1] * radius];
298
- const p2 = [curr[0] + v2[0] * radius, curr[1] + v2[1] * radius];
299
- pathCommands.push(`L ${p1[0]} ${p1[1]}`);
300
- pathCommands.push(`A ${radius} ${radius} 0 0 1 ${p2[0]} ${p2[1]}`);
301
- }
302
- const lastPoint = transformedPoints[transformedPoints.length - 1];
303
- pathCommands.push(`L ${lastPoint[0]} ${lastPoint[1]}`);
304
- return {
305
- name: "path",
306
- type: "element",
307
- attributes: {
308
- class: "pcb-trace",
309
- d: pathCommands.join(" "),
310
- "stroke-width": trace.stroke_width ? (trace.stroke_width * Math.abs(transform.a)).toString() : "0.3",
311
- "stroke-linecap": "round",
312
- "stroke-linejoin": "round"
313
- }
314
- };
315
- }
316
303
  function createPcbSilkscreenPath(silkscreenPath, transform) {
317
304
  if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null;
318
305
  let path = silkscreenPath.route.map((point, index) => {
319
- const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [point.x, point.y]);
306
+ const [x, y] = applyToPoint2(transform, [point.x, point.y]);
320
307
  return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
321
308
  }).join(" ");
322
309
  const firstPoint = silkscreenPath.route[0];
@@ -336,9 +323,9 @@ function createPcbSilkscreenPath(silkscreenPath, transform) {
336
323
  }
337
324
  };
338
325
  }
339
- function createPcbBoundary(transform, minX, minY, maxX, maxY) {
340
- const [x1, y1] = (0, import_transformation_matrix.applyToPoint)(transform, [minX, minY]);
341
- const [x2, y2] = (0, import_transformation_matrix.applyToPoint)(transform, [maxX, maxY]);
326
+ function createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY) {
327
+ const [x1, y1] = applyToPoint2(transform, [minX, minY]);
328
+ const [x2, y2] = applyToPoint2(transform, [maxX, maxY]);
342
329
  const width = Math.abs(x2 - x1);
343
330
  const height = Math.abs(y2 - y1);
344
331
  const x = Math.min(x1, x2);
@@ -346,6 +333,8 @@ function createPcbBoundary(transform, minX, minY, maxX, maxY) {
346
333
  return {
347
334
  name: "rect",
348
335
  type: "element",
336
+ value: "",
337
+ children: [],
349
338
  attributes: {
350
339
  class: "pcb-boundary",
351
340
  x: x.toString(),
@@ -357,8 +346,8 @@ function createPcbBoundary(transform, minX, minY, maxX, maxY) {
357
346
  }
358
347
 
359
348
  // src/lib/circuit-to-schematic-svg.ts
360
- var import_schematic_symbols = require("schematic-symbols");
361
- var import_svgson2 = require("svgson");
349
+ import { getSvg, symbols } from "schematic-symbols";
350
+ import { parseSync, stringify as stringify3 } from "svgson";
362
351
  function circuitJsonToSchematicSvg(soup) {
363
352
  let minX = Number.POSITIVE_INFINITY;
364
353
  let minY = Number.POSITIVE_INFINITY;
@@ -452,7 +441,7 @@ function circuitJsonToSchematicSvg(soup) {
452
441
  ...svgChildren
453
442
  ]
454
443
  };
455
- return (0, import_svgson2.stringify)({ value: "", ...svgObject });
444
+ return stringify3({ value: "", ...svgObject });
456
445
  function updateBounds(center, size, rotation) {
457
446
  const corners = [
458
447
  { x: -size.width / 2, y: -size.height / 2 },
@@ -473,14 +462,14 @@ function circuitJsonToSchematicSvg(soup) {
473
462
  function createSchematicComponent(center, size, rotation, symbolName) {
474
463
  const transform = `translate(${center.x}, ${center.y}) rotate(${rotation * 180 / Math.PI})`;
475
464
  if (symbolName) {
476
- const symbol = import_schematic_symbols.symbols[symbolName];
465
+ const symbol = symbols[symbolName];
477
466
  const paths = symbol.primitives.filter((p) => p.type === "path");
478
467
  const updatedSymbol = {
479
468
  ...symbol,
480
469
  primitives: paths
481
470
  };
482
- const svg = (0, import_svgson2.parseSync)(
483
- (0, import_schematic_symbols.getSvg)(updatedSymbol, {
471
+ const svg = parseSync(
472
+ getSvg(updatedSymbol, {
484
473
  width: size.width,
485
474
  height: size.height
486
475
  })
@@ -656,9 +645,8 @@ function getTextAnchor(anchor) {
656
645
  return "middle";
657
646
  }
658
647
  }
659
- // Annotate the CommonJS export names for ESM import in node:
660
- 0 && (module.exports = {
648
+ export {
661
649
  circuitJsonToPcbSvg,
662
650
  circuitJsonToSchematicSvg
663
- });
651
+ };
664
652
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/circuit-to-pcb-svg.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["export * from \"./lib\";\n\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { type INode, stringify } from \"svgson\"\nimport { applyToPoint, compose, scale, translate } from \"transformation-matrix\"\n\ninterface SvgObject {\n name: string\n type: \"element\" | \"text\"\n attributes?: { [key: string]: string }\n children?: SvgObject[]\n value?: string\n}\n\ninterface PointObjectNotation {\n x: number\n y: number\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): 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 all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const traceElements = soup\n .filter((item) => item.type === \"pcb_trace\")\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n const holeElements = soup\n .filter((item) => item.type === \"pcb_plated_hole\")\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n const silkscreenElements = soup\n .filter((item) => item.type === \"pcb_silkscreen_path\")\n .map((item) => createPcbSilkscreenPath(item, transform))\n .filter((element) => element !== null)\n\n const otherElements = soup\n .filter(\n (item) =>\n ![\"pcb_trace\", \"pcb_plated_hole\", \"pcb_silkscreen_path\"].includes(\n item.type,\n ),\n )\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { stroke: rgb(200, 52, 52); stroke-width: ${strokeWidth}; fill: none; }\n .pcb-hole-outer { fill: rgb(200, 52, 52); }\n .pcb-hole-inner { fill: rgb(255, 38, 226); }\n .pcb-pad { fill: rgb(200, 52, 52); }\n .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }\n .pcb-silkscreen { fill: none; }\n .pcb-silkscreen-top { stroke: #f2eda1; }\n .pcb-silkscreen-bottom { stroke: #f2eda1; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n createPcbBoundary(transform, minX, minY, maxX, maxY),\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"other-elements\" },\n children: otherElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"traces\" },\n children: traceElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"holes\" },\n children: holeElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"silkscreen\" },\n children: silkscreenElements,\n },\n ].filter((child) => child !== null),\n }\n\n try {\n return stringify(svgObject as INode)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\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\nfunction createSvgElement(item: AnySoupElement, transform: any): any {\n switch (item.type) {\n case \"pcb_component\":\n return createPcbComponent(item, transform)\n case \"pcb_trace\":\n return createPcbTrace(item, transform)\n case \"pcb_plated_hole\":\n return createPcbHole(item, transform)\n case \"pcb_smtpad\":\n return createPcbSMTPad(item, transform)\n default:\n return null\n }\n}\n\nfunction createPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledOuterRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n const scaledInnerRadius = (hole.hole_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-outer\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledOuterRadius.toString(),\n },\n },\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-inner\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledInnerRadius.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbSMTPad(pad: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nfunction createPcbTrace(trace: any, transform: any): any {\n if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)\n return null\n\n const cornerRadius = 0.2 // Adjust this value to change the roundness of corners\n const pathCommands: string[] = []\n const transformedPoints = trace.route.map((point: any) =>\n applyToPoint(transform, [point.x, point.y]),\n )\n\n // Start path\n pathCommands.push(`M ${transformedPoints[0][0]} ${transformedPoints[0][1]}`)\n\n for (let i = 1; i < transformedPoints.length - 1; i++) {\n const prev = transformedPoints[i - 1]\n const curr = transformedPoints[i]\n const next = transformedPoints[i + 1]\n\n // Calculate vectors\n const v1 = curr && prev ? [curr[0] - prev[0], curr[1] - prev[1]] : [0, 0]\n const v2 = next && curr ? [next[0] - curr[0], next[1] - curr[1]] : [0, 0]\n\n // Normalize vectors\n const l1 = Math.sqrt((v1[0] as number) * (v1[0] as number) + (v1[1] as number) * (v1[1] as number));\n const l2 = Math.sqrt((v2[0] as number) * (v2[0] as number) + (v2[1] as number) * (v2[1] as number));\n if (l1 !== 0) {\n v1[0]! /= l1;\n v1[1]! /= l1;\n }\n if (l2 !== 0) {\n v2[0]! /= l2;\n v2[1]! /= l2;\n }\n\n // Calculate the corner points\n const radius = Math.min(cornerRadius, Math.min(l1, l2) / 2)\n const p1 = [curr[0] - v1[0]! * radius, curr[1] - v1[1]! * radius] \n const p2 = [curr[0] + v2[0]! * radius, curr[1] + v2[1]! * radius]\n\n // Add line to the start of the corner\n pathCommands.push(`L ${p1[0]} ${p1[1]}`)\n\n // Add the arc\n pathCommands.push(`A ${radius} ${radius} 0 0 1 ${p2[0]} ${p2[1]}`)\n }\n\n // Add final line to last point\n const lastPoint = transformedPoints[transformedPoints.length - 1]\n pathCommands.push(`L ${lastPoint[0]} ${lastPoint[1]}`)\n\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"pcb-trace\",\n d: pathCommands.join(\" \"),\n \"stroke-width\": trace.stroke_width\n ? (trace.stroke_width * Math.abs(transform.a)).toString()\n : \"0.3\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n },\n }\n}\n\nfunction createPcbSilkscreenPath(silkscreenPath: any, transform: any): any {\n if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null\n\n let path = silkscreenPath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = silkscreenPath.route[0]\n const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1]\n if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {\n path += \" Z\"\n }\n\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,\n d: path,\n \"stroke-width\": (\n silkscreenPath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": silkscreenPath.pcb_component_id,\n \"data-pcb-silkscreen-path-id\": silkscreenPath.pcb_silkscreen_path_id,\n },\n }\n}\n\nfunction createPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): any {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-boundary\",\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","import type { AnySoupElement } from \"@tscircuit/soup\";\nimport { getSvg, symbols } from \"schematic-symbols\";\nimport { parseSync, stringify } from \"svgson\";\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): 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 const portSize = 0.2;\n const portPositions = new Map();\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0);\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0);\n portPositions.set(item.schematic_port_id, item.center);\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0);\n }\n }\n\n const height = maxY - minY;\n const flipY = (y: number) => height - (y - minY) + minY;\n\n const svgChildren: any[] = [];\n\n // Process components\n const componentMap = new Map();\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\"\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n };\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n component.symbol_name\n );\n svgChildren.push(svg);\n componentMap.set(component.schematic_component_id, component);\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) };\n const svg = createSchematicPort(flippedCenter);\n svgChildren.push(svg);\n\n const component = componentMap.get(port.schematic_component_id);\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\"\n );\n svgChildren.push(line);\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions);\n if (svg) svgChildren.push(svg);\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) };\n const svg = createSchematicText(text, flippedPosition);\n svgChildren.push(svg);\n }\n\n const padding = 1;\n const width = maxX - minX + 2 * padding;\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`;\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n };\n\n return stringify({ value: \"\", ...svgObject });\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\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`;\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName];\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\");\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n };\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n })\n );\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\"\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\"\n );\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString();\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n };\n });\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox;\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\");\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number);\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\");\n }\n const [minX, minY, width = 0, height = 0] = viewBox;\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1);\n const scaleY = size.height / (height || 1);\n\n const scale = Math.min(scaleX, scaleY);\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`;\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n };\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n };\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2;\n const x = center.x - portSize / 2;\n const y = center.y - portSize / 2;\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n };\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y };\n const halfWidth = component.size.width / 2;\n const halfHeight = component.size.height / 2;\n\n let endX = portCenter.x;\n let endY = portCenter.y;\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth;\n break;\n case \"right\":\n endX = componentCenter.x + halfWidth;\n break;\n case \"up\":\n endY = componentCenter.y - halfHeight;\n break;\n case \"down\":\n endY = componentCenter.y + halfHeight;\n break;\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n };\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>\n): any {\n const edges = trace.edges;\n if (edges.length === 0) return null;\n\n let path = \"\";\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from;\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to;\n\n if (!fromPoint || !toPoint) {\n return;\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`;\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`;\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`;\n } else {\n path += ` L ${toCoord}`;\n }\n });\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id);\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0];\n const lastEdge = edges[edges.length - 1];\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to;\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`;\n path += ` M ${lastFromPoint} L ${finalCoord}`;\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null;\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number }\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\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 { circuitJsonToSchematicSvg };\n"],"mappings":"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","names":["import_svgson","scale"]}
1
+ {"version":3,"sources":["../src/lib/circuit-to-pcb-svg.ts","../src/utils/pairs.ts","../src/lib/svg-object-fns/create-svg-object-from-pcb-trace.ts","../src/lib/layer-name-to-color.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport {\n applyToPoint,\n compose,\n scale,\n translate,\n type Matrix,\n} from \"transformation-matrix\"\nimport { createSvgObjectsFromPcbTrace } from \"./svg-object-fns/create-svg-object-from-pcb-trace\"\n\ninterface PointObjectNotation {\n x: number\n y: number\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): 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 all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const traceElements = soup\n .filter((item) => item.type === \"pcb_trace\")\n .flatMap((item) => createSvgObjects(item, transform))\n\n const holeElements = soup\n .filter((item) => item.type === \"pcb_plated_hole\")\n .flatMap((item) => createSvgObjects(item, transform))\n\n const silkscreenElements = soup\n .filter((item) => item.type === \"pcb_silkscreen_path\")\n .flatMap((item) => createPcbSilkscreenPath(item, transform))\n\n const otherElements = soup\n .filter(\n (item) =>\n ![\"pcb_trace\", \"pcb_plated_hole\", \"pcb_silkscreen_path\"].includes(\n item.type,\n ),\n )\n .flatMap((item) => createSvgObjects(item, transform))\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n value: \"\",\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { fill: none; }\n .pcb-hole-outer { fill: rgb(200, 52, 52); }\n .pcb-hole-inner { fill: rgb(255, 38, 226); }\n .pcb-pad { fill: rgb(200, 52, 52); }\n .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }\n .pcb-silkscreen { fill: none; }\n .pcb-silkscreen-top { stroke: #f2eda1; }\n .pcb-silkscreen-bottom { stroke: #f2eda1; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY),\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"other-elements\" },\n children: otherElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"traces\" },\n children: traceElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"holes\" },\n children: holeElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"silkscreen\" },\n children: silkscreenElements,\n },\n ].filter((child): child is SvgObject => child !== null),\n }\n\n try {\n return stringify(svgObject as SvgObject)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\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\nfunction createSvgObjects(elm: AnySoupElement, transform: Matrix): SvgObject[] {\n switch (elm.type) {\n case \"pcb_component\":\n return [createSvgObjectsFromPcbComponent(elm, transform)].filter(Boolean)\n case \"pcb_trace\":\n return createSvgObjectsFromPcbTrace(elm, transform)\n case \"pcb_plated_hole\":\n return [createSvgObjectsFromPcbHole(elm, transform)].filter(Boolean)\n case \"pcb_smtpad\":\n return [createSvgObjectsFromSmtPad(elm, transform)].filter(Boolean)\n default:\n return []\n }\n}\n\nfunction createSvgObjectsFromPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSvgObjectsFromPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledOuterRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n const scaledInnerRadius = (hole.hole_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-outer\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledOuterRadius.toString(),\n },\n },\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-inner\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledInnerRadius.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSvgObjectsFromSmtPad(pad: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nfunction createPcbSilkscreenPath(silkscreenPath: any, transform: any): any {\n if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null\n\n let path = silkscreenPath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = silkscreenPath.route[0]\n const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1]\n if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {\n path += \" Z\"\n }\n\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,\n d: path,\n \"stroke-width\": (\n silkscreenPath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": silkscreenPath.pcb_component_id,\n \"data-pcb-silkscreen-path-id\": silkscreenPath.pcb_silkscreen_path_id,\n },\n }\n}\n\nfunction createSvgObjectFromPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): SvgObject {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n return {\n name: \"rect\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-boundary\",\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","/**\n * Return pairs of adjacent elements in an array.\n */\nexport function pairs<T>(arr: Array<T>): Array<[T, T]> {\n const result: Array<[T, T]> = []\n for (let i = 0; i < arr.length - 1; i++) {\n result.push([arr[i]!, arr[i + 1]!])\n }\n return result\n}\n","import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { pairs } from \"src/utils/pairs\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport { LAYER_NAME_TO_COLOR } from \"../layer-name-to-color\"\n\nexport function createSvgObjectsFromPcbTrace(\n trace: PCBTrace,\n transform: any,\n): SvgObject[] {\n if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)\n return []\n\n const segments = pairs(trace.route)\n const svgObjects: SvgObject[] = []\n\n for (const [start, end] of segments) {\n const startPoint = applyToPoint(transform, [start.x, start.y])\n const endPoint = applyToPoint(transform, [end.x, end.y])\n\n const layer =\n \"layer\" in start ? start.layer : \"layer\" in end ? end.layer : null\n if (!layer) continue\n\n const layerColor =\n LAYER_NAME_TO_COLOR[layer as keyof typeof LAYER_NAME_TO_COLOR] ?? \"white\"\n\n const traceWidth =\n \"width\" in start ? start.width : \"width\" in end ? end.width : null\n\n svgObjects.push({\n name: \"path\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-trace\",\n stroke: layerColor,\n d: `M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,\n \"stroke-width\": traceWidth\n ? (traceWidth * Math.abs(transform.a)).toString()\n : \"0.3\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"shape-rendering\": \"crispEdges\",\n },\n })\n }\n return svgObjects\n}\n","/**\n * TODO use @tscircuit/pcb-colors when it's published\n */\nexport const LAYER_NAME_TO_COLOR = {\n top: \"rgb(200, 52, 52)\",\n bottom: \"rgb(77, 127, 196)\",\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { getSvg, symbols } from \"schematic-symbols\"\nimport { parseSync, stringify } from \"svgson\"\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): 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 const portSize = 0.2\n const portPositions = new Map()\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0)\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0)\n portPositions.set(item.schematic_port_id, item.center)\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0)\n }\n }\n\n const height = maxY - minY\n const flipY = (y: number) => height - (y - minY) + minY\n\n const svgChildren: any[] = []\n\n // Process components\n const componentMap = new Map()\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\",\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n }\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n (component as any).symbol_name,\n )\n svgChildren.push(svg)\n componentMap.set(component.schematic_component_id, component)\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) }\n const svg = createSchematicPort(flippedCenter)\n svgChildren.push(svg)\n\n const component = componentMap.get(port.schematic_component_id)\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\",\n )\n svgChildren.push(line)\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions)\n if (svg) svgChildren.push(svg)\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) }\n const svg = createSchematicText(text, flippedPosition)\n svgChildren.push(svg)\n }\n\n const padding = 1\n const width = maxX - minX + 2 * padding\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n }\n\n return stringify({ value: \"\", ...svgObject })\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) - corner.y * Math.sin(rotation) + center.x\n const rotatedY =\n corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + 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\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string,\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName]\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\")\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n }\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n }),\n )\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\",\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\",\n )\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString()\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n }\n })\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\")\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number)\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\")\n }\n const [minX, minY, width = 0, height = 0] = viewBox\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1)\n const scaleY = size.height / (height || 1)\n\n const scale = Math.min(scaleX, scaleY)\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n }\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2\n const x = center.x - portSize / 2\n const y = center.y - portSize / 2\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n }\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string,\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y }\n const halfWidth = component.size.width / 2\n const halfHeight = component.size.height / 2\n\n let endX = portCenter.x\n let endY = portCenter.y\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth\n break\n case \"right\":\n endX = componentCenter.x + halfWidth\n break\n case \"up\":\n endY = componentCenter.y - halfHeight\n break\n case \"down\":\n endY = componentCenter.y + halfHeight\n break\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n }\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>,\n): any {\n const edges = trace.edges\n if (edges.length === 0) return null\n\n let path = \"\"\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to\n\n if (!fromPoint || !toPoint) {\n return\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`\n } else {\n path += ` L ${toCoord}`\n }\n })\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id)\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0]\n const lastEdge = edges[edges.length - 1]\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`\n path += ` M ${lastFromPoint} L ${finalCoord}`\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number },\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\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 { circuitJsonToSchematicSvg }\n"],"mappings":"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","names":["stringify","applyToPoint","stringify","applyToPoint","stringify","scale"]}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "circuit-to-svg",
3
- "version": "0.0.19",
3
+ "type": "module",
4
+ "version": "0.0.21",
4
5
  "description": "Convert Circuit JSON to SVG",
5
6
  "main": "dist/index.js",
6
7
  "files": [
@@ -8,7 +9,7 @@
8
9
  ],
9
10
  "scripts": {
10
11
  "prepublish": "npm run build",
11
- "build": "tsup ./src/index.ts --dts --sourcemap",
12
+ "build": "tsup-node ./src/index.ts --format esm --dts --sourcemap",
12
13
  "format": "biome format . --write",
13
14
  "storybook": "storybook dev -p 6006",
14
15
  "build-storybook": "storybook build"
@@ -26,10 +27,12 @@
26
27
  "@storybook/react-vite": "^8.2.5",
27
28
  "@storybook/test": "^8.2.5",
28
29
  "@tscircuit/plop": "^0.0.10",
30
+ "bun-match-svg": "^0.0.3",
29
31
  "esbuild": "^0.20.2",
30
32
  "storybook": "^8.2.5",
31
33
  "tsup": "^8.0.2",
32
- "typescript": "^5.4.5"
34
+ "typescript": "^5.4.5",
35
+ "vite-tsconfig-paths": "^5.0.1"
33
36
  },
34
37
  "peerDependencies": {
35
38
  "@tscircuit/soup": "^0.0.55"