circuit-to-svg 0.0.207 → 0.0.209

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.d.ts CHANGED
@@ -285,14 +285,6 @@ declare function convertCircuitJsonToSchematicSvg(circuitJson: AnyCircuitElement
285
285
  */
286
286
  declare const circuitJsonToSchematicSvg: typeof convertCircuitJsonToSchematicSvg;
287
287
 
288
- interface Options {
289
- layer: "top" | "bottom";
290
- width?: number;
291
- height?: number;
292
- includeVersion?: boolean;
293
- }
294
- declare function convertCircuitJsonToSolderPasteMask(circuitJson: AnyCircuitElement[], options: Options): string;
295
-
296
288
  type ExperimentType = string;
297
289
  interface SimulationExperimentElement {
298
290
  type: "simulation_experiment";
@@ -315,6 +307,26 @@ interface SimulationTransientVoltageGraphElement {
315
307
  }
316
308
  type CircuitJsonWithSimulation = AnyCircuitElement | SimulationExperimentElement | SimulationTransientVoltageGraphElement;
317
309
 
310
+ interface ConvertSchematicSimulationParams {
311
+ circuitJson: CircuitJsonWithSimulation[];
312
+ simulation_experiment_id: string;
313
+ simulation_transient_voltage_graph_ids?: string[];
314
+ width?: number;
315
+ height?: number;
316
+ schematicHeightRatio?: number;
317
+ schematicOptions?: Omit<Parameters<typeof convertCircuitJsonToSchematicSvg>[1], "width" | "height" | "includeVersion">;
318
+ includeVersion?: boolean;
319
+ }
320
+ declare function convertCircuitJsonToSchematicSimulationSvg({ circuitJson, simulation_experiment_id, simulation_transient_voltage_graph_ids, width, height, schematicHeightRatio, schematicOptions, includeVersion, }: ConvertSchematicSimulationParams): string;
321
+
322
+ interface Options {
323
+ layer: "top" | "bottom";
324
+ width?: number;
325
+ height?: number;
326
+ includeVersion?: boolean;
327
+ }
328
+ declare function convertCircuitJsonToSolderPasteMask(circuitJson: AnyCircuitElement[], options: Options): string;
329
+
318
330
  interface ConvertSimulationGraphParams {
319
331
  circuitJson: CircuitJsonWithSimulation[];
320
332
  simulation_experiment_id: string;
@@ -335,4 +347,4 @@ declare const createSvgObjectsForSchComponentPortHovers: ({ component, transform
335
347
  circuitJson: AnyCircuitElement[];
336
348
  }) => INode[];
337
349
 
338
- export { type AssemblySvgContext, CIRCUIT_TO_SVG_VERSION, type ColorMap, type ColorOverrides, type PcbColorMap, type PcbColorOverrides, type PcbContext, type PinoutSvgContext, circuitJsonToPcbSvg, circuitJsonToSchematicSvg, convertCircuitJsonToAssemblySvg, convertCircuitJsonToPcbSvg, convertCircuitJsonToPinoutSvg, convertCircuitJsonToSchematicSvg, convertCircuitJsonToSimulationGraphSvg, convertCircuitJsonToSolderPasteMask, createSvgObjectsForSchComponentPortHovers, getSoftwareUsedString };
350
+ export { type AssemblySvgContext, CIRCUIT_TO_SVG_VERSION, type ColorMap, type ColorOverrides, type PcbColorMap, type PcbColorOverrides, type PcbContext, type PinoutSvgContext, circuitJsonToPcbSvg, circuitJsonToSchematicSvg, convertCircuitJsonToAssemblySvg, convertCircuitJsonToPcbSvg, convertCircuitJsonToPinoutSvg, convertCircuitJsonToSchematicSimulationSvg, convertCircuitJsonToSchematicSvg, convertCircuitJsonToSimulationGraphSvg, convertCircuitJsonToSolderPasteMask, createSvgObjectsForSchComponentPortHovers, getSoftwareUsedString };
package/dist/index.js CHANGED
@@ -1783,7 +1783,7 @@ function getSoftwareUsedString(circuitJson) {
1783
1783
  var package_default = {
1784
1784
  name: "circuit-to-svg",
1785
1785
  type: "module",
1786
- version: "0.0.206",
1786
+ version: "0.0.208",
1787
1787
  description: "Convert Circuit JSON to SVG",
1788
1788
  main: "dist/index.js",
1789
1789
  files: [
@@ -7933,249 +7933,11 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
7933
7933
  }
7934
7934
  var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
7935
7935
 
7936
- // lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
7937
- import { stringify as stringify5 } from "svgson";
7938
- import {
7939
- applyToPoint as applyToPoint60,
7940
- compose as compose14,
7941
- scale as scale9,
7942
- translate as translate14
7943
- } from "transformation-matrix";
7944
-
7945
- // lib/pcb/svg-object-fns/convert-circuit-json-to-solder-paste-mask.ts
7946
- import { applyToPoint as applyToPoint59 } from "transformation-matrix";
7947
- function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
7948
- const { transform, layer: layerFilter } = ctx;
7949
- if (layerFilter && solderPaste.layer !== layerFilter) return [];
7950
- const [x, y] = applyToPoint59(transform, [solderPaste.x, solderPaste.y]);
7951
- if (solderPaste.shape === "rect" || solderPaste.shape === "rotated_rect") {
7952
- const width = solderPaste.width * Math.abs(transform.a);
7953
- const height = solderPaste.height * Math.abs(transform.d);
7954
- if (solderPaste.shape === "rotated_rect" && solderPaste.ccw_rotation) {
7955
- return [
7956
- {
7957
- name: "rect",
7958
- type: "element",
7959
- attributes: {
7960
- class: "pcb-solder-paste",
7961
- fill: solderPasteLayerNameToColor(solderPaste.layer),
7962
- x: (-width / 2).toString(),
7963
- y: (-height / 2).toString(),
7964
- width: width.toString(),
7965
- height: height.toString(),
7966
- transform: `translate(${x} ${y}) rotate(${-solderPaste.ccw_rotation})`
7967
- }
7968
- }
7969
- ];
7970
- }
7971
- return [
7972
- {
7973
- name: "rect",
7974
- type: "element",
7975
- attributes: {
7976
- class: "pcb-solder-paste",
7977
- fill: solderPasteLayerNameToColor(solderPaste.layer),
7978
- x: (x - width / 2).toString(),
7979
- y: (y - height / 2).toString(),
7980
- width: width.toString(),
7981
- height: height.toString()
7982
- }
7983
- }
7984
- ];
7985
- }
7986
- if (solderPaste.shape === "pill") {
7987
- const width = solderPaste.width * Math.abs(transform.a);
7988
- const height = solderPaste.height * Math.abs(transform.d);
7989
- const radius = solderPaste.radius * Math.abs(transform.a);
7990
- return [
7991
- {
7992
- name: "rect",
7993
- type: "element",
7994
- attributes: {
7995
- class: "pcb-solder-paste",
7996
- fill: solderPasteLayerNameToColor(solderPaste.layer),
7997
- x: (x - width / 2).toString(),
7998
- y: (y - height / 2).toString(),
7999
- width: width.toString(),
8000
- height: height.toString(),
8001
- rx: radius.toString()
8002
- }
8003
- }
8004
- ];
8005
- }
8006
- if (solderPaste.shape === "circle") {
8007
- const radius = solderPaste.radius * Math.abs(transform.a);
8008
- return [
8009
- {
8010
- name: "circle",
8011
- type: "element",
8012
- attributes: {
8013
- class: "pcb-solder-paste",
8014
- fill: solderPasteLayerNameToColor(solderPaste.layer),
8015
- cx: x.toString(),
8016
- cy: y.toString(),
8017
- r: radius.toString()
8018
- }
8019
- }
8020
- ];
8021
- }
8022
- }
8023
-
8024
- // lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
8025
- var OBJECT_ORDER4 = [
8026
- "pcb_board",
8027
- "pcb_solder_paste"
8028
- ];
8029
- function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
8030
- let minX = Number.POSITIVE_INFINITY;
8031
- let minY = Number.POSITIVE_INFINITY;
8032
- let maxX = Number.NEGATIVE_INFINITY;
8033
- let maxY = Number.NEGATIVE_INFINITY;
8034
- const filteredCircuitJson = circuitJson.filter(
8035
- (elm) => elm.type === "pcb_board" || elm.type === "pcb_solder_paste" && elm.layer === options.layer
8036
- );
8037
- for (const item of filteredCircuitJson) {
8038
- if (item.type === "pcb_board") {
8039
- if (item.outline && Array.isArray(item.outline) && item.outline.length >= 3) {
8040
- updateBoundsToIncludeOutline(item.outline);
8041
- } else if ("center" in item && "width" in item && "height" in item) {
8042
- updateBounds(item.center, item.width, item.height);
8043
- }
8044
- } else if (item.type === "pcb_solder_paste" && "x" in item && "y" in item) {
8045
- updateBounds({ x: item.x, y: item.y }, 0, 0);
8046
- }
8047
- }
8048
- const padding = 1;
8049
- const circuitWidth = maxX - minX + 2 * padding;
8050
- const circuitHeight = maxY - minY + 2 * padding;
8051
- const svgWidth = options.width ?? 800;
8052
- const svgHeight = options.height ?? 600;
8053
- const scaleX = svgWidth / circuitWidth;
8054
- const scaleY = svgHeight / circuitHeight;
8055
- const scaleFactor = Math.min(scaleX, scaleY);
8056
- const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
8057
- const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
8058
- const transform = compose14(
8059
- translate14(
8060
- offsetX - minX * scaleFactor + padding * scaleFactor,
8061
- svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
8062
- ),
8063
- scale9(scaleFactor, -scaleFactor)
8064
- // Flip in y-direction
8065
- );
8066
- const ctx = {
8067
- transform,
8068
- layer: options.layer,
8069
- colorMap: DEFAULT_PCB_COLOR_MAP
8070
- };
8071
- const svgObjects = filteredCircuitJson.sort(
8072
- (a, b) => (OBJECT_ORDER4.indexOf(b.type) ?? 9999) - (OBJECT_ORDER4.indexOf(a.type) ?? 9999)
8073
- ).flatMap((item) => createSvgObjects4({ elm: item, ctx }));
8074
- const softwareUsedString = getSoftwareUsedString(circuitJson);
8075
- const version = CIRCUIT_TO_SVG_VERSION;
8076
- const svgObject = {
8077
- name: "svg",
8078
- type: "element",
8079
- attributes: {
8080
- xmlns: "http://www.w3.org/2000/svg",
8081
- width: svgWidth.toString(),
8082
- height: svgHeight.toString(),
8083
- ...softwareUsedString && {
8084
- "data-software-used-string": softwareUsedString
8085
- },
8086
- ...options.includeVersion && {
8087
- "data-circuit-to-svg-version": version
8088
- }
8089
- },
8090
- value: "",
8091
- children: [
8092
- {
8093
- name: "style",
8094
- type: "element",
8095
- children: [
8096
- {
8097
- type: "text",
8098
- value: ""
8099
- }
8100
- ]
8101
- },
8102
- {
8103
- name: "rect",
8104
- type: "element",
8105
- attributes: {
8106
- class: "boundary",
8107
- x: "0",
8108
- y: "0",
8109
- fill: "#000",
8110
- width: svgWidth.toString(),
8111
- height: svgHeight.toString()
8112
- }
8113
- },
8114
- createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY),
8115
- ...svgObjects
8116
- ].filter((child) => child !== null)
8117
- };
8118
- try {
8119
- return stringify5(svgObject);
8120
- } catch (error) {
8121
- console.error("Error stringifying SVG object:", error);
8122
- throw error;
8123
- }
8124
- function updateBounds(center, width, height) {
8125
- const halfWidth = width / 2;
8126
- const halfHeight = height / 2;
8127
- minX = Math.min(minX, center.x - halfWidth);
8128
- minY = Math.min(minY, center.y - halfHeight);
8129
- maxX = Math.max(maxX, center.x + halfWidth);
8130
- maxY = Math.max(maxY, center.y + halfHeight);
8131
- }
8132
- function updateBoundsToIncludeOutline(outline) {
8133
- for (const point of outline) {
8134
- minX = Math.min(minX, point.x);
8135
- minY = Math.min(minY, point.y);
8136
- maxX = Math.max(maxX, point.x);
8137
- maxY = Math.max(maxY, point.y);
8138
- }
8139
- }
8140
- }
8141
- function createSvgObjects4({ elm, ctx }) {
8142
- const { transform } = ctx;
8143
- switch (elm.type) {
8144
- case "pcb_board":
8145
- return createSvgObjectsFromPcbBoard(elm, ctx);
8146
- case "pcb_solder_paste":
8147
- return createSvgObjectsFromSolderPaste(elm, ctx);
8148
- default:
8149
- return [];
8150
- }
8151
- }
8152
- function createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY) {
8153
- const [x1, y1] = applyToPoint60(transform, [minX, minY]);
8154
- const [x2, y2] = applyToPoint60(transform, [maxX, maxY]);
8155
- const width = Math.abs(x2 - x1);
8156
- const height = Math.abs(y2 - y1);
8157
- const x = Math.min(x1, x2);
8158
- const y = Math.min(y1, y2);
8159
- return {
8160
- name: "rect",
8161
- type: "element",
8162
- value: "",
8163
- children: [],
8164
- attributes: {
8165
- class: "pcb-boundary",
8166
- fill: "none",
8167
- stroke: "#fff",
8168
- "stroke-width": "0.3",
8169
- x: x.toString(),
8170
- y: y.toString(),
8171
- width: width.toString(),
8172
- height: height.toString()
8173
- }
8174
- };
8175
- }
7936
+ // lib/convert-circuit-json-to-schematic-simulation-svg.ts
7937
+ import { stringify as stringify6, parseSync as parseSync3 } from "svgson";
8176
7938
 
8177
7939
  // lib/sim/convert-circuit-json-to-simulation-graph-svg.ts
8178
- import { stringify as stringify6 } from "svgson";
7940
+ import { stringify as stringify5 } from "svgson";
8179
7941
 
8180
7942
  // lib/sim/types.ts
8181
7943
  function isSimulationTransientVoltageGraph(value) {
@@ -8284,7 +8046,7 @@ function convertCircuitJsonToSimulationGraphSvg({
8284
8046
  },
8285
8047
  svgChildren
8286
8048
  );
8287
- return stringify6(svgObject);
8049
+ return stringify5(svgObject);
8288
8050
  }
8289
8051
  function prepareSimulationGraphs(graphs) {
8290
8052
  const palette = Array.isArray(colorMap.palette) ? colorMap.palette : [];
@@ -8702,6 +8464,360 @@ function textNode(value) {
8702
8464
  children: []
8703
8465
  };
8704
8466
  }
8467
+
8468
+ // lib/convert-circuit-json-to-schematic-simulation-svg.ts
8469
+ var DEFAULT_WIDTH2 = 1200;
8470
+ var DEFAULT_HEIGHT2 = 1200;
8471
+ var DEFAULT_SCHEMATIC_RATIO = 0.55;
8472
+ function convertCircuitJsonToSchematicSimulationSvg({
8473
+ circuitJson,
8474
+ simulation_experiment_id,
8475
+ simulation_transient_voltage_graph_ids,
8476
+ width = DEFAULT_WIDTH2,
8477
+ height = DEFAULT_HEIGHT2,
8478
+ schematicHeightRatio = DEFAULT_SCHEMATIC_RATIO,
8479
+ schematicOptions,
8480
+ includeVersion
8481
+ }) {
8482
+ const schematicElements = circuitJson.filter(
8483
+ (element) => !isSimulationExperiment(element) && !isSimulationTransientVoltageGraph(element)
8484
+ );
8485
+ const clampedRatio = clamp01(schematicHeightRatio);
8486
+ const rawSchematicHeight = Math.max(1, height * clampedRatio);
8487
+ const rawSimulationHeight = Math.max(1, height - rawSchematicHeight);
8488
+ const totalRawHeight = rawSchematicHeight + rawSimulationHeight;
8489
+ const scale10 = totalRawHeight === 0 ? 1 : height / totalRawHeight;
8490
+ const schematicHeight = rawSchematicHeight * scale10;
8491
+ const simulationHeight = rawSimulationHeight * scale10;
8492
+ const schematicSvg = convertCircuitJsonToSchematicSvg(schematicElements, {
8493
+ ...schematicOptions,
8494
+ width,
8495
+ height: schematicHeight,
8496
+ includeVersion: false
8497
+ });
8498
+ const simulationSvg = convertCircuitJsonToSimulationGraphSvg({
8499
+ circuitJson,
8500
+ simulation_experiment_id,
8501
+ simulation_transient_voltage_graph_ids,
8502
+ width,
8503
+ height: simulationHeight,
8504
+ includeVersion: false
8505
+ });
8506
+ const schematicNode = ensureElementNode(parseSync3(schematicSvg));
8507
+ const simulationNode = ensureElementNode(parseSync3(simulationSvg));
8508
+ const combinedChildren = [];
8509
+ combinedChildren.push(
8510
+ translateNestedSvg(schematicNode, 0, 0, width, schematicHeight)
8511
+ );
8512
+ combinedChildren.push(
8513
+ translateNestedSvg(
8514
+ simulationNode,
8515
+ 0,
8516
+ schematicHeight,
8517
+ width,
8518
+ simulationHeight
8519
+ )
8520
+ );
8521
+ const softwareUsedString = getSoftwareUsedString(schematicElements);
8522
+ const svgObject = {
8523
+ name: "svg",
8524
+ type: "element",
8525
+ value: "",
8526
+ attributes: {
8527
+ xmlns: "http://www.w3.org/2000/svg",
8528
+ width: formatNumber2(width),
8529
+ height: formatNumber2(height),
8530
+ viewBox: `0 0 ${formatNumber2(width)} ${formatNumber2(height)}`,
8531
+ "data-simulation-experiment-id": simulation_experiment_id,
8532
+ ...softwareUsedString && {
8533
+ "data-software-used-string": softwareUsedString
8534
+ },
8535
+ ...includeVersion && {
8536
+ "data-circuit-to-svg-version": CIRCUIT_TO_SVG_VERSION
8537
+ }
8538
+ },
8539
+ children: combinedChildren
8540
+ };
8541
+ return stringify6(svgObject);
8542
+ }
8543
+ function translateNestedSvg(node, x, y, width, height) {
8544
+ const clone = cloneSvgObject(node);
8545
+ clone.attributes = {
8546
+ ...clone.attributes,
8547
+ x: formatNumber2(x),
8548
+ y: formatNumber2(y),
8549
+ width: formatNumber2(width),
8550
+ height: formatNumber2(height)
8551
+ };
8552
+ delete clone.attributes.xmlns;
8553
+ return clone;
8554
+ }
8555
+ function ensureElementNode(node) {
8556
+ if (node.type !== "element") {
8557
+ throw new Error("Expected SVG root element to be of type 'element'");
8558
+ }
8559
+ return node;
8560
+ }
8561
+ function cloneSvgObject(node) {
8562
+ return {
8563
+ ...node,
8564
+ attributes: { ...node.attributes ?? {} },
8565
+ children: node.children?.map(cloneSvgObject) ?? []
8566
+ };
8567
+ }
8568
+ function clamp01(value) {
8569
+ if (!Number.isFinite(value)) return DEFAULT_SCHEMATIC_RATIO;
8570
+ if (value <= 0) return 0;
8571
+ if (value >= 1) return 1;
8572
+ return value;
8573
+ }
8574
+ function formatNumber2(value) {
8575
+ if (!Number.isFinite(value)) return "0";
8576
+ const rounded = Number.parseFloat(value.toFixed(6));
8577
+ if (Number.isInteger(rounded)) return rounded.toString();
8578
+ return rounded.toString();
8579
+ }
8580
+
8581
+ // lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
8582
+ import { stringify as stringify7 } from "svgson";
8583
+ import {
8584
+ applyToPoint as applyToPoint60,
8585
+ compose as compose14,
8586
+ scale as scale9,
8587
+ translate as translate14
8588
+ } from "transformation-matrix";
8589
+
8590
+ // lib/pcb/svg-object-fns/convert-circuit-json-to-solder-paste-mask.ts
8591
+ import { applyToPoint as applyToPoint59 } from "transformation-matrix";
8592
+ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8593
+ const { transform, layer: layerFilter } = ctx;
8594
+ if (layerFilter && solderPaste.layer !== layerFilter) return [];
8595
+ const [x, y] = applyToPoint59(transform, [solderPaste.x, solderPaste.y]);
8596
+ if (solderPaste.shape === "rect" || solderPaste.shape === "rotated_rect") {
8597
+ const width = solderPaste.width * Math.abs(transform.a);
8598
+ const height = solderPaste.height * Math.abs(transform.d);
8599
+ if (solderPaste.shape === "rotated_rect" && solderPaste.ccw_rotation) {
8600
+ return [
8601
+ {
8602
+ name: "rect",
8603
+ type: "element",
8604
+ attributes: {
8605
+ class: "pcb-solder-paste",
8606
+ fill: solderPasteLayerNameToColor(solderPaste.layer),
8607
+ x: (-width / 2).toString(),
8608
+ y: (-height / 2).toString(),
8609
+ width: width.toString(),
8610
+ height: height.toString(),
8611
+ transform: `translate(${x} ${y}) rotate(${-solderPaste.ccw_rotation})`
8612
+ }
8613
+ }
8614
+ ];
8615
+ }
8616
+ return [
8617
+ {
8618
+ name: "rect",
8619
+ type: "element",
8620
+ attributes: {
8621
+ class: "pcb-solder-paste",
8622
+ fill: solderPasteLayerNameToColor(solderPaste.layer),
8623
+ x: (x - width / 2).toString(),
8624
+ y: (y - height / 2).toString(),
8625
+ width: width.toString(),
8626
+ height: height.toString()
8627
+ }
8628
+ }
8629
+ ];
8630
+ }
8631
+ if (solderPaste.shape === "pill") {
8632
+ const width = solderPaste.width * Math.abs(transform.a);
8633
+ const height = solderPaste.height * Math.abs(transform.d);
8634
+ const radius = solderPaste.radius * Math.abs(transform.a);
8635
+ return [
8636
+ {
8637
+ name: "rect",
8638
+ type: "element",
8639
+ attributes: {
8640
+ class: "pcb-solder-paste",
8641
+ fill: solderPasteLayerNameToColor(solderPaste.layer),
8642
+ x: (x - width / 2).toString(),
8643
+ y: (y - height / 2).toString(),
8644
+ width: width.toString(),
8645
+ height: height.toString(),
8646
+ rx: radius.toString()
8647
+ }
8648
+ }
8649
+ ];
8650
+ }
8651
+ if (solderPaste.shape === "circle") {
8652
+ const radius = solderPaste.radius * Math.abs(transform.a);
8653
+ return [
8654
+ {
8655
+ name: "circle",
8656
+ type: "element",
8657
+ attributes: {
8658
+ class: "pcb-solder-paste",
8659
+ fill: solderPasteLayerNameToColor(solderPaste.layer),
8660
+ cx: x.toString(),
8661
+ cy: y.toString(),
8662
+ r: radius.toString()
8663
+ }
8664
+ }
8665
+ ];
8666
+ }
8667
+ }
8668
+
8669
+ // lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
8670
+ var OBJECT_ORDER4 = [
8671
+ "pcb_board",
8672
+ "pcb_solder_paste"
8673
+ ];
8674
+ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
8675
+ let minX = Number.POSITIVE_INFINITY;
8676
+ let minY = Number.POSITIVE_INFINITY;
8677
+ let maxX = Number.NEGATIVE_INFINITY;
8678
+ let maxY = Number.NEGATIVE_INFINITY;
8679
+ const filteredCircuitJson = circuitJson.filter(
8680
+ (elm) => elm.type === "pcb_board" || elm.type === "pcb_solder_paste" && elm.layer === options.layer
8681
+ );
8682
+ for (const item of filteredCircuitJson) {
8683
+ if (item.type === "pcb_board") {
8684
+ if (item.outline && Array.isArray(item.outline) && item.outline.length >= 3) {
8685
+ updateBoundsToIncludeOutline(item.outline);
8686
+ } else if ("center" in item && "width" in item && "height" in item) {
8687
+ updateBounds(item.center, item.width, item.height);
8688
+ }
8689
+ } else if (item.type === "pcb_solder_paste" && "x" in item && "y" in item) {
8690
+ updateBounds({ x: item.x, y: item.y }, 0, 0);
8691
+ }
8692
+ }
8693
+ const padding = 1;
8694
+ const circuitWidth = maxX - minX + 2 * padding;
8695
+ const circuitHeight = maxY - minY + 2 * padding;
8696
+ const svgWidth = options.width ?? 800;
8697
+ const svgHeight = options.height ?? 600;
8698
+ const scaleX = svgWidth / circuitWidth;
8699
+ const scaleY = svgHeight / circuitHeight;
8700
+ const scaleFactor = Math.min(scaleX, scaleY);
8701
+ const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
8702
+ const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
8703
+ const transform = compose14(
8704
+ translate14(
8705
+ offsetX - minX * scaleFactor + padding * scaleFactor,
8706
+ svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
8707
+ ),
8708
+ scale9(scaleFactor, -scaleFactor)
8709
+ // Flip in y-direction
8710
+ );
8711
+ const ctx = {
8712
+ transform,
8713
+ layer: options.layer,
8714
+ colorMap: DEFAULT_PCB_COLOR_MAP
8715
+ };
8716
+ const svgObjects = filteredCircuitJson.sort(
8717
+ (a, b) => (OBJECT_ORDER4.indexOf(b.type) ?? 9999) - (OBJECT_ORDER4.indexOf(a.type) ?? 9999)
8718
+ ).flatMap((item) => createSvgObjects4({ elm: item, ctx }));
8719
+ const softwareUsedString = getSoftwareUsedString(circuitJson);
8720
+ const version = CIRCUIT_TO_SVG_VERSION;
8721
+ const svgObject = {
8722
+ name: "svg",
8723
+ type: "element",
8724
+ attributes: {
8725
+ xmlns: "http://www.w3.org/2000/svg",
8726
+ width: svgWidth.toString(),
8727
+ height: svgHeight.toString(),
8728
+ ...softwareUsedString && {
8729
+ "data-software-used-string": softwareUsedString
8730
+ },
8731
+ ...options.includeVersion && {
8732
+ "data-circuit-to-svg-version": version
8733
+ }
8734
+ },
8735
+ value: "",
8736
+ children: [
8737
+ {
8738
+ name: "style",
8739
+ type: "element",
8740
+ children: [
8741
+ {
8742
+ type: "text",
8743
+ value: ""
8744
+ }
8745
+ ]
8746
+ },
8747
+ {
8748
+ name: "rect",
8749
+ type: "element",
8750
+ attributes: {
8751
+ class: "boundary",
8752
+ x: "0",
8753
+ y: "0",
8754
+ fill: "#000",
8755
+ width: svgWidth.toString(),
8756
+ height: svgHeight.toString()
8757
+ }
8758
+ },
8759
+ createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY),
8760
+ ...svgObjects
8761
+ ].filter((child) => child !== null)
8762
+ };
8763
+ try {
8764
+ return stringify7(svgObject);
8765
+ } catch (error) {
8766
+ console.error("Error stringifying SVG object:", error);
8767
+ throw error;
8768
+ }
8769
+ function updateBounds(center, width, height) {
8770
+ const halfWidth = width / 2;
8771
+ const halfHeight = height / 2;
8772
+ minX = Math.min(minX, center.x - halfWidth);
8773
+ minY = Math.min(minY, center.y - halfHeight);
8774
+ maxX = Math.max(maxX, center.x + halfWidth);
8775
+ maxY = Math.max(maxY, center.y + halfHeight);
8776
+ }
8777
+ function updateBoundsToIncludeOutline(outline) {
8778
+ for (const point of outline) {
8779
+ minX = Math.min(minX, point.x);
8780
+ minY = Math.min(minY, point.y);
8781
+ maxX = Math.max(maxX, point.x);
8782
+ maxY = Math.max(maxY, point.y);
8783
+ }
8784
+ }
8785
+ }
8786
+ function createSvgObjects4({ elm, ctx }) {
8787
+ const { transform } = ctx;
8788
+ switch (elm.type) {
8789
+ case "pcb_board":
8790
+ return createSvgObjectsFromPcbBoard(elm, ctx);
8791
+ case "pcb_solder_paste":
8792
+ return createSvgObjectsFromSolderPaste(elm, ctx);
8793
+ default:
8794
+ return [];
8795
+ }
8796
+ }
8797
+ function createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY) {
8798
+ const [x1, y1] = applyToPoint60(transform, [minX, minY]);
8799
+ const [x2, y2] = applyToPoint60(transform, [maxX, maxY]);
8800
+ const width = Math.abs(x2 - x1);
8801
+ const height = Math.abs(y2 - y1);
8802
+ const x = Math.min(x1, x2);
8803
+ const y = Math.min(y1, y2);
8804
+ return {
8805
+ name: "rect",
8806
+ type: "element",
8807
+ value: "",
8808
+ children: [],
8809
+ attributes: {
8810
+ class: "pcb-boundary",
8811
+ fill: "none",
8812
+ stroke: "#fff",
8813
+ "stroke-width": "0.3",
8814
+ x: x.toString(),
8815
+ y: y.toString(),
8816
+ width: width.toString(),
8817
+ height: height.toString()
8818
+ }
8819
+ };
8820
+ }
8705
8821
  export {
8706
8822
  CIRCUIT_TO_SVG_VERSION,
8707
8823
  circuitJsonToPcbSvg,
@@ -8709,6 +8825,7 @@ export {
8709
8825
  convertCircuitJsonToAssemblySvg,
8710
8826
  convertCircuitJsonToPcbSvg,
8711
8827
  convertCircuitJsonToPinoutSvg,
8828
+ convertCircuitJsonToSchematicSimulationSvg,
8712
8829
  convertCircuitJsonToSchematicSvg,
8713
8830
  convertCircuitJsonToSimulationGraphSvg,
8714
8831
  convertCircuitJsonToSolderPasteMask,