circuit-to-svg 0.0.124 → 0.0.125
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 +14 -7
- package/dist/index.js +238 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { AnyCircuitElement } from 'circuit-json';
|
|
2
2
|
|
|
3
|
-
interface Options$
|
|
3
|
+
interface Options$3 {
|
|
4
4
|
width?: number;
|
|
5
5
|
height?: number;
|
|
6
6
|
shouldDrawErrors?: boolean;
|
|
7
7
|
shouldDrawRatsNest?: boolean;
|
|
8
8
|
}
|
|
9
|
-
declare function convertCircuitJsonToPcbSvg(soup: AnyCircuitElement[], options?: Options$
|
|
9
|
+
declare function convertCircuitJsonToPcbSvg(soup: AnyCircuitElement[], options?: Options$3): string;
|
|
10
10
|
/**
|
|
11
11
|
* @deprecated use `convertCircuitJsonToPcbSvg` instead
|
|
12
12
|
*/
|
|
13
13
|
declare const circuitJsonToPcbSvg: typeof convertCircuitJsonToPcbSvg;
|
|
14
14
|
|
|
15
|
-
interface Options$
|
|
15
|
+
interface Options$2 {
|
|
16
16
|
width?: number;
|
|
17
17
|
height?: number;
|
|
18
18
|
}
|
|
19
|
-
declare function convertCircuitJsonToAssemblySvg(soup: AnyCircuitElement[], options?: Options$
|
|
19
|
+
declare function convertCircuitJsonToAssemblySvg(soup: AnyCircuitElement[], options?: Options$2): string;
|
|
20
20
|
|
|
21
21
|
declare const colorMap: {
|
|
22
22
|
"3d_viewer": {
|
|
@@ -181,7 +181,7 @@ type ColorMap = typeof colorMap;
|
|
|
181
181
|
type ColorOverrides = {
|
|
182
182
|
schematic?: Partial<ColorMap["schematic"]>;
|
|
183
183
|
};
|
|
184
|
-
interface Options {
|
|
184
|
+
interface Options$1 {
|
|
185
185
|
colorOverrides?: ColorOverrides;
|
|
186
186
|
width?: number;
|
|
187
187
|
height?: number;
|
|
@@ -195,10 +195,17 @@ interface Options {
|
|
|
195
195
|
label: string;
|
|
196
196
|
}>;
|
|
197
197
|
}
|
|
198
|
-
declare function convertCircuitJsonToSchematicSvg(circuitJson: AnyCircuitElement[], options?: Options): string;
|
|
198
|
+
declare function convertCircuitJsonToSchematicSvg(circuitJson: AnyCircuitElement[], options?: Options$1): string;
|
|
199
199
|
/**
|
|
200
200
|
* @deprecated use `convertCircuitJsonToSchematicSvg` instead
|
|
201
201
|
*/
|
|
202
202
|
declare const circuitJsonToSchematicSvg: typeof convertCircuitJsonToSchematicSvg;
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
interface Options {
|
|
205
|
+
layer: "top" | "bottom";
|
|
206
|
+
width?: number;
|
|
207
|
+
height?: number;
|
|
208
|
+
}
|
|
209
|
+
declare function convertCircuitJsonToSolderPasteMask(soup: AnyCircuitElement[], options: Options): string;
|
|
210
|
+
|
|
211
|
+
export { type ColorMap, type ColorOverrides, circuitJsonToPcbSvg, circuitJsonToSchematicSvg, convertCircuitJsonToAssemblySvg, convertCircuitJsonToPcbSvg, convertCircuitJsonToSchematicSvg, convertCircuitJsonToSolderPasteMask };
|
package/dist/index.js
CHANGED
|
@@ -773,6 +773,13 @@ var LAYER_NAME_TO_COLOR = {
|
|
|
773
773
|
function layerNameToColor(layerName) {
|
|
774
774
|
return LAYER_NAME_TO_COLOR[layerName] ?? "white";
|
|
775
775
|
}
|
|
776
|
+
var SOLDER_PASTE_LAYER_NAME_TO_COLOR = {
|
|
777
|
+
bottom: "rgb(105, 105, 105)",
|
|
778
|
+
top: "rgb(105, 105, 105)"
|
|
779
|
+
};
|
|
780
|
+
function solderPasteLayerNameToColor(layerName) {
|
|
781
|
+
return SOLDER_PASTE_LAYER_NAME_TO_COLOR[layerName] ?? "rgb(105, 105, 105)";
|
|
782
|
+
}
|
|
776
783
|
|
|
777
784
|
// lib/pcb/svg-object-fns/create-svg-objects-from-pcb-trace.ts
|
|
778
785
|
function createSvgObjectsFromPcbTrace(trace, transform) {
|
|
@@ -4093,8 +4100,8 @@ var ninePointAnchorToDominantBaseline = {
|
|
|
4093
4100
|
middle_bottom: "hanging"
|
|
4094
4101
|
};
|
|
4095
4102
|
function getTextOffsets(pathRotation, transform) {
|
|
4096
|
-
const
|
|
4097
|
-
const baseOffset =
|
|
4103
|
+
const scale9 = Math.abs(transform.a);
|
|
4104
|
+
const baseOffset = scale9 * 0.1;
|
|
4098
4105
|
const rotationOffsetMap = {
|
|
4099
4106
|
"0": { x: baseOffset * 0.8, y: -baseOffset },
|
|
4100
4107
|
// Left
|
|
@@ -4248,8 +4255,8 @@ var createSvgObjectsForSchNetLabelWithSymbol = ({
|
|
|
4248
4255
|
} else if (textValue === "{VAL}") {
|
|
4249
4256
|
textValue = "";
|
|
4250
4257
|
}
|
|
4251
|
-
const
|
|
4252
|
-
const baseOffset =
|
|
4258
|
+
const scale9 = Math.abs(realToScreenTransform.a);
|
|
4259
|
+
const baseOffset = scale9 * 0.1;
|
|
4253
4260
|
const rotationOffset = getTextOffsets(pathRotation, realToScreenTransform);
|
|
4254
4261
|
const offsetScreenPos = {
|
|
4255
4262
|
x: screenTextPos.x + rotationOffset.x,
|
|
@@ -4659,11 +4666,237 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
|
|
|
4659
4666
|
return stringify3(svgObject);
|
|
4660
4667
|
}
|
|
4661
4668
|
var circuitJsonToSchematicSvg = convertCircuitJsonToSchematicSvg;
|
|
4669
|
+
|
|
4670
|
+
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
4671
|
+
import { stringify as stringify4 } from "svgson";
|
|
4672
|
+
import {
|
|
4673
|
+
applyToPoint as applyToPoint38,
|
|
4674
|
+
compose as compose10,
|
|
4675
|
+
scale as scale8,
|
|
4676
|
+
translate as translate10
|
|
4677
|
+
} from "transformation-matrix";
|
|
4678
|
+
|
|
4679
|
+
// lib/pcb/svg-object-fns/convert-circuit-json-to-solder-paste-mask.ts
|
|
4680
|
+
import { applyToPoint as applyToPoint37 } from "transformation-matrix";
|
|
4681
|
+
function createSvgObjectsFromSolderPaste(solderPaste, transform) {
|
|
4682
|
+
const [x, y] = applyToPoint37(transform, [solderPaste.x, solderPaste.y]);
|
|
4683
|
+
if (solderPaste.shape === "rect" || solderPaste.shape === "rotated_rect") {
|
|
4684
|
+
const width = solderPaste.width * Math.abs(transform.a);
|
|
4685
|
+
const height = solderPaste.height * Math.abs(transform.d);
|
|
4686
|
+
if (solderPaste.shape === "rotated_rect" && solderPaste.ccw_rotation) {
|
|
4687
|
+
return [
|
|
4688
|
+
{
|
|
4689
|
+
name: "rect",
|
|
4690
|
+
type: "element",
|
|
4691
|
+
attributes: {
|
|
4692
|
+
class: "pcb-solder-paste",
|
|
4693
|
+
fill: solderPasteLayerNameToColor(solderPaste.layer),
|
|
4694
|
+
x: (-width / 2).toString(),
|
|
4695
|
+
y: (-height / 2).toString(),
|
|
4696
|
+
width: width.toString(),
|
|
4697
|
+
height: height.toString(),
|
|
4698
|
+
transform: `translate(${x} ${y}) rotate(${-solderPaste.ccw_rotation})`
|
|
4699
|
+
}
|
|
4700
|
+
}
|
|
4701
|
+
];
|
|
4702
|
+
}
|
|
4703
|
+
return [
|
|
4704
|
+
{
|
|
4705
|
+
name: "rect",
|
|
4706
|
+
type: "element",
|
|
4707
|
+
attributes: {
|
|
4708
|
+
class: "pcb-solder-paste",
|
|
4709
|
+
fill: solderPasteLayerNameToColor(solderPaste.layer),
|
|
4710
|
+
x: (x - width / 2).toString(),
|
|
4711
|
+
y: (y - height / 2).toString(),
|
|
4712
|
+
width: width.toString(),
|
|
4713
|
+
height: height.toString()
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4716
|
+
];
|
|
4717
|
+
}
|
|
4718
|
+
if (solderPaste.shape === "pill") {
|
|
4719
|
+
const width = solderPaste.width * Math.abs(transform.a);
|
|
4720
|
+
const height = solderPaste.height * Math.abs(transform.d);
|
|
4721
|
+
const radius = solderPaste.radius * Math.abs(transform.a);
|
|
4722
|
+
return [
|
|
4723
|
+
{
|
|
4724
|
+
name: "rect",
|
|
4725
|
+
type: "element",
|
|
4726
|
+
attributes: {
|
|
4727
|
+
class: "pcb-solder-paste",
|
|
4728
|
+
fill: solderPasteLayerNameToColor(solderPaste.layer),
|
|
4729
|
+
x: (x - width / 2).toString(),
|
|
4730
|
+
y: (y - height / 2).toString(),
|
|
4731
|
+
width: width.toString(),
|
|
4732
|
+
height: height.toString(),
|
|
4733
|
+
rx: radius.toString()
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
];
|
|
4737
|
+
}
|
|
4738
|
+
if (solderPaste.shape === "circle") {
|
|
4739
|
+
const radius = solderPaste.radius * Math.abs(transform.a);
|
|
4740
|
+
return [
|
|
4741
|
+
{
|
|
4742
|
+
name: "circle",
|
|
4743
|
+
type: "element",
|
|
4744
|
+
attributes: {
|
|
4745
|
+
class: "pcb-solder-paste",
|
|
4746
|
+
fill: solderPasteLayerNameToColor(solderPaste.layer),
|
|
4747
|
+
cx: x.toString(),
|
|
4748
|
+
cy: y.toString(),
|
|
4749
|
+
r: radius.toString()
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4752
|
+
];
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
|
|
4756
|
+
// lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
|
|
4757
|
+
var OBJECT_ORDER3 = [
|
|
4758
|
+
"pcb_board",
|
|
4759
|
+
"pcb_solder_paste"
|
|
4760
|
+
];
|
|
4761
|
+
function convertCircuitJsonToSolderPasteMask(soup, options) {
|
|
4762
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
4763
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
4764
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
4765
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
4766
|
+
const filteredSoup = soup.filter(
|
|
4767
|
+
(elm) => elm.type === "pcb_board" || elm.type === "pcb_solder_paste" && elm.layer === options.layer
|
|
4768
|
+
);
|
|
4769
|
+
for (const item of filteredSoup) {
|
|
4770
|
+
if (item.type === "pcb_board") {
|
|
4771
|
+
if (item.outline && Array.isArray(item.outline) && item.outline.length >= 3) {
|
|
4772
|
+
updateBoundsToIncludeOutline(item.outline);
|
|
4773
|
+
} else if ("center" in item && "width" in item && "height" in item) {
|
|
4774
|
+
updateBounds(item.center, item.width, item.height);
|
|
4775
|
+
}
|
|
4776
|
+
} else if (item.type === "pcb_solder_paste" && "x" in item && "y" in item) {
|
|
4777
|
+
updateBounds({ x: item.x, y: item.y }, 0, 0);
|
|
4778
|
+
}
|
|
4779
|
+
}
|
|
4780
|
+
const padding = 1;
|
|
4781
|
+
const circuitWidth = maxX - minX + 2 * padding;
|
|
4782
|
+
const circuitHeight = maxY - minY + 2 * padding;
|
|
4783
|
+
const svgWidth = options.width ?? 800;
|
|
4784
|
+
const svgHeight = options.height ?? 600;
|
|
4785
|
+
const scaleX = svgWidth / circuitWidth;
|
|
4786
|
+
const scaleY = svgHeight / circuitHeight;
|
|
4787
|
+
const scaleFactor = Math.min(scaleX, scaleY);
|
|
4788
|
+
const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
|
|
4789
|
+
const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
|
|
4790
|
+
const transform = compose10(
|
|
4791
|
+
translate10(
|
|
4792
|
+
offsetX - minX * scaleFactor + padding * scaleFactor,
|
|
4793
|
+
svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
|
|
4794
|
+
),
|
|
4795
|
+
scale8(scaleFactor, -scaleFactor)
|
|
4796
|
+
// Flip in y-direction
|
|
4797
|
+
);
|
|
4798
|
+
const svgObjects = filteredSoup.sort(
|
|
4799
|
+
(a, b) => (OBJECT_ORDER3.indexOf(b.type) ?? 9999) - (OBJECT_ORDER3.indexOf(a.type) ?? 9999)
|
|
4800
|
+
).flatMap((item) => createSvgObjects3(item, transform));
|
|
4801
|
+
const svgObject = {
|
|
4802
|
+
name: "svg",
|
|
4803
|
+
type: "element",
|
|
4804
|
+
attributes: {
|
|
4805
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4806
|
+
width: svgWidth.toString(),
|
|
4807
|
+
height: svgHeight.toString()
|
|
4808
|
+
},
|
|
4809
|
+
value: "",
|
|
4810
|
+
children: [
|
|
4811
|
+
{
|
|
4812
|
+
name: "style",
|
|
4813
|
+
type: "element",
|
|
4814
|
+
children: [
|
|
4815
|
+
{
|
|
4816
|
+
type: "text",
|
|
4817
|
+
value: ""
|
|
4818
|
+
}
|
|
4819
|
+
]
|
|
4820
|
+
},
|
|
4821
|
+
{
|
|
4822
|
+
name: "rect",
|
|
4823
|
+
type: "element",
|
|
4824
|
+
attributes: {
|
|
4825
|
+
class: "boundary",
|
|
4826
|
+
x: "0",
|
|
4827
|
+
y: "0",
|
|
4828
|
+
fill: "#000",
|
|
4829
|
+
width: svgWidth.toString(),
|
|
4830
|
+
height: svgHeight.toString()
|
|
4831
|
+
}
|
|
4832
|
+
},
|
|
4833
|
+
createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY),
|
|
4834
|
+
...svgObjects
|
|
4835
|
+
].filter((child) => child !== null)
|
|
4836
|
+
};
|
|
4837
|
+
try {
|
|
4838
|
+
return stringify4(svgObject);
|
|
4839
|
+
} catch (error) {
|
|
4840
|
+
console.error("Error stringifying SVG object:", error);
|
|
4841
|
+
throw error;
|
|
4842
|
+
}
|
|
4843
|
+
function updateBounds(center, width, height) {
|
|
4844
|
+
const halfWidth = width / 2;
|
|
4845
|
+
const halfHeight = height / 2;
|
|
4846
|
+
minX = Math.min(minX, center.x - halfWidth);
|
|
4847
|
+
minY = Math.min(minY, center.y - halfHeight);
|
|
4848
|
+
maxX = Math.max(maxX, center.x + halfWidth);
|
|
4849
|
+
maxY = Math.max(maxY, center.y + halfHeight);
|
|
4850
|
+
}
|
|
4851
|
+
function updateBoundsToIncludeOutline(outline) {
|
|
4852
|
+
for (const point of outline) {
|
|
4853
|
+
minX = Math.min(minX, point.x);
|
|
4854
|
+
minY = Math.min(minY, point.y);
|
|
4855
|
+
maxX = Math.max(maxX, point.x);
|
|
4856
|
+
maxY = Math.max(maxY, point.y);
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
}
|
|
4860
|
+
function createSvgObjects3(elm, transform) {
|
|
4861
|
+
switch (elm.type) {
|
|
4862
|
+
case "pcb_board":
|
|
4863
|
+
return createSvgObjectsFromPcbBoard(elm, transform);
|
|
4864
|
+
case "pcb_solder_paste":
|
|
4865
|
+
return createSvgObjectsFromSolderPaste(elm, transform);
|
|
4866
|
+
default:
|
|
4867
|
+
return [];
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
function createSvgObjectFromPcbBoundary2(transform, minX, minY, maxX, maxY) {
|
|
4871
|
+
const [x1, y1] = applyToPoint38(transform, [minX, minY]);
|
|
4872
|
+
const [x2, y2] = applyToPoint38(transform, [maxX, maxY]);
|
|
4873
|
+
const width = Math.abs(x2 - x1);
|
|
4874
|
+
const height = Math.abs(y2 - y1);
|
|
4875
|
+
const x = Math.min(x1, x2);
|
|
4876
|
+
const y = Math.min(y1, y2);
|
|
4877
|
+
return {
|
|
4878
|
+
name: "rect",
|
|
4879
|
+
type: "element",
|
|
4880
|
+
value: "",
|
|
4881
|
+
children: [],
|
|
4882
|
+
attributes: {
|
|
4883
|
+
class: "pcb-boundary",
|
|
4884
|
+
fill: "none",
|
|
4885
|
+
stroke: "#fff",
|
|
4886
|
+
"stroke-width": "0.3",
|
|
4887
|
+
x: x.toString(),
|
|
4888
|
+
y: y.toString(),
|
|
4889
|
+
width: width.toString(),
|
|
4890
|
+
height: height.toString()
|
|
4891
|
+
}
|
|
4892
|
+
};
|
|
4893
|
+
}
|
|
4662
4894
|
export {
|
|
4663
4895
|
circuitJsonToPcbSvg,
|
|
4664
4896
|
circuitJsonToSchematicSvg,
|
|
4665
4897
|
convertCircuitJsonToAssemblySvg,
|
|
4666
4898
|
convertCircuitJsonToPcbSvg,
|
|
4667
|
-
convertCircuitJsonToSchematicSvg
|
|
4899
|
+
convertCircuitJsonToSchematicSvg,
|
|
4900
|
+
convertCircuitJsonToSolderPasteMask
|
|
4668
4901
|
};
|
|
4669
4902
|
//# sourceMappingURL=index.js.map
|