calculate-packing 0.0.49 → 0.0.51

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/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  **calculate-packing** is a small TypeScript library that ships the placement /
4
4
  packing algorithm used by the [tscircuit tool-chain](https://github.com/tscircuit/tscircuit) for automatically laying out PCB components.
5
5
 
6
+ [Paste PackInput and Debug Online](https://calculate-packing.tscircuit.com/?fixture=%7B%22path%22%3A%22site%2Fpack%2Fpack-debugger-from-input.page.tsx%22%7D)
7
+
6
8
  The solver turns a user-supplied `PackInput` (components, pads & strategy
7
9
  settings) into a collision-free `PackOutput` while
8
10
 
package/dist/index.js CHANGED
@@ -2519,6 +2519,38 @@ gap_distance=${candidate.gapDistance}`,
2519
2519
 
2520
2520
  // lib/PackSolver2/PackSolver2.ts
2521
2521
  import { computeDistanceBetweenBoxes as computeDistanceBetweenBoxes3 } from "@tscircuit/math-utils";
2522
+
2523
+ // lib/math/getPolygonCentroid.ts
2524
+ function getPolygonCentroid(points) {
2525
+ if (points.length < 3) {
2526
+ const sumX = points.reduce((sum, p) => sum + p.x, 0);
2527
+ const sumY = points.reduce((sum, p) => sum + p.y, 0);
2528
+ return { x: sumX / points.length, y: sumY / points.length };
2529
+ }
2530
+ let signedArea = 0;
2531
+ let cx = 0;
2532
+ let cy = 0;
2533
+ for (let i = 0; i < points.length; i++) {
2534
+ const p1 = points[i];
2535
+ const p2 = points[(i + 1) % points.length];
2536
+ const crossProduct = p1.x * p2.y - p2.x * p1.y;
2537
+ signedArea += crossProduct;
2538
+ cx += (p1.x + p2.x) * crossProduct;
2539
+ cy += (p1.y + p2.y) * crossProduct;
2540
+ }
2541
+ signedArea *= 0.5;
2542
+ const area = Math.abs(signedArea);
2543
+ if (area < 1e-10) {
2544
+ const sumX = points.reduce((sum, p) => sum + p.x, 0);
2545
+ const sumY = points.reduce((sum, p) => sum + p.y, 0);
2546
+ return { x: sumX / points.length, y: sumY / points.length };
2547
+ }
2548
+ cx /= 6 * signedArea;
2549
+ cy /= 6 * signedArea;
2550
+ return { x: cx, y: cy };
2551
+ }
2552
+
2553
+ // lib/PackSolver2/PackSolver2.ts
2522
2554
  var PackSolver2 = class extends BaseSolver {
2523
2555
  packInput;
2524
2556
  unpackedComponentQueue = [];
@@ -2542,9 +2574,13 @@ var PackSolver2 = class extends BaseSolver {
2542
2574
  }
2543
2575
  packFirstComponent() {
2544
2576
  const firstComponentToPack = this.unpackedComponentQueue.shift();
2577
+ let initialPosition = { x: 0, y: 0 };
2578
+ if (this.packInput.boundaryOutline && this.packInput.boundaryOutline.length >= 3) {
2579
+ initialPosition = getPolygonCentroid(this.packInput.boundaryOutline);
2580
+ }
2545
2581
  const newPackedComponent = {
2546
2582
  ...firstComponentToPack,
2547
- center: { x: 0, y: 0 },
2583
+ center: initialPosition,
2548
2584
  ccwRotationOffset: 0,
2549
2585
  pads: firstComponentToPack.pads.map((p) => ({
2550
2586
  ...p,
@@ -2569,7 +2605,23 @@ var PackSolver2 = class extends BaseSolver {
2569
2605
  return distance + 1e-6 < this.packInput.minGap;
2570
2606
  });
2571
2607
  });
2572
- if (!tooCloseToObstacles) {
2608
+ let outsideBoundaryOutline = false;
2609
+ if (this.packInput.boundaryOutline && this.packInput.boundaryOutline.length >= 3) {
2610
+ const componentBounds = getComponentBounds(newPackedComponent, 0);
2611
+ const allPadsInside = newPackedComponent.pads.every(
2612
+ (pad) => isPointInPolygon(pad.absoluteCenter, this.packInput.boundaryOutline)
2613
+ );
2614
+ const cornersInside = [
2615
+ { x: componentBounds.minX, y: componentBounds.minY },
2616
+ { x: componentBounds.minX, y: componentBounds.maxY },
2617
+ { x: componentBounds.maxX, y: componentBounds.minY },
2618
+ { x: componentBounds.maxX, y: componentBounds.maxY }
2619
+ ].every(
2620
+ (corner) => isPointInPolygon(corner, this.packInput.boundaryOutline)
2621
+ );
2622
+ outsideBoundaryOutline = !allPadsInside || !cornersInside;
2623
+ }
2624
+ if (!tooCloseToObstacles && !outsideBoundaryOutline) {
2573
2625
  this.packedComponents.push(newPackedComponent);
2574
2626
  return;
2575
2627
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "calculate-packing",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.49",
5
+ "version": "0.0.51",
6
6
  "description": "Calculate a packing layout with support for different strategy configurations",
7
7
  "scripts": {
8
8
  "start": "cosmos",