Click here to Skip to main content
15,895,667 members
Articles / Programming Languages / C#
Tip/Trick

BIN Packing 3D Item Most Efficiently Given Pack Quantity

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
10 Nov 2017CPOL 9.7K   2   1
Posting this solution because I found all other options out there except this one. In this particular case, I have 1 item that can be packed a # of times and the goal is to pack it in the most efficient manner not to exceed UPS/FedEX LxWxH limitations, not providing box dimensions to fit the item in

BIN Packing Item given LxWxH Number of Times

I was able to find a bunch of solutions out there, but for example to get a UPS/FedEx shipping quote, my items can be packed provided a specified pack quantity. Packing same items in NON defined boxes is not something I found out there. So this method will: provided LxWxH and Quantity, return the best way to pack it with smallest area and least amount of empty space.

Using the Code

The code is fairly simple. This is a brute force approach to finding the first most adequate package size to provide to UPS/FedEx to get a quote. For example: suppose you have an item 22" x 8" x 8" and you want to pack 10 of them together to have a single package. Adequate packed dimensions are: 22x40x16, 44x40x8... Below recursive method will return the result in a decimal[3] array where [0] = Length, [1] = Width and [2] = Height of the newly packed box. Please note that in my code, any given dimension was set not to exceed 108".

C#
protected decimal[] PackItemsInBin(decimal[] PackingDimensions, decimal Length, 
                                   decimal Width, decimal Height, decimal Quantity )
    {
        decimal[] dimensions_l;
        decimal[] dimensions_w;
        decimal[] dimensions_h;

        decimal LengthPackingQuantity, WidthPackingQuantity, 
                HeightPackingQuantity, LengthArea, WidthArea, HeightArea = 0; 
        try
        {
            if (Math.Floor(PackingDimensions[0] / Length) * Math.Floor(PackingDimensions[1] / Width) * 
                       Math.Floor(PackingDimensions[2] / Height) >= Quantity)
            {
                return PackingDimensions;
            }
            else
            {
                //HAVE NOT FOUND THE SOLUTION 
                //so lets go in all directions until we get a solution. 
                dimensions_l = new decimal[3] { PackingDimensions[0], 
                                                PackingDimensions[1], PackingDimensions[2] };
                dimensions_w = new decimal[3] { PackingDimensions[0], 
                                                PackingDimensions[1], PackingDimensions[2] };
                dimensions_h = new decimal[3] { PackingDimensions[0], 
                                                PackingDimensions[1], PackingDimensions[2] };

                dimensions_l[0] += Length;//go with length
                dimensions_w[1] += Width;//go with width
                dimensions_h[2] += Height;//go with height

                //get the results from each direciton 
                dimensions_l = PackItemsInBin(dimensions_l, Length, Width, Height, Quantity);
                dimensions_w = PackItemsInBin(dimensions_w, Length, Width, Height, Quantity);
                dimensions_h = PackItemsInBin(dimensions_h, Length, Width, Height, Quantity);

                //calculate some of the measurements to use to determine the best packed choice 
                LengthPackingQuantity = Math.Floor(dimensions_l[0] / Length) * 
                    Math.Floor(dimensions_l[1] / Width) * Math.Floor(dimensions_l[2] / Height);
                WidthPackingQuantity = Math.Floor(dimensions_w[0] / Length) * 
                    Math.Floor(dimensions_w[1] / Width) * Math.Floor(dimensions_w[2] / Height);
                HeightPackingQuantity = Math.Floor(dimensions_h[0] / Length) * 
                    Math.Floor(dimensions_h[1] / Width) * Math.Floor(dimensions_h[2] / Height);

                LengthArea = dimensions_l[0] + dimensions_l[1] + dimensions_l[2];
                WidthArea = dimensions_w[0] + dimensions_w[1] + dimensions_w[2];
                HeightArea = dimensions_h[0] + dimensions_h[1] + dimensions_h[2];

                //GB. determine if the best solution is here based on several decisions, 
                //for example if there is empty space or not and what the area is 
                //GB. best decision is made on the packed box that takes the least amount of space 
                //and has the least amount of empty space considering the area 
                if (LengthPackingQuantity + LengthArea <= WidthArea + WidthPackingQuantity && 
                    LengthPackingQuantity + LengthArea <= HeightArea + 
                    HeightPackingQuantity && dimensions_l[0] < 108)
                {
                    return dimensions_l;
                }
                else if (WidthArea + WidthPackingQuantity <= LengthPackingQuantity + 
                         LengthArea && WidthArea + WidthPackingQuantity <= HeightArea + 
                         HeightPackingQuantity && dimensions_l[0] < 108)
                {
                    return dimensions_w;
                }
                else
                    return dimensions_h; 
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message, ex);
        }
    }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionCould I suggest an improvement? Pin
hotfirewire13-Nov-17 4:11
hotfirewire13-Nov-17 4:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.