Skip to content

Commit

Permalink
When packing vertically, use new layer merge functionality to pack sp…
Browse files Browse the repository at this point in the history
…ace fully rather than simply stack
  • Loading branch information
dvdoug committed May 4, 2021
1 parent 790e899 commit c892558
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 186 deletions.
51 changes: 9 additions & 42 deletions src/LayerPacker.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,26 @@ public function packLayer(ItemList &$items, PackedItemList $packedItemList, int
if ($orientatedItem instanceof OrientatedItem) {
$packedItem = PackedItem::fromOrientatedItem($orientatedItem, $x, $y, $z);
$layer->insert($packedItem);
$remainingWeightAllowed -= $itemToPack->getWeight();
$packedItemList->insert($packedItem);

$rowLength = max($rowLength, $packedItem->getLength());
$prevItem = $orientatedItem;

//Figure out if we can stack the next item vertically on top of this rather than side by side
//Figure out if we can stack items on top of this rather than side by side
//e.g. when we've packed a tall item, and have just put a shorter one next to it.
$this->packVerticallyInsideItemFootprint($layer, $packedItem, $packedItemList, $items, $remainingWeightAllowed, $guidelineLayerDepth, $rowLength, $x, $y, $z, $considerStability);

$prevItem = $orientatedItem;
$stackableDepth = ($guidelineLayerDepth ?: $layer->getDepth()) - $packedItem->getDepth();
if ($stackableDepth > 0) {
$stackedLayer = $this->packLayer($items, $packedItemList, $x, $y, $z + $packedItem->getDepth(), $x + $packedItem->getWidth(), $y + $packedItem->getLength(), $stackableDepth, $stackableDepth, $considerStability);
$layer->merge($stackedLayer);
}

//Having now placed an item, there is space *within the same row* along the length. Pack into that.
if (!$this->singlePassMode && $rowLength - $orientatedItem->getLength() > 0) {
if ($rowLength - $orientatedItem->getLength() > 0) {
$layer->merge($this->packLayer($items, $packedItemList, $x, $y + $orientatedItem->getLength(), $z, $widthForLayer, $rowLength, $depthForLayer, $layer->getDepth(), $considerStability));
}

$x += $packedItem->getWidth();
$remainingWeightAllowed = $this->box->getMaxWeight() - $this->box->getEmptyWeight() - $packedItemList->getWeight(); // remember may have packed additional items

if ($items->count() === 0 && $skippedItems) {
$items = ItemList::fromArray(array_merge($skippedItems, iterator_to_array($items)), true);
Expand Down Expand Up @@ -162,42 +165,6 @@ public function packLayer(ItemList &$items, PackedItemList $packedItemList, int
return $layer;
}

private function packVerticallyInsideItemFootprint(PackedLayer $layer, PackedItem $packedItem, PackedItemList $packedItemList, ItemList &$items, int &$remainingWeightAllowed, int $guidelineLayerDepth, int $rowLength, int $x, int $y, int $z, bool $considerStability): void
{
$stackableDepth = ($guidelineLayerDepth ?: $layer->getDepth()) - $packedItem->getDepth();
$stackedZ = $z + $packedItem->getDepth();
$stackSkippedItems = [];
$stackedItem = $packedItem->toOrientatedItem();
while ($stackableDepth > 0 && $items->count() > 0) {
$itemToTryStacking = $items->extract();

//skip items that will never fit
if (!$this->checkNonDimensionalConstraints($itemToTryStacking, $remainingWeightAllowed, $packedItemList)) {
continue;
}

$stackedItem = $this->orientatedItemFactory->getBestOrientation($itemToTryStacking, $stackedItem, $items, $packedItem->getWidth(), $packedItem->getLength(), $stackableDepth, $rowLength, $x, $y, $stackedZ, $packedItemList, $considerStability);
if ($stackedItem) {
$packedStackedItem = PackedItem::fromOrientatedItem($stackedItem, $x, $y, $stackedZ);
$layer->insert($packedStackedItem);
$remainingWeightAllowed -= $itemToTryStacking->getWeight();
$packedItemList->insert($packedStackedItem);
$stackableDepth -= $stackedItem->getDepth();
$stackedZ += $stackedItem->getDepth();
continue;
}

$stackSkippedItems[] = $itemToTryStacking;
// abandon here if next item is the same, no point trying to keep going
while ($items->count() > 0 && static::isSameDimensions($itemToTryStacking, $items->top())) {
$stackSkippedItems[] = $items->extract();
}
}
if ($stackSkippedItems) {
$items = ItemList::fromArray(array_merge($stackSkippedItems, iterator_to_array($items)), true);
}
}

/**
* As well as purely dimensional constraints, there are other constraints that need to be met
* e.g. weight limits or item-specific restrictions (e.g. max <x> batteries per box).
Expand Down
2 changes: 1 addition & 1 deletion tests/InfalliblePackerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,6 @@ public function testIssue182B(): void
/** @var PackedBox[] $packedBoxes */
$packedBoxes = iterator_to_array($packer->pack(), false);

self::assertCount(41, $packedBoxes);
self::assertCount(42, $packedBoxes);
}
}
16 changes: 16 additions & 0 deletions tests/PackerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -557,4 +557,20 @@ public function testIssue206(): void

self::assertCount(2, $packedBoxes);
}

public function testIssue231(): void
{
$packer = new Packer();
$packer->setMaxBoxesToBalanceWeight(0);
$packer->addBox(new TestBox('Box 2.5-1', 30, 20, 20, 2, 30, 20, 20, 1000));

$packer->addItem(new TestItem('Item 1', 20, 20, 2, 0, false), 4);
$packer->addItem(new TestItem('Item 2', 8, 3, 2, 0, false), 5);
$packer->addItem(new TestItem('Item 3', 10, 10, 10, 0, false), 4);
$packer->addItem(new TestItem('Item 4', 12, 12, 10, 0, false), 2);
$packer->addItem(new TestItem('Item 5', 6, 4, 2, 0, false), 2);
$packedBoxes = $packer->pack();

self::assertCount(1, $packedBoxes);
}
}
18 changes: 9 additions & 9 deletions tests/data/expected.csv
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@
1672e9897bfb16f7f644365da8d6992c,1,0,26.4,1,0,26.4
167db38fa514a30e70f167f70d19f214,1,0,16.2,1,0,16.2
168065302d10d2f4b683e3d5e7475594,2,180200.3,32.7,1,0,19.8
1680b70ba864c313d28c9386ce54ac25,3,11023938.7,44,3,8617.6,38.5
1680b70ba864c313d28c9386ce54ac25,3,11023938.7,44,3,6590.9,38.5
1694662b95ac32661ee2b45826bb54f6,1,0,42.4,1,0,42.4
16a2283358cddda00bf2e47e5ad746d3,1,0,24,1,0,24
16a59c72d05be053c19e4b32ceafaef0,1,0,29.2,1,0,29.2
Expand Down Expand Up @@ -1039,7 +1039,7 @@
3bdea76452dfd0a2dd349e05688ceea7,1,0,36.2,1,0,36.2
3bec6daa3c92aab45d0db63b688bad9e,5,89240,34.3,2,3543806.3,18.1
3becb246809835f192b15039849f3528,1,0,27.5,1,0,27.5
3bee0a82a9098c92945daac991fca070,2,12.3,23.7,1,0,7.1
3bee0a82a9098c92945daac991fca070,2,812.3,23.7,1,0,7.1
3c1b74fc52f870503d59c3327da6d203,2,607620.3,40,1,0,24.2
3c29ccbdb900b4ade8f05884d9bafb1c,1,0,38.1,1,0,38.1
3c2bc39429c8d1a0db6369149f454d65,2,2916,39.5,1,0,11.9
Expand Down Expand Up @@ -1379,7 +1379,7 @@
4fb44d17cda18d0c04605f4374ffdb1a,2,35344,31.3,1,0,9.4
4fc2ca67d296a3e0d82f8b854923d168,1,0,15.9,1,0,15.9
4fcd699375dfa7df1c0eb12192d63b7c,3,51416.2,39.8,1,0,17.9
4fd15118c3e987fccfbad711528ff651,2,20306.3,33.2,1,0,20.1
4fd15118c3e987fccfbad711528ff651,2,137270.3,33.2,1,0,20.1
4fe79c3227acbda1fe01333d510f123d,1,0,18.8,1,0,18.8
500766fa9c90269017ac1194fa6c1e0e,1,0,22.9,1,0,22.9
500db53f251bd71c4d30a298b982f6ac,1,0,45.5,1,0,45.5
Expand Down Expand Up @@ -1890,7 +1890,7 @@
6d0c88f8167434fcab5a7b9f330f0885,2,0,42.6,2,0,42.6
6d111f1a879a3c039d73657ccfe74005,1,0,31,1,0,31
6d1ebe448310ccf0f310b0236a9992d5,1,0,40.4,1,0,40.4
6d30ec00cea682d3aadfab28a2665e39,1,0,44.8,1,0,44.8
6d30ec00cea682d3aadfab28a2665e39,2,2500,22.4,1,0,6.7
6d31a51a06785af8acc76099922e6c77,1,0,33.1,1,0,33.1
6d3a1f35383f5a21e69f0477bfe8ba3b,2,11923209,66.7,2,11923209,66.7
6d3ac65f88396d25753aafd4abbf6b0c,1,0,28.5,1,0,28.5
Expand Down Expand Up @@ -2811,7 +2811,7 @@ a4e8c2d7bb8e21c07d5d5bae9a48e4d6,1,0,50.3,1,0,50.3
a4fd5a590aaa3f655ba15495467d6f70,1,0,18.6,1,0,18.6
a4ff6a3aaf181e8d271f83f5f54c08f0,1,0,22.4,1,0,22.4
a519050b60f3a28945c3af20e54c98e5,1,0,34.1,1,0,34.1
a52ed384032d0d764c40c5b198b0cfe1,1,0,60.9,1,0,60.9
a52ed384032d0d764c40c5b198b0cfe1,2,506.3,30.4,1,0,9.1
a5328f72f09fcc8322081db3107d25de,1,0,40.1,1,0,40.1
a534bd597a5e786f47acade9b5189bb0,2,2352.3,29.4,1,0,17.8
a536b666854eead81fb1bf325fedcf9a,1,0,42.1,1,0,42.1
Expand All @@ -2826,7 +2826,7 @@ a5d6c152df8c6966ed3b39588106079f,1,0,17.2,1,0,17.2
a5ec92541060f2793041970dd5de10c3,1,0,16.2,1,0,16.2
a5efd1b0c6ca442b1c7a59bf00938d3e,1,0,46.9,1,0,46.9
a60d82e7aaff19e99d10de4cc5444356,1,0,27.5,1,0,27.5
a6301dc72697cfd7e96312f0b33f51ac,2,3152400.3,51,1,0,30.9
a6301dc72697cfd7e96312f0b33f51ac,2,3106406.3,51,1,0,30.9
a631d607f7a57e526b5c1fe63bab1a62,1,0,20.6,1,0,20.6
a632234c51a55c0ff877973a0198fcba,2,462.3,34.9,1,0,10.5
a6354eea25581f1805f09ffcd40eabe8,1,0,18.1,1,0,18.1
Expand Down Expand Up @@ -3736,7 +3736,7 @@ dc9737ca1f92510793b36d8ae7cb5e3d,1,0,15.8,1,0,15.8
dcaca1dd153991ec35057c6d4fee3486,1,0,44.6,1,0,44.6
dcc277e172757d58122d2ccb930f8c4b,1,0,43.9,1,0,43.9
dcf2491716b475d4ecbd6cc3982a415e,2,1156,31.8,1,0,9.5
dcf5b5a83a9848963949ab6a6ba6abd7,4,4363573.3,46.4,2,23104,38.6
dcf5b5a83a9848963949ab6a6ba6abd7,4,4363573.3,46.4,2,1156,38.6
dd0a4b2010a740c448bd83907d2980ea,1,0,28.5,1,0,28.5
dd0b36c45e6dd7c0bbca1132041a2bc8,1,0,36.1,1,0,36.1
dd10cf63e03f3226d61c074d9d8e1caf,1,0,20.3,1,0,20.3
Expand All @@ -3746,7 +3746,7 @@ dd655a5bf318ca48d36010fce2709553,1,0,22.3,1,0,22.3
dd74f550bb177a933b62b5d2836fa4ac,1,0,47.6,1,0,47.6
dd8191420604dcedf2ec59a470b09b4b,2,6642.3,30.5,1,0,9.1
dd897cf7eea6d6a7cc0380f78f29ba4f,1,0,35.5,1,0,35.5
dd9218a4b66b8a0378dc16a8fba27f67,2,12089529,45.5,2,27556,35.9
dd9218a4b66b8a0378dc16a8fba27f67,2,12089529,45.5,2,25,35.9
dd9fb38020ae211a57e53460275d0669,1,0,26.4,1,0,26.4
ddaa30c4e2af2de865dda0e017d98665,2,110.3,49.9,1,0,15
ddd908a2c90918db7e76f544b2a35883,1,0,44,1,0,44
Expand Down Expand Up @@ -4199,7 +4199,7 @@ fa5d9ae6b63e9d33769081f7d4f2b115,1,0,30,1,0,30
fa74eadd074843a8c78542d7602c31d4,1,0,48.4,1,0,48.4
faa914e796a804997c19804300db0204,1,0,42.7,1,0,42.7
faae756f0de0eef0384474255db1e662,1,0,41.6,1,0,41.6
fac6c548649f983888821cb370e87966,1,0,34,1,0,34
fac6c548649f983888821cb370e87966,1,0,74.5,1,0,34
fad39d2e603bae2ac15387a3662de7ff,2,22201,37.6,1,0,11.3
fae22f77df7666ed2fdc5757bd78ed07,1,0,33.9,1,0,33.9
faec3db769a11d268cd4845fb3966167,1,0,41.1,1,0,41.1
Expand Down
Loading

0 comments on commit c892558

Please sign in to comment.