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 +0 -5
- package/dist/index.js +91 -41
- package/package.json +1 -1
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 =
|
|
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 =
|
|
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