enzoruiz / 3dbinpacking Goto Github PK
View Code? Open in Web Editor NEWA python library for 3D Bin Packing
License: MIT License
A python library for 3D Bin Packing
License: MIT License
Does this algorithm take into account the problem of packing stability? For example, an item may not be supported by another item under it.
If I add the print statement below to main.py, the appended items don't match the returned "fitted items". More specifically, it seems like the rotation_type can continue to loop to 5 but I don't know what causes this behavior. The result is that the items exceed the bounds of the bin.
if fit:
if self.get_total_weight() + item.weight > self.max_weight:
fit = False
return fit
print("item appended to bin:", item.string())
self.items.append(item)
Hello,
I would like to propose to add the functionality to sort by bigger bin first and by bigger item first separately. This enhances the algorithm efficiency when trying to determine the number of bins necessary to pack all items.
By starting to fit the largest item in the smallest box first, I'm able to pack all my items in one large box less!
I also added the Bin.weight and Bin.empty_bin_weight attribute so we get the real total weight.
LinkedIn
Twitter
Best regards,
Jonathan Rhau
packer = Packer()
packer.add_bin(Bin('Main', int(200), int(200), int(300),int(630)))
for x in range(1,101):
packer.add_item(Item('mm' + str(x),int(65) ,int(66),int(83),int(19) ))
packer.pack(bigger_first=True)
for b in packer.bins:
for item in b.items:
print("====> ", item.string())
The result is 24 - In reality 27 should fit.
As the code only compares whether there is an overlapping part between two items in xy-plane, z-dimension stacking isn't accurate.
Just tested with
-> Bin('large-3-box', 23.6875, 11.75, 35.0, 1000.0)
and items
-> packer.add_item(Item('50g [powder 1]', 3.9370, 1.9685, 11.9685, 1))
packer.add_item(Item('50g [powder 2]', 3.9370, 1.9685, 1.9685, 2))
packer.add_item(Item('50g [powder 3]', 3.9370, 1.9685, 1.9685, 3))
packer.add_item(Item('250g [powder 4]', 7.8740, 3.9370, 1.9685, 4))
packer.add_item(Item('250g [powder 5]', 7.8740, 3.9370, 1.9685, 5))
packer.add_item(Item('250g [powder 6]', 7.8740, 3.9370, 1.9685, 6))
packer.add_item(Item('250g [powder 7]', 7.8740, 3.9370, 1.9685, 7))
packer.add_item(Item('250g [powder 8]', 7.8740, 3.9370, 1.9685, 8))
packer.add_item(Item('250g [powder 9]', 7.8740, 3.9370, 1.9685, 9))
packer.add_item(Item('250g [powder 10]', 7.8740, 3.9370, 1.9685, 10))
packer.add_item(Item('250g [powder 11]', 7.8740, 3.9370, 1.9685, 11))
packer.add_item(Item('250g [powder 12]', 7.8740, 3.9370, 1.9685, 6))
packer.add_item(Item('250g [powder 7]', 7.8740, 3.9370, 1.9685, 7))
packer.add_item(Item('250g [powder 8]', 7.8740, 3.9370, 1.9685, 8))
packer.add_item(Item('250g [powder 9]', 7.8740, 3.9370, 1.9685, 9))
packer.add_item(Item('250g [powder 4]', 7.8740, 3.9370, 1.9685, 4))
packer.add_item(Item('250g [powder 5]', 7.8740, 3.9370, 1.9685, 5))
packer.add_item(Item('250g [powder 6]', 7.8740, 3.9370, 1.9685, 6))
packer.add_item(Item('250g [powder 7]', 7.8740, 3.9370, 1.9685, 7))
packer.add_item(Item('250g [powder 8]', 7.8740, 3.9370, 1.9685, 8))
packer.add_item(Item('250g [powder 9]', 7.8740, 3.9370, 1.9685, 9))
I have arbitrarily given 11.9685 as the height of 'powder 1' for a bigger box with dimension [23.6875, 11.75, 35.0] just for the sake of random experiment. Each item gets stacked fine in the base layer (z=0) but when the base layer is all filled, things get stacked at z=11.9685 for the remainder of items, which makes the items float.
Hello folks,
I am new to 3dbinpacking and python in general, so go easy on me.
I've been trying to use 3dbinpacking to create a simulation in Anylogic in which operators use a pallet-trolley to pick boxes/items in a specific order from a warehouse. The pick order is based on the results of the Bin-Packing algorithm.
the container/bin is based on the standard dimension of a EuroPallet and the boxes are standard carton boxes with different sizes.
My issue is that some of the boxes do not overlap 100%. This is ok if the pallet is actually enclosed but in a real-world scenario like using a pallet trolley to pick boxes if the boxes are not put one on top of the other they will probably fall down
my question is there a way to remove the items/boxes that do not stack on top of each other?
Current results of running 3dbinpacking
Desire results after removing items/boxes with the surface not overlapping 100% another item/box (the remaining boxes should be packed in another container/bin)
Hey, this package is a good idea. However, I tried running a simple test case with one very large bin and a number of items. The solver fails to put them in the bin. I might be missing something though. Test case and result is below:
#TEST CASE:
from py3dbp import Packer, Bin, Item
packer = Packer()
packer.add_bin(Bin('very-very-large-box', 10000.6875, 10000.75, 10000.0, 2000000.0))
packer.add_item(Item('50g [powder 1]', 1.1, 1.9685, 1.9685, 1))
packer.add_item(Item('50g [powder 2]', 1.1, 1.9685, 1.9685, 2))
packer.add_item(Item('50g [powder 3]', 1.1, 1.9685, 1.9685, 3))
packer.add_item(Item('250g [powder 4]', 1.1, 3.9370, 1.9685, 4))
packer.add_item(Item('250g [powder 5]', 7.8740, 3.9370, 1.9685, 5))
packer.add_item(Item('250g [powder 6]', 7.8740, 3.9370, 1.9685, 6))
packer.add_item(Item('250g [powder 7]', 7.8740, 3.9370, 1.9685, 7))
packer.add_item(Item('250g [powder 8]', 7.8740, 3.9370, 1.9685, 8))
packer.add_item(Item('250g [powder 9]', 7.8740, 3.9370, 1.9685, 9))
packer.add_item(Item('50g [powder 10]', 3.9370, 1.9685, 1.9685, 10))
packer.add_item(Item('50g [powder 11]', 3.9370, 1.9685, 1.9685, 11))
packer.add_item(Item('50g [powder 12]', 3.9370, 1.9685, 1.9685, 12))
packer.add_item(Item('250g [powder 12]', 7.8740, 3.9370, 1.9685, 13))
packer.add_item(Item('250g [powder 13]', 7.8740, 3.9370, 1.9685, 14))
packer.add_item(Item('250g [powder 14]', 7.8740, 3.9370, 1.9685, 15))
packer.add_item(Item('250g [powder 15]', 7.8740, 3.9370, 1.9685, 16))
packer.add_item(Item('250g [powder 16]', 1.1, 3.9370, 1.9685, 17))
packer.add_item(Item('250g [powder 17]', 1.8740, 3.9370, 1.9685, 18))
packer.pack()
for b in packer.bins:
print(":::::::::::", b.string())
print("FITTED ITEMS:")
for item in b.items:
print("====> ", item.string())
print("UNFITTED ITEMS:")
for item in b.unfitted_items:
print("====> ", item.string())
print("***************************************************")
print("***************************************************")
::::::::::: very-very-large-box(10000.6875x10000.75x10000.0, max_weight:2000000.0) vol(1000143755156.25)
FITTED ITEMS:
====> 50g [powder 1](1.1x1.9685x1.9685, weight: 1) pos([0, 0, 0]) rt(0) vol(4.26)
====> 50g [powder 2](1.1x1.9685x1.9685, weight: 2) pos([1.1, 0, 0]) rt(0) vol(4.26)
====> 50g [powder 3](1.1x1.9685x1.9685, weight: 3) pos([0, 1.9685, 0]) rt(0) vol(4.26)
====> 250g [powder 4](1.1x3.937x1.9685, weight: 4) pos([1.1, 1.9685, 0]) rt(0) vol(8.52)
====> 250g [powder 16](1.1x3.937x1.9685, weight: 17) pos([0, 3.937, 0]) rt(0) vol(8.52)
====> 250g [powder 17](1.874x3.937x1.9685, weight: 18) pos([2.2, 0, 0]) rt(0) vol(14.52)
====> 50g [powder 10](3.937x1.9685x1.9685, weight: 10) pos([1.1, 5.9055, 0]) rt(0) vol(15.26)
====> 50g [powder 11](3.937x1.9685x1.9685, weight: 11) pos([0, 0, 1.9685]) rt(0) vol(15.26)
====> 50g [powder 12](3.937x1.9685x1.9685, weight: 12) pos([3.937, 0, 1.9685]) rt(0) vol(15.26)
====> 250g [powder 5](7.874x3.937x1.9685, weight: 5) pos([5.037, 5.9055, 0]) rt(0) vol(61.02)
====> 250g [powder 6](7.874x3.937x1.9685, weight: 6) pos([7.874, 0, 1.9685]) rt(0) vol(61.02)
====> 250g [powder 7](7.874x3.937x1.9685, weight: 7) pos([0, 1.9685, 1.9685]) rt(0) vol(61.02)
====> 250g [powder 8](7.874x3.937x1.9685, weight: 8) pos([5.037, 9.8425, 0]) rt(0) vol(61.02)
====> 250g [powder 9](7.874x3.937x1.9685, weight: 9) pos([7.874, 3.937, 1.9685]) rt(0) vol(61.02)
====> 250g [powder 12](7.874x3.937x1.9685, weight: 13) pos([0, 5.9055, 1.9685]) rt(0) vol(61.02)
====> 250g [powder 13](7.874x3.937x1.9685, weight: 14) pos([0, 9.8425, 1.9685]) rt(0) vol(61.02)
====> 250g [powder 14](7.874x3.937x1.9685, weight: 15) pos([7.874, 9.8425, 1.9685]) rt(0) vol(61.02)
UNFITTED ITEMS:
====> 250g [powder 15](7.874x3.937x1.9685, weight: 16) pos([0, 0, 0]) rt(0) vol(61.02)
I have tried Py3dbp for arrangement. After loading the items in the container, there remains empty spaces. Is there any method to find the dimension of the empty spaces?
How can I get empty space dimension?
Any better suggestions?
Running the provide example.py gives:
***************************************************
::::::::::: large-box(12.000x12.000x5.500, max_weight:70.000) vol(792.000)
FITTED ITEMS:
====> 50g [powder 1](3.937x1.968x1.968, weight: 1.000) pos([0, 0, 0]) rt(0) vol(15.248)
====> 50g [powder 2](3.937x1.968x1.968, weight: 2.000) pos([Decimal('3.937'), 0, 0]) rt(0) vol(15.248)
====> 50g [powder 3](3.937x1.968x1.968, weight: 3.000) pos([Decimal('7.874'), 0, 0]) rt(0) vol(15.248)
====> 250g [powder 4](7.874x3.937x1.968, weight: 4.000) pos([Decimal('11.811'), 0, 0]) rt(0) vol(61.008)
====> 250g [powder 5](7.874x3.937x1.968, weight: 5.000) pos([Decimal('19.685'), 0, 0]) rt(1) vol(61.008)
====> 250g [powder 6](7.874x3.937x1.968, weight: 6.000) pos([0, Decimal('1.968'), 0]) rt(0) vol(61.008)
====> 250g [powder 7](7.874x3.937x1.968, weight: 7.000) pos([Decimal('11.811'), Decimal('3.937'), 0]) rt(0) vol(61.008)
====> 250g [powder 8](7.874x3.937x1.968, weight: 8.000) pos([0, Decimal('5.905'), 0]) rt(0) vol(61.008)
====> 250g [powder 9](7.874x3.937x1.968, weight: 9.000) pos([Decimal('7.874'), 0, Decimal('1.968')]) rt(5) vol(61.008)
UNFITTED ITEMS:
***************************************************
The position of the 5th item pos([Decimal('19.685'), 0, 0])
seems to be outside the box, which is set as 12.000x12.000x5.500
Is this a bug, or my understanding of the notation is wrong?
Run condition:
git checkout latest master
python 3.8.10
I've a very simple test case, where the algorithm can't fit all items. But when I change the orientation of the bin, it can fit all. Is this a bug or is the algorithm very limited and can't solve such a simple combination?
from py3dbp import Packer, Bin, Item
packer = Packer()
packer.add_bin(Bin('Bin-1', 6, 1, 5, 100))
packer.add_bin(Bin('Bin-2', 5, 1, 6, 100))
packer.add_item(Item('Box-1', 3, 1, 2, 1))
packer.add_item(Item('Box-2', 3, 1, 2, 1))
packer.add_item(Item('Box-3', 3, 1, 2, 1))
packer.add_item(Item('Box-4', 3, 1, 2, 1))
packer.add_item(Item('Box-5', 3, 1, 2, 1))
packer.pack()
for b in packer.bins:
print(":::::::::::", b.string())
print("FITTED ITEMS:")
for item in b.items:
print("====> ", item.string())
print("UNFITTED ITEMS:")
for item in b.unfitted_items:
print("====> ", item.string())
print("***************************************************")
print("***************************************************")
Result:
::::::::::: Bin-1(6.000x1.000x5.000, max_weight:100.000) vol(30.000)
FITTED ITEMS:
====> Box-1(3.000x1.000x2.000, weight: 1.000) pos([0, 0, 0]) rt(0) vol(6.000)
====> Box-2(3.000x1.000x2.000, weight: 1.000) pos([Decimal('3.000'), 0, 0]) rt(3) vol(6.000)
====> Box-3(3.000x1.000x2.000, weight: 1.000) pos([0, 0, Decimal('2.000')]) rt(0) vol(6.000)
====> Box-4(3.000x1.000x2.000, weight: 1.000) pos([Decimal('3.000'), 0, Decimal('3.000')]) rt(3) vol(6.000)
UNFITTED ITEMS:
====> Box-5(3.000x1.000x2.000, weight: 1.000) pos([0, 0, Decimal('4.000')]) rt(0) vol(6.000)
***************************************************
***************************************************
::::::::::: Bin-2(5.000x1.000x6.000, max_weight:100.000) vol(30.000)
FITTED ITEMS:
====> Box-1(3.000x1.000x2.000, weight: 1.000) pos([0, 0, 0]) rt(0) vol(6.000)
====> Box-2(3.000x1.000x2.000, weight: 1.000) pos([Decimal('3.000'), 0, 0]) rt(3) vol(6.000)
====> Box-3(3.000x1.000x2.000, weight: 1.000) pos([0, 0, Decimal('2.000')]) rt(0) vol(6.000)
====> Box-4(3.000x1.000x2.000, weight: 1.000) pos([Decimal('3.000'), 0, Decimal('3.000')]) rt(3) vol(6.000)
====> Box-5(3.000x1.000x2.000, weight: 1.000) pos([0, 0, Decimal('4.000')]) rt(0) vol(6.000)
UNFITTED ITEMS:
***************************************************
***************************************************
Hi there,
Is there a way to contact you via email?
I have some questions about the 3d packing.
Are you considered with weight? rotatable items? stacking /unstacking/ self stacking items?
Can we communicate via email?
betzalel.racovsky at gmail
Thanks
B
I like to see the option to remove an item from a bin. Also a great addition would be to empty the bin entirely.
Hi,
I get different answers if I change the wdh for one of the boxes. For example, if I go with this:
#adding a bin
packer.add_bin(Bin('small-envelope', 3,3,3, 100))
#adding boxes
packer.add_item(Item('50g [powder 1]', 3,3,1, 1))
packer.add_item(Item('50g [powder 2]', 3,3,1, 2))
packer.add_item(Item('50g [powder 3]', 3,2,1, 3))
#answer I get
FITTED ITEMS:
====> 50g [powder 3](3.000x2.000x1.000, weight: 3.000) pos([0, 0, 0]) rt(0) vol(6.000)
====> 50g [powder 1](3.000x3.000x1.000, weight: 1.000) pos([0, Decimal('2.000'), 0]) rt(2) vol(9.000)
UNFITTED ITEMS:
====> 50g [powder 2](3.000x3.000x1.000, weight: 2.000) pos([0, 0, 0]) rt(5) vol(9.000)
It should be able to add all the three boxes in this particular bin.
But if I change the wdh positions for the third item,
#adding a bin
packer.add_bin(Bin('small-envelope', 3,3,3, 100))
#adding boxes
packer.add_item(Item('50g [powder 1]', 3,3,1, 1))
packer.add_item(Item('50g [powder 2]', 3,3,1, 2))
packer.add_item(Item('50g [powder 3]', 1,2,3, 3))
#answer I get
FITTED ITEMS:
====> 50g [powder 3](1.000x2.000x3.000, weight: 3.000) pos([0, 0, 0]) rt(0) vol(6.000)
====> 50g [powder 1](3.000x3.000x1.000, weight: 1.000) pos([Decimal('1.000'), 0, 0]) rt(3) vol(9.000)
====> 50g [powder 2](3.000x3.000x1.000, weight: 2.000) pos([Decimal('2.000'), 0, 0]) rt(3) vol(9.000)
UNFITTED ITEMS:
Hi,
I am trying to make a crude packing implementation in Blender using this library. So far I have not gotten a good results. I am wondering if this is an issue with this lib in general, like working in 3d coordiates . Does it require the pivot to be in certain location other than the center?
Also I seem to be getting only 0 and 1 for the rotation type.
Please see the screenshot for the details (after running the script). As you can see the packing result shows some items positioned outside of the bin and there are overlaps, basically does not look like these boxes are packed inside the bin.
Output
***************************************************
::::::::::: Bin(6.072x6.072x6.072, max_weight:1000.000) vol(223.870)
FITTED ITEMS:
====> Box.005(2.714x0.114x1.413, weight: 1.000) pos([0, 0, 0]) rt(0) vol(0.437) -> [0, 0, 0]
<Vector (0.0000, 0.0000, 0.0000)>
====> Box.003(1.364x0.638x1.442, weight: 1.000) pos([Decimal('2.714'), 0, 0]) rt(0) vol(1.255) -> [Decimal('2.714'), 0, 0]
<Vector (2.7140, 0.0000, 0.0000)>
====> Box(1.281x0.745x1.412, weight: 1.000) pos([Decimal('4.078'), 0, 0]) rt(0) vol(1.348) -> [Decimal('4.078'), 0, 0]
<Vector (4.0780, 0.0000, 0.0000)>
====> Box.001(2.428x0.426x1.453, weight: 1.000) pos([Decimal('5.359'), 0, 0]) rt(1) vol(1.503) -> [Decimal('5.359'), 0, 0]
<Vector (5.3590, 0.0000, 0.0000)>
====> Box.002(0.607x3.611x1.586, weight: 1.000) pos([0, Decimal('0.114'), 0]) rt(0) vol(3.476) -> [0, Decimal('0.114'), 0]
<Vector (0.0000, 0.1140, 0.0000)>
====> Box.004(2.990x2.050x1.592, weight: 1.000) pos([0, Decimal('3.725'), 0]) rt(0) vol(9.758) -> [0, Decimal('3.725'), 0]
<Vector (0.0000, 3.7250, 0.0000)>
I have a use case where I try to fit a set of items that stays constant to a varying set of bins (or actually one bin at a time). Which means I would like to try different bins one at a time, starting with the cheapest package and then moving to more expensive ones if the items don't fit.
However, I am running into problems since it seems to me that the initialisation call of Packer() does not work properly. It would seem it maintains some history of the items I've tried to pack but clears the initialisation of bins, which leads to a situation where two subsequent packing attempts generate different results - the latter requiring a larger bin than on the previous run, and failing to pack in the bin it had found a solution for on the previous run. The only way to get stable results is if the kernel is restarted in between. I think one would expect the call to initialise Packer() to be equivalent to getting a fresh start, but that does not seem to be the case.
The problem is not visible in the results, which shows just the items I've tried to pack both times, but the fact that the 2nd attempt requires a larger bin makes the library where hard to use in practice.
First run:
Found solution:
::::::::::: 790713(800.000x270.000x330.000, max_weight:999.000) vol(71280000.000)
FITTED ITEMS:
====> 226(130.000x200.000x100.000, weight: 0.000) pos([0, 0, 0]) rt(0) vol(2600000.000)
====> 330(330.000x120.000x220.000, weight: 4.800) pos([Decimal('130.000'), 0, 0]) rt(0) vol(8712000.000)
====> 330(330.000x120.000x220.000, weight: 4.800) pos([Decimal('460.000'), 0, 0]) rt(0) vol(8712000.000)
====> 206(300.000x650.000x150.000, weight: 10.000) pos([Decimal('130.000'), Decimal('120.000'), 0]) rt(2) vol(29250000.000)
UNFITTED ITEMS:
Second run:
Found solution:
::::::::::: 790079(790.000x300.000x580.000, max_weight:999.000) vol(137460000.000)
FITTED ITEMS:
====> 226(130.000x200.000x100.000, weight: 0.000) pos([0, 0, 0]) rt(0) vol(2600000.000)
====> 330(330.000x120.000x220.000, weight: 4.800) pos([Decimal('130.000'), 0, 0]) rt(0) vol(8712000.000)
====> 330(330.000x120.000x220.000, weight: 4.800) pos([Decimal('460.000'), 0, 0]) rt(0) vol(8712000.000)
====> 206(300.000x650.000x150.000, weight: 10.000) pos([Decimal('130.000'), Decimal('120.000'), 0]) rt(2) vol(29250000.000)
UNFITTED ITEMS:
Hi All,
I am looking for any sample example to create 3d bin packing with a blender. I am trying to achieve bin shape with items and it reshapes if I change item sizes.
Thanks
This isn't so much of an issue moreso a problem I ran into which took some time to debug.
Since the three objects are built out as standalone classes bins keep their mutated data between runs. To work around this I had to manually reset the data back to the init values on every loop in each bin. This isn't really an issue with the code but more an issue with the implementation/design. If a new packer is initialized and bins are added those bins should be reinitialized as well.
More of a PSA I suppose since nobody in the gh issues brought this up (Except maybe #15 ?)
I am using this library to fill a shipping container of parts. The shipping container has an option of adding shelves. I am trying to add this to the Bin class such that you can add an additional layer in the bin to add parts on. I am getting a handful of errors when trying to output the container with parts intersecting and the packer class not able to understand the layers in the bin. Is there a work around for this issue or do you have different recommendations on adding the shelves? Thank you.
hello,
Is "[distribute_items=True]" or "[distribute_items=False]" some kind of parameter that can be configured?
If so, where can i configure it?
In my project, I want to pack image stacks (my packages) in a container using py3dbp. I can arrange them and know each image location inside the container I defined. After, I extract the locations of each image and try to use this information to place the "packages" in a NumPy array full of ones that is the same size as the container I defined previously. However, when I extract the image positions I notice that some of them are partially "outside" the bin, i.e if my bin is defined by:
final_image = Bin("final Image", 3300 , 3300, 17, 100000)
when I access some of the item's position and size information, I get the next
print(packer.items[514].position)
print(packer.items[514].width)
print(packer.items[514].height)
print(packer.items[514].depth)
Output:
[Decimal('3278.000'), Decimal('264.000'), 0]
70.000
22.000
17.000
As you can see, the width of package 514 is bigger than the space left for it in the container, 70 against 22. My question is, How this can be possible? The package size corresponding to item 514 is the same as the image I want to locate. Besides, the list of unfitted objects is empty and the list of fitted objects corresponds to the total number of objects I have. The code I am using to pack the objects and locate them in the NumPy array is:
final_image2 = np.ones((17, 3300, 3300), dtype = int)
packer = Packer()
final_image = Bin("final Image", 3300 , 3300, 17, 100000)
packer.add_bin(final_image )
for label in unique_labels:
zero_padding = np.pad(single_nuclei_dic[label], [(0, z_padding), (y_padding_2, y_padding_2), (x_padding_2, x_padding_2)],
mode='constant', constant_values=0)
final_size_dic[label] = zero_padding.shape
zero_padding_nuclei[label] = zero_padding.astype(int)
my_item = Item(str(label), final_size_dic[label][2], final_size_dic[label][1], final_size_dic[label][0], 1)
packer.add_item(my_item)
packer.pack(bigger_first=True, number_of_decimals=0)
for image in packer.items:
label1= int(image.name)
z_incial = int(image.position[2])
y_inicial = int(image.position[1])
x_inicial = int(image.position[0])
items_position[label1] = [x_inicial, y_inicial, z_incial]
box = zero_padding_nuclei[label1].astype(int)
z_final = z_incial + box.shape[0]
y_final = y_inicial + box.shape[1]
x_final = x_inicial + box.shape[2]
final_image2[z_incial:z_final, y_inicial:y_final, x_inicial:x_final] = zero_padding_nuclei[label1]
Thank you for your help
reduce the number of bins utilized
It changes the x, y, z values of the package to fit the product in the package on the x plane.
I'm trying to fit 30 same products into the package. but It gives incorrect information because it changes the dimensions of some products.
#Package dimensions
packageHeightX = 7.5
packageWidthY = 12.5
packageLengthZ = 16.5
#item dimensions
itemX = 0.787
itemY = 3.937
itemZ = 3.937
But for some products, it changes the dimensions like this:
#item dimensions
itemX = 3.937
itemY = 3.937
itemZ = 0.787
I'm not sure exactly what causes the problem. Can anyone help?
Thank you
The packing goes through all 6 permutations of each item, which is awesome, but for my purposes, it makes sense to disallow certain rotations. In fact I only need 1, leading to 2 permutation.
Is it possible to include this as an option?
Just notice a problem where when an item in the bin is rotated, the calculation for the pivot will use its dimensions as if the rotation was WHD which produces the wrong pivot.
e.g. we have a (1, 2, 3) WHD item already in the bin at position (0, 0, 0).
If the item is in the WHD rotation, that means that a pivot in the width axis for that item would be (1, 0, 0).
But if this item is rotated to, lets say, HWD, the same pivot for the width axis for that item would have to be (2, 0, 0).
The fix is easy, the dimensions need to be converted to the default WHD system, which you already have a function for (the get_dimensions
).
I'm sending a PR in a few minutes with the fix.
hello.
When I was testing the package I got the wrong answer in some cases.
For example. A container with shape [width, height, depth, weight] as [4, 4, 4, 10] can only contain 8 Items with shape [2, 2, 2, 1] (same dimension as above).
however, when running the code below,
'from py3dbp.main import Packer, Bin, Item
packer = Packer()
TESTBIN = Bin("Small Bin", 4, 4, 4, 10)
packer.add_bin(TESTBIN)
for i in range(10):
packer.add_item(Item(str(i+1), 2, 2, 2, 1))
packer.pack()
for b in packer.bins:
print(b.string())
for i in b.items:
print("====> ", i.string())'
I got the answer like this:
Small Bin(4x4x4, max_weight:10) ====> 1(2x2x2, weight: 1) pos([0, 0, 0]) rt(0) ====> 2(2x2x2, weight: 1) pos([0, 0, 4]) rt(5) ====> 3(2x2x2, weight: 1) pos([0, 0, 8]) rt(5) ====> 4(2x2x2, weight: 1) pos([0, 0, 12]) rt(5) ====> 5(2x2x2, weight: 1) pos([0, 0, 16]) rt(5) ====> 6(2x2x2, weight: 1) pos([0, 0, 20]) rt(5) ====> 7(2x2x2, weight: 1) pos([0, 0, 24]) rt(5) ====> 8(2x2x2, weight: 1) pos([0, 0, 28]) rt(5) ====> 9(2x2x2, weight: 1) pos([0, 0, 32]) rt(5) ====> 10(2x2x2, weight: 1) pos([0, 0, 36]) rt(5)
Did I use it in a wrong way?
If I have 3 items and 1 box with following specs:
Bins:
packer.add_bin(Bin('MID-SIZE', 60,60,60, 10))
Items:
packer.add_item(Item('Item 1', 60,60,20, 1))
packer.add_item(Item('Item 2', 60,20,60, 2))
packer.add_item(Item('Item 3', 20,60,60, 3))
Output: The output is as expected with 100% of space being utilized.
::::::::::: MID-SIZE(60.000x60.000x60.000, max_weight:10.000) vol(216000.000)
FITTED ITEMS:
====> Item 1(60.000x60.000x20.000, weight: 1.000) pos([0, 0, 0]) rt(0) vol(72000.000)
====> Item 2(60.000x20.000x60.000, weight: 2.000) pos([0, 0, Decimal('20.000')]) rt(4) vol(72000.000)
====> Item 3(20.000x60.000x60.000, weight: 3.000) pos([0, 0, Decimal('40.000')]) rt(2) vol(72000.000)
UNFITTED ITEMS:
However, if I add one more item with same box, the suggested packing is:
Bins:
packer.add_bin(Bin('MID-SIZE', 60,60,60, 10))
Items:
packer.add_item(Item('Item 1', 60,60,20, 1))
packer.add_item(Item('Item 2', 60,20,60, 2))
packer.add_item(Item('Item 3', 20,60,60, 3))
packer.add_item(Item('Item 4', 20,20,20, 1))
Output: The suggested utilization falls to 70.3%; ideally the 4th item should have been shown in the unfitted items.
::::::::::: MID-SIZE(60.000x60.000x60.000, max_weight:10.000) vol(216000.000)
FITTED ITEMS:
====> Item 4(20.000x20.000x20.000, weight: 1.000) pos([0, 0, 0]) rt(0) vol(8000.000)
====> Item 1(60.000x60.000x20.000, weight: 1.000) pos([Decimal('20.000'), 0, 0]) rt(3) vol(72000.000)
====> Item 2(60.000x20.000x60.000, weight: 2.000) pos([Decimal('40.000'), 0, 0]) rt(1) vol(72000.000)
UNFITTED ITEMS:
====> Item 3(20.000x60.000x60.000, weight: 3.000) pos([0, 0, 0]) rt(5) vol(72000.000)
Can you check if this understanding is correct?
Best
Nitin
As you can see, i have 5 Item
objects.
They were all properly fit into a reasonable Bin
<py3dbp.main.Packer object at 0x7fbdbda04b00>
bins:[ ... ]
items:[]
total_items:5
unfit_items:[]
But when accessing the bin (the only one with contents)..
it says it contains just 1 item? Where are the other 4?
3:<py3dbp.main.Bin object at 0x7fbdbd772c18>
depth:5.5
height:8.5
items:[<py3dbp.main.Item ob...dbcb39198>]
0:<py3dbp.main.Item object at 0x7fbdbcb39198>
__len__:1
max_weight:70.0
name:'medium-box'
width:11.0
Can provide sample data if needed.
Thanks,
for providing such a wonderful library,
gg
It appears that some solution would show some box half hanging over another smaller box. Is there any option to allow all boxes should be on a flat surface larger enough so that it does not fall?
Or this packing algorithm is considering packing without considering gravity or the pack layout is stable?
Thanks
Thanks for v1.0 and v1.1.
Now I'm just curious, suppose there are multiple (good?) ways to pack the bins with items.. how does it choose the first solution? Is there a mode to see set of all solutions, or a way to pass a cost factor per bin?
Best,
gg
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.