Skip to content

Commit

Permalink
Backport doc improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dvdoug committed Jul 26, 2023
1 parent 6a7908a commit 854a27b
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 124 deletions.
95 changes: 7 additions & 88 deletions docs/advanced-usage.rst → docs/custom-constraints.rst
@@ -1,69 +1,5 @@
Advanced usage
==============

Used / remaining space
----------------------

After packing it is possible to see how much physical space in each ``PackedBox`` is taken up with items,
and how much space was unused (air). This information might be useful to determine whether it would be useful to source
alternative/additional sizes of box.

At a high level, the ``getVolumeUtilisation()`` method exists which calculates how full the box is as a percentage of volume.

Lower-level methods are also available for examining this data in detail either using ``getUsed[Width|Length|Depth()]``
(a hypothetical box placed around the items) or ``getRemaining[Width|Length|Depth()]`` (the difference between the dimensions of
the actual box and the hypothetical box).

.. note::

BoxPacker will always try to pack items into the smallest box available

Example - warning on a massively oversized box
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: php
<?php
// assuming packing already took place
foreach ($packedBoxes as $packedBox) {
if ($packedBox->getVolumeUtilisation() < 20) {
// box is 80% air, log a warning
}
}
Positional information
----------------------
It is also possible to see the precise positional and dimensional information of each item as packed. This is exposed as x,y,z
co-ordinates from origin, alongside width/length/depth in the packed orientation. ::

z y
| /
| /
| /
|/
0------x

Example
^^^^^^^

.. code-block:: php
<?php
// assuming packing already took place
foreach ($packedBoxes as $packedBox) {
$packedItems = $packedBox->getItems();
foreach ($packedItems as $packedItem) { // $packedItem->getItem() is your own item object
echo $packedItem->getItem()->getDescription() . ' was packed at co-ordinate ' ;
echo '(' . $packedItem->getX() . ', ' . $packedItem->getY() . ', ' . $packedItem->getZ() . ') with ';
echo 'l' . $packedItem->getLength() . ', w' . $packedItem->getWidth() . ', d' . $packedItem->getDepth();
echo PHP_EOL;
}
}
Custom Constraints
------------------
Custom constraints
==================

For more advanced use cases where greater control over the contents of each box is required (e.g. legal limits on the number of
hazardous items per box, or perhaps fragile items requiring an extra-strong outer box) you may implement the ``BoxPacker\ConstrainedPlacementItem``
Expand All @@ -74,14 +10,12 @@ As with all other library methods, the objects passed into this callback are you
properties and methods to use when evaluating a constraint, not only those defined by the standard ``BoxPacker\Item`` interface.

Example - only allow 2 batteries per box
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
----------------------------------------

.. code-block:: php
<?php
use DVDoug\BoxPacker\Box;
use DVDoug\BoxPacker\Item;
use DVDoug\BoxPacker\PackedItemList;
use DVDoug\BoxPacker\PackedBox;
class LithiumBattery implements ConstrainedPlacementItem
{
Expand Down Expand Up @@ -125,14 +59,13 @@ Example - only allow 2 batteries per box
}
Example - don't allow batteries to be stacked
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------------------------

.. code-block:: php
<?php
use DVDoug\BoxPacker\Box;
use DVDoug\BoxPacker\Item;
use DVDoug\BoxPacker\PackedItemList;
use DVDoug\BoxPacker\PackedBox;
use DVDoug\BoxPacker\PackedItem;
class LithiumBattery implements ConstrainedPlacementItem
{
Expand Down Expand Up @@ -180,17 +113,3 @@ Example - don't allow batteries to be stacked
return true;
}
}
Limited supply boxes
--------------------

In standard/basic use, BoxPacker will assume you have an adequate enough supply of each box type on hand to cover all
eventualities i.e. your warehouse will be very well stocked and the concept of "running low" is not applicable.

However, if you only have limited quantities of boxes available and you have accurate stock control information, you can
feed this information into BoxPacker which will then take it into account so that it won't suggest a packing which would
take you into negative stock.

To do this, have your box objects implement the ``BoxPacker\LimitedSupplyBox`` interface which has a single additional method
over the standard ``BoxPacker\Box`` namely ``getQuantityAvailable()``. The library will automatically detect this and
use the information accordingly.
130 changes: 106 additions & 24 deletions docs/getting-started.rst
Expand Up @@ -40,6 +40,7 @@ Packing a set of items into a given set of box types
.. code-block:: php
<?php
use DVDoug\BoxPacker\Rotation;
use DVDoug\BoxPacker\Packer;
use DVDoug\BoxPacker\Test\TestBox; // use your own `Box` implementation
use DVDoug\BoxPacker\Test\TestItem; // use your own `Item` implementation
Expand All @@ -50,46 +51,127 @@ Packing a set of items into a given set of box types
* Add choices of box type - in this example the dimensions are passed in directly via constructor,
* but for real code you would probably pass in objects retrieved from a database instead
*/
$packer->addBox(new TestBox('Le petite box', 300, 300, 10, 10, 296, 296, 8, 1000));
$packer->addBox(new TestBox('Le grande box', 3000, 3000, 100, 100, 2960, 2960, 80, 10000));
$packer->addBox(
new TestBox(
reference: 'Le petite box',
outerWidth: 300,
outerLength: 300,
outerDepth: 10,
emptyWeight: 10,
innerWidth: 296,
innerLength: 296,
innerDepth: 8,
maxWeight: 1000
)
);
$packer->addBox(
new TestBox(
reference: 'Le grande box',
outerWidth: 3000,
outerLength: 3000,
outerDepth: 100,
emptyWeight: 100,
innerWidth: 2960,
innerLength: 2960,
innerDepth: 80,
maxWeight: 10000
)
);
/*
* Add items to be packed - e.g. from shopping cart stored in user session. Again, the dimensional information
* (and keep-flat requirement) would normally come from a DB
*/
$packer->addItem(new TestItem('Item 1', 250, 250, 12, 200, true), 1); // item, quantity
$packer->addItem(new TestItem('Item 2', 250, 250, 12, 200, true), 2);
$packer->addItem(new TestItem('Item 3', 250, 250, 24, 200, false), 1);
$packedBoxes = $packer->pack();
echo "These items fitted into " . count($packedBoxes) . " box(es)" . PHP_EOL;
foreach ($packedBoxes as $packedBox) {
$boxType = $packedBox->getBox(); // your own box object, in this case TestBox
echo "This box is a {$boxType->getReference()}, it is {$boxType->getOuterWidth()}mm wide, {$boxType->getOuterLength()}mm long and {$boxType->getOuterDepth()}mm high" . PHP_EOL;
echo "The combined weight of this box and the items inside it is {$packedBox->getWeight()}g" . PHP_EOL;
echo "The items in this box are:" . PHP_EOL;
$packedItems = $packedBox->getItems();
foreach ($packedItems as $packedItem) { // $packedItem->getItem() is your own item object, in this case TestItem
echo $packedItem->getItem()->getDescription() . PHP_EOL;
}
}
$packer->addItem(
item: new TestItem(
description: 'Item 1',
width: 250,
length: 250,
depth: 12,
weight: 200,
allowedRotation: Rotation::KeepFlat
),
qty: 1
);
$packer->addItem(
item: new TestItem(
description: 'Item 2',
width: 250,
length: 250,
depth: 12,
weight: 200,
allowedRotation: Rotation::KeepFlat
),
qty: 2
);
$packer->addItem(
item: new TestItem(
description: 'Item 3',
width: 250,
length: 250,
depth: 24,
weight: 200,
allowedRotation: Rotation::BestFit
),
qty: 1
);
Does a set of items fit into a particular box
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
<?php
use DVDoug\BoxPacker\Rotation;
use DVDoug\BoxPacker\Packer;
use DVDoug\BoxPacker\Test\TestBox; // use your own `Box` implementation
use DVDoug\BoxPacker\Test\TestItem; // use your own `Item` implementation
/*
* To just see if a selection of items will fit into one specific box
*/
$box = new TestBox('Le box', 300, 300, 10, 10, 296, 296, 8, 1000);
$box = new TestBox(
reference: 'Le box',
outerWidth: 300,
outerLength: 300,
outerDepth: 10,
emptyWeight: 10,
innerWidth: 296,
innerLength: 296,
innerDepth: 8,
maxWeight: 1000
);
$items = new ItemList();
$items->insert(new TestItem('Item 1', 297, 296, 2, 200, false));
$items->insert(new TestItem('Item 2', 297, 296, 2, 500, false));
$items->insert(new TestItem('Item 3', 296, 296, 4, 290, false));
$items->insert(
new TestItem(
description: 'Item 1',
width: 297,
length: 296,
depth: 2,
weight: 200,
allowedRotation: Rotation::BestFit
)
);
$items->insert(
new TestItem(
description: 'Item 2',
width: 297,
length: 296,
depth: 2,
weight: 500,
allowedRotation: Rotation::BestFit
)
);
$items->insert(
new TestItem(
description: 'Item 3',
width: 296,
length: 296,
depth: 4,
weight: 290,
allowedRotation: Rotation::BestFit
)
);
$volumePacker = new VolumePacker($box, $items);
$packedBox = $volumePacker->pack(); //$packedBox->getItems() contains the items that fit
5 changes: 4 additions & 1 deletion docs/index.rst
Expand Up @@ -25,5 +25,8 @@ BoxPacker is licensed under the `MIT license`_.
sortation
weight-distribution
too-large-items
advanced-usage
positional-information
limited-supply-boxes
custom-constraints
used-remaining-space
whatsnew
13 changes: 13 additions & 0 deletions docs/limited-supply-boxes.rst
@@ -0,0 +1,13 @@
Limited supply boxes
====================

In standard/basic use, BoxPacker will assume you have an adequate enough supply of each box type on hand to cover all
eventualities i.e. your warehouse will be very well stocked and the concept of "running low" is not applicable.

However, if you only have limited quantities of boxes available and you have accurate stock control information, you can
feed this information into BoxPacker which will then take it into account so that it won't suggest a packing which would
take you into negative stock.

To do this, have your box objects implement the ``BoxPacker\LimitedSupplyBox`` interface which has a single additional method
over the standard ``BoxPacker\Box`` namely ``getQuantityAvailable()``. The library will automatically detect this and
use the information accordingly.
31 changes: 31 additions & 0 deletions docs/positional-information.rst
@@ -0,0 +1,31 @@
.. _positional_information:

Positional information
======================

It is possible to see the precise positional and dimensional information of each item as packed. This is exposed as x,y,z
co-ordinates from origin, alongside width/length/depth in the packed orientation. ::

z y
| /
| /
| /
|/
0------x

Example:

.. code-block:: php
<?php
// assuming packing already took place
foreach ($packedBoxes as $packedBox) {
$packedItems = $packedBox->getItems();
foreach ($packedItems as $packedItem) { // $packedItem->getItem() is your own item object
echo $packedItem->getItem()->getDescription() . ' was packed at co-ordinate ' ;
echo '(' . $packedItem->getX() . ', ' . $packedItem->getY() . ', ' . $packedItem->getZ() . ') with ';
echo 'l' . $packedItem->getLength() . ', w' . $packedItem->getWidth() . ', d' . $packedItem->getDepth();
echo PHP_EOL;
}
}
2 changes: 0 additions & 2 deletions docs/rotation.rst
Expand Up @@ -9,7 +9,6 @@ BoxPacker gives you full control of how (or if) an individual item may be rotate

Best fit
^^^^^^^^

To allow an item to be placed in any orientation.

.. code-block:: php
Expand All @@ -27,7 +26,6 @@ To allow an item to be placed in any orientation.
Keep flat
^^^^^^^^^

For items that must be shipped "flat" or "this way up".

.. code-block:: php
Expand Down
2 changes: 2 additions & 0 deletions docs/sortation.rst
@@ -1,3 +1,5 @@
.. _sortation:

Sortation
=========

Expand Down

0 comments on commit 854a27b

Please sign in to comment.