Python py3dbp kutuya sığmayan itemleri boş kutulara dağıtma

Başlatan Dreatest, 23 Mayıs 2021 - 08:27:31

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

Dreatest

Python'da, eşyaları kutulara py3dbp benzeri bir modül ile yerleştiriyorum. İnşaat alanında kullanılıyor eşyalar dikdörtgen prizması şeklinde. 14 kutum ve 4 eşyam var. Program başlarken eşyaların miktarını giriyorum mesela a eşyasından 10 tane gibi 4 eşyanın amount değerlerini giriyorum. Bazı eşyalar kutuya sığıyor, bazıları uymuyor. Ve buna göre, diğer 13 kutu boş kalır. Çözümü hiçbir yerde bulamadım. Bana yardımcı olabilir misiniz? Modül sadece tüm eşyaları 1. kutuya yüklüyor ve sığmayanları boş kutulara dağıtmıyor. Sadece bu fonksiyonu yapamadım uzun bir çözüm istemiyorum. Kodları da hazır bir python modülü değil de kendi dosya modülümden oluşturmuştum anlamanız için atıyorum.

Modül Dosyam

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)



Main Dosyam

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()