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 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({ record, recordIndex });
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({ polygonIndex, record });
78
+ return convertCopperPolygon({
79
+ polygonIndex,
80
+ record,
81
+ sourceNetId: getSourceNetId(record)
82
+ });
73
83
  }
74
84
  if (record instanceof AltiumFillRecord) {
75
- return convertCopperFill({ record, recordIndex });
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(...convertAltiumCopperAreas(document));
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
- if (explicitText && explicitText !== "<>") return explicitText;
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 convertTrack(record, index) {
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(