基于 三维装箱问题的算法研究-1 的基础上,对整个装箱过程发生的函数进行封装
# -*- coding: utf-8 -*-
from matplotlib import pyplot as plt
#设置图表刻度等格式
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
#make_pic内置函数
def box(ax,x, y, z, dx, dy, dz, color='red'):
xx = [x, x, x+dx, x+dx, x]
yy = [y, y+dy, y+dy, y, y]
kwargs = {'alpha': 1, 'color': color}
ax.plot3D(xx, yy, [z]*5, **kwargs)#下底
ax.plot3D(xx, yy, [z+dz]*5, **kwargs)#上底
ax.plot3D([x, x], [y, y], [z, z+dz], **kwargs)
ax.plot3D([x, x], [y+dy, y+dy], [z, z+dz], **kwargs)
ax.plot3D([x+dx, x+dx], [y+dy, y+dy], [z, z+dz], **kwargs)
ax.plot3D([x+dx, x+dx], [y, y], [z, z+dz], **kwargs)
return ax
#显示图形的函数:Items = [[num[0],num[1],num[2],num[3],num[4],num[5],num[6]],]
def make_pic(Items):
fig = plt.figure()
ax = Axes3D(fig)
ax.xaxis.set_major_locator(MultipleLocator(50))
ax.yaxis.set_major_locator(MultipleLocator(50))
ax.zaxis.set_major_locator(MultipleLocator(50))
for num in Items:
box(ax,num[0],num[1],num[2],num[3],num[4],num[5],num[6])
plt.title('Cube')
plt.show()
#把尺寸数据生成绘图数据
def make(O,C,color):
data = [O[0],O[1],O[2],C[0],C[1],C[2],color]
return data
#可用点的生成方法
def newsite(O,B_i):
# 在X轴方向上生成
O1 = (O[0]+B_i[0],O[1],O[2])
# 在Y轴方向上生成
O2 = (O[0],O[1]+B_i[1],O[2])
# 在Z轴方向上生成
O3 = (O[0],O[1],O[2]+B_i[2])
return [O1,O2,O3]
#3.拟人化依次堆叠方体
def packing3D(show_num,color,O,Box_list):
canput = 0
O_items = [O]
O_pop = []
for i in range(0,len(Box_list)):
#货物次序应小于等于可用点数量,如:第四个货物i=3,使用列表内的第4个放置点O_items[3],i+1即常见意义的第几个,len即总数,可用点总数要大于等于目前个数
if i+1 <= len(O_items):
#如果放置点放置货物后,三个方向都不会超过箱体限制,则认为可以堆放
if O_items[i-1][0]+Box_list[i][0]<=C[0] and O_items[i-1][1]+Box_list[i][1]<=C[1] and O_items[i-1][2]+Box_list[i][2]<=C[2]:
#使用放置点,添加一个图显信息
new_show = make(O_items[i-1],Box_list[i],color)
if new_show not in show_num:
show_num.append(make(O_items[i-1],Box_list[i],color))
#计数加1
canput = len(show_num) - 1
#把堆叠后产生的新的点,加入放置点列表
for new_O in newsite(O_items[i-1],Box_list[i]):
#保证放入的可用点是不重复的
if new_O not in O_items:
O_items.append(new_O)
#如果轮到的这个放置点不可用
else:
#把这个可用点弹出弃用
O_pop.append(O_items.pop(i-1))
#弃用可用点后,货物次序应小于等于剩余可用点数量
if i+1 <= len(O_items):# and len(O_items)-1>=0:
#当可用点一直不可用时
while O_items[i-1][0]+Box_list[i][0]>C[0] or O_items[i-1][1]+Box_list[i][1]>C[1] or O_items[i-1][2]+Box_list[i][2]>C[2]:
#一直把可用点弹出弃用
O_pop.append(O_items.pop(i-1))
#如果弹出后货物次序超出剩余可用点,则认为无法继续放置
if i-1 > len(O_items)-1:
break
#货物次序应小于等于剩余可用点数量
if i+1 <= len(O_items):
#如果不再超出限制,在这个可用点上堆叠
new_show = make(O_items[i-1],Box_list[i],color)
if new_show not in show_num:
show_num.append(make(O_items[i-1],Box_list[i],color))
#计数加1
canput = len(show_num) - 1
#把堆叠后产生的新的点,加入放置点列表
for new_O in newsite(O_items[i-1],Box_list[i]):
#保证放入的可用点是不重复的
if new_O not in O_items:
O_items.append(new_O)
return canput,O_items,O_pop
#<<<---写一个函数专门用来调整方向和计算剩余货物
def surplus(num,Box_list,change):#change='ab','bc','ac',0有三组对调可能,共6种朝向
new_Box_list = Box_list[num-1:-1]
if num == 0:
new_Box_list = Box_list
if change == 'ab':
for i in range(0,len(new_Box_list)):
new_Box_list[i]=(new_Box_list[i][1],new_Box_list[i][0],new_Box_list[i][2])
elif change == 'bc':
for i in range(0,len(new_Box_list)):
new_Box_list[i]=(new_Box_list[i][0],new_Box_list[i][2],new_Box_list[i][1])
elif change == 'ac':
for i in range(0,len(new_Box_list)):
new_Box_list[i]=(new_Box_list[i][2],new_Box_list[i][1],new_Box_list[i][0])
elif change == 0:
return new_Box_list
else:
return new_Box_list
return new_Box_list
#残余点二次分配函数
def twice(show_num,color,O_pop,Box_list):
for a2 in O_pop:
if a2[0]==0 and a2[1]==0:
Plan = packing3D(show_num,color,a2,Box_list)
Box_list = surplus(Plan[0],Box_list,0)
elif a2[1]==0 and a2[2]==0:
Plan = packing3D(show_num,color,a2,Box_list)
Box_list = surplus(Plan[0],Box_list,0)
elif a2[0]==0 and a2[2]==0:
Plan = packing3D(show_num,color,a2,Box_list)
Box_list = surplus(Plan[0],Box_list,0)
return Box_list
调用这些函数进行一次初步装箱和二次转向装箱
#1.给定空间容器C 4.2*1.9*1.8
O = (0,0,0) #原点坐标
C = (420,190,180) #箱体长宽高
color = 'red' #箱体颜色
#显示箱体
show_num = [make(O,C,color)]
#2.给定有限量个方体 500个(60,40,50)的方体,当方体大小存在差异时,我们将按照体积大小降序排列,优先摆放大体积的
B=[(40,50,60) for num in range(0,1200)]
#把货物第一次装箱
Plan1 = packing3D(show_num,'blue',(0,0,0),B)
#print(len(show_num))
#把剩下的货物分出来
B2 = surplus(Plan1[0],B,'ab')
#把剩下的货物再次尝试装箱,针对三个在轴线上的点为新的原点
twice(show_num,'orange',Plan1[2],B2)
print(len(show_num))
make_pic(show_num)
最终显示效果
可以看到在第二次发生简单转向后,箱体的利用率再一次得到提升,这个时候装载率达到114/箱,那么如果全部货物1200件,1200/114向上舍入,11车能够装完