altium-to-circuit-json 0.0.39 → 0.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +97 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,7 +47,9 @@ function mapAltiumCopperLayer(layer) {
|
|
|
47
47
|
|
|
48
48
|
// lib/pcb/convert-altium-copper-areas.ts
|
|
49
49
|
var MILS_TO_MILLIMETERS = 0.0254;
|
|
50
|
-
function convertAltiumCopperAreas(document
|
|
50
|
+
function convertAltiumCopperAreas(document, {
|
|
51
|
+
getSourceNetId = () => void 0
|
|
52
|
+
} = {}) {
|
|
51
53
|
const polygonIndexesWithRegions = new Set(
|
|
52
54
|
document.records.flatMap((record) => {
|
|
53
55
|
if (!(record instanceof AltiumRegionRecord) || record.recordKind !== "Region") {
|
|
@@ -62,24 +64,37 @@ function convertAltiumCopperAreas(document) {
|
|
|
62
64
|
);
|
|
63
65
|
return document.records.flatMap((record, recordIndex) => {
|
|
64
66
|
if (record instanceof AltiumRegionRecord) {
|
|
65
|
-
return convertCopperRegion({
|
|
67
|
+
return convertCopperRegion({
|
|
68
|
+
record,
|
|
69
|
+
recordIndex,
|
|
70
|
+
sourceNetId: getSourceNetId(record)
|
|
71
|
+
});
|
|
66
72
|
}
|
|
67
73
|
if (record instanceof AltiumPolygonRecord) {
|
|
68
74
|
const polygonIndex = polygonIndexes.get(record);
|
|
69
75
|
if (record.shelved === true || polygonIndex === void 0 || polygonIndexesWithRegions.has(polygonIndex)) {
|
|
70
76
|
return [];
|
|
71
77
|
}
|
|
72
|
-
return convertCopperPolygon({
|
|
78
|
+
return convertCopperPolygon({
|
|
79
|
+
polygonIndex,
|
|
80
|
+
record,
|
|
81
|
+
sourceNetId: getSourceNetId(record)
|
|
82
|
+
});
|
|
73
83
|
}
|
|
74
84
|
if (record instanceof AltiumFillRecord) {
|
|
75
|
-
return convertCopperFill({
|
|
85
|
+
return convertCopperFill({
|
|
86
|
+
record,
|
|
87
|
+
recordIndex,
|
|
88
|
+
sourceNetId: getSourceNetId(record)
|
|
89
|
+
});
|
|
76
90
|
}
|
|
77
91
|
return [];
|
|
78
92
|
});
|
|
79
93
|
}
|
|
80
94
|
function convertCopperRegion({
|
|
81
95
|
record,
|
|
82
|
-
recordIndex
|
|
96
|
+
recordIndex,
|
|
97
|
+
sourceNetId
|
|
83
98
|
}) {
|
|
84
99
|
if (record.recordKind !== "Region" || record.regionKind !== "COPPER") {
|
|
85
100
|
return [];
|
|
@@ -95,6 +110,7 @@ function convertCopperRegion({
|
|
|
95
110
|
{
|
|
96
111
|
type: "pcb_copper_pour",
|
|
97
112
|
pcb_copper_pour_id: `pcb_copper_pour_altium_region_${recordIndex}`,
|
|
113
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
98
114
|
covered_with_solder_mask: true,
|
|
99
115
|
layer,
|
|
100
116
|
shape: "polygon",
|
|
@@ -106,6 +122,7 @@ function convertCopperRegion({
|
|
|
106
122
|
{
|
|
107
123
|
type: "pcb_copper_pour",
|
|
108
124
|
pcb_copper_pour_id: `pcb_copper_pour_altium_region_${recordIndex}`,
|
|
125
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
109
126
|
covered_with_solder_mask: true,
|
|
110
127
|
layer,
|
|
111
128
|
shape: "brep",
|
|
@@ -118,7 +135,8 @@ function convertCopperRegion({
|
|
|
118
135
|
}
|
|
119
136
|
function convertCopperPolygon({
|
|
120
137
|
polygonIndex,
|
|
121
|
-
record
|
|
138
|
+
record,
|
|
139
|
+
sourceNetId
|
|
122
140
|
}) {
|
|
123
141
|
const layer = mapAltiumCopperLayer(record.layer);
|
|
124
142
|
if (!layer) return [];
|
|
@@ -128,6 +146,7 @@ function convertCopperPolygon({
|
|
|
128
146
|
{
|
|
129
147
|
type: "pcb_copper_pour",
|
|
130
148
|
pcb_copper_pour_id: `pcb_copper_pour_altium_polygon_${polygonIndex}`,
|
|
149
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
131
150
|
covered_with_solder_mask: true,
|
|
132
151
|
layer,
|
|
133
152
|
shape: "polygon",
|
|
@@ -137,7 +156,8 @@ function convertCopperPolygon({
|
|
|
137
156
|
}
|
|
138
157
|
function convertCopperFill({
|
|
139
158
|
record,
|
|
140
|
-
recordIndex
|
|
159
|
+
recordIndex,
|
|
160
|
+
sourceNetId
|
|
141
161
|
}) {
|
|
142
162
|
const layer = mapAltiumCopperLayer(record.layer);
|
|
143
163
|
if (!layer || !record.bounds) return [];
|
|
@@ -148,6 +168,7 @@ function convertCopperFill({
|
|
|
148
168
|
{
|
|
149
169
|
type: "pcb_copper_pour",
|
|
150
170
|
pcb_copper_pour_id: `pcb_copper_pour_altium_fill_${recordIndex}`,
|
|
171
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
151
172
|
covered_with_solder_mask: true,
|
|
152
173
|
layer,
|
|
153
174
|
shape: "rect",
|
|
@@ -463,6 +484,8 @@ var ALTIUM_TEXT_ANCHORS = [
|
|
|
463
484
|
];
|
|
464
485
|
function convertAltiumPcbDocToCircuitJson(document, options = {}) {
|
|
465
486
|
const elements = [];
|
|
487
|
+
const netContext = createPcbNetContext(document);
|
|
488
|
+
elements.push(...netContext.elements);
|
|
466
489
|
if (options.includeBoardOutline !== false) {
|
|
467
490
|
elements.push(createBoard(document));
|
|
468
491
|
for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {
|
|
@@ -503,7 +526,11 @@ function convertAltiumPcbDocToCircuitJson(document, options = {}) {
|
|
|
503
526
|
elements.push(...convertCourtyards(document));
|
|
504
527
|
}
|
|
505
528
|
if (options.includeCopperAreas !== false) {
|
|
506
|
-
elements.push(
|
|
529
|
+
elements.push(
|
|
530
|
+
...convertAltiumCopperAreas(document, {
|
|
531
|
+
getSourceNetId: netContext.getSourceNetId
|
|
532
|
+
})
|
|
533
|
+
);
|
|
507
534
|
}
|
|
508
535
|
for (const [index, record] of document.records.entries()) {
|
|
509
536
|
if (record instanceof AltiumArcRecord2 && isKeepoutLayer2(record.layer) && options.includeKeepouts !== false) {
|
|
@@ -537,13 +564,13 @@ function convertAltiumPcbDocToCircuitJson(document, options = {}) {
|
|
|
537
564
|
const line = convertSilkscreenLine(record, index);
|
|
538
565
|
if (line) elements.push(line);
|
|
539
566
|
} else if (options.includeTraces !== false) {
|
|
540
|
-
const trace = convertTrack(record, index);
|
|
567
|
+
const trace = convertTrack(record, index, netContext);
|
|
541
568
|
if (trace) elements.push(trace);
|
|
542
569
|
}
|
|
543
570
|
continue;
|
|
544
571
|
}
|
|
545
572
|
if (record instanceof AltiumViaRecord2 && options.includeVias !== false) {
|
|
546
|
-
const via = convertVia(record, index);
|
|
573
|
+
const via = convertVia(record, index, netContext);
|
|
547
574
|
if (via) elements.push(via);
|
|
548
575
|
continue;
|
|
549
576
|
}
|
|
@@ -554,7 +581,7 @@ function convertAltiumPcbDocToCircuitJson(document, options = {}) {
|
|
|
554
581
|
const path = convertSilkscreenArc(record, index);
|
|
555
582
|
if (path) elements.push(path);
|
|
556
583
|
} else if (options.includeTraces !== false) {
|
|
557
|
-
const trace = convertArcTrack(record, index);
|
|
584
|
+
const trace = convertArcTrack(record, index, netContext);
|
|
558
585
|
if (trace) elements.push(trace);
|
|
559
586
|
}
|
|
560
587
|
continue;
|
|
@@ -684,7 +711,10 @@ function convertDimension(record, index) {
|
|
|
684
711
|
}
|
|
685
712
|
function getDimensionText(record, measuredDistanceMils) {
|
|
686
713
|
const explicitText = record.getDecoded("TEXTFORMAT")?.trim();
|
|
687
|
-
|
|
714
|
+
const isMeasurementShapedFormat = explicitText !== void 0 && parseAltiumMeasurementToMils2(explicitText) !== void 0;
|
|
715
|
+
if (explicitText && explicitText !== "<>" && !isMeasurementShapedFormat) {
|
|
716
|
+
return explicitText;
|
|
717
|
+
}
|
|
688
718
|
const precision = Math.min(Math.max(record.precision ?? 2, 0), 6);
|
|
689
719
|
const normalizedUnit = record.unit?.toUpperCase() ?? "MILS";
|
|
690
720
|
let amount = measuredDistanceMils;
|
|
@@ -852,15 +882,61 @@ function getFallbackPcbBounds(records) {
|
|
|
852
882
|
}
|
|
853
883
|
return getAltiumBounds2(points) ?? { minX: 0, minY: 0, maxX: 1e3, maxY: 800 };
|
|
854
884
|
}
|
|
855
|
-
function
|
|
885
|
+
function createPcbNetContext(document) {
|
|
886
|
+
const sourceNetIdByAltiumNet = new Map(
|
|
887
|
+
document.nets.map((net, index) => [net, `source_net_altium_pcb_${index}`])
|
|
888
|
+
);
|
|
889
|
+
const sourceTraceIdByAltiumNet = new Map(
|
|
890
|
+
document.nets.map((net, index) => [
|
|
891
|
+
net,
|
|
892
|
+
`source_trace_altium_pcb_${index}`
|
|
893
|
+
])
|
|
894
|
+
);
|
|
895
|
+
const elements = document.nets.flatMap((net, index) => {
|
|
896
|
+
const name = net.name?.trim() || `Net ${index + 1}`;
|
|
897
|
+
const sourceNetId = sourceNetIdByAltiumNet.get(net);
|
|
898
|
+
const sourceTraceId = sourceTraceIdByAltiumNet.get(net);
|
|
899
|
+
if (!sourceNetId || !sourceTraceId) return [];
|
|
900
|
+
return [
|
|
901
|
+
{
|
|
902
|
+
type: "source_net",
|
|
903
|
+
source_net_id: sourceNetId,
|
|
904
|
+
name,
|
|
905
|
+
member_source_group_ids: []
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
type: "source_trace",
|
|
909
|
+
source_trace_id: sourceTraceId,
|
|
910
|
+
connected_source_port_ids: [],
|
|
911
|
+
connected_source_net_ids: [sourceNetId],
|
|
912
|
+
name,
|
|
913
|
+
display_name: name
|
|
914
|
+
}
|
|
915
|
+
];
|
|
916
|
+
});
|
|
917
|
+
return {
|
|
918
|
+
elements,
|
|
919
|
+
getSourceNetId: (record) => {
|
|
920
|
+
const net = document.getNetForRecord(record);
|
|
921
|
+
return net ? sourceNetIdByAltiumNet.get(net) : void 0;
|
|
922
|
+
},
|
|
923
|
+
getSourceTraceId: (record) => {
|
|
924
|
+
const net = document.getNetForRecord(record);
|
|
925
|
+
return net ? sourceTraceIdByAltiumNet.get(net) : void 0;
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function convertTrack(record, index, netContext) {
|
|
856
930
|
const start = record.start;
|
|
857
931
|
const end = record.end;
|
|
858
932
|
const layer = mapAltiumCopperLayer(record.layer);
|
|
859
933
|
if (!start || !end || !layer) return void 0;
|
|
860
934
|
const width = milsToMillimeters2(record.widthMils ?? 4);
|
|
935
|
+
const sourceTraceId = netContext.getSourceTraceId(record);
|
|
861
936
|
return {
|
|
862
937
|
type: "pcb_trace",
|
|
863
938
|
pcb_trace_id: `pcb_trace_altium_${index}`,
|
|
939
|
+
...sourceTraceId ? { source_trace_id: sourceTraceId } : {},
|
|
864
940
|
should_round_corners: true,
|
|
865
941
|
route: [
|
|
866
942
|
{ route_type: "wire", ...toMillimeterPoint(start), width, layer },
|
|
@@ -868,7 +944,7 @@ function convertTrack(record, index) {
|
|
|
868
944
|
]
|
|
869
945
|
};
|
|
870
946
|
}
|
|
871
|
-
function convertArcTrack(record, index) {
|
|
947
|
+
function convertArcTrack(record, index, netContext) {
|
|
872
948
|
if (!record.center || !record.radiusMils) return void 0;
|
|
873
949
|
const layer = mapAltiumCopperLayer(record.layer);
|
|
874
950
|
if (!layer) return void 0;
|
|
@@ -879,9 +955,11 @@ function convertArcTrack(record, index) {
|
|
|
879
955
|
startAngle: record.startAngle,
|
|
880
956
|
endAngle: record.endAngle
|
|
881
957
|
});
|
|
958
|
+
const sourceTraceId = netContext.getSourceTraceId(record);
|
|
882
959
|
return {
|
|
883
960
|
type: "pcb_trace",
|
|
884
961
|
pcb_trace_id: `pcb_trace_altium_arc_${index}`,
|
|
962
|
+
...sourceTraceId ? { source_trace_id: sourceTraceId } : {},
|
|
885
963
|
should_round_corners: true,
|
|
886
964
|
route: points.map((point) => ({
|
|
887
965
|
route_type: "wire",
|
|
@@ -910,15 +988,19 @@ function convertCopperText(record, index) {
|
|
|
910
988
|
is_mirrored: record.mirrored
|
|
911
989
|
};
|
|
912
990
|
}
|
|
913
|
-
function convertVia(record, index) {
|
|
991
|
+
function convertVia(record, index, netContext) {
|
|
914
992
|
if (!record.position) return void 0;
|
|
915
993
|
const startLayer = mapAltiumCopperLayer(record.startLayer) ?? "top";
|
|
916
994
|
const endLayer = mapAltiumCopperLayer(record.endLayer) ?? "bottom";
|
|
917
995
|
const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer];
|
|
918
996
|
const outerDiameter = milsToMillimeters2(record.diameterMils ?? 20);
|
|
997
|
+
const sourceNetId = netContext.getSourceNetId(record);
|
|
998
|
+
const sourceTraceId = netContext.getSourceTraceId(record);
|
|
919
999
|
return {
|
|
920
1000
|
type: "pcb_via",
|
|
921
1001
|
pcb_via_id: `pcb_via_altium_${index}`,
|
|
1002
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
1003
|
+
...sourceTraceId ? { source_trace_id: sourceTraceId } : {},
|
|
922
1004
|
...toMillimeterPoint(record.position),
|
|
923
1005
|
outer_diameter: outerDiameter,
|
|
924
1006
|
hole_diameter: milsToMillimeters2(
|