From 6fcff2ed6cea100a3f0d6ed161ab4dc9db018323 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sat, 10 Oct 2015 19:59:04 +0000 Subject: [PATCH 1/4] Add tests for observed bug where items get rotated by the "can we squeeze this and the next item in efficiently" check even when there's not enough width remaining for them to fit --- tests/PackerTest.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/PackerTest.php b/tests/PackerTest.php index c8b46e73..55c52bd3 100644 --- a/tests/PackerTest.php +++ b/tests/PackerTest.php @@ -387,6 +387,42 @@ public function testIssue14() { self::assertEquals(1, $packedBoxes->count()); } + public function testPackerPacksRotatedBoxesInNewRow() { + $packer = new Packer(); + $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); + + //Box can hold 7 items in a row and then is completely full, so 9 items won't fit + $packer->addBox(new TestBox('30x70x30InternalBox', 30, 70, 30, 0, 30, 70, 30, 0, 1000)); + $packedBoxes = $packer->pack(); + self::assertEquals(2, $packedBoxes->count()); + + //Box can hold 7 items in a row, plus two more rotated, making 9 items + // with a 10x10x30 hole in the corner. + // + // Overhead view: + // + // +--+--++ + // ++++++++ + // |||||||| + // ++++++++ + // + $packer = new Packer(); + $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); + $packer->addBox(new TestBox('40x70x30InternalBox', 40, 70, 30, 0, 40, 70, 30, 0, 1000)); + $packedBoxes = $packer->pack(); + self::assertEquals(1, $packedBoxes->count()); + } + + public function testPackerDoesNotPackRotatedBoxesInNewRowWhenWidthGreaterThanSpace() { + $packer = new Packer(); + $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); + + //Box can hold 7 items in a row, but boxes are 10mm deep and gap is 5mm deep + //therefore there's length left for two rotated boxes but not enough width + $packer->addBox(new TestBox('35x70x30InternalBox', 35, 70, 30, 0, 35, 70, 30, 0, 1000)); + $packedBoxes = $packer->pack(); + self::assertEquals(2, $packedBoxes->count()); + } /** * @dataProvider getSamples From f6892899a641b28e78aa471dfca35b312ac068f9 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sun, 11 Oct 2015 17:24:16 +0000 Subject: [PATCH 2/4] Turn items around for vertical packing and fix test for actual broken situation --- tests/PackerTest.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/PackerTest.php b/tests/PackerTest.php index 55c52bd3..4b3fea35 100644 --- a/tests/PackerTest.php +++ b/tests/PackerTest.php @@ -389,7 +389,7 @@ public function testIssue14() { public function testPackerPacksRotatedBoxesInNewRow() { $packer = new Packer(); - $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); + $packer->addItem(new TestItem('30x10x30item', 30, 10, 30, 0), 9); //Box can hold 7 items in a row and then is completely full, so 9 items won't fit $packer->addBox(new TestBox('30x70x30InternalBox', 30, 70, 30, 0, 30, 70, 30, 0, 1000)); @@ -407,19 +407,15 @@ public function testPackerPacksRotatedBoxesInNewRow() { // ++++++++ // $packer = new Packer(); - $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); + $packer->addItem(new TestItem('30x10x30item', 30, 10, 30, 0), 9); $packer->addBox(new TestBox('40x70x30InternalBox', 40, 70, 30, 0, 40, 70, 30, 0, 1000)); $packedBoxes = $packer->pack(); self::assertEquals(1, $packedBoxes->count()); - } - public function testPackerDoesNotPackRotatedBoxesInNewRowWhenWidthGreaterThanSpace() { + // Make sure that it doesn't try to fit in a 10th item $packer = new Packer(); - $packer->addItem(new TestItem('30x30x10item', 30, 30, 10, 0), 9); - - //Box can hold 7 items in a row, but boxes are 10mm deep and gap is 5mm deep - //therefore there's length left for two rotated boxes but not enough width - $packer->addBox(new TestBox('35x70x30InternalBox', 35, 70, 30, 0, 35, 70, 30, 0, 1000)); + $packer->addItem(new TestItem('30x10x30item', 30, 10, 30, 0), 10); + $packer->addBox(new TestBox('40x70x30InternalBox', 40, 70, 30, 0, 40, 70, 30, 0, 1000)); $packedBoxes = $packer->pack(); self::assertEquals(2, $packedBoxes->count()); } From cefa66778870a086bd94603cd09086c304368605 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sun, 11 Oct 2015 17:25:31 +0000 Subject: [PATCH 3/4] Make sure that we only pack unrotated when it'll fit unrotated The shortcut look-ahead "do we have another identical item that can fit in more efficiently" got the wrong answer in some situations --- Packer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packer.php b/Packer.php index 1695986f..fa0e189d 100644 --- a/Packer.php +++ b/Packer.php @@ -289,7 +289,7 @@ public function packIntoBox(Box $aBox, ItemList $aItems) { if ($fitsRotatedGap < 0 || ($fitsSameGap >= 0 && $fitsSameGap <= $fitsRotatedGap) || - (!$aItems->isEmpty() && $aItems->top() == $itemToPack && $remainingLength >= 2 * $itemLength)) { + ($itemWidth <= $remainingWidth && !$aItems->isEmpty() && $aItems->top() == $itemToPack && $remainingLength >= 2 * $itemLength)) { $this->logger->log(LogLevel::DEBUG, "fits (better) unrotated"); $remainingLength -= $itemLength; $layerLength += $itemLength; From 0f8c07abb2aa3b3db322ac68f9e31c5aeec09619 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sun, 25 Oct 2015 17:58:14 +0000 Subject: [PATCH 4/4] Fix expected result for failing test Expected boxes is actually 1 because * Item 3 fits unrotated * Item 7s fit next to each other rotated Box: +--------------+ | | | | 3 | | 6 | | 0 | | +--------------+ 675 3 +----+ 3 | +-------+ 5 | #3 | #7 | 2 . | +-------+ 5 2 | | #7 | 4 8 +----+-------+ 335.28+330.2 = 665.4 ~15mm spare width, ~10mm spare length The #7s could also fit unrotated (they're narrower than #3 and total depth is less than when rotated) --- tests/PackerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PackerTest.php b/tests/PackerTest.php index 4b3fea35..310b526b 100644 --- a/tests/PackerTest.php +++ b/tests/PackerTest.php @@ -338,7 +338,7 @@ public function testIssue6() { $packer->addItem(new TestItem('Item 7', 330.2, 127, 101.6, 1)); $packedBoxes = $packer->pack(); - self::assertEquals(2, $packedBoxes->count()); + self::assertEquals(1, $packedBoxes->count()); }