python - 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)
解决方案
推荐阅读
- cassandra - Cassandra 集群可以有偶数个节点吗?
- reactjs - 从 firebase 中选择所有用户帖子
- deployment - 如果 ASP.NET 解决方案连续发布超过 1 次,Visual Studio 2019 会出错
- python - Matillion 网格变量未通过 updateGridVariable 更新
- javascript - 减少reactjs中按类别区分的数组
- java - 无法同时检索内容和 postId
- c# - 为什么使用 ASP.NET MVC 更新数据库时不支持连接字符串关键字“服务器”
- azure-cosmosdb - Cosmos SQL API:基于数组条目的过滤器
- amazon-web-services - 使用单个构建规范文件在 CodeBuild 中运行批量构建
- c - 内存访问错误的原因是什么?