circuit-json-to-kicad 0.0.23 → 0.0.25

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.
Files changed (2) hide show
  1. package/dist/index.js +123 -41
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -399,14 +399,14 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
399
399
  */
400
400
  createPolylineFromPoints({
401
401
  points,
402
- scale: scale3,
402
+ scale: scale4,
403
403
  center,
404
404
  fillType
405
405
  }) {
406
406
  const polyline = new SymbolPolyline();
407
407
  const cx = center?.x ?? 0;
408
408
  const cy = center?.y ?? 0;
409
- const scaleMatrix = createScaleMatrix(scale3, scale3);
409
+ const scaleMatrix = createScaleMatrix(scale4, scale4);
410
410
  const xyPoints = points.map((p) => {
411
411
  const translated = applyToPoint(scaleMatrix, { x: p.x - cx, y: p.y - cy });
412
412
  return new Xy(translated.x, translated.y);
@@ -1277,7 +1277,7 @@ var CircuitJsonToKicadSchConverter = class {
1277
1277
  // lib/pcb/CircuitJsonToKicadPcbConverter.ts
1278
1278
  import { KicadPcb } from "kicadts";
1279
1279
  import { cju as cju2 } from "@tscircuit/circuit-json-util";
1280
- import { compose as compose2, translate as translate2, scale as scale2 } from "transformation-matrix";
1280
+ import { compose as compose3, translate as translate3, scale as scale3 } from "transformation-matrix";
1281
1281
 
1282
1282
  // lib/pcb/stages/InitializePcbStage.ts
1283
1283
  import {
@@ -1380,38 +1380,93 @@ import { Footprint } from "kicadts";
1380
1380
  import { applyToPoint as applyToPoint9 } from "transformation-matrix";
1381
1381
 
1382
1382
  // lib/pcb/stages/utils/CreateSmdPadFromCircuitJson.ts
1383
- import { FootprintPad } from "kicadts";
1384
- import { applyToPoint as applyToPoint5, rotate, identity } from "transformation-matrix";
1383
+ import {
1384
+ FootprintPad,
1385
+ PadPrimitives,
1386
+ PadPrimitiveGrPoly,
1387
+ Pts as Pts3,
1388
+ Xy as Xy3,
1389
+ PadOptions
1390
+ } from "kicadts";
1391
+ import {
1392
+ applyToPoint as applyToPoint5,
1393
+ compose as compose2,
1394
+ translate as translate2,
1395
+ scale as scale2,
1396
+ rotate
1397
+ } from "transformation-matrix";
1385
1398
  function createSmdPadFromCircuitJson({
1386
1399
  pcbPad,
1387
1400
  componentCenter,
1388
1401
  padNumber,
1389
1402
  componentRotation = 0
1390
1403
  }) {
1391
- if (!("x" in pcbPad && "y" in pcbPad)) {
1392
- throw new Error("no support for polygon pads (or any pads w/o X/Y) yet");
1393
- }
1394
- const relativeX = pcbPad.x - componentCenter.x;
1395
- const relativeY = -(pcbPad.y - componentCenter.y);
1396
- const rotationMatrix = componentRotation !== 0 ? rotate(componentRotation * Math.PI / 180) : identity();
1397
- const rotatedPos = applyToPoint5(rotationMatrix, {
1398
- x: relativeX,
1399
- y: relativeY
1404
+ let padX;
1405
+ let padY;
1406
+ if ("x" in pcbPad && "y" in pcbPad) {
1407
+ padX = pcbPad.x;
1408
+ padY = pcbPad.y;
1409
+ } else if ("points" in pcbPad && Array.isArray(pcbPad.points)) {
1410
+ const points = pcbPad.points;
1411
+ padX = points.reduce((sum, p) => sum + p.x, 0) / points.length;
1412
+ padY = points.reduce((sum, p) => sum + p.y, 0) / points.length;
1413
+ } else {
1414
+ throw new Error("Pad must have either x/y coordinates or points array");
1415
+ }
1416
+ const cj2kicadMatrix = compose2(
1417
+ componentRotation !== 0 ? rotate(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 },
1418
+ scale2(1, -1),
1419
+ // Flip Y-axis
1420
+ translate2(-componentCenter.x, -componentCenter.y)
1421
+ );
1422
+ const rotatedPos = applyToPoint5(cj2kicadMatrix, {
1423
+ x: padX,
1424
+ y: padY
1400
1425
  });
1401
1426
  const layerMap = {
1402
1427
  top: "F.Cu",
1403
1428
  bottom: "B.Cu"
1404
1429
  };
1405
1430
  const padLayer = layerMap[pcbPad.layer] || "F.Cu";
1406
- const padShape = pcbPad.shape === "circle" ? "circle" : "rect";
1407
- const padSize = pcbPad.shape === "circle" ? [
1408
- "radius" in pcbPad ? pcbPad.radius * 2 : 0.5,
1409
- "radius" in pcbPad ? pcbPad.radius * 2 : 0.5
1410
- ] : [
1411
- "width" in pcbPad ? pcbPad.width : 0.5,
1412
- "height" in pcbPad ? pcbPad.height : 0.5
1413
- ];
1414
- return new FootprintPad({
1431
+ let padShape;
1432
+ let padSize;
1433
+ let padOptions;
1434
+ let padPrimitives;
1435
+ if (pcbPad.shape === "circle") {
1436
+ padShape = "circle";
1437
+ padSize = [
1438
+ "radius" in pcbPad ? pcbPad.radius * 2 : 0.5,
1439
+ "radius" in pcbPad ? pcbPad.radius * 2 : 0.5
1440
+ ];
1441
+ } else if (pcbPad.shape === "polygon" && "points" in pcbPad) {
1442
+ const points = pcbPad.points;
1443
+ const pointTransformMatrix = compose2(
1444
+ scale2(1, -1),
1445
+ // Flip Y-axis
1446
+ translate2(-padX, -padY)
1447
+ );
1448
+ const relativePoints = points.map((p) => {
1449
+ const transformed = applyToPoint5(pointTransformMatrix, { x: p.x, y: p.y });
1450
+ return new Xy3(transformed.x, transformed.y);
1451
+ });
1452
+ const grPoly = new PadPrimitiveGrPoly();
1453
+ grPoly.contours = [new Pts3(relativePoints)];
1454
+ grPoly.width = 0;
1455
+ grPoly.filled = true;
1456
+ padPrimitives = new PadPrimitives();
1457
+ padPrimitives.addGraphic(grPoly);
1458
+ padShape = "custom";
1459
+ padOptions = new PadOptions();
1460
+ padOptions.anchor = "circle";
1461
+ padSize = [0.2, 0.2];
1462
+ } else {
1463
+ padShape = "rect";
1464
+ padSize = [
1465
+ "width" in pcbPad ? pcbPad.width : 0.5,
1466
+ "height" in pcbPad ? pcbPad.height : 0.5
1467
+ ];
1468
+ }
1469
+ const pad = new FootprintPad({
1415
1470
  number: String(padNumber),
1416
1471
  padType: "smd",
1417
1472
  shape: padShape,
@@ -1424,11 +1479,18 @@ function createSmdPadFromCircuitJson({
1424
1479
  ],
1425
1480
  uuid: crypto.randomUUID()
1426
1481
  });
1482
+ if (padOptions) {
1483
+ pad.options = padOptions;
1484
+ }
1485
+ if (padPrimitives) {
1486
+ pad.primitives = padPrimitives;
1487
+ }
1488
+ return pad;
1427
1489
  }
1428
1490
 
1429
1491
  // lib/pcb/stages/utils/CreateThruHolePadFromCircuitJson.ts
1430
1492
  import { FootprintPad as FootprintPad2, PadDrill } from "kicadts";
1431
- import { applyToPoint as applyToPoint6, rotate as rotate2, identity as identity2 } from "transformation-matrix";
1493
+ import { applyToPoint as applyToPoint6, rotate as rotate2, identity } from "transformation-matrix";
1432
1494
  function createThruHolePadFromCircuitJson({
1433
1495
  platedHole,
1434
1496
  componentCenter,
@@ -1440,7 +1502,7 @@ function createThruHolePadFromCircuitJson({
1440
1502
  }
1441
1503
  const relativeX = platedHole.x - componentCenter.x;
1442
1504
  const relativeY = -(platedHole.y - componentCenter.y);
1443
- const rotationMatrix = componentRotation !== 0 ? rotate2(componentRotation * Math.PI / 180) : identity2();
1505
+ const rotationMatrix = componentRotation !== 0 ? rotate2(componentRotation * Math.PI / 180) : identity();
1444
1506
  const rotatedPos = applyToPoint6(rotationMatrix, {
1445
1507
  x: relativeX,
1446
1508
  y: relativeY
@@ -1449,11 +1511,27 @@ function createThruHolePadFromCircuitJson({
1449
1511
  let padSize;
1450
1512
  let drill;
1451
1513
  let rotation = 0;
1514
+ const hasHoleOffset = "hole_offset_x" in platedHole || "hole_offset_y" in platedHole;
1515
+ let drillOffset;
1516
+ if (hasHoleOffset) {
1517
+ const rawOffset = {
1518
+ x: platedHole.hole_offset_x ?? 0,
1519
+ y: platedHole.hole_offset_y ?? 0
1520
+ };
1521
+ if (rawOffset.x !== 0 || rawOffset.y !== 0) {
1522
+ const rotatedOffset = applyToPoint6(rotationMatrix, {
1523
+ x: -rawOffset.x,
1524
+ y: rawOffset.y
1525
+ });
1526
+ drillOffset = rotatedOffset;
1527
+ }
1528
+ }
1452
1529
  if (platedHole.shape === "circle") {
1453
1530
  padShape = "circle";
1454
1531
  padSize = [platedHole.outer_diameter, platedHole.outer_diameter];
1455
1532
  drill = new PadDrill({
1456
- diameter: platedHole.hole_diameter
1533
+ diameter: platedHole.hole_diameter,
1534
+ offset: drillOffset
1457
1535
  });
1458
1536
  } else if (platedHole.shape === "pill" || platedHole.shape === "oval") {
1459
1537
  padShape = "oval";
@@ -1464,7 +1542,8 @@ function createThruHolePadFromCircuitJson({
1464
1542
  drill = new PadDrill({
1465
1543
  oval: true,
1466
1544
  diameter: platedHole.hole_width,
1467
- width: platedHole.hole_height
1545
+ width: platedHole.hole_height,
1546
+ offset: drillOffset
1468
1547
  });
1469
1548
  } else if (platedHole.shape === "pill_hole_with_rect_pad") {
1470
1549
  padShape = "rect";
@@ -1475,7 +1554,8 @@ function createThruHolePadFromCircuitJson({
1475
1554
  drill = new PadDrill({
1476
1555
  oval: true,
1477
1556
  diameter: platedHole.hole_width,
1478
- width: platedHole.hole_height
1557
+ width: platedHole.hole_height,
1558
+ offset: drillOffset
1479
1559
  });
1480
1560
  } else if (platedHole.shape === "circular_hole_with_rect_pad") {
1481
1561
  padShape = "rect";
@@ -1484,7 +1564,8 @@ function createThruHolePadFromCircuitJson({
1484
1564
  platedHole.rect_pad_height
1485
1565
  ];
1486
1566
  drill = new PadDrill({
1487
- diameter: platedHole.hole_diameter
1567
+ diameter: platedHole.hole_diameter,
1568
+ offset: drillOffset
1488
1569
  });
1489
1570
  } else if (platedHole.shape === "rotated_pill_hole_with_rect_pad") {
1490
1571
  padShape = "rect";
@@ -1495,13 +1576,14 @@ function createThruHolePadFromCircuitJson({
1495
1576
  drill = new PadDrill({
1496
1577
  oval: true,
1497
1578
  diameter: platedHole.hole_width,
1498
- width: platedHole.hole_height
1579
+ width: platedHole.hole_height,
1580
+ offset: drillOffset
1499
1581
  });
1500
1582
  rotation = platedHole.rect_ccw_rotation || 0;
1501
1583
  } else {
1502
1584
  padShape = "circle";
1503
1585
  padSize = [1.6, 1.6];
1504
- drill = new PadDrill({ diameter: 0.8 });
1586
+ drill = new PadDrill({ diameter: 0.8, offset: drillOffset });
1505
1587
  }
1506
1588
  return new FootprintPad2({
1507
1589
  number: String(padNumber),
@@ -1518,7 +1600,7 @@ function createThruHolePadFromCircuitJson({
1518
1600
 
1519
1601
  // lib/pcb/stages/utils/CreateNpthPadFromCircuitJson.ts
1520
1602
  import { FootprintPad as FootprintPad3, PadDrill as PadDrill2 } from "kicadts";
1521
- import { applyToPoint as applyToPoint7, rotate as rotate3, identity as identity3 } from "transformation-matrix";
1603
+ import { applyToPoint as applyToPoint7, rotate as rotate3, identity as identity2 } from "transformation-matrix";
1522
1604
  function createNpthPadFromCircuitJson({
1523
1605
  pcbHole,
1524
1606
  componentCenter,
@@ -1529,7 +1611,7 @@ function createNpthPadFromCircuitJson({
1529
1611
  }
1530
1612
  const relativeX = pcbHole.x - componentCenter.x;
1531
1613
  const relativeY = -(pcbHole.y - componentCenter.y);
1532
- const rotationMatrix = componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : identity3();
1614
+ const rotationMatrix = componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : identity2();
1533
1615
  const rotatedPos = applyToPoint7(rotationMatrix, {
1534
1616
  x: relativeX,
1535
1617
  y: relativeY
@@ -1556,7 +1638,7 @@ function createNpthPadFromCircuitJson({
1556
1638
  });
1557
1639
  } else {
1558
1640
  padShape = "circle";
1559
- const diameter = pcbHole.hole_diameter || 1;
1641
+ const diameter = "hole_diameter" in pcbHole ? pcbHole.hole_diameter : 1;
1560
1642
  padSize = [diameter, diameter];
1561
1643
  drill = new PadDrill2({ diameter });
1562
1644
  }
@@ -1576,7 +1658,7 @@ function createNpthPadFromCircuitJson({
1576
1658
 
1577
1659
  // lib/pcb/stages/utils/CreateFpTextFromCircuitJson.ts
1578
1660
  import { FpText, TextEffects as TextEffects4, TextEffectsFont as TextEffectsFont4 } from "kicadts";
1579
- import { applyToPoint as applyToPoint8, rotate as rotate4, identity as identity4 } from "transformation-matrix";
1661
+ import { applyToPoint as applyToPoint8, rotate as rotate4, identity as identity3 } from "transformation-matrix";
1580
1662
  function createFpTextFromCircuitJson({
1581
1663
  textElement,
1582
1664
  componentCenter,
@@ -1587,7 +1669,7 @@ function createFpTextFromCircuitJson({
1587
1669
  }
1588
1670
  const relativeX = textElement.anchor_position.x - componentCenter.x;
1589
1671
  const relativeY = -(textElement.anchor_position.y - componentCenter.y);
1590
- const rotationMatrix = componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : identity4();
1672
+ const rotationMatrix = componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : identity3();
1591
1673
  const rotatedPos = applyToPoint8(rotationMatrix, {
1592
1674
  x: relativeX,
1593
1675
  y: relativeY
@@ -1972,8 +2054,8 @@ var AddGraphicsStage = class extends ConverterStage {
1972
2054
  if (board.outline && board.outline.length > 0) {
1973
2055
  corners = board.outline;
1974
2056
  } else {
1975
- const halfWidth = board.width / 2;
1976
- const halfHeight = board.height / 2;
2057
+ const halfWidth = board.width ? board.width / 2 : 0;
2058
+ const halfHeight = board.height ? board.height / 2 : 0;
1977
2059
  corners = [
1978
2060
  { x: board.center.x - halfWidth, y: board.center.y - halfHeight },
1979
2061
  { x: board.center.x + halfWidth, y: board.center.y - halfHeight },
@@ -2026,9 +2108,9 @@ var CircuitJsonToKicadPcbConverter = class {
2026
2108
  generator: "circuit-json-to-kicad",
2027
2109
  generatorVersion: "0.0.1"
2028
2110
  }),
2029
- c2kMatPcb: compose2(
2030
- translate2(KICAD_PCB_CENTER_X, KICAD_PCB_CENTER_Y),
2031
- scale2(CIRCUIT_JSON_TO_MM_SCALE, -CIRCUIT_JSON_TO_MM_SCALE)
2111
+ c2kMatPcb: compose3(
2112
+ translate3(KICAD_PCB_CENTER_X, KICAD_PCB_CENTER_Y),
2113
+ scale3(CIRCUIT_JSON_TO_MM_SCALE, -CIRCUIT_JSON_TO_MM_SCALE)
2032
2114
  )
2033
2115
  };
2034
2116
  this.pipeline = [
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.23",
4
+ "version": "0.0.25",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -18,13 +18,13 @@
18
18
  "@tscircuit/circuit-json-util": "^0.0.72",
19
19
  "@tscircuit/common": "^0.0.5",
20
20
  "@types/bun": "latest",
21
- "circuit-json": "^0.0.267",
21
+ "circuit-json": "^0.0.302",
22
22
  "circuit-to-svg": "^0.0.208",
23
- "kicadts": "^0.0.10",
23
+ "kicadts": "^0.0.22",
24
24
  "schematic-symbols": "^0.0.202",
25
25
  "sharp": "^0.34.4",
26
26
  "transformation-matrix": "^3.1.0",
27
- "tscircuit": "^0.0.713",
27
+ "tscircuit": "^0.0.866",
28
28
  "tsup": "^8.5.0"
29
29
  },
30
30
  "peerDependencies": {