altium-to-circuit-json 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/index.js +272 -48
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -78,6 +78,19 @@ bun run test:update-svg
|
|
|
78
78
|
|
|
79
79
|
Every imported reference used by the test suite has a side-by-side SVG snapshot. The committed fixtures are generated from pinned upstream URLs and are not stored in this repository.
|
|
80
80
|
|
|
81
|
+
The TI SPRCAL9 / TMDS62LEVM Rev. B regression corpus includes all 57
|
|
82
|
+
schematic sheets and a top-copper PCB comparison. Its large downloaded source
|
|
83
|
+
files are checksum-verified and cached in CI. To also write the complete
|
|
84
|
+
converted Circuit JSON artifacts locally, run:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
bun run convert:ti-reference
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This creates `artifacts/ti-tmds62levm-rev-b/pcb.circuit.json`, one Circuit JSON
|
|
91
|
+
file per schematic sheet, and a conversion manifest. The artifact directory is
|
|
92
|
+
gitignored; the compact SVG regression snapshots remain committed.
|
|
93
|
+
|
|
81
94
|
## Development
|
|
82
95
|
|
|
83
96
|
```sh
|
package/dist/index.js
CHANGED
|
@@ -750,35 +750,69 @@ function convertSchematicRecord(record, index, context, options) {
|
|
|
750
750
|
const rectangle = getRectangle(record);
|
|
751
751
|
const text = decodeMultilineText(record.getDecoded("TEXT") ?? "");
|
|
752
752
|
if (!rectangle || !text || options.includeText === false) return [];
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
753
|
+
const fontSize = getFontSize(record, context);
|
|
754
|
+
const fontFamily = getFontFamily(record, context);
|
|
755
|
+
const margin = Math.max(getCoordinate(record, "TEXTMARGIN", 0), 0);
|
|
756
|
+
const frameWidth = rectangle.maxX - rectangle.minX;
|
|
757
|
+
const frameHeight = rectangle.maxY - rectangle.minY;
|
|
758
|
+
const availableWidth = Math.max(frameWidth - margin * 2, fontSize);
|
|
759
|
+
const availableHeight = Math.max(frameHeight - margin * 2, fontSize);
|
|
760
|
+
const wrappedLines = record.getBoolean("WORDWRAP") === false ? text.split("\n") : wrapSchematicText(text, availableWidth, fontSize, fontFamily);
|
|
761
|
+
const lineHeight = fontSize;
|
|
762
|
+
const visibleLines = record.getBoolean("CLIPTORECT") === false ? wrappedLines : wrappedLines.slice(
|
|
763
|
+
0,
|
|
764
|
+
Math.max(Math.ceil(availableHeight / lineHeight), 1)
|
|
765
|
+
);
|
|
766
|
+
const alignment = Number(record.getCaseInsensitive("ALIGNMENT") ?? 1);
|
|
767
|
+
const horizontalAnchor = alignment === 2 ? "center" : alignment === 3 ? "right" : "left";
|
|
768
|
+
const textX = horizontalAnchor === "center" ? (rectangle.minX + rectangle.maxX) / 2 : horizontalAnchor === "right" ? rectangle.maxX - margin : rectangle.minX + margin;
|
|
769
|
+
const textColor = altiumColorToCss(
|
|
770
|
+
record.getCaseInsensitive("TEXTCOLOR") ?? record.getCaseInsensitive("COLOR"),
|
|
771
|
+
"#1f2937"
|
|
772
|
+
);
|
|
773
|
+
const elements = visibleLines.map(
|
|
774
|
+
(line, lineIndex) => createDirectText(
|
|
775
|
+
`schematic_text_frame_line_altium_${index}_${lineIndex}`,
|
|
776
|
+
line,
|
|
758
777
|
{
|
|
759
|
-
x:
|
|
760
|
-
y:
|
|
778
|
+
x: textX,
|
|
779
|
+
y: rectangle.maxY - margin - lineIndex * lineHeight
|
|
761
780
|
},
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
color,
|
|
769
|
-
is_filled: false,
|
|
770
|
-
is_dashed: false
|
|
771
|
-
};
|
|
772
|
-
const textElement = createText(
|
|
773
|
-
record,
|
|
774
|
-
index,
|
|
775
|
-
text,
|
|
776
|
-
{ x: rectangle.minX + 2, y: rectangle.maxY - 2 },
|
|
777
|
-
color,
|
|
778
|
-
context,
|
|
779
|
-
"top_left"
|
|
781
|
+
fontSize,
|
|
782
|
+
textColor,
|
|
783
|
+
scale,
|
|
784
|
+
0,
|
|
785
|
+
`top_${horizontalAnchor}`
|
|
786
|
+
)
|
|
780
787
|
);
|
|
781
|
-
|
|
788
|
+
const isSolid = record.getBoolean("ISSOLID") === true;
|
|
789
|
+
const showBorder = record.getBoolean("SHOWBORDER") === true;
|
|
790
|
+
if (isSolid || showBorder) {
|
|
791
|
+
elements.unshift({
|
|
792
|
+
type: "schematic_rect",
|
|
793
|
+
schematic_rect_id: `schematic_text_frame_altium_${index}`,
|
|
794
|
+
schematic_sheet_id: SCHEMATIC_SHEET_ID,
|
|
795
|
+
center: scalePoint(
|
|
796
|
+
{
|
|
797
|
+
x: (rectangle.minX + rectangle.maxX) / 2,
|
|
798
|
+
y: (rectangle.minY + rectangle.maxY) / 2
|
|
799
|
+
},
|
|
800
|
+
scale
|
|
801
|
+
),
|
|
802
|
+
width: frameWidth * scale,
|
|
803
|
+
height: frameHeight * scale,
|
|
804
|
+
rotation: 0,
|
|
805
|
+
stroke_width: showBorder ? strokeWidth : 0,
|
|
806
|
+
color: showBorder ? color : "transparent",
|
|
807
|
+
is_filled: isSolid,
|
|
808
|
+
fill_color: altiumColorToCss(
|
|
809
|
+
record.getCaseInsensitive("AREACOLOR"),
|
|
810
|
+
"#ffffff"
|
|
811
|
+
),
|
|
812
|
+
is_dashed: false
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
return elements;
|
|
782
816
|
}
|
|
783
817
|
return [];
|
|
784
818
|
}
|
|
@@ -825,7 +859,7 @@ function convertPin(record, index, context, options, color) {
|
|
|
825
859
|
x: location.x - direction.x * textOffset,
|
|
826
860
|
y: location.y - direction.y * textOffset
|
|
827
861
|
},
|
|
828
|
-
|
|
862
|
+
6,
|
|
829
863
|
color,
|
|
830
864
|
context.scale,
|
|
831
865
|
rotation,
|
|
@@ -842,7 +876,7 @@ function convertPin(record, index, context, options, color) {
|
|
|
842
876
|
x: location.x + direction.x * textOffset,
|
|
843
877
|
y: location.y + direction.y * textOffset
|
|
844
878
|
},
|
|
845
|
-
|
|
879
|
+
6,
|
|
846
880
|
color,
|
|
847
881
|
context.scale,
|
|
848
882
|
rotation,
|
|
@@ -855,36 +889,163 @@ function convertPin(record, index, context, options, color) {
|
|
|
855
889
|
function convertPowerPort(record, index, context, options, color) {
|
|
856
890
|
const location = getLocation(record);
|
|
857
891
|
if (!location) return [];
|
|
858
|
-
const
|
|
859
|
-
|
|
860
|
-
{ x:
|
|
861
|
-
{ x:
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
892
|
+
const orientation = (Math.round(record.getNumber("ORIENTATION") ?? 0) % 4 + 4) % 4;
|
|
893
|
+
const direction = [
|
|
894
|
+
{ x: 1, y: 0 },
|
|
895
|
+
{ x: 0, y: 1 },
|
|
896
|
+
{ x: -1, y: 0 },
|
|
897
|
+
{ x: 0, y: -1 }
|
|
898
|
+
][orientation] ?? { x: 1, y: 0 };
|
|
899
|
+
const perpendicular = { x: -direction.y, y: direction.x };
|
|
900
|
+
const point = (along, across = 0) => ({
|
|
901
|
+
x: location.x + direction.x * along + perpendicular.x * across,
|
|
902
|
+
y: location.y + direction.y * along + perpendicular.y * across
|
|
903
|
+
});
|
|
904
|
+
const style = Math.round(Number(record.getCaseInsensitive("STYLE") ?? 2));
|
|
905
|
+
const elements = [];
|
|
906
|
+
let labelDistance;
|
|
907
|
+
if (style === 2) {
|
|
908
|
+
elements.push(
|
|
909
|
+
createLine(
|
|
910
|
+
index,
|
|
911
|
+
location,
|
|
912
|
+
point(8),
|
|
913
|
+
color,
|
|
914
|
+
0.1,
|
|
915
|
+
context.scale,
|
|
916
|
+
"power_port_stem"
|
|
917
|
+
),
|
|
918
|
+
createLine(
|
|
919
|
+
index,
|
|
920
|
+
point(8, -5),
|
|
921
|
+
point(8, 5),
|
|
922
|
+
color,
|
|
923
|
+
0.1,
|
|
924
|
+
context.scale,
|
|
925
|
+
"power_port_bar"
|
|
926
|
+
)
|
|
927
|
+
);
|
|
928
|
+
labelDistance = 12;
|
|
929
|
+
} else if (style === 5) {
|
|
930
|
+
elements.push(
|
|
931
|
+
createLine(
|
|
932
|
+
index,
|
|
933
|
+
location,
|
|
934
|
+
point(4),
|
|
935
|
+
color,
|
|
936
|
+
0.1,
|
|
937
|
+
context.scale,
|
|
938
|
+
"power_port_stem"
|
|
939
|
+
),
|
|
940
|
+
{
|
|
941
|
+
type: "schematic_path",
|
|
942
|
+
schematic_path_id: `schematic_power_port_altium_${index}`,
|
|
943
|
+
schematic_sheet_id: SCHEMATIC_SHEET_ID,
|
|
944
|
+
points: [point(4, -7), point(4, 7), point(12)].map(
|
|
945
|
+
(value) => scalePoint(value, context.scale)
|
|
946
|
+
),
|
|
947
|
+
stroke_width: 0.1,
|
|
948
|
+
stroke_color: color,
|
|
949
|
+
is_filled: false,
|
|
950
|
+
is_dashed: false
|
|
951
|
+
}
|
|
952
|
+
);
|
|
953
|
+
labelDistance = 16;
|
|
954
|
+
} else if (style === 4) {
|
|
955
|
+
elements.push(
|
|
956
|
+
createLine(
|
|
957
|
+
index,
|
|
958
|
+
location,
|
|
959
|
+
point(4),
|
|
960
|
+
color,
|
|
961
|
+
0.1,
|
|
962
|
+
context.scale,
|
|
963
|
+
"power_port_stem"
|
|
964
|
+
),
|
|
965
|
+
...[
|
|
966
|
+
{ along: 4, halfWidth: 7 },
|
|
967
|
+
{ along: 8, halfWidth: 4.5 },
|
|
968
|
+
{ along: 12, halfWidth: 2 }
|
|
969
|
+
].map(
|
|
970
|
+
({ along, halfWidth }, lineIndex) => createLine(
|
|
971
|
+
index,
|
|
972
|
+
point(along, -halfWidth),
|
|
973
|
+
point(along, halfWidth),
|
|
974
|
+
color,
|
|
975
|
+
0.1,
|
|
976
|
+
context.scale,
|
|
977
|
+
`power_port_ground_${lineIndex}`
|
|
978
|
+
)
|
|
979
|
+
)
|
|
980
|
+
);
|
|
981
|
+
labelDistance = 16;
|
|
982
|
+
} else if (style === 6) {
|
|
983
|
+
elements.push(
|
|
984
|
+
createLine(
|
|
985
|
+
index,
|
|
986
|
+
location,
|
|
987
|
+
point(4),
|
|
988
|
+
color,
|
|
989
|
+
0.1,
|
|
990
|
+
context.scale,
|
|
991
|
+
"power_port_stem"
|
|
992
|
+
),
|
|
993
|
+
createLine(
|
|
994
|
+
index,
|
|
995
|
+
point(4, -7),
|
|
996
|
+
point(4, 7),
|
|
997
|
+
color,
|
|
998
|
+
0.1,
|
|
999
|
+
context.scale,
|
|
1000
|
+
"power_port_chassis_bar"
|
|
1001
|
+
),
|
|
1002
|
+
...[
|
|
1003
|
+
{ from: -7, to: -9 },
|
|
1004
|
+
{ from: 0, to: -2 },
|
|
1005
|
+
{ from: 7, to: 5 }
|
|
1006
|
+
].map(
|
|
1007
|
+
({ from, to }, lineIndex) => createLine(
|
|
1008
|
+
index,
|
|
1009
|
+
point(4, from),
|
|
1010
|
+
point(9, to),
|
|
1011
|
+
color,
|
|
1012
|
+
0.1,
|
|
1013
|
+
context.scale,
|
|
1014
|
+
`power_port_chassis_${lineIndex}`
|
|
1015
|
+
)
|
|
1016
|
+
)
|
|
1017
|
+
);
|
|
1018
|
+
labelDistance = 14;
|
|
1019
|
+
} else {
|
|
1020
|
+
elements.push({
|
|
865
1021
|
type: "schematic_path",
|
|
866
1022
|
schematic_path_id: `schematic_power_port_altium_${index}`,
|
|
867
1023
|
schematic_sheet_id: SCHEMATIC_SHEET_ID,
|
|
868
|
-
points:
|
|
1024
|
+
points: [location, point(10, -5), point(10, 5)].map(
|
|
1025
|
+
(value) => scalePoint(value, context.scale)
|
|
1026
|
+
),
|
|
869
1027
|
stroke_width: 0.1,
|
|
870
1028
|
stroke_color: color,
|
|
871
1029
|
fill_color: color,
|
|
872
1030
|
is_filled: true,
|
|
873
1031
|
is_dashed: false
|
|
874
|
-
}
|
|
875
|
-
|
|
1032
|
+
});
|
|
1033
|
+
labelDistance = 14;
|
|
1034
|
+
}
|
|
876
1035
|
const text = record.getDecoded("TEXT") ?? record.getDecoded("NAME");
|
|
877
|
-
if (text && options.includeText !== false) {
|
|
1036
|
+
if (text && options.includeText !== false && record.getBoolean("SHOWNETNAME") !== false) {
|
|
1037
|
+
const vertical = direction.y !== 0;
|
|
1038
|
+
const anchor = vertical ? direction.y > 0 ? "bottom_center" : "top_center" : direction.x > 0 ? "center_left" : "center_right";
|
|
878
1039
|
elements.push(
|
|
879
1040
|
createDirectText(
|
|
880
1041
|
`schematic_power_port_text_altium_${index}`,
|
|
881
1042
|
text,
|
|
882
|
-
|
|
1043
|
+
point(labelDistance),
|
|
883
1044
|
getFontSize(record, context),
|
|
884
1045
|
color,
|
|
885
1046
|
context.scale,
|
|
886
1047
|
0,
|
|
887
|
-
|
|
1048
|
+
anchor
|
|
888
1049
|
)
|
|
889
1050
|
);
|
|
890
1051
|
}
|
|
@@ -894,12 +1055,33 @@ function convertPort(record, index, context, options, color) {
|
|
|
894
1055
|
const location = getLocation(record);
|
|
895
1056
|
if (!location) return [];
|
|
896
1057
|
const width = Math.max(Number(record.getCaseInsensitive("WIDTH") ?? 16), 10);
|
|
897
|
-
const
|
|
1058
|
+
const height = Math.max(Number(record.getCaseInsensitive("HEIGHT") ?? 10), 4);
|
|
1059
|
+
const halfHeight = height / 2;
|
|
1060
|
+
const pointDepth = Math.min(width * 0.22, height);
|
|
1061
|
+
const ioType = Number(record.getCaseInsensitive("IOTYPE") ?? 0);
|
|
1062
|
+
const points = ioType === 1 ? [
|
|
898
1063
|
{ x: location.x, y: location.y },
|
|
899
|
-
{ x: location.x +
|
|
900
|
-
{ x: location.x + width, y: location.y +
|
|
901
|
-
{ x: location.x + width, y: location.y -
|
|
902
|
-
{ x: location.x +
|
|
1064
|
+
{ x: location.x + pointDepth, y: location.y + halfHeight },
|
|
1065
|
+
{ x: location.x + width, y: location.y + halfHeight },
|
|
1066
|
+
{ x: location.x + width, y: location.y - halfHeight },
|
|
1067
|
+
{ x: location.x + pointDepth, y: location.y - halfHeight }
|
|
1068
|
+
] : ioType === 2 ? [
|
|
1069
|
+
{ x: location.x, y: location.y + halfHeight },
|
|
1070
|
+
{
|
|
1071
|
+
x: location.x + width - pointDepth,
|
|
1072
|
+
y: location.y + halfHeight
|
|
1073
|
+
},
|
|
1074
|
+
{ x: location.x + width, y: location.y },
|
|
1075
|
+
{
|
|
1076
|
+
x: location.x + width - pointDepth,
|
|
1077
|
+
y: location.y - halfHeight
|
|
1078
|
+
},
|
|
1079
|
+
{ x: location.x, y: location.y - halfHeight }
|
|
1080
|
+
] : [
|
|
1081
|
+
{ x: location.x, y: location.y + halfHeight },
|
|
1082
|
+
{ x: location.x + width, y: location.y + halfHeight },
|
|
1083
|
+
{ x: location.x + width, y: location.y - halfHeight },
|
|
1084
|
+
{ x: location.x, y: location.y - halfHeight }
|
|
903
1085
|
];
|
|
904
1086
|
const elements = [
|
|
905
1087
|
{
|
|
@@ -909,7 +1091,10 @@ function convertPort(record, index, context, options, color) {
|
|
|
909
1091
|
points: points.map((point) => scalePoint(point, context.scale)),
|
|
910
1092
|
stroke_width: 0.1,
|
|
911
1093
|
stroke_color: color,
|
|
912
|
-
fill_color:
|
|
1094
|
+
fill_color: altiumColorToCss(
|
|
1095
|
+
record.getCaseInsensitive("AREACOLOR"),
|
|
1096
|
+
"#ffffff"
|
|
1097
|
+
),
|
|
913
1098
|
is_filled: true,
|
|
914
1099
|
is_dashed: false
|
|
915
1100
|
}
|
|
@@ -922,7 +1107,7 @@ function convertPort(record, index, context, options, color) {
|
|
|
922
1107
|
name,
|
|
923
1108
|
{ x: location.x + width / 2, y: location.y },
|
|
924
1109
|
getFontSize(record, context),
|
|
925
|
-
color,
|
|
1110
|
+
altiumColorToCss(record.getCaseInsensitive("TEXTCOLOR"), color),
|
|
926
1111
|
context.scale,
|
|
927
1112
|
0,
|
|
928
1113
|
"center"
|
|
@@ -1004,6 +1189,13 @@ function getFontSize(record, context) {
|
|
|
1004
1189
|
1
|
|
1005
1190
|
);
|
|
1006
1191
|
}
|
|
1192
|
+
function getFontFamily(record, context) {
|
|
1193
|
+
const fontId = Math.max(
|
|
1194
|
+
Math.round(Number(record.getCaseInsensitive("FONTID") ?? 1)),
|
|
1195
|
+
1
|
|
1196
|
+
);
|
|
1197
|
+
return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? "Arial";
|
|
1198
|
+
}
|
|
1007
1199
|
function getTextPositioning(record) {
|
|
1008
1200
|
const justification = Math.min(
|
|
1009
1201
|
Math.max(Math.round(record.getNumber("JUSTIFICATION") ?? 0), 0),
|
|
@@ -1098,6 +1290,38 @@ function approximateEllipse(center, radiusX, radiusY) {
|
|
|
1098
1290
|
function decodeMultilineText(text) {
|
|
1099
1291
|
return text.replaceAll("~1", "\n").replaceAll("\\n", "\n");
|
|
1100
1292
|
}
|
|
1293
|
+
function wrapSchematicText(text, maximumWidth, fontSize, fontFamily) {
|
|
1294
|
+
return text.split("\n").flatMap((paragraph) => {
|
|
1295
|
+
if (estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <= maximumWidth) {
|
|
1296
|
+
return [paragraph];
|
|
1297
|
+
}
|
|
1298
|
+
const words = paragraph.split(/\s+/u);
|
|
1299
|
+
const lines = [];
|
|
1300
|
+
let line = "";
|
|
1301
|
+
for (const word of words) {
|
|
1302
|
+
if (!line) {
|
|
1303
|
+
line = word;
|
|
1304
|
+
} else if (estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <= maximumWidth) {
|
|
1305
|
+
line = `${line} ${word}`;
|
|
1306
|
+
} else {
|
|
1307
|
+
lines.push(line);
|
|
1308
|
+
line = word;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
if (line) lines.push(line);
|
|
1312
|
+
return lines.length > 0 ? lines : [paragraph];
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
function estimateSchematicTextWidth(text, fontSize, fontFamily) {
|
|
1316
|
+
if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6;
|
|
1317
|
+
if (!/times|cambria|serif/iu.test(fontFamily)) {
|
|
1318
|
+
return text.length * fontSize * 0.52;
|
|
1319
|
+
}
|
|
1320
|
+
return [...text].reduce((width, character) => {
|
|
1321
|
+
const emWidth = character === " " ? 0.23 : /[ilI1.,:;!'`|]/u.test(character) ? 0.2 : /[mwMW@%]/u.test(character) ? 0.7 : /[A-Z0-9]/u.test(character) ? 0.5 : 0.4;
|
|
1322
|
+
return width + emWidth * fontSize;
|
|
1323
|
+
}, 0);
|
|
1324
|
+
}
|
|
1101
1325
|
function altiumColorToCss(raw, fallback) {
|
|
1102
1326
|
if (raw === void 0) return fallback;
|
|
1103
1327
|
const value = Number(raw);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints(x, y, width, height, record.rotation),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints(x, y, width, height, record.rotation),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc(\n center: AltiumPoint,\n radius: number,\n startAngle: number,\n endAngle: number,\n): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints(\n x: number,\n y: number,\n width: number,\n height: number,\n rotation: number,\n): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicArc,\n SchematicCircle,\n SchematicLine,\n SchematicPath,\n SchematicRect,\n SchematicSheet,\n SchematicText,\n SchematicTrace,\n} from \"circuit-json\"\n\nconst DEFAULT_SCHEMATIC_UNIT_SCALE = 0.1\nconst SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n\nexport interface ConvertAltiumSchDocOptions {\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\ninterface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const scale = options.schematicUnitScale ?? DEFAULT_SCHEMATIC_UNIT_SCALE\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder !== false) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n for (const [index, record] of records.entries()) {\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = convertSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n return elements\n}\n\nfunction convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [createLine(index, location, corner, color, strokeWidth, scale)]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse(center, radiusX, radiusY).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n if (kind === \"2\") {\n return convertPin(record, index, context, options, color)\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n const radius = 0.4 / scale\n return [\n createLine(\n index,\n { x: location.x - radius, y: location.y - radius },\n { x: location.x + radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"a\",\n ),\n createLine(\n index,\n { x: location.x + radius, y: location.y - radius },\n { x: location.x - radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"b\",\n ),\n ]\n }\n\n if (kind === \"17\") {\n return convertPowerPort(record, index, context, options, color)\n }\n\n if (kind === \"18\") {\n return convertPort(record, index, context, options, color)\n }\n\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText(record, index, text, location, color, context)]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const rect = {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicRect\n const textElement = createText(\n record,\n index,\n text,\n { x: rectangle.minX + 2, y: rectangle.maxY - 2 },\n color,\n context,\n \"top_left\",\n )\n return [rect, textElement]\n }\n\n return []\n}\n\nfunction convertPin(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine(index, location, end, color, 0.1, context.scale, \"pin\"),\n ]\n if (options.includeText === false) return elements\n\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const nameAnchor = directionMatchesText ? \"right\" : \"left\"\n const designatorAnchor = directionMatchesText ? \"left\" : \"right\"\n const textOffset = 2\n\n if (showName && name) {\n elements.push(\n createDirectText(\n `schematic_pin_name_altium_${index}`,\n name,\n {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n 0.6,\n color,\n context.scale,\n rotation,\n nameAnchor,\n ),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText(\n `schematic_pin_designator_altium_${index}`,\n designator,\n {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n 0.6,\n color,\n context.scale,\n rotation,\n designatorAnchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPowerPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const points = [\n { x: location.x, y: location.y },\n { x: location.x - 5, y: location.y + 7 },\n { x: location.x + 5, y: location.y + 7 },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (text && options.includeText !== false) {\n elements.push(\n createDirectText(\n `schematic_power_port_text_altium_${index}`,\n text,\n { x: location.x + 7, y: location.y + 3 },\n getFontSize(record, context),\n color,\n context.scale,\n 0,\n \"left\",\n ),\n )\n }\n return elements\n}\n\nfunction convertPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const points = [\n { x: location.x, y: location.y },\n { x: location.x + width * 0.22, y: location.y + 5 },\n { x: location.x + width, y: location.y + 5 },\n { x: location.x + width, y: location.y - 5 },\n { x: location.x + width * 0.22, y: location.y - 5 },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: \"#ffffff\",\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText(\n `schematic_port_text_altium_${index}`,\n name,\n { x: location.x + width / 2, y: location.y },\n getFontSize(record, context),\n color,\n context.scale,\n 0,\n \"center\",\n ),\n )\n }\n return elements\n}\n\nfunction createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const width = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMX\") ?? 1000),\n 1,\n )\n const height = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMY\") ?? 800),\n 1,\n )\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nfunction createLine(\n index: number,\n start: AltiumPoint,\n end: AltiumPoint,\n color: string,\n strokeWidth: number,\n scale: number,\n suffix = \"line\",\n): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nfunction createText(\n record: AltiumRecord,\n index: number,\n text: string,\n location: AltiumPoint,\n color: string,\n context: SchematicContext,\n anchorOverride?: SchematicText[\"anchor\"],\n): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText(\n `schematic_text_altium_${index}`,\n text,\n location,\n getFontSize(record, context),\n color,\n context.scale,\n positioning.rotation,\n anchorOverride ?? positioning.anchor,\n )\n}\n\nfunction createDirectText(\n id: string,\n text: string,\n location: AltiumPoint,\n fontSize: number,\n color: string,\n scale: number,\n rotation: number,\n anchor: SchematicText[\"anchor\"],\n): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nfunction getFontSize(record: AltiumRecord, context: SchematicContext): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return {\n anchor,\n rotation: orientation === 1 || orientation === 3 ? 90 : 0,\n }\n}\n\nfunction shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nfunction getRectangle(\n record: AltiumRecord,\n): { maxX: number; maxY: number; minX: number; minY: number } | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nfunction getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction approximateEllipse(\n center: AltiumPoint,\n radiusX: number,\n radiusY: number,\n): AltiumPoint[] {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n\nfunction decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nfunction altiumColorToCss(raw: string | undefined, fallback: string): string {\n if (raw === undefined) return fallback\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0) return fallback\n const red = value & 0xff\n const green = (value >>> 8) & 0xff\n const blue = (value >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":"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","names":["document"]}
|
|
1
|
+
{"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints(x, y, width, height, record.rotation),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints(x, y, width, height, record.rotation),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc(\n center: AltiumPoint,\n radius: number,\n startAngle: number,\n endAngle: number,\n): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints(\n x: number,\n y: number,\n width: number,\n height: number,\n rotation: number,\n): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicArc,\n SchematicCircle,\n SchematicLine,\n SchematicPath,\n SchematicRect,\n SchematicSheet,\n SchematicText,\n SchematicTrace,\n} from \"circuit-json\"\n\nconst DEFAULT_SCHEMATIC_UNIT_SCALE = 0.1\nconst SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n\nexport interface ConvertAltiumSchDocOptions {\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\ninterface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const scale = options.schematicUnitScale ?? DEFAULT_SCHEMATIC_UNIT_SCALE\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder !== false) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n for (const [index, record] of records.entries()) {\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = convertSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n return elements\n}\n\nfunction convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [createLine(index, location, corner, color, strokeWidth, scale)]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse(center, radiusX, radiusY).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n if (kind === \"2\") {\n return convertPin(record, index, context, options, color)\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n const radius = 0.4 / scale\n return [\n createLine(\n index,\n { x: location.x - radius, y: location.y - radius },\n { x: location.x + radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"a\",\n ),\n createLine(\n index,\n { x: location.x + radius, y: location.y - radius },\n { x: location.x - radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"b\",\n ),\n ]\n }\n\n if (kind === \"17\") {\n return convertPowerPort(record, index, context, options, color)\n }\n\n if (kind === \"18\") {\n return convertPort(record, index, context, options, color)\n }\n\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText(record, index, text, location, color, context)]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const fontSize = getFontSize(record, context)\n const fontFamily = getFontFamily(record, context)\n const margin = Math.max(getCoordinate(record, \"TEXTMARGIN\", 0), 0)\n const frameWidth = rectangle.maxX - rectangle.minX\n const frameHeight = rectangle.maxY - rectangle.minY\n const availableWidth = Math.max(frameWidth - margin * 2, fontSize)\n const availableHeight = Math.max(frameHeight - margin * 2, fontSize)\n const wrappedLines =\n record.getBoolean(\"WORDWRAP\") === false\n ? text.split(\"\\n\")\n : wrapSchematicText(text, availableWidth, fontSize, fontFamily)\n const lineHeight = fontSize\n const visibleLines =\n record.getBoolean(\"CLIPTORECT\") === false\n ? wrappedLines\n : wrappedLines.slice(\n 0,\n Math.max(Math.ceil(availableHeight / lineHeight), 1),\n )\n const alignment = Number(record.getCaseInsensitive(\"ALIGNMENT\") ?? 1)\n const horizontalAnchor =\n alignment === 2 ? \"center\" : alignment === 3 ? \"right\" : \"left\"\n const textX =\n horizontalAnchor === \"center\"\n ? (rectangle.minX + rectangle.maxX) / 2\n : horizontalAnchor === \"right\"\n ? rectangle.maxX - margin\n : rectangle.minX + margin\n const textColor = altiumColorToCss(\n record.getCaseInsensitive(\"TEXTCOLOR\") ??\n record.getCaseInsensitive(\"COLOR\"),\n \"#1f2937\",\n )\n const elements: AnyCircuitElement[] = visibleLines.map((line, lineIndex) =>\n createDirectText(\n `schematic_text_frame_line_altium_${index}_${lineIndex}`,\n line,\n {\n x: textX,\n y: rectangle.maxY - margin - lineIndex * lineHeight,\n },\n fontSize,\n textColor,\n scale,\n 0,\n `top_${horizontalAnchor}` as SchematicText[\"anchor\"],\n ),\n )\n\n const isSolid = record.getBoolean(\"ISSOLID\") === true\n const showBorder = record.getBoolean(\"SHOWBORDER\") === true\n if (isSolid || showBorder) {\n elements.unshift({\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: frameWidth * scale,\n height: frameHeight * scale,\n rotation: 0,\n stroke_width: showBorder ? strokeWidth : 0,\n color: showBorder ? color : \"transparent\",\n is_filled: isSolid,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect)\n }\n\n return elements\n }\n\n return []\n}\n\nfunction convertPin(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine(index, location, end, color, 0.1, context.scale, \"pin\"),\n ]\n if (options.includeText === false) return elements\n\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const nameAnchor = directionMatchesText ? \"right\" : \"left\"\n const designatorAnchor = directionMatchesText ? \"left\" : \"right\"\n const textOffset = 2\n\n if (showName && name) {\n elements.push(\n createDirectText(\n `schematic_pin_name_altium_${index}`,\n name,\n {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n nameAnchor,\n ),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText(\n `schematic_pin_designator_altium_${index}`,\n designator,\n {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n designatorAnchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPowerPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const perpendicular = { x: -direction.y, y: direction.x }\n const point = (along: number, across = 0): AltiumPoint => ({\n x: location.x + direction.x * along + perpendicular.x * across,\n y: location.y + direction.y * along + perpendicular.y * across,\n })\n const style = Math.round(Number(record.getCaseInsensitive(\"STYLE\") ?? 2))\n const elements: AnyCircuitElement[] = []\n let labelDistance: number\n\n if (style === 2) {\n elements.push(\n createLine(\n index,\n location,\n point(8),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(8, -5),\n point(8, 5),\n color,\n 0.1,\n context.scale,\n \"power_port_bar\",\n ),\n )\n labelDistance = 12\n } else if (style === 5) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [point(4, -7), point(4, 7), point(12)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicPath,\n )\n labelDistance = 16\n } else if (style === 4) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n ...[\n { along: 4, halfWidth: 7 },\n { along: 8, halfWidth: 4.5 },\n { along: 12, halfWidth: 2 },\n ].map(({ along, halfWidth }, lineIndex) =>\n createLine(\n index,\n point(along, -halfWidth),\n point(along, halfWidth),\n color,\n 0.1,\n context.scale,\n `power_port_ground_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 16\n } else if (style === 6) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(4, -7),\n point(4, 7),\n color,\n 0.1,\n context.scale,\n \"power_port_chassis_bar\",\n ),\n ...[\n { from: -7, to: -9 },\n { from: 0, to: -2 },\n { from: 7, to: 5 },\n ].map(({ from, to }, lineIndex) =>\n createLine(\n index,\n point(4, from),\n point(9, to),\n color,\n 0.1,\n context.scale,\n `power_port_chassis_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 14\n } else {\n elements.push({\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [location, point(10, -5), point(10, 5)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 14\n }\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (\n text &&\n options.includeText !== false &&\n record.getBoolean(\"SHOWNETNAME\") !== false\n ) {\n const vertical = direction.y !== 0\n const anchor: SchematicText[\"anchor\"] = vertical\n ? direction.y > 0\n ? \"bottom_center\"\n : \"top_center\"\n : direction.x > 0\n ? \"center_left\"\n : \"center_right\"\n elements.push(\n createDirectText(\n `schematic_power_port_text_altium_${index}`,\n text,\n point(labelDistance),\n getFontSize(record, context),\n color,\n context.scale,\n 0,\n anchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const height = Math.max(Number(record.getCaseInsensitive(\"HEIGHT\") ?? 10), 4)\n const halfHeight = height / 2\n const pointDepth = Math.min(width * 0.22, height)\n const ioType = Number(record.getCaseInsensitive(\"IOTYPE\") ?? 0)\n const points =\n ioType === 1\n ? [\n { x: location.x, y: location.y },\n { x: location.x + pointDepth, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x + pointDepth, y: location.y - halfHeight },\n ]\n : ioType === 2\n ? [\n { x: location.x, y: location.y + halfHeight },\n {\n x: location.x + width - pointDepth,\n y: location.y + halfHeight,\n },\n { x: location.x + width, y: location.y },\n {\n x: location.x + width - pointDepth,\n y: location.y - halfHeight,\n },\n { x: location.x, y: location.y - halfHeight },\n ]\n : [\n { x: location.x, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x, y: location.y - halfHeight },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText(\n `schematic_port_text_altium_${index}`,\n name,\n { x: location.x + width / 2, y: location.y },\n getFontSize(record, context),\n altiumColorToCss(record.getCaseInsensitive(\"TEXTCOLOR\"), color),\n context.scale,\n 0,\n \"center\",\n ),\n )\n }\n return elements\n}\n\nfunction createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const width = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMX\") ?? 1000),\n 1,\n )\n const height = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMY\") ?? 800),\n 1,\n )\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nfunction createLine(\n index: number,\n start: AltiumPoint,\n end: AltiumPoint,\n color: string,\n strokeWidth: number,\n scale: number,\n suffix = \"line\",\n): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nfunction createText(\n record: AltiumRecord,\n index: number,\n text: string,\n location: AltiumPoint,\n color: string,\n context: SchematicContext,\n anchorOverride?: SchematicText[\"anchor\"],\n): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText(\n `schematic_text_altium_${index}`,\n text,\n location,\n getFontSize(record, context),\n color,\n context.scale,\n positioning.rotation,\n anchorOverride ?? positioning.anchor,\n )\n}\n\nfunction createDirectText(\n id: string,\n text: string,\n location: AltiumPoint,\n fontSize: number,\n color: string,\n scale: number,\n rotation: number,\n anchor: SchematicText[\"anchor\"],\n): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nfunction getFontSize(record: AltiumRecord, context: SchematicContext): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nfunction getFontFamily(\n record: AltiumRecord,\n context: SchematicContext,\n): string {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? \"Arial\"\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return {\n anchor,\n rotation: orientation === 1 || orientation === 3 ? 90 : 0,\n }\n}\n\nfunction shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nfunction getRectangle(\n record: AltiumRecord,\n): { maxX: number; maxY: number; minX: number; minY: number } | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nfunction getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction approximateEllipse(\n center: AltiumPoint,\n radiusX: number,\n radiusY: number,\n): AltiumPoint[] {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n\nfunction decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nfunction wrapSchematicText(\n text: string,\n maximumWidth: number,\n fontSize: number,\n fontFamily: string,\n): string[] {\n return text.split(\"\\n\").flatMap((paragraph) => {\n if (\n estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <=\n maximumWidth\n ) {\n return [paragraph]\n }\n const words = paragraph.split(/\\s+/u)\n const lines: string[] = []\n let line = \"\"\n for (const word of words) {\n if (!line) {\n line = word\n } else if (\n estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <=\n maximumWidth\n ) {\n line = `${line} ${word}`\n } else {\n lines.push(line)\n line = word\n }\n }\n if (line) lines.push(line)\n return lines.length > 0 ? lines : [paragraph]\n })\n}\n\nfunction estimateSchematicTextWidth(\n text: string,\n fontSize: number,\n fontFamily: string,\n): number {\n if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6\n if (!/times|cambria|serif/iu.test(fontFamily)) {\n return text.length * fontSize * 0.52\n }\n\n return [...text].reduce((width, character) => {\n const emWidth =\n character === \" \"\n ? 0.23\n : /[ilI1.,:;!'`|]/u.test(character)\n ? 0.2\n : /[mwMW@%]/u.test(character)\n ? 0.7\n : /[A-Z0-9]/u.test(character)\n ? 0.5\n : 0.4\n return width + emWidth * fontSize\n }, 0)\n}\n\nfunction altiumColorToCss(raw: string | undefined, fallback: string): string {\n if (raw === undefined) return fallback\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0) return fallback\n const red = value & 0xff\n const green = (value >>> 8) & 0xff\n const blue = (value >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":"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","names":["document"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "altium-to-circuit-json",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Convert Altium schematic and PCB documents into Circuit JSON",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build": "tsup-node lib/index.ts --format esm --dts --sourcemap --clean",
|
|
30
|
+
"convert:ti-reference": "bun run download-references && bun run scripts/convert-ti-reference.ts",
|
|
30
31
|
"download-references": "bun run scripts/download-references.ts",
|
|
31
32
|
"format": "biome format --write .",
|
|
32
33
|
"format:check": "biome format .",
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
"bun-match-svg": "^0.0.15",
|
|
49
50
|
"circuit-json-to-connectivity-map": "^0.0.25",
|
|
50
51
|
"circuit-to-svg": "^0.0.394",
|
|
52
|
+
"fflate": "^0.8.3",
|
|
51
53
|
"format-si-unit": "^0.0.11",
|
|
52
54
|
"schematic-symbols": "^0.0.238",
|
|
53
55
|
"sharp": "^0.35.3",
|