@tscircuit/footprinter 0.0.343 → 0.0.345

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
@@ -181,6 +181,101 @@ var u_curve = Array.from(
181
181
  y: -Math.sqrt(1 - x ** 2)
182
182
  }));
183
183
 
184
+ // src/helpers/rect-union-outline.ts
185
+ var createRectUnionOutline = (rectBoundsFromOuterToInner) => {
186
+ if (rectBoundsFromOuterToInner.length < 2) {
187
+ throw new Error("Rect union outline requires at least two bounds");
188
+ }
189
+ for (const bounds of rectBoundsFromOuterToInner) {
190
+ if (bounds.minX >= bounds.maxX || bounds.minY >= bounds.maxY) {
191
+ throw new Error("Each rectangle bound must have min < max on both axes");
192
+ }
193
+ }
194
+ for (let i = 1; i < rectBoundsFromOuterToInner.length; i++) {
195
+ const previous = rectBoundsFromOuterToInner[i - 1];
196
+ const current = rectBoundsFromOuterToInner[i];
197
+ if (current.minX < previous.minX || current.maxX > previous.maxX || current.minY > previous.minY || current.maxY < previous.maxY) {
198
+ throw new Error(
199
+ "Bounds must be ordered outer-to-inner with tighter X and larger Y span"
200
+ );
201
+ }
202
+ }
203
+ const buildTopLeftRouteFromInnerToOuter = () => {
204
+ const route = [];
205
+ let index = rectBoundsFromOuterToInner.length - 1;
206
+ route.push({
207
+ x: rectBoundsFromOuterToInner[index].minX,
208
+ y: rectBoundsFromOuterToInner[index].maxY
209
+ });
210
+ while (index > 0) {
211
+ const current = rectBoundsFromOuterToInner[index];
212
+ const previous = rectBoundsFromOuterToInner[index - 1];
213
+ route.push({ x: current.minX, y: previous.maxY });
214
+ route.push({ x: previous.minX, y: previous.maxY });
215
+ index -= 1;
216
+ }
217
+ return route;
218
+ };
219
+ const buildTopRightRouteFromInnerToOuter = () => {
220
+ const route = [];
221
+ let index = rectBoundsFromOuterToInner.length - 1;
222
+ route.push({
223
+ x: rectBoundsFromOuterToInner[index].maxX,
224
+ y: rectBoundsFromOuterToInner[index].maxY
225
+ });
226
+ while (index > 0) {
227
+ const current = rectBoundsFromOuterToInner[index];
228
+ const previous = rectBoundsFromOuterToInner[index - 1];
229
+ route.push({ x: current.maxX, y: previous.maxY });
230
+ route.push({ x: previous.maxX, y: previous.maxY });
231
+ index -= 1;
232
+ }
233
+ return route;
234
+ };
235
+ const buildBottomRightRouteFromInnerToOuter = () => {
236
+ const route = [];
237
+ let index = rectBoundsFromOuterToInner.length - 1;
238
+ route.push({
239
+ x: rectBoundsFromOuterToInner[index].maxX,
240
+ y: rectBoundsFromOuterToInner[index].minY
241
+ });
242
+ while (index > 0) {
243
+ const current = rectBoundsFromOuterToInner[index];
244
+ const previous = rectBoundsFromOuterToInner[index - 1];
245
+ route.push({ x: current.maxX, y: previous.minY });
246
+ route.push({ x: previous.maxX, y: previous.minY });
247
+ index -= 1;
248
+ }
249
+ return route;
250
+ };
251
+ const buildBottomLeftRouteFromInnerToOuter = () => {
252
+ const route = [];
253
+ let index = rectBoundsFromOuterToInner.length - 1;
254
+ route.push({
255
+ x: rectBoundsFromOuterToInner[index].minX,
256
+ y: rectBoundsFromOuterToInner[index].minY
257
+ });
258
+ while (index > 0) {
259
+ const current = rectBoundsFromOuterToInner[index];
260
+ const previous = rectBoundsFromOuterToInner[index - 1];
261
+ route.push({ x: current.minX, y: previous.minY });
262
+ route.push({ x: previous.minX, y: previous.minY });
263
+ index -= 1;
264
+ }
265
+ return route;
266
+ };
267
+ const topLeftInnerToOuter = buildTopLeftRouteFromInnerToOuter();
268
+ const topRightInnerToOuter = buildTopRightRouteFromInnerToOuter();
269
+ const bottomRightInnerToOuter = buildBottomRightRouteFromInnerToOuter();
270
+ const bottomLeftInnerToOuter = buildBottomLeftRouteFromInnerToOuter();
271
+ return [
272
+ ...topLeftInnerToOuter.reverse(),
273
+ ...topRightInnerToOuter,
274
+ ...bottomRightInnerToOuter.reverse(),
275
+ ...bottomLeftInnerToOuter
276
+ ];
277
+ };
278
+
184
279
  // src/fn/dip.ts
185
280
  function convertMilToMm(value) {
186
281
  if (typeof value === "string") {
@@ -316,18 +411,30 @@ var dip = (raw_params) => {
316
411
  });
317
412
  }
318
413
  const silkscreenRefText = silkscreenRef(0, sh / 2 + 0.5, 0.4);
319
- const courtyardPadding = 0.25;
320
- const crtMinX = -(parameters.w / 2 + parameters.od / 2) - courtyardPadding;
321
- const crtMaxX = parameters.w / 2 + parameters.od / 2 + courtyardPadding;
322
- const crtMinY = -sh / 2 - courtyardPadding;
323
- const crtMaxY = sh / 2 + courtyardPadding;
414
+ const pinRowSpanX = parameters.w + parameters.od;
415
+ const pinRowSpanY = padEdgeHeight;
416
+ const courtyardStepOuterHalfWidth = pinRowSpanX / 2 + 0.25;
417
+ const courtyardStepInnerHalfWidth = courtyardStepOuterHalfWidth;
418
+ const courtyardStepOuterHalfHeight = pinRowSpanY / 2 + 0.72;
419
+ const courtyardStepInnerHalfHeight = courtyardStepOuterHalfHeight;
324
420
  const courtyard = {
325
- type: "pcb_courtyard_rect",
326
- pcb_courtyard_rect_id: "",
421
+ type: "pcb_courtyard_outline",
422
+ pcb_courtyard_outline_id: "",
327
423
  pcb_component_id: "",
328
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
329
- width: crtMaxX - crtMinX,
330
- height: crtMaxY - crtMinY,
424
+ outline: createRectUnionOutline([
425
+ {
426
+ minX: -courtyardStepOuterHalfWidth,
427
+ maxX: courtyardStepOuterHalfWidth,
428
+ minY: -courtyardStepInnerHalfHeight,
429
+ maxY: courtyardStepInnerHalfHeight
430
+ },
431
+ {
432
+ minX: -courtyardStepInnerHalfWidth,
433
+ maxX: courtyardStepInnerHalfWidth,
434
+ minY: -courtyardStepOuterHalfHeight,
435
+ maxY: courtyardStepOuterHalfHeight
436
+ }
437
+ ]),
331
438
  layer: "top"
332
439
  };
333
440
  return {
@@ -1182,14 +1289,36 @@ var bga = (raw_params) => {
1182
1289
  route: markerRoute,
1183
1290
  stroke_width: 0.05
1184
1291
  };
1185
- const courtyardPadding = 0.25;
1292
+ const padSpanX = (grid.x - 1) * p + pad2;
1293
+ const padSpanY = (grid.y - 1) * p + pad2;
1294
+ const bodySpanX = w ?? padSpanX;
1295
+ const bodySpanY = h ?? padSpanY;
1296
+ const courtyardEnvelopeHalfWidth = Math.max(padSpanX / 2, bodySpanX / 2);
1297
+ const courtyardEnvelopeHalfHeight = Math.max(padSpanY / 2, bodySpanY / 2);
1298
+ const courtyardClearanceX = 1.715;
1299
+ const courtyardClearanceY = 1.765;
1300
+ const courtyardStepOuterHalfWidth = courtyardEnvelopeHalfWidth + courtyardClearanceX;
1301
+ const courtyardStepInnerHalfWidth = courtyardStepOuterHalfWidth;
1302
+ const courtyardStepOuterHalfHeight = courtyardEnvelopeHalfHeight + courtyardClearanceY;
1303
+ const courtyardStepInnerHalfHeight = courtyardStepOuterHalfHeight;
1186
1304
  const courtyard = {
1187
- type: "pcb_courtyard_rect",
1188
- pcb_courtyard_rect_id: "",
1305
+ type: "pcb_courtyard_outline",
1306
+ pcb_courtyard_outline_id: "",
1189
1307
  pcb_component_id: "",
1190
- center: { x: 0, y: 0 },
1191
- width: 2 * (edgeX + courtyardPadding),
1192
- height: 2 * (edgeY + courtyardPadding),
1308
+ outline: createRectUnionOutline([
1309
+ {
1310
+ minX: -courtyardStepOuterHalfWidth,
1311
+ maxX: courtyardStepOuterHalfWidth,
1312
+ minY: -courtyardStepInnerHalfHeight,
1313
+ maxY: courtyardStepInnerHalfHeight
1314
+ },
1315
+ {
1316
+ minX: -courtyardStepInnerHalfWidth,
1317
+ maxX: courtyardStepInnerHalfWidth,
1318
+ minY: -courtyardStepOuterHalfHeight,
1319
+ maxY: courtyardStepOuterHalfHeight
1320
+ }
1321
+ ]),
1193
1322
  layer: "top"
1194
1323
  };
1195
1324
  return {
@@ -1223,101 +1352,6 @@ var pillpad = (pn, x, y, w, h) => {
1223
1352
  };
1224
1353
  };
1225
1354
 
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
-
1321
1355
  // src/fn/soic.ts
1322
1356
  var extendSoicDef = (newDefaults) => base_def.extend({
1323
1357
  fn: z13.string(),
@@ -1408,14 +1442,11 @@ var soicWithoutParsing = (parameters) => {
1408
1442
  { x: -sw / 2, y: -sh / 2 }
1409
1443
  ]
1410
1444
  };
1411
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
1412
1445
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * parameters.p + parameters.pw;
1413
- const courtyardStepInnerHalfX = roundToCourtyardGrid(parameters.w / 2 + 0.25);
1414
- const courtyardStepOuterHalfX = roundToCourtyardGrid(
1415
- courtyardStepInnerHalfX + 1.93
1416
- );
1417
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.27);
1418
- const courtyardStepOuterHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.63);
1446
+ const courtyardStepInnerHalfWidth = parameters.w / 2 + 0.25;
1447
+ const courtyardStepOuterHalfWidth = courtyardStepInnerHalfWidth + 1.93;
1448
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.275;
1449
+ const courtyardStepOuterHalfHeight = pinRowSpanY / 2 + 0.635;
1419
1450
  const courtyard = {
1420
1451
  type: "pcb_courtyard_outline",
1421
1452
  pcb_courtyard_outline_id: "",
@@ -1423,16 +1454,16 @@ var soicWithoutParsing = (parameters) => {
1423
1454
  layer: "top",
1424
1455
  outline: createRectUnionOutline([
1425
1456
  {
1426
- minX: -courtyardStepOuterHalfX,
1427
- maxX: courtyardStepOuterHalfX,
1428
- minY: -courtyardStepInnerHalfY,
1429
- maxY: courtyardStepInnerHalfY
1457
+ minX: -courtyardStepOuterHalfWidth,
1458
+ maxX: courtyardStepOuterHalfWidth,
1459
+ minY: -courtyardStepInnerHalfHeight,
1460
+ maxY: courtyardStepInnerHalfHeight
1430
1461
  },
1431
1462
  {
1432
- minX: -courtyardStepInnerHalfX,
1433
- maxX: courtyardStepInnerHalfX,
1434
- minY: -courtyardStepOuterHalfY,
1435
- maxY: courtyardStepOuterHalfY
1463
+ minX: -courtyardStepInnerHalfWidth,
1464
+ maxX: courtyardStepInnerHalfWidth,
1465
+ minY: -courtyardStepOuterHalfHeight,
1466
+ maxY: courtyardStepOuterHalfHeight
1436
1467
  }
1437
1468
  ])
1438
1469
  };
@@ -1774,20 +1805,19 @@ var quad = (raw_params) => {
1774
1805
  parameters.h / 2 + (parameters.legsoutside ? parameters.pl * 1.2 : 0.5),
1775
1806
  0.3
1776
1807
  );
1777
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
1778
1808
  const roundUpToCourtyardOuterGrid = (value) => Math.ceil(value / 0.05) * 0.05;
1779
1809
  const pinRowSpanX = (spc - 1) * parameters.p + parameters.pw;
1780
1810
  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,
1811
+ const courtyardStepInnerHalfWidth = pinRowSpanX / 2 + 0.25;
1812
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.25;
1813
+ const courtyardStepOuterHalfWidth = parameters.w / 2 + 0.25;
1814
+ const courtyardStepOuterHalfHeight = parameters.h / 2 + 0.25;
1815
+ const courtyardOuterHalfWidth = Math.max(
1816
+ courtyardStepOuterHalfWidth,
1787
1817
  roundUpToCourtyardOuterGrid(padOuterHalfX + 0.25)
1788
1818
  );
1789
- const courtyardOuterHalfY = Math.max(
1790
- courtyardStepOuterHalfY,
1819
+ const courtyardOuterHalfHeight = Math.max(
1820
+ courtyardStepOuterHalfHeight,
1791
1821
  roundUpToCourtyardOuterGrid(padOuterHalfY + 0.25)
1792
1822
  );
1793
1823
  const courtyard = {
@@ -1797,22 +1827,22 @@ var quad = (raw_params) => {
1797
1827
  layer: "top",
1798
1828
  outline: createRectUnionOutline([
1799
1829
  {
1800
- minX: -courtyardOuterHalfX,
1801
- maxX: courtyardOuterHalfX,
1802
- minY: -courtyardStepInnerHalfY,
1803
- maxY: courtyardStepInnerHalfY
1830
+ minX: -courtyardOuterHalfWidth,
1831
+ maxX: courtyardOuterHalfWidth,
1832
+ minY: -courtyardStepInnerHalfHeight,
1833
+ maxY: courtyardStepInnerHalfHeight
1804
1834
  },
1805
1835
  {
1806
- minX: -courtyardStepOuterHalfX,
1807
- maxX: courtyardStepOuterHalfX,
1808
- minY: -courtyardStepOuterHalfY,
1809
- maxY: courtyardStepOuterHalfY
1836
+ minX: -courtyardStepOuterHalfWidth,
1837
+ maxX: courtyardStepOuterHalfWidth,
1838
+ minY: -courtyardStepOuterHalfHeight,
1839
+ maxY: courtyardStepOuterHalfHeight
1810
1840
  },
1811
1841
  {
1812
- minX: -courtyardStepInnerHalfX,
1813
- maxX: courtyardStepInnerHalfX,
1814
- minY: -courtyardOuterHalfY,
1815
- maxY: courtyardOuterHalfY
1842
+ minX: -courtyardStepInnerHalfWidth,
1843
+ maxX: courtyardStepInnerHalfWidth,
1844
+ minY: -courtyardOuterHalfHeight,
1845
+ maxY: courtyardOuterHalfHeight
1816
1846
  }
1817
1847
  ])
1818
1848
  };
@@ -2039,21 +2069,31 @@ var ssop = (raw_params) => {
2039
2069
  { x: -sw / 2, y: -sh / 2 }
2040
2070
  ]
2041
2071
  };
2042
- const courtyardPadding = 0.25;
2043
- const silkXs = silkscreenBorder.route.map((pt) => pt.x);
2044
- const silkYs = silkscreenBorder.route.map((pt) => pt.y);
2045
- const padXExtent = parameters.legsoutside ? parameters.w / 2 + parameters.pl : (parameters.w + 0.2) / 2 + parameters.pl / 2;
2046
- const crtMinX = Math.min(-padXExtent, ...silkXs) - courtyardPadding;
2047
- const crtMaxX = Math.max(padXExtent, ...silkXs) + courtyardPadding;
2048
- const crtMinY = Math.min(...silkYs) - courtyardPadding;
2049
- const crtMaxY = Math.max(...silkYs) + courtyardPadding;
2072
+ const pinRowSpanY = (parameters.num_pins / 2 - 1) * parameters.p + parameters.pw;
2073
+ const padToeHalfX = parameters.legsoutside ? parameters.w / 2 + parameters.pl : (parameters.w + 0.2) / 2 + parameters.pl / 2;
2074
+ const pinRowHalfY = pinRowSpanY / 2;
2075
+ const courtyardStepOuterHalfWidth = padToeHalfX + 0.25;
2076
+ const courtyardStepInnerHalfWidth = courtyardStepOuterHalfWidth;
2077
+ const courtyardStepOuterHalfHeight = pinRowHalfY + 0.445;
2078
+ const courtyardStepInnerHalfHeight = courtyardStepOuterHalfHeight;
2050
2079
  const courtyard = {
2051
- type: "pcb_courtyard_rect",
2052
- pcb_courtyard_rect_id: "",
2080
+ type: "pcb_courtyard_outline",
2081
+ pcb_courtyard_outline_id: "",
2053
2082
  pcb_component_id: "",
2054
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
2055
- width: crtMaxX - crtMinX,
2056
- height: crtMaxY - crtMinY,
2083
+ outline: createRectUnionOutline([
2084
+ {
2085
+ minX: -courtyardStepOuterHalfWidth,
2086
+ maxX: courtyardStepOuterHalfWidth,
2087
+ minY: -courtyardStepInnerHalfHeight,
2088
+ maxY: courtyardStepInnerHalfHeight
2089
+ },
2090
+ {
2091
+ minX: -courtyardStepInnerHalfWidth,
2092
+ maxX: courtyardStepInnerHalfWidth,
2093
+ minY: -courtyardStepOuterHalfHeight,
2094
+ maxY: courtyardStepOuterHalfHeight
2095
+ }
2096
+ ]),
2057
2097
  layer: "top"
2058
2098
  };
2059
2099
  return {
@@ -2132,15 +2172,12 @@ var tssop = (raw_params) => {
2132
2172
  { x: -sw / 2, y: -sh / 2 }
2133
2173
  ]
2134
2174
  };
2135
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
2136
2175
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * parameters.p + parameters.pw;
2137
2176
  const pinToeHalfSpanX = parameters.w / 2 + (parameters.legsoutside ? parameters.pl : 0);
2138
- const courtyardStepInnerHalfX = roundToCourtyardGrid(parameters.w / 2 + 0.25);
2139
- const courtyardStepOuterHalfX = roundToCourtyardGrid(pinToeHalfSpanX + 0.18);
2140
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.25);
2141
- const courtyardStepOuterHalfY = roundToCourtyardGrid(
2142
- courtyardStepInnerHalfY + 0.35
2143
- );
2177
+ const courtyardStepInnerHalfWidth = parameters.w / 2 + 0.25;
2178
+ const courtyardStepOuterHalfWidth = pinToeHalfSpanX + 0.18;
2179
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.25;
2180
+ const courtyardStepOuterHalfHeight = courtyardStepInnerHalfHeight + 0.35;
2144
2181
  const courtyard = {
2145
2182
  type: "pcb_courtyard_outline",
2146
2183
  pcb_courtyard_outline_id: "",
@@ -2148,16 +2185,16 @@ var tssop = (raw_params) => {
2148
2185
  layer: "top",
2149
2186
  outline: createRectUnionOutline([
2150
2187
  {
2151
- minX: -courtyardStepOuterHalfX,
2152
- maxX: courtyardStepOuterHalfX,
2153
- minY: -courtyardStepInnerHalfY,
2154
- maxY: courtyardStepInnerHalfY
2188
+ minX: -courtyardStepOuterHalfWidth,
2189
+ maxX: courtyardStepOuterHalfWidth,
2190
+ minY: -courtyardStepInnerHalfHeight,
2191
+ maxY: courtyardStepInnerHalfHeight
2155
2192
  },
2156
2193
  {
2157
- minX: -courtyardStepInnerHalfX,
2158
- maxX: courtyardStepInnerHalfX,
2159
- minY: -courtyardStepOuterHalfY,
2160
- maxY: courtyardStepOuterHalfY
2194
+ minX: -courtyardStepInnerHalfWidth,
2195
+ maxX: courtyardStepInnerHalfWidth,
2196
+ minY: -courtyardStepOuterHalfHeight,
2197
+ maxY: courtyardStepOuterHalfHeight
2161
2198
  }
2162
2199
  ])
2163
2200
  };
@@ -3409,18 +3446,34 @@ var axial = (raw_params) => {
3409
3446
  pcb_silkscreen_path_id: ""
3410
3447
  };
3411
3448
  const silkscreenRefText = silkscreenRef(0, 1.5, 0.5);
3412
- const courtyardPadding = 0.25;
3413
- const crtMinX = -(p / 2 + od / 2 + courtyardPadding);
3414
- const crtMaxX = p / 2 + od / 2 + courtyardPadding;
3415
- const crtMinY = -(od / 2 + courtyardPadding);
3416
- const crtMaxY = od / 2 + courtyardPadding;
3449
+ const pin1CenterX = -p / 2;
3450
+ const pin2CenterX = p / 2;
3451
+ const pinPadHalfX = od / 2;
3452
+ const pinPadHalfY = od / 2;
3453
+ const courtyardStepOuterMinX = pin1CenterX - pinPadHalfX - 0.35;
3454
+ const courtyardStepOuterMaxX = pin2CenterX + pinPadHalfX + 0.26;
3455
+ const courtyardStepOuterHalfHeight = pinPadHalfY + 0.35;
3456
+ const courtyardStepInnerMinX = courtyardStepOuterMinX;
3457
+ const courtyardStepInnerMaxX = courtyardStepOuterMaxX;
3458
+ const courtyardStepInnerHalfHeight = courtyardStepOuterHalfHeight;
3417
3459
  const courtyard = {
3418
- type: "pcb_courtyard_rect",
3419
- pcb_courtyard_rect_id: "",
3460
+ type: "pcb_courtyard_outline",
3461
+ pcb_courtyard_outline_id: "",
3420
3462
  pcb_component_id: "",
3421
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
3422
- width: crtMaxX - crtMinX,
3423
- height: crtMaxY - crtMinY,
3463
+ outline: createRectUnionOutline([
3464
+ {
3465
+ minX: courtyardStepOuterMinX,
3466
+ maxX: courtyardStepOuterMaxX,
3467
+ minY: -courtyardStepInnerHalfHeight,
3468
+ maxY: courtyardStepInnerHalfHeight
3469
+ },
3470
+ {
3471
+ minX: courtyardStepInnerMinX,
3472
+ maxX: courtyardStepInnerMaxX,
3473
+ minY: -courtyardStepOuterHalfHeight,
3474
+ maxY: courtyardStepOuterHalfHeight
3475
+ }
3476
+ ]),
3424
3477
  layer: "top"
3425
3478
  };
3426
3479
  return {
@@ -4988,12 +5041,11 @@ var sop8 = (raw_params) => {
4988
5041
  ],
4989
5042
  stroke_width: 0.1
4990
5043
  };
4991
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
4992
5044
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * parameters.p + parameters.pw;
4993
- const courtyardStepInnerHalfX = roundToCourtyardGrid(parameters.w / 2 - 1.395);
4994
- const courtyardStepOuterHalfX = roundToCourtyardGrid(parameters.w / 2 + 0.255);
4995
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.25);
4996
- const courtyardStepOuterHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.5);
5045
+ const courtyardStepInnerHalfWidth = parameters.w / 2 - 1.395;
5046
+ const courtyardStepOuterHalfWidth = parameters.w / 2 + 0.255;
5047
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.25;
5048
+ const courtyardStepOuterHalfHeight = pinRowSpanY / 2 + 0.5;
4997
5049
  const courtyard = {
4998
5050
  type: "pcb_courtyard_outline",
4999
5051
  pcb_courtyard_outline_id: "",
@@ -5001,16 +5053,16 @@ var sop8 = (raw_params) => {
5001
5053
  layer: "top",
5002
5054
  outline: createRectUnionOutline([
5003
5055
  {
5004
- minX: -courtyardStepOuterHalfX,
5005
- maxX: courtyardStepOuterHalfX,
5006
- minY: -courtyardStepInnerHalfY,
5007
- maxY: courtyardStepInnerHalfY
5056
+ minX: -courtyardStepOuterHalfWidth,
5057
+ maxX: courtyardStepOuterHalfWidth,
5058
+ minY: -courtyardStepInnerHalfHeight,
5059
+ maxY: courtyardStepInnerHalfHeight
5008
5060
  },
5009
5061
  {
5010
- minX: -courtyardStepInnerHalfX,
5011
- maxX: courtyardStepInnerHalfX,
5012
- minY: -courtyardStepOuterHalfY,
5013
- maxY: courtyardStepOuterHalfY
5062
+ minX: -courtyardStepInnerHalfWidth,
5063
+ maxX: courtyardStepInnerHalfWidth,
5064
+ minY: -courtyardStepOuterHalfHeight,
5065
+ maxY: courtyardStepOuterHalfHeight
5014
5066
  }
5015
5067
  ])
5016
5068
  };
@@ -5309,45 +5361,69 @@ var sod_def5 = base_def.extend({
5309
5361
  });
5310
5362
  var sod923 = (raw_params) => {
5311
5363
  const parameters = sod_def5.parse(raw_params);
5312
- const silkscreenRefText = silkscreenRef(
5313
- 0,
5314
- length31.parse(parameters.h),
5315
- 0.3
5316
- );
5364
+ const w = length31.parse(parameters.w);
5365
+ const h = length31.parse(parameters.h);
5366
+ const pl = length31.parse(parameters.pl);
5367
+ const pw = length31.parse(parameters.pw);
5368
+ const p = length31.parse(parameters.p);
5369
+ const silkscreenRefText = silkscreenRef(0, h, 0.3);
5317
5370
  const silkscreenLine = {
5318
5371
  type: "pcb_silkscreen_path",
5319
5372
  layer: "top",
5320
5373
  pcb_component_id: "",
5321
5374
  route: [
5322
5375
  {
5323
- x: length31.parse(parameters.p) / 2 + 0.15,
5324
- y: length31.parse(parameters.h) / 2
5376
+ x: p / 2 + 0.15,
5377
+ y: h / 2
5325
5378
  },
5326
5379
  {
5327
- x: -length31.parse(parameters.w) / 2 - 0.15,
5328
- y: length31.parse(parameters.h) / 2
5380
+ x: -w / 2 - 0.15,
5381
+ y: h / 2
5329
5382
  },
5330
5383
  {
5331
- x: -length31.parse(parameters.w) / 2 - 0.15,
5332
- y: -length31.parse(parameters.h) / 2
5384
+ x: -w / 2 - 0.15,
5385
+ y: -h / 2
5333
5386
  },
5334
5387
  {
5335
- x: length31.parse(parameters.p) / 2 + 0.15,
5336
- y: -length31.parse(parameters.h) / 2
5388
+ x: p / 2 + 0.15,
5389
+ y: -h / 2
5337
5390
  }
5338
5391
  ],
5339
5392
  stroke_width: 0.1,
5340
5393
  pcb_silkscreen_path_id: ""
5341
5394
  };
5342
- const courtyardWidthMm = 1.5;
5343
- const courtyardHeightMm = 0.9;
5395
+ const pinRowSpanX = p + pl;
5396
+ const pinRowSpanY = pw;
5397
+ const bodyHalfX = w / 2;
5398
+ const bodyHalfY = h / 2;
5399
+ const pinToeHalfX = pinRowSpanX / 2;
5400
+ const pinRowHalfY = pinRowSpanY / 2;
5401
+ const courtyardEnvelopeHalfWidth = Math.max(bodyHalfX, pinToeHalfX);
5402
+ const courtyardEnvelopeHalfHeight = Math.max(bodyHalfY, pinRowHalfY);
5403
+ const courtyardNarrowHalfWidth = Math.min(bodyHalfX, pinToeHalfX);
5404
+ const courtyardNarrowHalfHeight = Math.min(bodyHalfY, pinRowHalfY);
5405
+ const courtyardStepOuterHalfWidth = courtyardEnvelopeHalfWidth + 0.05;
5406
+ const courtyardStepInnerHalfWidth = courtyardNarrowHalfWidth - 0.055;
5407
+ const courtyardStepOuterHalfHeight = courtyardEnvelopeHalfHeight;
5408
+ const courtyardStepInnerHalfHeight = courtyardNarrowHalfHeight + 0.155;
5344
5409
  const courtyard = {
5345
- type: "pcb_courtyard_rect",
5346
- pcb_courtyard_rect_id: "",
5410
+ type: "pcb_courtyard_outline",
5411
+ pcb_courtyard_outline_id: "",
5347
5412
  pcb_component_id: "",
5348
- center: { x: 0, y: 0 },
5349
- width: courtyardWidthMm,
5350
- height: courtyardHeightMm,
5413
+ outline: createRectUnionOutline([
5414
+ {
5415
+ minX: -courtyardStepOuterHalfWidth,
5416
+ maxX: courtyardStepOuterHalfWidth,
5417
+ minY: -courtyardStepInnerHalfHeight,
5418
+ maxY: courtyardStepInnerHalfHeight
5419
+ },
5420
+ {
5421
+ minX: -courtyardStepInnerHalfWidth,
5422
+ maxX: courtyardStepInnerHalfWidth,
5423
+ minY: -courtyardStepOuterHalfHeight,
5424
+ maxY: courtyardStepOuterHalfHeight
5425
+ }
5426
+ ]),
5351
5427
  layer: "top"
5352
5428
  };
5353
5429
  return {
@@ -6176,11 +6252,19 @@ var to220 = (raw_params) => {
6176
6252
  }
6177
6253
  ];
6178
6254
  const silkscreenRefText = silkscreenRef(0, h / 2 + 0.6, 0.5);
6179
- const courtyardPadding = 0.25;
6180
- const crtMinX = -(halfWidth + courtyardPadding);
6181
- const crtMaxX = halfWidth + courtyardPadding;
6182
- const crtMinY = -(halfHeight + courtyardPadding);
6183
- const crtMaxY = halfHeight + courtyardPadding;
6255
+ const pinToeHalfSpanX = Math.max(...plated_holes.map((hole) => Math.abs(hole.x))) + od / 2;
6256
+ const pinToeTopY = holeY + od / 2;
6257
+ const pinToeBottomY = holeY - od / 2;
6258
+ const courtyardHalfWidth = Math.max(
6259
+ pinToeHalfSpanX + 0.25,
6260
+ halfWidth - od * 0.59
6261
+ );
6262
+ const courtyardTopY = halfHeight - od * 0.63;
6263
+ const courtyardBottomY = pinToeBottomY - (od / 2 + 0.01);
6264
+ const crtMinX = -courtyardHalfWidth;
6265
+ const crtMaxX = courtyardHalfWidth;
6266
+ const crtMinY = Math.min(courtyardBottomY, pinToeBottomY - 0.25);
6267
+ const crtMaxY = Math.max(courtyardTopY, pinToeTopY + 0.25);
6184
6268
  const courtyard = {
6185
6269
  type: "pcb_courtyard_rect",
6186
6270
  pcb_courtyard_rect_id: "",
@@ -7146,6 +7230,8 @@ var get2CcwSot2235Coords = (parameters) => {
7146
7230
  };
7147
7231
  var sot223_5 = (parameters) => {
7148
7232
  const pads = [];
7233
+ let padOuterHalfX = 0;
7234
+ let padOuterHalfY = 0;
7149
7235
  for (let i = 1; i <= parameters.num_pins; i++) {
7150
7236
  const { x, y } = get2CcwSot2235Coords({
7151
7237
  h: Number.parseFloat(parameters.h),
@@ -7162,6 +7248,8 @@ var sot223_5 = (parameters) => {
7162
7248
  pinWidth = 1;
7163
7249
  pinLength = 2.2;
7164
7250
  }
7251
+ padOuterHalfX = Math.max(padOuterHalfX, Math.abs(x) + pinLength / 2);
7252
+ padOuterHalfY = Math.max(padOuterHalfY, Math.abs(y) + pinWidth / 2);
7165
7253
  pads.push(rectpad(i, x, y, pinLength, pinWidth));
7166
7254
  }
7167
7255
  const width = Number.parseFloat(parameters.w) / 2 - 2.4;
@@ -7191,21 +7279,28 @@ var sot223_5 = (parameters) => {
7191
7279
  stroke_width: 0.1
7192
7280
  };
7193
7281
  const silkscreenRefText = silkscreenRef(0, 0, 0.3);
7194
- const w = Number.parseFloat(parameters.w);
7195
- const courtyardPadding = 0.25;
7196
- const padOuterX = w / 2 - 1.2 + 2.2 / 2;
7197
- const crtMinX = -(padOuterX + courtyardPadding);
7198
- const crtMaxX = padOuterX + courtyardPadding;
7199
- const h5 = Number.parseFloat(parameters.h);
7200
- const crtMinY = -(Math.max(h5 / 2, 2.25 + 0.5) + courtyardPadding);
7201
- const crtMaxY = Math.max(h5 / 2, 2.25 + 0.5) + courtyardPadding;
7282
+ const courtyardStepOuterHalfWidth = padOuterHalfX + 0.25;
7283
+ const courtyardStepInnerHalfWidth = courtyardStepOuterHalfWidth;
7284
+ const courtyardStepOuterHalfHeight = padOuterHalfY + 0.85;
7285
+ const courtyardStepInnerHalfHeight = courtyardStepOuterHalfHeight;
7202
7286
  const courtyard = {
7203
- type: "pcb_courtyard_rect",
7204
- pcb_courtyard_rect_id: "",
7287
+ type: "pcb_courtyard_outline",
7288
+ pcb_courtyard_outline_id: "",
7205
7289
  pcb_component_id: "",
7206
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
7207
- width: crtMaxX - crtMinX,
7208
- height: crtMaxY - crtMinY,
7290
+ outline: createRectUnionOutline([
7291
+ {
7292
+ minX: -courtyardStepOuterHalfWidth,
7293
+ maxX: courtyardStepOuterHalfWidth,
7294
+ minY: -courtyardStepInnerHalfHeight,
7295
+ maxY: courtyardStepInnerHalfHeight
7296
+ },
7297
+ {
7298
+ minX: -courtyardStepInnerHalfWidth,
7299
+ maxX: courtyardStepInnerHalfWidth,
7300
+ minY: -courtyardStepOuterHalfHeight,
7301
+ maxY: courtyardStepOuterHalfHeight
7302
+ }
7303
+ ]),
7209
7304
  layer: "top"
7210
7305
  };
7211
7306
  return [
@@ -7538,6 +7633,26 @@ var jst_def = base_def.extend({
7538
7633
  ),
7539
7634
  string: z61.string().optional()
7540
7635
  });
7636
+ var createEmptyBounds = () => ({
7637
+ minX: Number.POSITIVE_INFINITY,
7638
+ maxX: Number.NEGATIVE_INFINITY,
7639
+ minY: Number.POSITIVE_INFINITY,
7640
+ maxY: Number.NEGATIVE_INFINITY
7641
+ });
7642
+ var modifyBoundsToIncludeRect = ({
7643
+ bounds,
7644
+ centerX,
7645
+ centerY,
7646
+ width,
7647
+ height
7648
+ }) => {
7649
+ const halfWidth = width / 2;
7650
+ const halfHeight = height / 2;
7651
+ bounds.minX = Math.min(bounds.minX, centerX - halfWidth);
7652
+ bounds.maxX = Math.max(bounds.maxX, centerX + halfWidth);
7653
+ bounds.minY = Math.min(bounds.minY, centerY - halfHeight);
7654
+ bounds.maxY = Math.max(bounds.maxY, centerY + halfHeight);
7655
+ };
7541
7656
  var variantDefaults = {
7542
7657
  ph: {
7543
7658
  p: length48.parse("2.2mm"),
@@ -7569,8 +7684,17 @@ function getVariant(params) {
7569
7684
  if (params.zh) return "zh";
7570
7685
  return "ph";
7571
7686
  }
7572
- function generatePads(variant, numPins, p, id, pw, pl) {
7687
+ function generatePads({
7688
+ variant,
7689
+ numPins,
7690
+ p,
7691
+ id,
7692
+ pw,
7693
+ pl
7694
+ }) {
7573
7695
  const pads = [];
7696
+ const padBounds = createEmptyBounds();
7697
+ let maxPadHalfY = 0;
7574
7698
  if (variant === "ph") {
7575
7699
  const startX = -((numPins - 1) / 2) * p;
7576
7700
  for (let i = 0; i < numPins; i++) {
@@ -7585,6 +7709,14 @@ function generatePads(variant, numPins, p, id, pw, pl) {
7585
7709
  rectPadHeight: pl
7586
7710
  })
7587
7711
  );
7712
+ modifyBoundsToIncludeRect({
7713
+ bounds: padBounds,
7714
+ centerX: x,
7715
+ centerY: 2,
7716
+ width: pw,
7717
+ height: pl
7718
+ });
7719
+ maxPadHalfY = Math.max(maxPadHalfY, pl / 2);
7588
7720
  }
7589
7721
  } else if (variant === "zh") {
7590
7722
  const startX = -((numPins - 1) / 2) * p;
@@ -7605,20 +7737,57 @@ function generatePads(variant, numPins, p, id, pw, pl) {
7605
7737
  } else {
7606
7738
  pads.push(platedHolePill(i + 1, x, 0, id, pw, pl));
7607
7739
  }
7740
+ modifyBoundsToIncludeRect({
7741
+ bounds: padBounds,
7742
+ centerX: x,
7743
+ centerY: 0,
7744
+ width: pw,
7745
+ height: pl
7746
+ });
7747
+ maxPadHalfY = Math.max(maxPadHalfY, pl / 2);
7608
7748
  }
7609
7749
  } else {
7610
7750
  const startX = -((numPins - 1) / 2) * p;
7611
7751
  for (let i = 0; i < numPins; i++) {
7612
7752
  const x = startX + i * p;
7613
7753
  pads.push(rectpad(i + 1, x, -1.325, pw, pl));
7754
+ modifyBoundsToIncludeRect({
7755
+ bounds: padBounds,
7756
+ centerX: x,
7757
+ centerY: -1.325,
7758
+ width: pw,
7759
+ height: pl
7760
+ });
7761
+ maxPadHalfY = Math.max(maxPadHalfY, pl / 2);
7614
7762
  }
7615
7763
  const sideOffset = (numPins - 1) / 2 * p + 1.3;
7616
7764
  pads.push(rectpad(numPins + 1, -sideOffset, 1.22, 1.2, 1.8));
7617
7765
  pads.push(rectpad(numPins + 2, sideOffset, 1.22, 1.2, 1.8));
7766
+ modifyBoundsToIncludeRect({
7767
+ bounds: padBounds,
7768
+ centerX: -sideOffset,
7769
+ centerY: 1.22,
7770
+ width: 1.2,
7771
+ height: 1.8
7772
+ });
7773
+ modifyBoundsToIncludeRect({
7774
+ bounds: padBounds,
7775
+ centerX: sideOffset,
7776
+ centerY: 1.22,
7777
+ width: 1.2,
7778
+ height: 1.8
7779
+ });
7780
+ maxPadHalfY = Math.max(maxPadHalfY, 0.9);
7618
7781
  }
7619
- return pads;
7782
+ return { pads, padBounds, maxPadHalfY };
7620
7783
  }
7621
- function generateSilkscreenBody(variant, w, h, numPins, p) {
7784
+ function generateSilkscreenBody({
7785
+ variant,
7786
+ w,
7787
+ h,
7788
+ numPins,
7789
+ p
7790
+ }) {
7622
7791
  if (variant === "ph") {
7623
7792
  return {
7624
7793
  type: "pcb_silkscreen_path",
@@ -7700,34 +7869,37 @@ var jst = (raw_params) => {
7700
7869
  `JST requires an explicit pin count (e.g. jst6_sh or .jst(6))${params.string ? `, from string "${params.string}"` : ""}`
7701
7870
  );
7702
7871
  }
7703
- const pads = generatePads(variant, numPins, p, id, pw, pl);
7704
- const silkscreenBody = generateSilkscreenBody(variant, w, h, numPins, p);
7872
+ const padGeometry = generatePads({
7873
+ variant,
7874
+ numPins,
7875
+ p,
7876
+ id,
7877
+ pw,
7878
+ pl
7879
+ });
7880
+ const { pads, padBounds, maxPadHalfY } = padGeometry;
7881
+ const silkscreenBody = generateSilkscreenBody({
7882
+ variant,
7883
+ w,
7884
+ h,
7885
+ numPins,
7886
+ p
7887
+ });
7705
7888
  const silkscreenRefText = silkscreenRef(0, h / 2 + 1, 0.5);
7706
- const courtyardPadding = 0.25;
7707
- let crtMinX;
7708
- let crtMaxX;
7709
- let crtMinY;
7710
- let crtMaxY;
7711
- if (variant === "ph") {
7712
- const pinHalfSpan = (numPins - 1) / 2 * p + pw / 2;
7713
- crtMinX = -Math.max(pinHalfSpan, 3) - courtyardPadding;
7714
- crtMaxX = Math.max(pinHalfSpan, 3) + courtyardPadding;
7715
- crtMinY = -2 - courtyardPadding;
7716
- crtMaxY = 3 + courtyardPadding;
7717
- } else if (variant === "sh") {
7718
- const sideOffset = (numPins - 1) / 2 * p + 1.3;
7719
- crtMinX = -(sideOffset + 0.6 + courtyardPadding);
7720
- crtMaxX = sideOffset + 0.6 + courtyardPadding;
7721
- crtMinY = -1.325 - pl / 2 - courtyardPadding;
7722
- crtMaxY = 1.22 + 0.9 + courtyardPadding;
7723
- } else {
7724
- const pinSpan = (numPins - 1) * p;
7725
- const bodyHalfW = pinSpan / 2 + 1.5;
7726
- crtMinX = -(bodyHalfW + courtyardPadding);
7727
- crtMaxX = bodyHalfW + courtyardPadding;
7728
- crtMinY = -h / 2 - courtyardPadding;
7729
- crtMaxY = h / 2 + courtyardPadding;
7730
- }
7889
+ const silkscreenXs = silkscreenBody.route.map((point) => point.x);
7890
+ const silkscreenYs = silkscreenBody.route.map((point) => point.y);
7891
+ const hasSilkscreenGeometry = silkscreenXs.length > 0 && silkscreenYs.length > 0;
7892
+ const featureMinX = hasSilkscreenGeometry ? Math.min(padBounds.minX, Math.min(...silkscreenXs)) : padBounds.minX;
7893
+ const featureMaxX = hasSilkscreenGeometry ? Math.max(padBounds.maxX, Math.max(...silkscreenXs)) : padBounds.maxX;
7894
+ const featureMinY = hasSilkscreenGeometry ? Math.min(padBounds.minY, Math.min(...silkscreenYs)) : padBounds.minY;
7895
+ const featureMaxY = hasSilkscreenGeometry ? Math.max(padBounds.maxY, Math.max(...silkscreenYs)) : padBounds.maxY;
7896
+ const courtyardSideClearanceX = 0.5;
7897
+ const courtyardFrontClearanceY = 0.05;
7898
+ const courtyardRearClearanceY = maxPadHalfY + 0.085;
7899
+ const crtMinX = featureMinX - courtyardSideClearanceX;
7900
+ const crtMaxX = featureMaxX + courtyardSideClearanceX;
7901
+ const crtMinY = featureMinY - courtyardRearClearanceY;
7902
+ const crtMaxY = featureMaxY + courtyardFrontClearanceY;
7731
7903
  const courtyard = {
7732
7904
  type: "pcb_courtyard_rect",
7733
7905
  pcb_courtyard_rect_id: "",
@@ -7959,14 +8131,11 @@ var vssop = (raw_params) => {
7959
8131
  silkscreenBoxHeight / 2 + 0.5,
7960
8132
  0.3
7961
8133
  );
7962
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
7963
8134
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * p + pw;
7964
- const courtyardStepInnerHalfX = roundToCourtyardGrid(w / 2 + 0.25);
7965
- const courtyardStepOuterHalfX = roundToCourtyardGrid(
7966
- courtyardStepInnerHalfX + 1.43
7967
- );
7968
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.255);
7969
- const courtyardStepOuterHalfY = roundToCourtyardGrid(h / 2 + 0.25);
8135
+ const courtyardStepInnerHalfWidth = w / 2 + 0.25;
8136
+ const courtyardStepOuterHalfWidth = courtyardStepInnerHalfWidth + 1.43;
8137
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.255;
8138
+ const courtyardStepOuterHalfHeight = h / 2 + 0.25;
7970
8139
  const courtyard = {
7971
8140
  type: "pcb_courtyard_outline",
7972
8141
  pcb_courtyard_outline_id: "",
@@ -7974,16 +8143,16 @@ var vssop = (raw_params) => {
7974
8143
  layer: "top",
7975
8144
  outline: createRectUnionOutline([
7976
8145
  {
7977
- minX: -courtyardStepOuterHalfX,
7978
- maxX: courtyardStepOuterHalfX,
7979
- minY: -courtyardStepInnerHalfY,
7980
- maxY: courtyardStepInnerHalfY
8146
+ minX: -courtyardStepOuterHalfWidth,
8147
+ maxX: courtyardStepOuterHalfWidth,
8148
+ minY: -courtyardStepInnerHalfHeight,
8149
+ maxY: courtyardStepInnerHalfHeight
7981
8150
  },
7982
8151
  {
7983
- minX: -courtyardStepInnerHalfX,
7984
- maxX: courtyardStepInnerHalfX,
7985
- minY: -courtyardStepOuterHalfY,
7986
- maxY: courtyardStepOuterHalfY
8152
+ minX: -courtyardStepInnerHalfWidth,
8153
+ maxX: courtyardStepInnerHalfWidth,
8154
+ minY: -courtyardStepOuterHalfHeight,
8155
+ maxY: courtyardStepOuterHalfHeight
7987
8156
  }
7988
8157
  ])
7989
8158
  };
@@ -8134,14 +8303,11 @@ var msop = (raw_params) => {
8134
8303
  silkscreenBoxHeight / 2 + 0.5,
8135
8304
  0.3
8136
8305
  );
8137
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
8138
8306
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * p + pw;
8139
- const courtyardStepInnerHalfX = roundToCourtyardGrid(w / 2 + 0.25);
8140
- const courtyardStepOuterHalfX = roundToCourtyardGrid(
8141
- courtyardStepInnerHalfX + 1.43
8142
- );
8143
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.255);
8144
- const courtyardStepOuterHalfY = roundToCourtyardGrid(h / 2 + 0.25);
8307
+ const courtyardStepInnerHalfWidth = w / 2 + 0.25;
8308
+ const courtyardStepOuterHalfWidth = courtyardStepInnerHalfWidth + 1.43;
8309
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.255;
8310
+ const courtyardStepOuterHalfHeight = h / 2 + 0.25;
8145
8311
  const courtyard = {
8146
8312
  type: "pcb_courtyard_outline",
8147
8313
  pcb_courtyard_outline_id: "",
@@ -8149,16 +8315,16 @@ var msop = (raw_params) => {
8149
8315
  layer: "top",
8150
8316
  outline: createRectUnionOutline([
8151
8317
  {
8152
- minX: -courtyardStepOuterHalfX,
8153
- maxX: courtyardStepOuterHalfX,
8154
- minY: -courtyardStepInnerHalfY,
8155
- maxY: courtyardStepInnerHalfY
8318
+ minX: -courtyardStepOuterHalfWidth,
8319
+ maxX: courtyardStepOuterHalfWidth,
8320
+ minY: -courtyardStepInnerHalfHeight,
8321
+ maxY: courtyardStepInnerHalfHeight
8156
8322
  },
8157
8323
  {
8158
- minX: -courtyardStepInnerHalfX,
8159
- maxX: courtyardStepInnerHalfX,
8160
- minY: -courtyardStepOuterHalfY,
8161
- maxY: courtyardStepOuterHalfY
8324
+ minX: -courtyardStepInnerHalfWidth,
8325
+ maxX: courtyardStepInnerHalfWidth,
8326
+ minY: -courtyardStepOuterHalfHeight,
8327
+ maxY: courtyardStepOuterHalfHeight
8162
8328
  }
8163
8329
  ])
8164
8330
  };
@@ -8452,16 +8618,15 @@ var son = (raw_params) => {
8452
8618
  silkscreenBoxHeight / 2 + 0.5,
8453
8619
  0.3
8454
8620
  );
8455
- const roundToCourtyardGrid = (value) => Math.round(value / 0.01) * 0.01;
8456
8621
  const pinColumnCenterX = Math.abs(
8457
8622
  getSonPadCoord(parameters.num_pins, 1, w, p).x
8458
8623
  );
8459
8624
  const pinRowSpanY = (parameters.num_pins / 2 - 1) * p + pw;
8460
8625
  const pinRowSpanX = pinColumnCenterX * 2 + pl;
8461
- const courtyardStepInnerHalfX = roundToCourtyardGrid(w / 2 + 0.25);
8462
- const courtyardStepOuterHalfX = roundToCourtyardGrid(pinRowSpanX / 2 + 0.25);
8463
- const courtyardStepInnerHalfY = roundToCourtyardGrid(pinRowSpanY / 2 + 0.25);
8464
- const courtyardStepOuterHalfY = roundToCourtyardGrid(h / 2 + 0.25);
8626
+ const courtyardStepInnerHalfWidth = w / 2 + 0.25;
8627
+ const courtyardStepOuterHalfWidth = pinRowSpanX / 2 + 0.25;
8628
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.25;
8629
+ const courtyardStepOuterHalfHeight = h / 2 + 0.25;
8465
8630
  const courtyard = {
8466
8631
  type: "pcb_courtyard_outline",
8467
8632
  pcb_courtyard_outline_id: "",
@@ -8469,16 +8634,16 @@ var son = (raw_params) => {
8469
8634
  layer: "top",
8470
8635
  outline: createRectUnionOutline([
8471
8636
  {
8472
- minX: -courtyardStepOuterHalfX,
8473
- maxX: courtyardStepOuterHalfX,
8474
- minY: -courtyardStepInnerHalfY,
8475
- maxY: courtyardStepInnerHalfY
8637
+ minX: -courtyardStepOuterHalfWidth,
8638
+ maxX: courtyardStepOuterHalfWidth,
8639
+ minY: -courtyardStepInnerHalfHeight,
8640
+ maxY: courtyardStepInnerHalfHeight
8476
8641
  },
8477
8642
  {
8478
- minX: -courtyardStepInnerHalfX,
8479
- maxX: courtyardStepInnerHalfX,
8480
- minY: -courtyardStepOuterHalfY,
8481
- maxY: courtyardStepOuterHalfY
8643
+ minX: -courtyardStepInnerHalfWidth,
8644
+ maxX: courtyardStepInnerHalfWidth,
8645
+ minY: -courtyardStepOuterHalfHeight,
8646
+ maxY: courtyardStepOuterHalfHeight
8482
8647
  }
8483
8648
  ])
8484
8649
  };
@@ -8544,20 +8709,46 @@ var vson = (raw_params) => {
8544
8709
  grid.y / 2 + p,
8545
8710
  grid.y / 6
8546
8711
  );
8547
- const courtyardPadding = 0.25;
8548
- const centerY = (num_pins / 2 - 1) * p / 2;
8549
- const crtMinX = -(w / 2 + pinw / 2 + courtyardPadding);
8550
- const crtMaxX = w / 2 + pinw / 2 + courtyardPadding;
8551
- const crtMinY = -(Math.max(grid.y / 2, centerY + pinh / 2) + courtyardPadding);
8552
- const crtMaxY = Math.max(grid.y / 2, centerY + pinh / 2) + courtyardPadding;
8712
+ const pinRowSpanY = (num_pins / 2 - 1) * p + pinh;
8713
+ const pinRowSpanX = w + pinw;
8714
+ const courtyardStepInnerHalfWidth = grid.x / 2 + 0.25;
8715
+ const courtyardStepOuterHalfWidth = pinRowSpanX / 2 + 0.25;
8716
+ const pinRowCourtyardHalfY = pinRowSpanY / 2 + 0.25;
8717
+ const pinRowExtendedCourtyardHalfY = pinRowSpanY / 2 + 0.45 + Math.max(0, 0.8 - p);
8718
+ const courtyardStepOuterHalfHeight = Math.min(
8719
+ grid.y / 2 + 0.25,
8720
+ pinRowExtendedCourtyardHalfY
8721
+ );
8722
+ const courtyardStepNotchDepthY = Math.max(
8723
+ 0,
8724
+ 0.37 - Math.max(
8725
+ 0,
8726
+ courtyardStepOuterHalfWidth - courtyardStepInnerHalfWidth - 0.38
8727
+ ) * 1.4
8728
+ );
8729
+ const courtyardStepInnerHalfHeight = Math.max(
8730
+ pinRowCourtyardHalfY,
8731
+ courtyardStepOuterHalfHeight - courtyardStepNotchDepthY
8732
+ );
8553
8733
  const courtyard = {
8554
- type: "pcb_courtyard_rect",
8555
- pcb_courtyard_rect_id: "",
8734
+ type: "pcb_courtyard_outline",
8735
+ pcb_courtyard_outline_id: "",
8556
8736
  pcb_component_id: "",
8557
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
8558
- width: crtMaxX - crtMinX,
8559
- height: crtMaxY - crtMinY,
8560
- layer: "top"
8737
+ layer: "top",
8738
+ outline: createRectUnionOutline([
8739
+ {
8740
+ minX: -courtyardStepOuterHalfWidth,
8741
+ maxX: courtyardStepOuterHalfWidth,
8742
+ minY: -courtyardStepInnerHalfHeight,
8743
+ maxY: courtyardStepInnerHalfHeight
8744
+ },
8745
+ {
8746
+ minX: -courtyardStepInnerHalfWidth,
8747
+ maxX: courtyardStepInnerHalfWidth,
8748
+ minY: -courtyardStepOuterHalfHeight,
8749
+ maxY: courtyardStepOuterHalfHeight
8750
+ }
8751
+ ])
8561
8752
  };
8562
8753
  return {
8563
8754
  circuitJson: [...pads, ...silkscreenPaths, silkscreenRefText, courtyard],
@@ -9227,20 +9418,16 @@ var electrolytic = (raw_params) => {
9227
9418
  pcb_silkscreen_path_id: ""
9228
9419
  };
9229
9420
  const silkscreenRefText = silkscreenRef(0, d / 2 + 1, 0.5);
9230
- const bodyR = d / 2 + 0.1;
9231
- const plusLeftExtent = Math.abs(X) + Size;
9232
- const courtyardPadding = 0.25;
9233
- const crtMinX = -Math.max(bodyR, plusLeftExtent) - courtyardPadding;
9234
- const crtMaxX = bodyR + courtyardPadding;
9235
- const crtMinY = -(bodyR + courtyardPadding);
9236
- const crtMaxY = bodyR + courtyardPadding;
9421
+ const bodyOuterRadius = d / 2;
9422
+ const pinOuterRadius = p / 2 + od / 2;
9423
+ const courtyardClearance = 0.25;
9424
+ const courtyardRadius = Math.max(bodyOuterRadius, pinOuterRadius) + courtyardClearance;
9237
9425
  const courtyard = {
9238
- type: "pcb_courtyard_rect",
9239
- pcb_courtyard_rect_id: "",
9426
+ type: "pcb_courtyard_circle",
9427
+ pcb_courtyard_circle_id: "",
9240
9428
  pcb_component_id: "",
9241
- center: { x: (crtMinX + crtMaxX) / 2, y: 0 },
9242
- width: crtMaxX - crtMinX,
9243
- height: crtMaxY - crtMinY,
9429
+ center: { x: 0, y: 0 },
9430
+ radius: courtyardRadius,
9244
9431
  layer: "top"
9245
9432
  };
9246
9433
  return {
@@ -9730,21 +9917,32 @@ var sotWithoutParsing = (parameters) => {
9730
9917
  const p_val = Number.parseFloat(parameters.p);
9731
9918
  const pl_val = Number.parseFloat(parameters.pl);
9732
9919
  const pw_val = Number.parseFloat(parameters.pw);
9733
- const courtyardPadding = 0.25;
9734
- const padCenterX = h_val / 2 + 0.5;
9735
- const silkscreenY = h_val / 2 + p_val / 1.3;
9736
- const crtMinX = -(padCenterX + pl_val / 2 + courtyardPadding);
9737
- const crtMaxX = padCenterX + pl_val / 2 + courtyardPadding;
9738
- const crtMinY = -(Math.max(silkscreenY, p_val + pw_val / 2) + courtyardPadding);
9739
- const crtMaxY = Math.max(silkscreenY, p_val + pw_val / 2) + courtyardPadding;
9920
+ const pinColumnCenterX = h_val / 2 + 0.5;
9921
+ const pinRowSpanY = p_val * 2 + pw_val;
9922
+ const pinToeHalfSpanX = pinColumnCenterX + pl_val / 2;
9923
+ const courtyardStepInnerHalfWidth = h_val / 2 + 0.25;
9924
+ const courtyardStepOuterHalfWidth = pinToeHalfSpanX + 0.25;
9925
+ const courtyardStepInnerHalfHeight = pinRowSpanY / 2 + 0.2;
9926
+ const courtyardStepOuterHalfHeight = courtyardStepInnerHalfHeight + 0.2;
9740
9927
  const courtyard = {
9741
- type: "pcb_courtyard_rect",
9742
- pcb_courtyard_rect_id: "",
9928
+ type: "pcb_courtyard_outline",
9929
+ pcb_courtyard_outline_id: "",
9743
9930
  pcb_component_id: "",
9744
- center: { x: (crtMinX + crtMaxX) / 2, y: (crtMinY + crtMaxY) / 2 },
9745
- width: crtMaxX - crtMinX,
9746
- height: crtMaxY - crtMinY,
9747
- layer: "top"
9931
+ layer: "top",
9932
+ outline: createRectUnionOutline([
9933
+ {
9934
+ minX: -courtyardStepOuterHalfWidth,
9935
+ maxX: courtyardStepOuterHalfWidth,
9936
+ minY: -courtyardStepInnerHalfHeight,
9937
+ maxY: courtyardStepInnerHalfHeight
9938
+ },
9939
+ {
9940
+ minX: -courtyardStepInnerHalfWidth,
9941
+ maxX: courtyardStepInnerHalfWidth,
9942
+ minY: -courtyardStepOuterHalfHeight,
9943
+ maxY: courtyardStepOuterHalfHeight
9944
+ }
9945
+ ])
9748
9946
  };
9749
9947
  return [
9750
9948
  ...pads,