circuit-json-to-kicad 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,6 +13,10 @@ interface PaperDimensions {
13
13
  type SchematicPortId = string;
14
14
  type SchematicTraceId = string;
15
15
  type PcbPortId = string;
16
+ interface PcbNetInfo {
17
+ id: number;
18
+ name: string;
19
+ }
16
20
  interface ConverterContext {
17
21
  db: CircuitJsonUtilObjects;
18
22
  circuitJson: CircuitJson;
@@ -33,7 +37,7 @@ interface ConverterContext {
33
37
  x: number;
34
38
  y: number;
35
39
  }>;
36
- pcbNetMap?: Map<string, number>;
40
+ pcbNetMap?: Map<string, PcbNetInfo>;
37
41
  }
38
42
  declare abstract class ConverterStage<Input, Output> {
39
43
  MAX_ITERATIONS: number;
package/dist/index.js CHANGED
@@ -1347,27 +1347,49 @@ var AddNetsStage = class extends ConverterStage {
1347
1347
  if (!kicadPcb) {
1348
1348
  throw new Error("KicadPcb instance not initialized in context");
1349
1349
  }
1350
- if (!this.ctx.pcbNetMap) {
1351
- this.ctx.pcbNetMap = /* @__PURE__ */ new Map();
1352
- }
1353
- const pcbTraces = this.ctx.db.pcb_trace.list();
1354
- const netNames = /* @__PURE__ */ new Set();
1355
- netNames.add("GND");
1356
- for (const trace of pcbTraces) {
1357
- if (trace.route && trace.route.length > 0) {
1358
- const netName = `Net-${trace.pcb_trace_id}`;
1359
- netNames.add(netName);
1350
+ this.ctx.pcbNetMap = /* @__PURE__ */ new Map();
1351
+ const netNameByKey = /* @__PURE__ */ new Map();
1352
+ const sourceNets = this.ctx.db.source_net?.list() ?? [];
1353
+ for (const sourceNet of sourceNets) {
1354
+ const connectivityKey = sourceNet.subcircuit_connectivity_map_key || sourceNet.source_net_id;
1355
+ if (!connectivityKey) continue;
1356
+ const candidateName = sourceNet.name || sourceNet.source_net_id || "";
1357
+ const netName = candidateName && candidateName.trim().length > 0 ? candidateName : connectivityKey;
1358
+ netNameByKey.set(connectivityKey, netName);
1359
+ }
1360
+ const sourceTraces = this.ctx.db.source_trace?.list() ?? [];
1361
+ for (const sourceTrace of sourceTraces) {
1362
+ let connectivityKey = sourceTrace.subcircuit_connectivity_map_key;
1363
+ if (!connectivityKey && sourceTrace.connected_source_net_ids?.length) {
1364
+ for (const sourceNetId of sourceTrace.connected_source_net_ids) {
1365
+ const connectedNet = this.ctx.db.source_net?.get(sourceNetId);
1366
+ if (connectedNet?.subcircuit_connectivity_map_key && connectedNet.subcircuit_connectivity_map_key.length > 0) {
1367
+ connectivityKey = connectedNet.subcircuit_connectivity_map_key;
1368
+ break;
1369
+ }
1370
+ }
1371
+ }
1372
+ if (!connectivityKey) continue;
1373
+ if (!netNameByKey.has(connectivityKey)) {
1374
+ const candidateName = sourceTrace.display_name || sourceTrace.source_trace_id || "";
1375
+ const netName = candidateName && candidateName.trim().length > 0 ? candidateName : connectivityKey;
1376
+ netNameByKey.set(connectivityKey, netName);
1360
1377
  }
1361
1378
  }
1362
- let netNumber = 0;
1363
- for (const netName of Array.from(netNames).sort()) {
1364
- const net = new PcbNet(netNumber, netName);
1365
- const nets = kicadPcb.nets;
1366
- nets.push(net);
1367
- kicadPcb.nets = nets;
1368
- this.ctx.pcbNetMap.set(netName, netNumber);
1379
+ const sortedEntries = Array.from(netNameByKey.entries()).sort(
1380
+ (a, b) => a[0].localeCompare(b[0])
1381
+ );
1382
+ const nets = [];
1383
+ nets.push(new PcbNet(0, ""));
1384
+ let netNumber = 1;
1385
+ for (const [connectivityKey, netName] of sortedEntries) {
1386
+ const pcbNet = new PcbNet(netNumber, netName);
1387
+ nets.push(pcbNet);
1388
+ const netInfo = { id: netNumber, name: netName };
1389
+ this.ctx.pcbNetMap.set(connectivityKey, netInfo);
1369
1390
  netNumber++;
1370
1391
  }
1392
+ kicadPcb.nets = nets;
1371
1393
  this.finished = true;
1372
1394
  }
1373
1395
  getOutput() {
@@ -1386,7 +1408,8 @@ import {
1386
1408
  PadPrimitiveGrPoly,
1387
1409
  Pts as Pts3,
1388
1410
  Xy as Xy3,
1389
- PadOptions
1411
+ PadOptions,
1412
+ PadNet
1390
1413
  } from "kicadts";
1391
1414
  import {
1392
1415
  applyToPoint as applyToPoint5,
@@ -1399,7 +1422,8 @@ function createSmdPadFromCircuitJson({
1399
1422
  pcbPad,
1400
1423
  componentCenter,
1401
1424
  padNumber,
1402
- componentRotation = 0
1425
+ componentRotation = 0,
1426
+ netInfo
1403
1427
  }) {
1404
1428
  let padX;
1405
1429
  let padY;
@@ -1485,17 +1509,21 @@ function createSmdPadFromCircuitJson({
1485
1509
  if (padPrimitives) {
1486
1510
  pad.primitives = padPrimitives;
1487
1511
  }
1512
+ if (netInfo) {
1513
+ pad.net = new PadNet(netInfo.id, netInfo.name);
1514
+ }
1488
1515
  return pad;
1489
1516
  }
1490
1517
 
1491
1518
  // lib/pcb/stages/utils/CreateThruHolePadFromCircuitJson.ts
1492
- import { FootprintPad as FootprintPad2, PadDrill } from "kicadts";
1519
+ import { FootprintPad as FootprintPad2, PadDrill, PadNet as PadNet2 } from "kicadts";
1493
1520
  import { applyToPoint as applyToPoint6, rotate as rotate2, identity } from "transformation-matrix";
1494
1521
  function createThruHolePadFromCircuitJson({
1495
1522
  platedHole,
1496
1523
  componentCenter,
1497
1524
  padNumber,
1498
- componentRotation = 0
1525
+ componentRotation = 0,
1526
+ netInfo
1499
1527
  }) {
1500
1528
  if (!("x" in platedHole && "y" in platedHole)) {
1501
1529
  return null;
@@ -1511,11 +1539,27 @@ function createThruHolePadFromCircuitJson({
1511
1539
  let padSize;
1512
1540
  let drill;
1513
1541
  let rotation = 0;
1542
+ const hasHoleOffset = "hole_offset_x" in platedHole || "hole_offset_y" in platedHole;
1543
+ let drillOffset;
1544
+ if (hasHoleOffset) {
1545
+ const rawOffset = {
1546
+ x: platedHole.hole_offset_x ?? 0,
1547
+ y: platedHole.hole_offset_y ?? 0
1548
+ };
1549
+ if (rawOffset.x !== 0 || rawOffset.y !== 0) {
1550
+ const rotatedOffset = applyToPoint6(rotationMatrix, {
1551
+ x: -rawOffset.x,
1552
+ y: rawOffset.y
1553
+ });
1554
+ drillOffset = rotatedOffset;
1555
+ }
1556
+ }
1514
1557
  if (platedHole.shape === "circle") {
1515
1558
  padShape = "circle";
1516
1559
  padSize = [platedHole.outer_diameter, platedHole.outer_diameter];
1517
1560
  drill = new PadDrill({
1518
- diameter: platedHole.hole_diameter
1561
+ diameter: platedHole.hole_diameter,
1562
+ offset: drillOffset
1519
1563
  });
1520
1564
  } else if (platedHole.shape === "pill" || platedHole.shape === "oval") {
1521
1565
  padShape = "oval";
@@ -1526,7 +1570,8 @@ function createThruHolePadFromCircuitJson({
1526
1570
  drill = new PadDrill({
1527
1571
  oval: true,
1528
1572
  diameter: platedHole.hole_width,
1529
- width: platedHole.hole_height
1573
+ width: platedHole.hole_height,
1574
+ offset: drillOffset
1530
1575
  });
1531
1576
  } else if (platedHole.shape === "pill_hole_with_rect_pad") {
1532
1577
  padShape = "rect";
@@ -1537,7 +1582,8 @@ function createThruHolePadFromCircuitJson({
1537
1582
  drill = new PadDrill({
1538
1583
  oval: true,
1539
1584
  diameter: platedHole.hole_width,
1540
- width: platedHole.hole_height
1585
+ width: platedHole.hole_height,
1586
+ offset: drillOffset
1541
1587
  });
1542
1588
  } else if (platedHole.shape === "circular_hole_with_rect_pad") {
1543
1589
  padShape = "rect";
@@ -1546,7 +1592,8 @@ function createThruHolePadFromCircuitJson({
1546
1592
  platedHole.rect_pad_height
1547
1593
  ];
1548
1594
  drill = new PadDrill({
1549
- diameter: platedHole.hole_diameter
1595
+ diameter: platedHole.hole_diameter,
1596
+ offset: drillOffset
1550
1597
  });
1551
1598
  } else if (platedHole.shape === "rotated_pill_hole_with_rect_pad") {
1552
1599
  padShape = "rect";
@@ -1557,15 +1604,16 @@ function createThruHolePadFromCircuitJson({
1557
1604
  drill = new PadDrill({
1558
1605
  oval: true,
1559
1606
  diameter: platedHole.hole_width,
1560
- width: platedHole.hole_height
1607
+ width: platedHole.hole_height,
1608
+ offset: drillOffset
1561
1609
  });
1562
1610
  rotation = platedHole.rect_ccw_rotation || 0;
1563
1611
  } else {
1564
1612
  padShape = "circle";
1565
1613
  padSize = [1.6, 1.6];
1566
- drill = new PadDrill({ diameter: 0.8 });
1614
+ drill = new PadDrill({ diameter: 0.8, offset: drillOffset });
1567
1615
  }
1568
- return new FootprintPad2({
1616
+ const pad = new FootprintPad2({
1569
1617
  number: String(padNumber),
1570
1618
  padType: "thru_hole",
1571
1619
  shape: padShape,
@@ -1576,6 +1624,10 @@ function createThruHolePadFromCircuitJson({
1576
1624
  removeUnusedLayers: false,
1577
1625
  uuid: crypto.randomUUID()
1578
1626
  });
1627
+ if (netInfo) {
1628
+ pad.net = new PadNet2(netInfo.id, netInfo.name);
1629
+ }
1630
+ return pad;
1579
1631
  }
1580
1632
 
1581
1633
  // lib/pcb/stages/utils/CreateNpthPadFromCircuitJson.ts
@@ -1687,6 +1739,18 @@ function createFpTextFromCircuitJson({
1687
1739
  var AddFootprintsStage = class extends ConverterStage {
1688
1740
  componentsProcessed = 0;
1689
1741
  pcbComponents = [];
1742
+ getNetInfoForPcbPort(pcbPortId) {
1743
+ if (!pcbPortId) return void 0;
1744
+ const pcbPort = this.ctx.db.pcb_port?.get(pcbPortId);
1745
+ if (!pcbPort) return void 0;
1746
+ const sourcePortId = pcbPort.source_port_id;
1747
+ if (!sourcePortId) return void 0;
1748
+ const sourcePort = this.ctx.db.source_port?.get(sourcePortId);
1749
+ if (!sourcePort) return void 0;
1750
+ const connectivityKey = sourcePort.subcircuit_connectivity_map_key;
1751
+ if (!connectivityKey) return void 0;
1752
+ return this.ctx.pcbNetMap?.get(connectivityKey);
1753
+ }
1690
1754
  constructor(input, ctx) {
1691
1755
  super(input, ctx);
1692
1756
  this.pcbComponents = this.ctx.db.pcb_component.list();
@@ -1737,11 +1801,13 @@ var AddFootprintsStage = class extends ConverterStage {
1737
1801
  const fpPads = footprint.fpPads;
1738
1802
  let padNumber = 1;
1739
1803
  for (const pcbPad of pcbPads) {
1804
+ const netInfo = this.getNetInfoForPcbPort(pcbPad.pcb_port_id);
1740
1805
  const pad = createSmdPadFromCircuitJson({
1741
1806
  pcbPad,
1742
1807
  componentCenter: component.center,
1743
1808
  padNumber,
1744
- componentRotation: component.rotation || 0
1809
+ componentRotation: component.rotation || 0,
1810
+ netInfo
1745
1811
  });
1746
1812
  fpPads.push(pad);
1747
1813
  padNumber++;
@@ -1750,11 +1816,13 @@ var AddFootprintsStage = class extends ConverterStage {
1750
1816
  (hole) => hole.pcb_component_id === component.pcb_component_id
1751
1817
  ) || [];
1752
1818
  for (const platedHole of pcbPlatedHoles) {
1819
+ const netInfo = this.getNetInfoForPcbPort(platedHole.pcb_port_id);
1753
1820
  const pad = createThruHolePadFromCircuitJson({
1754
1821
  platedHole,
1755
1822
  componentCenter: component.center,
1756
1823
  padNumber,
1757
- componentRotation: component.rotation || 0
1824
+ componentRotation: component.rotation || 0,
1825
+ netInfo
1758
1826
  });
1759
1827
  if (pad) {
1760
1828
  fpPads.push(pad);
@@ -1823,10 +1891,35 @@ var AddTracesStage = class extends ConverterStage {
1823
1891
  x: endPoint.x,
1824
1892
  y: endPoint.y
1825
1893
  });
1826
- let netNumber = 0;
1894
+ let netInfo;
1827
1895
  if (pcbNetMap) {
1828
- const netName = `Net-${trace.pcb_trace_id}`;
1829
- netNumber = pcbNetMap.get(netName) ?? 0;
1896
+ let connectivityKey = trace.subcircuit_connectivity_map_key;
1897
+ if (!connectivityKey && trace.source_trace_id) {
1898
+ const sourceTrace = this.ctx.db.source_trace?.get(
1899
+ trace.source_trace_id
1900
+ );
1901
+ if (sourceTrace) {
1902
+ connectivityKey = sourceTrace.subcircuit_connectivity_map_key;
1903
+ if (!connectivityKey && sourceTrace.connected_source_net_ids?.length) {
1904
+ for (const sourceNetId of sourceTrace.connected_source_net_ids) {
1905
+ const sourceNet = this.ctx.db.source_net?.get(sourceNetId);
1906
+ if (sourceNet?.subcircuit_connectivity_map_key) {
1907
+ connectivityKey = sourceNet.subcircuit_connectivity_map_key;
1908
+ break;
1909
+ }
1910
+ }
1911
+ }
1912
+ }
1913
+ }
1914
+ if (!connectivityKey && typeof trace.connection_name === "string") {
1915
+ const sourceNet = this.ctx.db.source_net?.get(trace.connection_name);
1916
+ if (sourceNet?.subcircuit_connectivity_map_key) {
1917
+ connectivityKey = sourceNet.subcircuit_connectivity_map_key;
1918
+ }
1919
+ }
1920
+ if (connectivityKey) {
1921
+ netInfo = pcbNetMap.get(connectivityKey);
1922
+ }
1830
1923
  }
1831
1924
  const layerMap = {
1832
1925
  top: "F.Cu",
@@ -1838,7 +1931,8 @@ var AddTracesStage = class extends ConverterStage {
1838
1931
  end: { x: transformedEnd.x, y: transformedEnd.y },
1839
1932
  layer: kicadLayer,
1840
1933
  width: trace.width || 0.25,
1841
- net: new SegmentNet(netNumber)
1934
+ net: new SegmentNet(netInfo?.id ?? 0),
1935
+ uuid: crypto.randomUUID()
1842
1936
  });
1843
1937
  const segments = kicadPcb.segments;
1844
1938
  segments.push(segment);
@@ -1878,16 +1972,53 @@ var AddViasStage = class extends ConverterStage {
1878
1972
  x: via.x,
1879
1973
  y: via.y
1880
1974
  });
1881
- let netNumber = 0;
1882
- if (pcbNetMap && via.net_name) {
1883
- netNumber = pcbNetMap.get(via.net_name) ?? 0;
1975
+ let netInfo;
1976
+ if (pcbNetMap) {
1977
+ let connectivityKey = via.subcircuit_connectivity_map_key;
1978
+ if (!connectivityKey && via.pcb_trace_id) {
1979
+ const pcbTrace = this.ctx.db.pcb_trace?.get(via.pcb_trace_id);
1980
+ if (pcbTrace) {
1981
+ if ("subcircuit_connectivity_map_key" in pcbTrace) {
1982
+ connectivityKey = pcbTrace.subcircuit_connectivity_map_key;
1983
+ }
1984
+ if (!connectivityKey && pcbTrace.source_trace_id) {
1985
+ const sourceTrace = this.ctx.db.source_trace?.get(
1986
+ pcbTrace.source_trace_id
1987
+ );
1988
+ if (sourceTrace) {
1989
+ if ("subcircuit_connectivity_map_key" in sourceTrace) {
1990
+ connectivityKey = sourceTrace.subcircuit_connectivity_map_key;
1991
+ }
1992
+ if (!connectivityKey && sourceTrace.connected_source_net_ids?.length) {
1993
+ for (const sourceNetId of sourceTrace.connected_source_net_ids) {
1994
+ const sourceNet = this.ctx.db.source_net?.get(sourceNetId);
1995
+ if (sourceNet?.subcircuit_connectivity_map_key) {
1996
+ connectivityKey = sourceNet.subcircuit_connectivity_map_key;
1997
+ break;
1998
+ }
1999
+ }
2000
+ }
2001
+ }
2002
+ }
2003
+ }
2004
+ }
2005
+ if (!connectivityKey && via.connection_name) {
2006
+ const sourceNet = this.ctx.db.source_net?.get(via.connection_name);
2007
+ if (sourceNet?.subcircuit_connectivity_map_key) {
2008
+ connectivityKey = sourceNet.subcircuit_connectivity_map_key;
2009
+ }
2010
+ }
2011
+ if (connectivityKey) {
2012
+ netInfo = pcbNetMap.get(connectivityKey);
2013
+ }
1884
2014
  }
1885
2015
  const kicadVia = new Via({
1886
2016
  at: [transformedPos.x, transformedPos.y],
1887
2017
  size: via.outer_diameter || 0.8,
1888
2018
  drill: via.hole_diameter || 0.4,
1889
2019
  layers: ["F.Cu", "B.Cu"],
1890
- net: new ViaNet(netNumber)
2020
+ net: new ViaNet(netInfo?.id ?? 0),
2021
+ uuid: crypto.randomUUID()
1891
2022
  });
1892
2023
  const vias = kicadPcb.vias;
1893
2024
  vias.push(kicadVia);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "circuit-json-to-kicad",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.24",
4
+ "version": "0.0.26",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"