3D Bin Packing Python Library

repository·master·Indexed 43 days ago

https://github.com/jerry800416/3d-bin-packing

A Python library for solving the 3D bin packing problem, optimizing the arrangement of cubes and cylinders within containers. Features include gravity correction, load-bearing priority, item stability checks via support_surface_ratio, and 3D visualization using the Painter class. Includes a Packer engine to manage Bin and Item objects, with support for item binding and gravity distribution analysis.

Tokens
4.2K
Snippets
12
Records
14
Agent score
55%

What's inside 3D Bin Packing

  1. Analyze gravity distribution in a Bin

    master
    After calling packer.pack(), each Bin object contains a gravity attribute. This attribute is a list of four floats representing the percentage of weight distribution across the four quadrants of the bin's base (e.g., [25.0, 25.0, 25.0, 25.0]). This helps in understanding the center of gravity and ensuring cargo stability during transport.
  2. Complete Simple Packing Example

    master

    This example demonstrates the full workflow: initializing the packer, adding a bin, adding multiple items, executing the packing algorithm, and visualizing the result.

    from py3dbp import Packer, Bin, Item, Painter
    import time
    
    start = time.time()
    
    # init packing function
    packer = Packer()
    
    # init bin
    box = Bin('example',(30, 10, 15), 99, 0)
    packer.addBin(box)
    
    # add item
    packer.addItem(Item('test1', 'test','cube',(9, 8, 7), 1, 1, 100, True,'red'))
    packer.addItem(Item('test2', 'test','cube',(4, 25, 1), 1, 1, 100, True,'blue'))
    packer.addItem(Item('test3', 'test','cube',(2, 13, 5), 1, 1, 100, True,'gray'))
    packer.addItem(Item('test4', 'test','cube',(7, 5, 4), 1, 1, 100, True,'orange'))
    packer.addItem(Item('test5', 'test','cube',(10, 5, 2), 1, 1, 100, True,'lawngreen'))
    
    # calculate packing 
    packer.pack(
        bigger_first=True,
        fix_point=True,
        distribute_items=True,
        check_stable=True,
        support_surface_ratio=0.75,
        number_of_decimals=0
    )
    
    # paint the results
    for b in packer:
        painter = Painter(b)
        fig = painter.plotBoxAndItems(
            title=b.partno,
            alpha=0.2,         
            write_num=True,   
            fontsize=10        
        )
    fig.show()
  3. Initialize an Item

    master

    Create an Item object to represent the objects being packed.

    Key parameters:

    • partno: A unique identifier (PN) for the item.
    • name: The type or name of the item.
    • typeof: The shape of the item; use 'cube' or 'cylinder'.
    • WHD: A tuple representing (width, height, depth).
    • weight: The weight of the item.
    • level: Priority for packing (lower numbers have higher priority).
    • loadbear: Load-bearing capacity (higher numbers have higher priority).
    • updown: Boolean; if True, the item can be placed upside down.
    • color: The color of the item (e.g., '#FFFF37', 'red', or 'r').
    item1 = Item(
        partno='testItem',
        name='wash',
        typeof='cube',
        WHD=(85, 60, 60),
        weight=10,
        level=1,
        loadbear=100,
        updown=True,
        color='#FFFF37'
    )
  4. Visualize Packing Results with Painter

    master

    Use the Painter class to generate a visual representation of the packed bins and items.

    Key parameters for plotBoxAndItems():

    • title: The title of the plot (usually the bin's partno).
    • alpha: Transparency of the items (e.g., 0.2 is recommended to see part numbers clearly).
    • write_num: Boolean; if True, writes the part number on the item.
    • fontsize: Controls the font size of the part numbers.
    for b in packer:
        painter = Painter(b)
        fig = painter.plotBoxAndItems(
            title=b.partno,
            alpha=0.2,
            write_num=True,
            fontsize=10
        )
    fig.show()
  5. Initialize a Bin

    master

    Create a Bin object to represent the container. You can specify dimensions, weight capacity, corner size, and the placement order type.

    Key parameters:

    • partno: A unique identifier (PN) for the bin.
    • WHD: A tuple representing (width, height, depth).
    • max_weight: The maximum weight the bin can bear.
    • corner: The size of the container corner in cm (affects visualization).
    • put_type: The order of placing items. Use 0 for general and 1 for open top.
    box1 = Bin(
        partno='Bin',
        WHD=(589, 243, 259),
        max_weight=28080,
        corner=15,
        put_type=1
    )
  6. Calculate 3D bin packing with calPacking

    master

    The calPacking endpoint performs the 3D bin packing calculation. You send container and item information via a POST request, and the API returns the calculated packing results, including positions and rotations.

    Endpoint Details:

    • URL: http://10.10.19.29:771/calPacking (Internal)
    • Method: POST

    Request Body Parameters:

    • box (Array of Objects): Container information (see Container Configuration).
    • item (Array of Objects): Item information (see Item Configuration).
    • binding (Array of Arrays): Item binding quantities, e.g., ["ItemA", "ItemB"].
    {
        "box": [
            {
                "name": "40ft High Cube",
                "WHD" : [1203,235,269],
                "weight": 26280,
                "openTop": [1,2],
                "coner":15
            }
        ],
        "item": [
            {
                "name":"Dyson_DC34_Animal",
                "WHD" : [170,82,46],
                "count": 5,
                "updown":1,
                "type":1,
                "level":0,
                "loadbear":100,
                "weight":85,
                "color" :1
            }
        ],
        "binding" : [
            ["Wood_Table", "50_Gal_Oil_Drum"]
        ]
    }
  7. Retrieve Packing Results

    master

    After calling packer.pack(), access the results through the following attributes:

    • packer.bins: Returns the list of bins.
    • packer.bins[i].items: Returns the items successfully fitted into the $i$-th bin.
    • packer.unfit_items: Returns the list of items that could not be packed.
  8. Execute the Packing Process

    master

    Use the Packer.pack() method to calculate the optimal arrangement of items within the bins.

    Key options:

    • bigger_first: If True, attempts to pack larger items first.
    • fix_point: If True, solves the 'floating item' problem by ensuring items are properly supported by gravity.
    • binding: A list of tuples (e.g., [('itemA', 'itemB')]) that forces specific items to be packed together as a set.
    • distribute_items:
      • True: Items are packed into bins sequentially. If a bin is full, remaining items move to the next bin.
      • False: Each bin is evaluated to see if it can fit all items (comparing all boxes).
    • check_stable: If True, checks if items are stable based on the support_surface_ratio.
    • support_surface_ratio: A value between 0 and 1 defining the required support area for an item to be considered stable.
    • number_of_decimals: Precision for calculations.
    packer.pack(
        bigger_first=True,
        fix_point=True,
        binding=[('server','cabint')],
        distribute_items=True,
        check_stable=True,
        support_surface_ratio=0.75,
        number_of_decimals=0
    )
  9. Understand the calPacking response format

    master

    The calPacking API returns a JSON object indicating success and providing detailed packing data.

    Root Object

    • Success (bool): true if the call was successful and input was valid.
    • data (Object): Contains box, fitItem, and unfitItem arrays.

    data.box (Array)

    Information about the container's state after packing:

    • WHD (Array): Dimensions [Width, Height, Depth].
    • position (Array): Starting position [x, y, z].
    • partNumber (string): Container PN code.
    • weight (int): Current container weight in KG.
    • gravity (Array): Weight distribution across four quadrants (as percentages).

    data.fitItem and data.unfitItem (Arrays)

    Both arrays share the same schema for items that were successfully packed (fitItem) or failed to pack (unfitItem):

    • WHD (Array): Dimensions [Width, Height, Depth].
    • color (string): Hexadecimal color code.
    • partNumber (string): Item PN code.
    • position (Array): Starting position [x, y, z].
    • rotationType (int): Rotation orientation (0-5).
    • name (string): Item type name.
    • type (string): Shape type (cube or cylinder).
    • weight (int): Item weight in KG.
    {
        "Success": true,
        "data": {
            "box": [
                {
                    "WHD": [1203, 235, 238],
                    "gravity": [26.37, 25.95, 27.88, 19.79],
                    "partNumber": "40ft Steel Container",
                    "position": [601.5, 117.5, 119.0],
                    "weight": 26480
                }
            ],
            "fitItem": [
                {
                    "WHD": [170, 82, 46],
                    "color": "red",
                    "name": "Dyson_DC34_Animal",
                    "partNumber": "Dyson_DC34_Animal-13",
                    "position": [935, 123, 23],
                    "rotationType": 0,
                    "type": "cube",
                    "weight": 85
                }
            ],
            "unfitItem": []
        }
    }
  10. Configure container and item data for API response

    master

    The getAllData (currently TODO) endpoint provides a data structure used for both input and output. The structure defines containers (box) and items (item). Note that certain fields are read-only (indicated by red text in the original documentation) and cannot be modified by the user, while others are user-configurable.

    Container (box) Object

    • name (String): Unique display name for the container.
    • WHD (Array of int): Dimensions [Length, Width, Height].
    • weight (Integer): Maximum weight capacity in KG.
    • openTop (Array): Supported door types (1: side opening, 2: top opening).
    • coner (int): Corner piece size in cm (0 for none, >0 for corner pieces).

    Item (item) Object

    • name (String): Unique display name for the item.
    • count (Integer): Quantity of items.
    • updown (Integer): Rotation capability (0: false, 1: true).
    • type (Integer): Shape type (1: cube, 2: cylinder).
    • level (Integer): Mandatory packing status (0: false, 1: true).
    • loadbear (Integer): Weight capacity of the item in KG.
    • weight (Integer): Weight of the item in KG.
    • color (Integer): Display color index (1: red, 2: yellow, 3: blue, 4: green, 5: purple, 6: brown, 7: orange).
    {
        "name":"Moving Box",
        "WHD" : [60,40,50],
        "count":80,
        "updown":1,
        "type":1,
        "level":0,
        "loadbear":40,
        "weight":30,
        "color" :6
    }
  11. Execute packing with the Packer class

    master

    The Packer class is the main engine used to coordinate bins and items. To use it, add your bins and items to a Packer instance and then call the pack() method.

    Workflow:

    1. Instantiate Packer.
    2. Add bins using addBin(bin).
    3. Add items using addItem(item).
    4. Call pack() with desired constraints.

    pack() arguments:

    • bigger_first: (bool) If True, sorts bins/items by volume in descending order.
    • distribute_items: (bool) If True, removes items from the master list once they are packed into a bin.
    • fix_point: (bool) If True, attempts to fix item positions to avoid floating point errors.
    • check_stable: (bool) If True, checks if items are placed stably.
    • support_surface_ratio: (float) The required ratio of support surface for stability (default 0.75).
    • binding: (list) A list of lists containing item names that should be packed together.
    • number_of_decimals: (int) Precision for dimensions and weights.
    from py3dbp.main import Packer
    
    packer = Packer()
    packer.addBin(bin)
    packer.addItem(item)
    
    packer.pack(
        bigger_first=True,
        distribute_items=True,
        fix_point=True,
        check_stable=True,
        support_surface_ratio=0.75
    )
  12. Visualize packing results with the Painter class

    master

    The Painter class provides 3D visualization of the packed bins and items using matplotlib.

    Usage:

    1. Instantiate Painter by passing a Bin object.
    2. Call plotBoxAndItems() to generate the 3D plot.

    plotBoxAndItems() arguments:

    • title: String title for the plot.
    • alpha: Transparency of the items.
    • write_num: (bool) If True, writes the item's partno on the object in the plot.
    from py3dbp.main import Painter
    
    painter = Painter(bin)
    plot = painter.plotBoxAndItems(title="Packing Result", write_num=True)
    plot.show()