箱の中に長方形を右下から配置していきたい
Q&A
解決したいこと
左下から長方形を配置するプログラム(Bottom-Left法)を右下から配置するプログラム(Bottom-Right法)に置き換えたい。
重さ順でソートされているので重い順で右下から配置していきたいです。
発生している問題・エラー
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import pandas as pd
import csv
import tkinter
import time
import numpy as np
def intersection_NFP(p, q):
if q[0][0] < p[0][1] < q[0][1] and p[1][0] < q[1][1] < p[1][1]:
return (p[0][1], q[1][1])
if p[0][0] < q[0][1] < p[0][1] and q[1][0] < p[1][1] < q[1][1]:
return (q[0][1], p[1][1])
return False
#p=[(x1,x2),(y1,y2)] NFPとx軸の交点を求め、 BL点候補点とする。
def intersection_x(p):
if p[0][0] < 0:
return (0, p[1][1])
return False
#p=[(x1,x2),(y1,y2)] NFPとy軸の交点を求め、 BL点候補点とする。
def intersection_y(p):
if p[1][0] < 0:
return (p[0][1], 0)
return False
#p=(a,b) q=[(x1,x2),(y1,y2)] 点pが領域q内に含まれているか、いないか。(境界線は含まない)
def include_p(p, q):
return q[0][0] < p[0] < q[0][1] and q[1][0] < p[1] < q[1][1]
#p=(a,b) q=[(x1,x2),(y1,y2)] 点pが領域q内に含まれているか、いないか。(境界線は含む)
def include_p_e(p, q):
return q[0][0] <= p[0] <= q[0][1] and q[1][0] <= p[1] <= q[1][1]
#p=(a,b) q=[{(x1,x2),(y1,y2)},{(x3,x4),(y3,y4)},...]
#点pが領域配列qのいずれか1つに含まれているか、いないか。(境界線は含まない)
def include_p_n(p, q, n):
for i in range(n):
if include_p(p, q[i]) == True:
ans = True
break
ans = False
return ans
class Rect:
def __init__(self, x, y, w, h, weight,name):
self.x = x
self.y = y
self.w = w
self.h = h
self.weight=weight
self.name=name
#未配置の長方形jの高さhb横幅wb配列 既に配置されている長方形iの高さha横幅ba配列
def NFP(self, b):
return [(self.x-b.w, self.x+self.w), (self.y-b.h, self.y+self.h)]
#箱の中に収まる範囲 UBはHの上界値
def include_room(self, W, H):
return [(0, W-self.w), (0, H-self.h)]
#長方形nにおいて既存に配置されている長方形とのNFPを計算
def NFP_r2(self, rects_after):
cand = []
if not rects_after:
return cand
else:
for rect in rects_after:
p = Rect.NFP(rect, self)
cand.append(p)
return cand
#p=(a,b) [(x1,y1),(x2,y2),...(xn, yn)] 求めたBL候補点pが既に使われていないか。
def point_search(rects_after, p):
for rect in rects_after:
if p[0] == rect.x and p[1] == rect.y:
return True
return False
#既存にm個の長方形が配置されている状態に長方形nのBL点を求める
def BL_method(self, rects_after, W, UB):
if not rects_after:
return (0, 0)
BL_point = []
a = self.NFP_r2(rects_after)
m = len(rects_after)
for i in range(m):
if not intersection_y(a[i]) == False \
and include_p_e(intersection_y(a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_y(a[i])) == False:
BL_point.append(intersection_y(a[i]))
if not intersection_x(a[i]) == False \
and include_p_e(intersection_x(a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_x(a[i])) == False:
BL_point.append(intersection_x(a[i]))
for j in range(i):
if not intersection_NFP(a[j], a[i]) == False \
and include_p_e(intersection_NFP(a[j], a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_NFP(a[j], a[i])) == False:
BL_point.append(intersection_NFP(a[j], a[i]))
BL_point = sorted(BL_point, key=lambda t:t[0])
BL_point = sorted(BL_point, key=lambda t:t[1])
for BL in BL_point:
if include_p_n(BL, a, m) == False:
p = (BL[0],BL[1])
break
return p
def __str__(self):
return "({}, {}, {}, {},{},{})".format(self.x, self.y, self.w, self.h, self.weight,self.name)
n=10
W=44.5
sort_key="weight"
h = pd.read_csv("具体的な数値.csv", usecols=[1]).squeeze('columns').values
print('高さ')
print(h[:n])
print('--------------------')
w = pd.read_csv("具体的な数値.csv", usecols=[2]).squeeze('columns').values
print('横幅')
print(w[:n])
print('--------------------')
weight= pd.read_csv("具体的な数値.csv", usecols=[3]).squeeze('columns').values
item=(np.random.randint(0,4,10)+1)//2
print(item)
name=pd.read_csv("具体的な数値.csv", usecols=[0]).squeeze('columns').values
before_list = []
for i in range(len(item)):
for j in range(item[i]):
before_list.append((w[i], h[i], weight[i],name[i]))
n = len(before_list)
print('before sort')
print(before_list)
print('--------------------')
UB=n*max(h)
rects_before=[]
for i in range(n):
new_rect = Rect(None, None, before_list[i][0], before_list[i][1],before_list[i][2],before_list[i][3])
rects_before.append(new_rect)
rects_before = sorted(rects_before, key=lambda t:t.h, reverse=True)
rects_before = sorted(rects_before, key=lambda t:t.w, reverse=True)
rects_before = sorted(rects_before, key=lambda t:t.weight, reverse=True)
print('配置前')
for rect in rects_before:
print(rect)
start = time.time()
rects_after = []
for rect in rects_before:
BL_point = Rect.BL_method(rect, rects_after, W, UB)
rect1 = Rect(BL_point[0], BL_point[1], rect.w, rect.h ,rect.weight,rect.name)
rects_after.append(rect1)
print('-----------------')
print('配置後')
for rect in rects_after:
print(rect)
H = max(rects_after[i].y+rects_after[i].h for i in range(n))
print(f'H={H}')
elapsed_time = time.time() - start
print("実行時間 = {:.3f} (秒)".format(elapsed_time))
%matplotlib inline
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111,aspect='equal')
ax.set_xlim ([0,W])
ax.set_ylim ([0,H])
name = 0
for rect in rects_after:
name = name + 1
if rect.y <= 24.9:
ax.text(rect.x+rect.w/2, rect.y+rect.h/2, f'{name}', horizontalalignment="center", verticalalignment="center")
rect_color = 'burlywood'
else:
ax.text(rect.x+rect.w/2, rect.y+rect.h/2, f'{name}', horizontalalignment="center", verticalalignment="center", color='white')
rect_color = 'lightblue'
rect1 = plt.Rectangle((rect.x,rect.y),rect.w,rect.h,fc=rect_color,ec="black")
ax.add_patch(rect1)
ax.text(0, H+1, f'H={H}', horizontalalignment="center")
ax.text(W+1, 0, f'W={W}', verticalalignment="center")
ax.axhline(y=25, color='red', linestyle='--')
plt.show()
「具体的な数値.csv」のエクセルファイルのデータは以下の通りです。
書き換える主な個所は以下のBL_methodだと思っているのですが左下を基準としているBL点をどのようにして右下に持っていくかが分かりません。もしかしたらここ以外の箇所も書き換えないといけないかもしれません。
該当するソースコード
def BL_method(self, rects_after, W, UB):
if not rects_after:
return (0, 0)
BL_point = []
a = self.NFP_r2(rects_after)
m = len(rects_after)
for i in range(m):
if not intersection_y(a[i]) == False \
and include_p_e(intersection_y(a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_y(a[i])) == False:
BL_point.append(intersection_y(a[i]))
if not intersection_x(a[i]) == False \
and include_p_e(intersection_x(a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_x(a[i])) == False:
BL_point.append(intersection_x(a[i]))
for j in range(i):
if not intersection_NFP(a[j], a[i]) == False \
and include_p_e(intersection_NFP(a[j], a[i]), self.include_room(W, UB)) == True \
and Rect.point_search(rects_after, intersection_NFP(a[j], a[i])) == False:
BL_point.append(intersection_NFP(a[j], a[i]))
BL_point = sorted(BL_point, key=lambda t:t[0])
BL_point = sorted(BL_point, key=lambda t:t[1])
for BL in BL_point:
if include_p_n(BL, a, m) == False:
p = (BL[0],BL[1])
break
return p
よろしくお願いします。