calculate-packing 0.0.36 → 0.0.37

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
@@ -390,11 +390,6 @@ declare class OutlineSegmentCandidatePointSolver extends BaseSolver {
390
390
  * Adjust position to avoid component bounds crossing to the inside of the outline
391
391
  */
392
392
  private adjustPositionForOutlineCollision;
393
- /**
394
- * Get the outward normal for the current segment by determining which side
395
- * is farther from the outline centroid
396
- */
397
- private getOutwardNormal;
398
393
  visualize(): GraphicsObject;
399
394
  }
400
395
 
package/dist/index.js CHANGED
@@ -966,6 +966,89 @@ function pointInOutline(p, segments, rule = "even-odd") {
966
966
  }
967
967
  }
968
968
 
969
+ // lib/OutlineSegmentCandidatePointSolver/getOutwardNormal.ts
970
+ function getOutwardNormal(outlineSegment, fullOutline) {
971
+ const [p1, p2] = outlineSegment;
972
+ const dx = p2.x - p1.x;
973
+ const dy = p2.y - p1.y;
974
+ const len = Math.hypot(dx, dy);
975
+ if (len === 0) {
976
+ return { x: 0, y: 1 };
977
+ }
978
+ const dirX = dx / len;
979
+ const dirY = dy / len;
980
+ const left = { x: -dirY, y: dirX };
981
+ const right = { x: dirY, y: -dirX };
982
+ const mid = {
983
+ x: (p1.x + p2.x) / 2,
984
+ y: (p1.y + p2.y) / 2
985
+ };
986
+ const bbox = getOutlineBoundsWithMargin(fullOutline);
987
+ const scale = Math.max(bbox.maxX - bbox.minX, bbox.maxY - bbox.minY) || 1;
988
+ const testDistance = Math.max(1e-4, 1e-3 * scale);
989
+ const testLeft = {
990
+ x: mid.x + left.x * testDistance,
991
+ y: mid.y + left.y * testDistance
992
+ };
993
+ const testRight = {
994
+ x: mid.x + right.x * testDistance,
995
+ y: mid.y + right.y * testDistance
996
+ };
997
+ const locLeft = pointInOutline(testLeft, fullOutline);
998
+ if (locLeft === "outside") {
999
+ return left;
1000
+ }
1001
+ const locRight = pointInOutline(testRight, fullOutline);
1002
+ if (locRight === "outside") {
1003
+ return right;
1004
+ }
1005
+ const verts = [];
1006
+ if (fullOutline.length > 0) {
1007
+ verts.push(fullOutline[0][0]);
1008
+ for (const seg of fullOutline) {
1009
+ verts.push(seg[1]);
1010
+ }
1011
+ }
1012
+ const signedArea = (() => {
1013
+ let a = 0;
1014
+ for (let i = 0; i < verts.length; i++) {
1015
+ const v1 = verts[i];
1016
+ const v2 = verts[(i + 1) % verts.length];
1017
+ a += v1.x * v2.y - v2.x * v1.y;
1018
+ }
1019
+ return a / 2;
1020
+ })();
1021
+ if (Math.abs(signedArea) > 1e-12) {
1022
+ return signedArea > 0 ? right : left;
1023
+ }
1024
+ const center = {
1025
+ x: (bbox.minX + bbox.maxX) / 2,
1026
+ y: (bbox.minY + bbox.maxY) / 2
1027
+ };
1028
+ const away = { x: mid.x - center.x, y: mid.y - center.y };
1029
+ const dotLeft = left.x * away.x + left.y * away.y;
1030
+ const dotRight = right.x * away.x + right.y * away.y;
1031
+ return dotRight >= dotLeft ? right : left;
1032
+ }
1033
+ function getOutlineBoundsWithMargin(fullOutline, margin = 0) {
1034
+ let minX = Infinity;
1035
+ let minY = Infinity;
1036
+ let maxX = -Infinity;
1037
+ let maxY = -Infinity;
1038
+ for (const [p1, p2] of fullOutline) {
1039
+ minX = Math.min(minX, p1.x, p2.x);
1040
+ minY = Math.min(minY, p1.y, p2.y);
1041
+ maxX = Math.max(maxX, p1.x, p2.x);
1042
+ maxY = Math.max(maxY, p1.y, p2.y);
1043
+ }
1044
+ return {
1045
+ minX: minX - margin,
1046
+ minY: minY - margin,
1047
+ maxX: maxX + margin,
1048
+ maxY: maxY + margin
1049
+ };
1050
+ }
1051
+
969
1052
  // lib/LargestRectOutsideOutlineFromPointSolver.ts
970
1053
  var LargestRectOutsideOutlineFromPointSolver = class extends BaseSolver {
971
1054
  fullOutline;
@@ -1356,7 +1439,10 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
1356
1439
  );
1357
1440
  return this.adjustPositionForOutlineCollision(projectedPoint);
1358
1441
  };
1359
- const outwardNormal = this.getOutwardNormal();
1442
+ const outwardNormal = getOutwardNormal(
1443
+ this.outlineSegment,
1444
+ this.fullOutline
1445
+ );
1360
1446
  const componentBounds = getInputComponentBounds(this.componentToPack, {
1361
1447
  rotationDegrees: this.componentRotationDegrees
1362
1448
  });
@@ -1556,7 +1642,10 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
1556
1642
  adjustPositionForOutlineCollision(center) {
1557
1643
  const tempComponent = this.createTemporaryPackedComponent(center);
1558
1644
  const bounds = getComponentBounds(tempComponent, 0);
1559
- const outwardNormal = this.getOutwardNormal();
1645
+ const outwardNormal = getOutwardNormal(
1646
+ this.outlineSegment,
1647
+ this.fullOutline
1648
+ );
1560
1649
  const isHorizontalNormal = Math.abs(outwardNormal.x) > Math.abs(outwardNormal.y);
1561
1650
  const isVerticalNormal = !isHorizontalNormal;
1562
1651
  if (isHorizontalNormal) {
@@ -1591,45 +1680,6 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
1591
1680
  }
1592
1681
  throw new Error("unreachable");
1593
1682
  }
1594
- /**
1595
- * Get the outward normal for the current segment by determining which side
1596
- * is farther from the outline centroid
1597
- */
1598
- getOutwardNormal() {
1599
- const [p1, p2] = this.outlineSegment;
1600
- const segmentX = p2.x - p1.x;
1601
- const segmentY = p2.y - p1.y;
1602
- const segmentLength = Math.hypot(segmentX, segmentY);
1603
- if (segmentLength === 0) {
1604
- return { x: 0, y: 1 };
1605
- }
1606
- const segmentDirX = segmentX / segmentLength;
1607
- const segmentDirY = segmentY / segmentLength;
1608
- const normal1X = -segmentDirY;
1609
- const normal1Y = segmentDirX;
1610
- const normal2X = segmentDirY;
1611
- const normal2Y = -segmentDirX;
1612
- const segmentMidpoint = {
1613
- x: (p1.x + p2.x) / 2,
1614
- y: (p1.y + p2.y) / 2
1615
- };
1616
- const testDistance = 1e-4;
1617
- const testPoint1 = {
1618
- x: segmentMidpoint.x + normal1X * testDistance,
1619
- y: segmentMidpoint.y + normal1Y * testDistance
1620
- };
1621
- const testPoint2 = {
1622
- x: segmentMidpoint.x + normal2X * testDistance,
1623
- y: segmentMidpoint.y + normal2Y * testDistance
1624
- };
1625
- if (pointInOutline(testPoint1, this.fullOutline) === "outside") {
1626
- return { x: normal1X, y: normal1Y };
1627
- }
1628
- if (pointInOutline(testPoint2, this.fullOutline) === "outside") {
1629
- return { x: normal2X, y: normal2Y };
1630
- }
1631
- throw new Error("No outward normal found");
1632
- }
1633
1683
  visualize() {
1634
1684
  const graphics = {
1635
1685
  lines: [],
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.36",
5
+ "version": "0.0.37",
6
6
  "description": "Calculate a packing layout with support for different strategy configurations",
7
7
  "scripts": {
8
8
  "start": "cosmos",