/** * Pack items into boxes using the principle of largest volume item first * * @throws \RuntimeException * @return PackedBoxList */ public function doVolumePacking() { $packedBoxes = new PackedBoxList(); //Keep going until everything packed while ($this->items->count()) { $boxesToEvaluate = clone $this->boxes; $packedBoxesIteration = new PackedBoxList(); //Loop through boxes starting with smallest, see what happens while (!$boxesToEvaluate->isEmpty()) { $box = $boxesToEvaluate->extract(); $packedBox = $this->packIntoBox($box, clone $this->items); if ($packedBox->getItems()->count()) { $packedBoxesIteration->insert($packedBox); //Have we found a single box that contains everything? if ($packedBox->getItems()->count() === $this->items->count()) { break; } } } //Check iteration was productive if ($packedBoxesIteration->isEmpty()) { throw new \RuntimeException('Item ' . $this->items->top()->getDescription() . ' is too large to fit into any box'); } //Find best box of iteration, and remove packed items from unpacked list $bestBox = $packedBoxesIteration->top(); for ($i = 0; $i < $bestBox->getItems()->count(); $i++) { $this->items->extract(); } $packedBoxes->insert($bestBox); } return $packedBoxes; }
/** * Pack items into boxes using the principle of largest volume item first * * @throws \RuntimeException * @return PackedBoxList */ public function doVolumePacking() { $packedBoxes = new PackedBoxList(); //Keep going until everything packed while ($this->items->count()) { $boxesToEvaluate = clone $this->boxes; $packedBoxesIteration = new PackedBoxList(); //Loop through boxes starting with smallest, see what happens while (!$boxesToEvaluate->isEmpty()) { $box = $boxesToEvaluate->extract(); $volumePacker = new VolumePacker($box, clone $this->items); $volumePacker->setLogger($this->logger); $packedBox = $volumePacker->pack(); if ($packedBox->getItems()->count()) { $packedBoxesIteration->insert($packedBox); //Have we found a single box that contains everything? if ($packedBox->getItems()->count() === $this->items->count()) { break; } } } //Check iteration was productive if ($packedBoxesIteration->isEmpty()) { throw new \RuntimeException('Item ' . $this->items->top()->getDescription() . ' is too large to fit into any box'); } //Find best box of iteration, and remove packed items from unpacked list $bestBox = $packedBoxesIteration->top(); $unPackedItems = $this->items->asArray(); foreach (clone $bestBox->getItems() as $packedItem) { foreach ($unPackedItems as $unpackedKey => $unpackedItem) { if ($packedItem === $unpackedItem) { unset($unPackedItems[$unpackedKey]); break; } } } $unpackedItemList = new ItemList(); foreach ($unPackedItems as $unpackedItem) { $unpackedItemList->insert($unpackedItem); } $this->items = $unpackedItemList; $packedBoxes->insert($bestBox); } return $packedBoxes; }