Skip to content

Commit

Permalink
Public API-compatible backport of Rework code packing for better clar…
Browse files Browse the repository at this point in the history
…ity on layer vs row and position of items
  • Loading branch information
dvdoug committed Aug 13, 2017
1 parent 0cd62f9 commit 03f1cc3
Show file tree
Hide file tree
Showing 15 changed files with 1,435 additions and 1,201 deletions.
5 changes: 5 additions & 0 deletions BoxList.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ class BoxList extends \SplMinHeap
/**
* Compare elements in order to place them correctly in the heap while sifting up.
* @see \SplMinHeap::compare()
*
* @param Box $boxA
* @param Box $boxB
*
* @return int
*/
public function compare($boxA, $boxB)
{
Expand Down
6 changes: 6 additions & 0 deletions ItemList.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ class ItemList extends \SplMaxHeap

/**
* Compare elements in order to place them correctly in the heap while sifting up.
*
* @see \SplMaxHeap::compare()
*
* @param mixed $itemA
* @param mixed $itemB
*
* @return int
*/
public function compare($itemA, $itemB)
{
Expand Down
72 changes: 53 additions & 19 deletions OrientatedItemFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,26 @@ class OrientatedItemFactory implements LoggerAwareInterface
{
use LoggerAwareTrait;

/**
* @var OrientatedItem[]
*/
protected static $emptyBoxCache = [];

/**
* Get the best orientation for an item
* @param Box $box
* @param Item $item
* @param OrientatedItem|null $prevItem
* @param Item|null $nextItem
* @param PackedItem|null $prevItem
* @param bool $isLastItem
* @param int $widthLeft
* @param int $lengthLeft
* @param int $depthLeft
* @return OrientatedItem|false
*/
public function getBestOrientation(Box $box, Item $item, OrientatedItem $prevItem = null, Item $nextItem = null, $widthLeft, $lengthLeft, $depthLeft) {
public function getBestOrientation(Box $box, Item $item, PackedItem $prevItem = null, $isLastItem, $widthLeft, $lengthLeft, $depthLeft) {

$possibleOrientations = $this->getPossibleOrientations($item, $prevItem, $widthLeft, $lengthLeft, $depthLeft);
$usableOrientations = $this->getUsableOrientations($possibleOrientations, $box, $item, $prevItem, $nextItem);
$usableOrientations = $this->getUsableOrientations($possibleOrientations, $box, $item, $isLastItem);

$orientationFits = [];
/** @var OrientatedItem $orientation */
Expand All @@ -55,17 +60,18 @@ public function getBestOrientation(Box $box, Item $item, OrientatedItem $prevIte
/**
* Find all possible orientations for an item
* @param Item $item
* @param OrientatedItem|null $prevItem
* @param PackedItem|null $prevItem
* @param int $widthLeft
* @param int $lengthLeft
* @param int $depthLeft
* @return OrientatedItem[]
*/
public function getPossibleOrientations(Item $item, OrientatedItem $prevItem = null, $widthLeft, $lengthLeft, $depthLeft) {
public function getPossibleOrientations(Item $item, PackedItem $prevItem = null, $widthLeft, $lengthLeft, $depthLeft) {

$orientations = [];

//Special case items that are the same as what we just packed - keep orientation
/** @noinspection PhpNonStrictObjectEqualityInspection */
if ($prevItem && $prevItem->getItem() == $item) {
$orientations[] = new OrientatedItem($item, $prevItem->getWidth(), $prevItem->getLength(), $prevItem->getDepth());
} else {
Expand All @@ -89,21 +95,55 @@ public function getPossibleOrientations(Item $item, OrientatedItem $prevItem = n
});
}

/**
* @param Item $item
* @param Box $box
* @return OrientatedItem[]
*/
public function getPossibleOrientationsInEmptyBox(Item $item, Box $box)
{
$cacheKey = $item->getWidth() .
'|' .
$item->getLength() .
'|' .
$item->getDepth() .
'|' .
($item->getKeepFlat() ? '2D' : '3D') .
'|' .
$box->getInnerWidth() .
'|' .
$box->getInnerLength() .
'|' .
$box->getInnerDepth();

if (isset(static::$emptyBoxCache[$cacheKey])) {
$orientations = static::$emptyBoxCache[$cacheKey];
} else {
$orientations = $this->getPossibleOrientations(
$item,
null,
$box->getInnerWidth(),
$box->getInnerLength(),
$box->getInnerDepth()
);
static::$emptyBoxCache[$cacheKey] = $orientations;
}
return $orientations;
}

/**
* @param OrientatedItem[] $possibleOrientations
* @param Box $box
* @param Item $item
* @param OrientatedItem $prevItem
* @param Item $nextItem
* @param bool $isLastItem
*
* @return array
* @return OrientatedItem[]
*/
protected function getUsableOrientations(
$possibleOrientations,
Box $box,
Item $item,
OrientatedItem $prevItem = null,
Item $nextItem = null
$isLastItem
) {
/*
* Divide possible orientations into stable (low centre of gravity) and unstable (high centre of gravity)
Expand All @@ -129,13 +169,7 @@ protected function getUsableOrientations(
if (count($stableOrientations) > 0) {
$orientationsToUse = $stableOrientations;
} else if (count($unstableOrientations) > 0) {
$orientationsInEmptyBox = $this->getPossibleOrientations(
$item,
$prevItem,
$box->getInnerWidth(),
$box->getInnerLength(),
$box->getInnerDepth()
);
$orientationsInEmptyBox = $this->getPossibleOrientationsInEmptyBox($item, $box);

$stableOrientationsInEmptyBox = array_filter(
$orientationsInEmptyBox,
Expand All @@ -144,7 +178,7 @@ function(OrientatedItem $orientation) {
}
);

if (is_null($nextItem) || count($stableOrientationsInEmptyBox) == 0) {
if ($isLastItem || count($stableOrientationsInEmptyBox) == 0) {
$orientationsToUse = $unstableOrientations;
}
}
Expand Down
35 changes: 33 additions & 2 deletions PackedBox.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ public function getItems()
*/
public function getWeight()
{

if (!is_null($this->weight)) {
return $this->weight;
}
Expand Down Expand Up @@ -192,7 +191,8 @@ public function getVolumeUtilisation()


/**
* Constructor
* Legacy constructor
* @deprecated
*
* @param Box $box
* @param ItemList $itemList
Expand Down Expand Up @@ -226,4 +226,35 @@ public function __construct(
$this->usedLength = $usedLength;
$this->usedDepth = $usedDepth;
}

/**
* The constructor from v3
* @param Box $box
* @param PackedItemList $packedItems
*/
public static function fromPackedItemList(Box $box, PackedItemList $packedItems)
{
$maxWidth = $maxLength = $maxDepth = $weight = 0;
/** @var PackedItem $item */
foreach (clone $packedItems as $item) {
$maxWidth = max($maxWidth, $item->getX() + $item->getWidth());
$maxLength = max($maxLength, $item->getY() + $item->getLength());
$maxDepth = max($maxDepth, $item->getZ() + $item->getDepth());
$weight += $item->getItem()->getWeight();
}

$packedBox = new self(
$box,
$packedItems->asItemList(),
$box->getInnerWidth() - $maxWidth,
$box->getInnerLength() - $maxLength,
$box->getInnerDepth() - $maxDepth,
$box->getMaxWeight() - $box->getEmptyWeight() - $weight,
$maxWidth,
$maxLength,
$maxDepth
);

return $packedBox;
}
}
11 changes: 10 additions & 1 deletion PackedBoxList.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class PackedBoxList extends \SplMinHeap
/**
* Compare elements in order to place them correctly in the heap while sifting up.
* @see \SplMinHeap::compare()
*
* @param PackedBox $boxA
* @param PackedBox $boxB
*
* @return int
*/
public function compare($boxA, $boxB)
{
Expand All @@ -38,6 +43,10 @@ public function compare($boxA, $boxB)

/**
* Reversed version of compare
*
* @param PackedBox $boxA
* @param PackedBox $boxB
*
* @return int
*/
public function reverseCompare($boxA, $boxB)
Expand Down Expand Up @@ -101,7 +110,7 @@ public function getVolumeUtilisation()
foreach (clone $this as $box) {
$boxVolume += $box->getBox()->getInnerVolume();

/** @var Item $item */
/** @var PackedItem $item */
foreach (clone $box->getItems() as $item) {
$itemVolume += $item->getVolume();
}
Expand Down
Loading

0 comments on commit 03f1cc3

Please sign in to comment.