首页 > 解决方案 > Python py3dbp 分配不适合空箱的项目

问题描述

在 python 上,我将盒子中的项目放在类似 py3dbp 模型上。我有 14 个箱子和 4 件物品。我在程序启动时输入项目数量。有些物品适合,有些不适合。因此,这些垃圾箱仍然是空的。我在任何地方都找不到解决方案。你能帮助我吗?我必须分发不适合空垃圾箱的物品。

from binpack import Packer, Bin, Item
import numpy as np
packer = Packer()

def descBin(name, width, height, depth, max_weight):
    packer.add_bin(Bin(name, width, height, depth, max_weight))

def addItem(name, width, height, depth, weight):
    packer.add_item(Item(name, width, height, depth, weight))

name = 'E1C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E2C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E3C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))


name = 'E4C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E5C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E6C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E7C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))


name = 'E8C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E9C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E10C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'E11C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))


name = 'E12C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'EC13C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

name = 'EC14C'
width = 200
height = 200
depth = 200
max_weight = 10
packer.add_bin(Bin(name, width, height, depth, max_weight))

#ITEMS
name = 'E1C'
width = 30
height = 20
depth = 30
weight = 1
amount1 = int(input("(E1C 30 x 20 x 30) Amount: "))
for i in range(amount1):
    packer.add_item(Item(name, width, height, depth, weight))

name = 'E2C'
width = 30
height = 40
depth = 30
weight = 1
amount2 = int(input("(E2C 30 x 40 x 30) Amount: "))
for i in range(amount2):
    packer.add_item(Item(name, width, height, depth, weight))

name = 'E3C'
width = 20
height = 40
depth = 20
weight = 1
amount3 = int(input("(E3C 20 x 40 x 20) Amount: "))
for i in range(amount3):
    packer.add_item(Item(name, width, height, depth, weight))

name = 'E4C'
width = 40
height = 40
depth = 40
weight = 1
amount4 = int(input("(E4C 40 x 40 x 40) Amount: "))
for i in range(amount4):
    packer.add_item(Item(name, width, height, depth, weight))

nameBinD = {0:"E1C", 1:"E2C", 2:"E3C", 3:"E4C", 4:"E5C", 5:"E6C", 6:"E7C", 7:"E8C", 8:"E9C", 9:"E10C", 10:"E11C", 11:"E12C"}
widthBinD = {0:200, 1:200, 2:200, 3:200, 4:200, 5:200, 6:200, 7:200, 8:200, 9:200, 10:200, 11:200}
heightBinD = {0:200, 1:200, 2:200, 3:200, 4:200, 5:200, 6:200, 7:200, 8:200, 9:200, 10:200, 11:200}
depthBinD = {0:200, 1:200, 2:200, 3:200, 4:200, 5:200, 6:200, 7:200, 8:200, 9:200, 10:200, 11:200}
max_weightBinD = {0:10, 1:10, 2:10, 3:10, 4:10, 5:10, 6:10, 7:10, 8:10, 9:10, 10:10, 11:10}

nameItemD = {0:"E1C", 1:"E2C", 2:"E3C", 3:"E4C"}
widthItemD = {0:30, 1:30, 2:20, 3:40}
heightItemD = {0:30, 1:40, 2:40, 3:40}
depthItemD = {0:30, 1:30, 2:20, 3:40}
weightItemD = {0:1, 1:1, 2:1, 3:1}
amountItemD = {0:amount1, 1:amount2, 2:amount3, 3:amount4}



def back():
    print()
    back = input('Anasayfaya Dönmek İster Misin [Y/N]: ')
    if back[0].upper() == 'Y':
        print()
        menu()
    elif back[0].upper() == 'N':
        print()
        exit()
    else:
        print('\033[92m?')
        exit(0)



def banner():
    print("""██████╗ ██╗   ██╗██████╗ ██████╗ ██████╗ ██████╗ 
██╔══██╗╚██╗ ██╔╝╚════██╗██╔══██╗██╔══██╗██╔══██╗
██████╔╝ ╚████╔╝  █████╔╝██║  ██║██████╔╝██████╔╝
██╔═══╝   ╚██╔╝   ╚═══██╗██║  ██║██╔══██╗██╔═══╝ 
██║        ██║   ██████╔╝██████╔╝██████╔╝██║     
╚═╝        ╚═╝   ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝     
                                                 
                                     
                                           """)

banner()



def menu():
    try:
        print("\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n ")
        banner()
        print()
        print("""E
    1. Add Bin             
    2. Add Items      
    3. Calculate
    """)

        choice = input(' (1-3): ')
        if choice == '1':
            name = input('[+] Name : ')
            width = input('[+] Width : ')
            height = input('[+] Height : ')
            depth = input('[+] Depth : ')
            max_weight = input('[+] Max Weight : ')
            descBin(name, width, height, depth, max_weight)
            back()

        elif choice == "2":
            name = input('[+] Name : ')
            width = input('[+] Width : ')
            height = input('[+] Height : ')
            depth = input('[+] Depth : ')
            weight = input('[+] Weight : ')
            amount = int(input("[+] Amount : "))
            for i in range(amount):
                packer.add_item(Item(name, width, height, depth, weight))
            back()
        
        elif choice == '3':
            packer.pack()
            for b in packer.bins:
                print("| |", b.string())

            print("FITTED ITEMS:")
            for item in b.items:
                print("====> ", item.string())
                
            print("YOU CAN'T LOAD THESE ITEMS ON THIS PALLET:")
            for item in b.unfitted_items:
                print("====> ", item.string())
            back()



    except():
        print("x")


        
menu()```

还有我的模型文件;

from decimal import Decimal

DEFAULT_NUMBER_OF_DECIMALS = 3
START_POSITION = [0, 0, 0]

def rect_intersect(item1, item2, x, y):
    d1 = item1.get_dimension()
    d2 = item2.get_dimension()

    cx1 = item1.position[x] + d1[x]/2
    cy1 = item1.position[y] + d1[y]/2
    cx2 = item2.position[x] + d2[x]/2
    cy2 = item2.position[y] + d2[y]/2

    ix = max(cx1, cx2) - min(cx1, cx2)
    iy = max(cy1, cy2) - min(cy1, cy2)

    return ix < (d1[x]+d2[x])/2 and iy < (d1[y]+d2[y])/2


def intersect(item1, item2):
    return (
        rect_intersect(item1, item2, Axis.WIDTH, Axis.HEIGHT) and
        rect_intersect(item1, item2, Axis.HEIGHT, Axis.DEPTH) and
        rect_intersect(item1, item2, Axis.WIDTH, Axis.DEPTH)
    )


def get_limit_number_of_decimals(number_of_decimals):
    return Decimal('1.{}'.format('0' * number_of_decimals))


def set_to_decimal(value, number_of_decimals):
    number_of_decimals = get_limit_number_of_decimals(number_of_decimals)

    return Decimal(value).quantize(number_of_decimals)

class RotationType:
    RT_WHD = 0
    RT_HWD = 1
    RT_HDW = 2
    RT_DHW = 3
    RT_DWH = 4
    RT_WDH = 5

    ALL = [RT_WHD, RT_HWD, RT_HDW, RT_DHW, RT_DWH, RT_WDH]


class Axis:
    WIDTH = 0
    HEIGHT = 1
    DEPTH = 2

    ALL = [WIDTH, HEIGHT, DEPTH]

class Item:
    def __init__(self, name, width, height, depth, weight):
        self.name = name
        self.width = width
        self.height = height
        self.depth = depth
        self.weight = weight
        self.rotation_type = 0
        self.position = START_POSITION
        self.number_of_decimals = DEFAULT_NUMBER_OF_DECIMALS

    def format_numbers(self, number_of_decimals):
        self.width = set_to_decimal(self.width, number_of_decimals)
        self.height = set_to_decimal(self.height, number_of_decimals)
        self.depth = set_to_decimal(self.depth, number_of_decimals)
        self.weight = set_to_decimal(self.weight, number_of_decimals)
        self.number_of_decimals = number_of_decimals

    def string(self):
        return "%s(%sx%sx%s, weight: %s) pos(%s) rt(%s) vol(%s)" % (
            self.name, self.width, self.height, self.depth, self.weight,
            self.position, self.rotation_type, self.get_volume()
        )

    def get_volume(self):
        return set_to_decimal(
            self.width * self.height * self.depth, self.number_of_decimals
        )

    def get_dimension(self):
        if self.rotation_type == RotationType.RT_WHD:
            dimension = [self.width, self.height, self.depth]
        elif self.rotation_type == RotationType.RT_HWD:
            dimension = [self.height, self.width, self.depth]
        elif self.rotation_type == RotationType.RT_HDW:
            dimension = [self.height, self.depth, self.width]
        elif self.rotation_type == RotationType.RT_DHW:
            dimension = [self.depth, self.height, self.width]
        elif self.rotation_type == RotationType.RT_DWH:
            dimension = [self.depth, self.width, self.height]
        elif self.rotation_type == RotationType.RT_WDH:
            dimension = [self.width, self.depth, self.height]
        else:
            dimension = []

        return dimension


class Bin:
    def __init__(self, name, width, height, depth, max_weight):
        self.name = name
        self.width = width
        self.height = height
        self.depth = depth
        self.max_weight = max_weight
        self.items = []
        self.unfitted_items = []
        self.number_of_decimals = DEFAULT_NUMBER_OF_DECIMALS

    def format_numbers(self, number_of_decimals):
        self.width = set_to_decimal(self.width, number_of_decimals)
        self.height = set_to_decimal(self.height, number_of_decimals)
        self.depth = set_to_decimal(self.depth, number_of_decimals)
        self.max_weight = set_to_decimal(self.max_weight, number_of_decimals)
        self.number_of_decimals = number_of_decimals

    def string(self):
        return "%s(%sx%sx%s, max_weight:%s) vol(%s)" % (
            self.name, self.width, self.height, self.depth, self.max_weight,
            self.get_volume()
        )

    def get_volume(self):
        return set_to_decimal(
            self.width * self.height * self.depth, self.number_of_decimals
        )

    def get_total_weight(self):
        total_weight = 0

        for item in self.items:
            total_weight += item.weight

        return set_to_decimal(total_weight, self.number_of_decimals)

    def put_item(self, item, pivot):
        fit = False
        valid_item_position = item.position
        item.position = pivot

        for i in range(0, len(RotationType.ALL)):
            item.rotation_type = i
            dimension = item.get_dimension()
            if (
                self.width < pivot[0] + dimension[0] or
                self.height < pivot[1] + dimension[1] or
                self.depth < pivot[2] + dimension[2]
            ):
                continue

            fit = True

            for current_item_in_bin in self.items:
                if intersect(current_item_in_bin, item):
                    fit = False
                    break

            if fit:
                if self.get_total_weight() + item.weight > self.max_weight:
                    fit = False
                    return fit

                self.items.append(item)

            if not fit:
                item.position = valid_item_position

            return fit

        if not fit:
            item.position = valid_item_position

        return fit


class Packer:
    def __init__(self):
        self.bins = []
        self.items = []
        self.unfit_items = []
        self.total_items = 0

    def add_bin(self, bin):
        return self.bins.append(bin)

    def remove_bin(self, bin):
        return self.bins.remove(bin)

    def add_item(self, item):
        self.total_items = len(self.items) + 1

        return self.items.append(item)

    def pack_to_bin(self, bin, item):
        fitted = False

        if not bin.items:
            response = bin.put_item(item, START_POSITION)

            if not response:
                bin.unfitted_items.append(item)

            return

        for axis in range(0, 3):
            items_in_bin = bin.items

            for ib in items_in_bin:
                pivot = [0, 0, 0]
                w, h, d = ib.get_dimension()
                if axis == Axis.WIDTH:
                    pivot = [
                        ib.position[0] + w,
                        ib.position[1],
                        ib.position[2]
                    ]
                elif axis == Axis.HEIGHT:
                    pivot = [
                        ib.position[0],
                        ib.position[1] + h,
                        ib.position[2]
                    ]
                elif axis == Axis.DEPTH:
                    pivot = [
                        ib.position[0],
                        ib.position[1],
                        ib.position[2] + d
                    ]

                if bin.put_item(item, pivot):
                    fitted = True
                    break
            if fitted:
                break

        if not fitted:
            bin.unfitted_items.append(item)

    def pack(
        self, bigger_first=False, distribute_items=False,
        number_of_decimals=DEFAULT_NUMBER_OF_DECIMALS
    ):
        for bin in self.bins:
            bin.format_numbers(number_of_decimals)

        for item in self.items:
            item.format_numbers(number_of_decimals)

        self.bins.sort(
            key=lambda bin: bin.get_volume(), reverse=bigger_first
        )
        self.items.sort(
            key=lambda item: item.get_volume(), reverse=bigger_first
        )

        for bin in self.bins:
            for item in self.items:
                self.pack_to_bin(bin, item)

            if distribute_items:
                for item in bin.items:
                    self.items.remove(item)


标签: pythonbin-packing

解决方案


推荐阅读