@tscircuit/footprinter 0.0.339 → 0.0.340

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
@@ -1223,6 +1223,101 @@ var pillpad = (pn, x, y, w, h) => {
1223
1223
  };
1224
1224
  };
1225
1225
 
1226
+ // src/helpers/rect-union-outline.ts
1227
+ var createRectUnionOutline = (rectBoundsFromOuterToInner) => {
1228
+ if (rectBoundsFromOuterToInner.length < 2) {
1229
+ throw new Error("Rect union outline requires at least two bounds");
1230
+ }
1231
+ for (const bounds of rectBoundsFromOuterToInner) {
1232
+ if (bounds.minX >= bounds.maxX || bounds.minY >= bounds.maxY) {
1233
+ throw new Error("Each rectangle bound must have min < max on both axes");
1234
+ }
1235
+ }
1236
+ for (let i = 1; i < rectBoundsFromOuterToInner.length; i++) {
1237
+ const previous = rectBoundsFromOuterToInner[i - 1];
1238
+ const current = rectBoundsFromOuterToInner[i];
1239
+ if (current.minX < previous.minX || current.maxX > previous.maxX || current.minY > previous.minY || current.maxY < previous.maxY) {
1240
+ throw new Error(
1241
+ "Bounds must be ordered outer-to-inner with tighter X and larger Y span"
1242
+ );
1243
+ }
1244
+ }
1245
+ const buildTopLeftRouteFromInnerToOuter = () => {
1246
+ const route = [];
1247
+ let index = rectBoundsFromOuterToInner.length - 1;
1248
+ route.push({
1249
+ x: rectBoundsFromOuterToInner[index].minX,
1250
+ y: rectBoundsFromOuterToInner[index].maxY
1251
+ });
1252
+ while (index > 0) {
1253
+ const current = rectBoundsFromOuterToInner[index];
1254
+ const previous = rectBoundsFromOuterToInner[index - 1];
1255
+ route.push({ x: current.minX, y: previous.maxY });
1256
+ route.push({ x: previous.minX, y: previous.maxY });
1257
+ index -= 1;
1258
+ }
1259
+ return route;
1260
+ };
1261
+ const buildTopRightRouteFromInnerToOuter = () => {
1262
+ const route = [];
1263
+ let index = rectBoundsFromOuterToInner.length - 1;
1264
+ route.push({
1265
+ x: rectBoundsFromOuterToInner[index].maxX,
1266
+ y: rectBoundsFromOuterToInner[index].maxY
1267
+ });
1268
+ while (index > 0) {
1269
+ const current = rectBoundsFromOuterToInner[index];
1270
+ const previous = rectBoundsFromOuterToInner[index - 1];
1271
+ route.push({ x: current.maxX, y: previous.maxY });
1272
+ route.push({ x: previous.maxX, y: previous.maxY });
1273
+ index -= 1;
1274
+ }
1275
+ return route;
1276
+ };
1277
+ const buildBottomRightRouteFromInnerToOuter = () => {
1278
+ const route = [];
1279
+ let index = rectBoundsFromOuterToInner.length - 1;
1280
+ route.push({
1281
+ x: rectBoundsFromOuterToInner[index].maxX,
1282
+ y: rectBoundsFromOuterToInner[index].minY
1283
+ });
1284
+ while (index > 0) {
1285
+ const current = rectBoundsFromOuterToInner[index];
1286
+ const previous = rectBoundsFromOuterToInner[index - 1];
1287
+ route.push({ x: current.maxX, y: previous.minY });
1288
+ route.push({ x: previous.maxX, y: previous.minY });
1289
+ index -= 1;
1290
+ }
1291
+ return route;
1292
+ };
1293
+ const buildBottomLeftRouteFromInnerToOuter = () => {
1294
+ const route = [];
1295
+ let index = rectBoundsFromOuterToInner.length - 1;
1296
+ route.push({
1297
+ x: rectBoundsFromOuterToInner[index].minX,
1298
+ y: rectBoundsFromOuterToInner[index].minY
1299
+ });
1300
+ while (index > 0) {
1301
+ const current = rectBoundsFromOuterToInner[index];
1302
+ const previous = rectBoundsFromOuterToInner[index - 1];
1303
+ route.push({ x: current.minX, y: previous.minY });
1304
+ route.push({ x: previous.minX, y: previous.minY });
1305
+ index -= 1;
1306
+ }
1307
+ return route;
1308
+ };
1309
+ const topLeftInnerToOuter = buildTopLeftRouteFromInnerToOuter();
1310
+ const topRightInnerToOuter = buildTopRightRouteFromInnerToOuter();
1311
+ const bottomRightInnerToOuter = buildBottomRightRouteFromInnerToOuter();
1312
+ const bottomLeftInnerToOuter = buildBottomLeftRouteFromInnerToOuter();
1313
+ return [
1314
+ ...topLeftInnerToOuter.reverse(),
1315
+ ...topRightInnerToOuter,
1316
+ ...bottomRightInnerToOuter.reverse(),
1317
+ ...bottomLeftInnerToOuter
1318
+ ];
1319
+ };
1320
+
1226
1321
  // src/fn/soic.ts
1227
1322
  var extendSoicDef = (newDefaults) => base_def.extend({
1228
1323
  fn: z13.string(),
@@ -1326,20 +1421,20 @@ var soicWithoutParsing = (parameters) => {
1326
1421
  pcb_courtyard_outline_id: "",
1327
1422
  pcb_component_id: "",
1328
1423
  layer: "top",
1329
- outline: [
1330
- { x: -courtyardStepOuterHalfX, y: courtyardStepInnerHalfY },
1331
- { x: -courtyardStepInnerHalfX, y: courtyardStepInnerHalfY },
1332
- { x: -courtyardStepInnerHalfX, y: courtyardStepOuterHalfY },
1333
- { x: courtyardStepInnerHalfX, y: courtyardStepOuterHalfY },
1334
- { x: courtyardStepInnerHalfX, y: courtyardStepInnerHalfY },
1335
- { x: courtyardStepOuterHalfX, y: courtyardStepInnerHalfY },
1336
- { x: courtyardStepOuterHalfX, y: -courtyardStepInnerHalfY },
1337
- { x: courtyardStepInnerHalfX, y: -courtyardStepInnerHalfY },
1338
- { x: courtyardStepInnerHalfX, y: -courtyardStepOuterHalfY },
1339
- { x: -courtyardStepInnerHalfX, y: -courtyardStepOuterHalfY },
1340
- { x: -courtyardStepInnerHalfX, y: -courtyardStepInnerHalfY },
1341
- { x: -courtyardStepOuterHalfX, y: -courtyardStepInnerHalfY }
1342
- ]
1424
+ outline: createRectUnionOutline([
1425
+ {
1426
+ minX: -courtyardStepOuterHalfX,
1427
+ maxX: courtyardStepOuterHalfX,
1428
+ minY: -courtyardStepInnerHalfY,
1429
+ maxY: courtyardStepInnerHalfY
1430
+ },
1431
+ {
1432
+ minX: -courtyardStepInnerHalfX,
1433
+ maxX: courtyardStepInnerHalfX,
1434
+ minY: -courtyardStepOuterHalfY,
1435
+ maxY: courtyardStepOuterHalfY
1436
+ }
1437
+ ])
1343
1438
  };
1344
1439
  return [
1345
1440
  ...pads,
@@ -1498,6 +1593,8 @@ var getQuadCoords = (params) => {
1498
1593
  var quad = (raw_params) => {
1499
1594
  const parameters = quad_def.parse(raw_params);
1500
1595
  const pads = [];
1596
+ let padOuterHalfX = 0;
1597
+ let padOuterHalfY = 0;
1501
1598
  const pin_map = getQuadPinMap(parameters);
1502
1599
  const spc = parameters.num_pins / 4;
1503
1600
  for (let i = 0; i < parameters.num_pins; i++) {
@@ -1514,21 +1611,27 @@ var quad = (raw_params) => {
1514
1611
  pl: parameters.pl,
1515
1612
  legsoutside: parameters.legsoutside
1516
1613
  });
1517
- let pw = parameters.pw;
1518
- let pl = parameters.pl;
1614
+ let padWidth = parameters.pw;
1615
+ let padHeight = parameters.pl;
1519
1616
  if (orientation === "vert") {
1520
1617
  ;
1521
- [pw, pl] = [pl, pw];
1618
+ [padWidth, padHeight] = [padHeight, padWidth];
1522
1619
  }
1523
1620
  const pn = pin_map[i + 1];
1524
- pads.push(rectpad(pn, x, y, pw, pl));
1621
+ padOuterHalfX = Math.max(padOuterHalfX, Math.abs(x) + padWidth / 2);
1622
+ padOuterHalfY = Math.max(padOuterHalfY, Math.abs(y) + padHeight / 2);
1623
+ pads.push(rectpad(pn, x, y, padWidth, padHeight));
1525
1624
  }
1526
1625
  if (parameters.thermalpad) {
1527
1626
  if (typeof parameters.thermalpad === "boolean") {
1528
1627
  const ibw = parameters.p * (spc - 1) + parameters.pw;
1529
1628
  const ibh = parameters.p * (spc - 1) + parameters.pw;
1629
+ padOuterHalfX = Math.max(padOuterHalfX, ibw / 2);
1630
+ padOuterHalfY = Math.max(padOuterHalfY, ibh / 2);
1530
1631
  pads.push(rectpad(["thermalpad"], 0, 0, ibw, ibh));
1531
1632
  } else {
1633
+ padOuterHalfX = Math.max(padOuterHalfX, parameters.thermalpad.x / 2);
1634
+ padOuterHalfY = Math.max(padOuterHalfY, parameters.thermalpad.y / 2);
1532
1635
  pads.push(
1533
1636
  rectpad(
1534
1637
  ["thermalpad"],
@@ -1671,21 +1774,47 @@ var quad = (raw_params) => {
1671
1774
  parameters.h / 2 + (parameters.legsoutside ? parameters.pl * 1.2 : 0.5),
1672
1775
  0.3
1673
1776
  );
1674
- const courtyardPadding = 0.25;
1675
- const padExtentX = parameters.legsoutside ? parameters.w / 2 + parameters.pl : parameters.w / 2;
1676
- const padExtentY = parameters.legsoutside ? parameters.h / 2 + parameters.pl : parameters.h / 2;
1677
- const crtMinX = -padExtentX - courtyardPadding;
1678
- const crtMaxX = padExtentX + courtyardPadding;
1679
- const crtMinY = -padExtentY - courtyardPadding;
1680
- const crtMaxY = padExtentY + courtyardPadding;
1777
+ const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
1778
+ const roundUpToCourtyardOuterGrid = (value) => Math.ceil(value / 0.05) * 0.05;
1779
+ const pinRowSpanX = (spc - 1) * parameters.p + parameters.pw;
1780
+ const pinRowSpanY = (spc - 1) * parameters.p + parameters.pw;
1781
+ const courtyardStepInnerHalfX = roundToCourtyardGrid(pinRowSpanX / 2 + 0.25);
1782
+ const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.25);
1783
+ const courtyardStepOuterHalfX = roundToCourtyardGrid(parameters.w / 2 + 0.25);
1784
+ const courtyardStepOuterHalfY = roundToCourtyardGrid(parameters.h / 2 + 0.25);
1785
+ const courtyardOuterHalfX = Math.max(
1786
+ courtyardStepOuterHalfX,
1787
+ roundUpToCourtyardOuterGrid(padOuterHalfX + 0.25)
1788
+ );
1789
+ const courtyardOuterHalfY = Math.max(
1790
+ courtyardStepOuterHalfY,
1791
+ roundUpToCourtyardOuterGrid(padOuterHalfY + 0.25)
1792
+ );
1681
1793
  const courtyard = {
1682
- type: "pcb_courtyard_rect",
1683
- pcb_courtyard_rect_id: "",
1794
+ type: "pcb_courtyard_outline",
1795
+ pcb_courtyard_outline_id: "",
1684
1796
  pcb_component_id: "",
1685
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
1686
- width: crtMaxX - crtMinX,
1687
- height: crtMaxY - crtMinY,
1688
- layer: "top"
1797
+ layer: "top",
1798
+ outline: createRectUnionOutline([
1799
+ {
1800
+ minX: -courtyardOuterHalfX,
1801
+ maxX: courtyardOuterHalfX,
1802
+ minY: -courtyardStepInnerHalfY,
1803
+ maxY: courtyardStepInnerHalfY
1804
+ },
1805
+ {
1806
+ minX: -courtyardStepOuterHalfX,
1807
+ maxX: courtyardStepOuterHalfX,
1808
+ minY: -courtyardStepOuterHalfY,
1809
+ maxY: courtyardStepOuterHalfY
1810
+ },
1811
+ {
1812
+ minX: -courtyardStepInnerHalfX,
1813
+ maxX: courtyardStepInnerHalfX,
1814
+ minY: -courtyardOuterHalfY,
1815
+ maxY: courtyardOuterHalfY
1816
+ }
1817
+ ])
1689
1818
  };
1690
1819
  return {
1691
1820
  circuitJson: [
@@ -7981,20 +8110,20 @@ var msop = (raw_params) => {
7981
8110
  pcb_courtyard_outline_id: "",
7982
8111
  pcb_component_id: "",
7983
8112
  layer: "top",
7984
- outline: [
7985
- { x: -courtyardStepOuterHalfX, y: courtyardStepInnerHalfY },
7986
- { x: -courtyardStepInnerHalfX, y: courtyardStepInnerHalfY },
7987
- { x: -courtyardStepInnerHalfX, y: courtyardStepOuterHalfY },
7988
- { x: courtyardStepInnerHalfX, y: courtyardStepOuterHalfY },
7989
- { x: courtyardStepInnerHalfX, y: courtyardStepInnerHalfY },
7990
- { x: courtyardStepOuterHalfX, y: courtyardStepInnerHalfY },
7991
- { x: courtyardStepOuterHalfX, y: -courtyardStepInnerHalfY },
7992
- { x: courtyardStepInnerHalfX, y: -courtyardStepInnerHalfY },
7993
- { x: courtyardStepInnerHalfX, y: -courtyardStepOuterHalfY },
7994
- { x: -courtyardStepInnerHalfX, y: -courtyardStepOuterHalfY },
7995
- { x: -courtyardStepInnerHalfX, y: -courtyardStepInnerHalfY },
7996
- { x: -courtyardStepOuterHalfX, y: -courtyardStepInnerHalfY }
7997
- ]
8113
+ outline: createRectUnionOutline([
8114
+ {
8115
+ minX: -courtyardStepOuterHalfX,
8116
+ maxX: courtyardStepOuterHalfX,
8117
+ minY: -courtyardStepInnerHalfY,
8118
+ maxY: courtyardStepInnerHalfY
8119
+ },
8120
+ {
8121
+ minX: -courtyardStepInnerHalfX,
8122
+ maxX: courtyardStepInnerHalfX,
8123
+ minY: -courtyardStepOuterHalfY,
8124
+ maxY: courtyardStepOuterHalfY
8125
+ }
8126
+ ])
7998
8127
  };
7999
8128
  return {
8000
8129
  circuitJson: [