def placePoly(self,index): ''' 放置某一个index的形状进去 ''' adjoin=self.polygons[index] ifp=self.getInnerFitRectangle(self.polygons[index]) differ_region=Polygon(ifp) multi=True if multi==True: if self.choose_nfp==True and index>8: target_polygon=self.polygons[index-8:index] bottom_height=self.getMinTop(target_polygon)+300 differ_region=differ_region.difference(Polygon([[0,0],[self.width,0],[self.width,bottom_height],[0,bottom_height]])) else: target_polygon=self.polygons[0:index] tasks=[(main,adjoin) for main in target_polygon] res=pool.starmap(NFP,tasks) for item in res: nfp=item.nfp differ_region=differ_region.difference(Polygon(nfp)) else: for main_index in range(0,index): main=self.polygons[main_index] nfp=NFP(main,adjoin).nfp differ_region=differ_region.difference(Polygon(nfp)) # print(differ_region) differ=GeoFunc.polyToArr(differ_region) differ_index=self.getBottomLeft(differ) refer_pt_index=GeoFunc.checkTop(adjoin) GeoFunc.slideToPoint(self.polygons[index],adjoin[refer_pt_index],differ[differ_index])
def shrink(self): self.new_height = self.height * 0.95 self.cur_polys = [] for poly in self.polys: top_index = GeoFunc.checkTop(poly) delta = self.new_height - poly[top_index][1] if delta >= 0: self.cur_polys.append(GeoFunc.copyPoly(poly)) else: self.cur_polys.append(GeoFunc.getSlide(poly, 0, delta))
def placeFirstPoly(self): ''' 放置第一个形状进去,并平移到left-bottom ''' poly=self.polygons[0] poly_index=GeoFunc.checkTop(poly) left_index,bottom_index,right_index,top_index=GeoFunc.checkBound(poly) move_x=poly[left_index][0] move_y=poly[bottom_index][1] GeoFunc.slidePoly(poly,0,-move_y)
def getConvexRandom(): polygon=[] num=10 for i in range(0,num): # radian=(2/num)*math.pi*i+math.pi*random.randrange(0,5,1)/12 # convex 4的角度 radian=(2/num)*math.pi*i+math.pi*random.randrange(0,3,1)/(num*2) # convex num>4的角度 radius=random.randrange(200,500,100) pt=[radius*math.cos(radian),radius*math.sin(radian)] polygon.append(pt) GeoFunc.slidePoly(polygon,750,750) storePolygon(polygon,num=num) PltFunc.addPolygon(polygon) PltFunc.showPlt()
def testGCS(self): # polygons=[] # polygons.append(self.getTestPolys()[0]) # polygons.append(self.getTestPolys()[1]) polygons = getData() num = 1 # 形状收缩 for poly in polygons: for ver in poly: ver[0] = ver[0] * num ver[1] = ver[1] * num gcs = GCS(polygons) GeoFunc.slidePoly(polygons[0], 500, 500) gcs.showAll() gcs.GuidedCuckooSearch(1500, 10) gcs.showAll()
def getMinTop(self,polygons): min_top=9999999999 for poly in polygons: bt_index=GeoFunc.checkTop(poly) if poly[bt_index][1]<min_top: min_top=poly[bt_index][1] return min_top
def updatePolyList(self): self.polyList = [] for i, poly in enumerate(self.polys): edges = GeoFunc.getPolyEdges(poly) poly_item = { "index": i, "pts": poly, "edges": edges, "horizontal": { "positive": [], "negative": [], "neutral": [] }, "vertical": { "positive": [], "negative": [], "neutral": [] }, } for edge in edges: netural = self.judgeNeutral(poly, edge) # 分别获得水平和垂直的计算结果 for i, cur in enumerate(["horizontal", "vertical"]): if netural[i] == 1: poly_item[cur]["positive"].append([edge[0], edge[1]]) elif netural[i] == -1: poly_item[cur]["negative"].append([edge[0], edge[1]]) else: poly_item[cur]["neutral"].append([edge[0], edge[1]]) self.polyList.append(poly_item)
def getData(): index=1 '''报错数据集有(空心):han,jakobs1,jakobs2 ''' '''形状过多暂时未处理:shapes、shirt、swim、trousers''' name=["ga","albano","blaz1","blaz2","dighe1","dighe2","fu","han","jakobs1","jakobs2","mao","marques","shapes","shirts","swim","trousers","convex"] print("开始处理",name[index],"数据集") # ga为测试数据集 '''暂时没有考虑宽度,全部缩放来表示''' scale=[100,0.25,100,100,20,20,20,10,20,20,0.5,20,50,1,1,1,1,1,1,1] print("缩放",scale[index],"倍") df = pd.read_csv("/Users/sean/Documents/Projects/Packing-Algorithm/euro_data/"+name[index]+".csv") polygons=[] for i in range(0,df.shape[0]): for j in range(0,df['num'][i]): poly=json.loads(df['polygon'][i]) GeoFunc.normData(poly,scale[index]) polygons.append(poly) return getDecreasing(polygons)
def getHeight(self): _max=0 for i in range(1,len(self.polygons)): top_index=GeoFunc.checkTop(self.polygons[i]) top=self.polygons[i][top_index][1] if top>_max: _max=top self.contain_height=_max PltFunc.addLine([[0,self.contain_height],[self.width,self.contain_height]],color="blue")
def getInnerFitRectangle(self,poly): ''' 获得IFR,同时平移到left-bottom ''' poly_index=GeoFunc.checkTop(poly) left_index,bottom_index,right_index,top_index=GeoFunc.checkBound(poly) move_x=poly[left_index][0] move_y=poly[bottom_index][1] GeoFunc.slidePoly(poly,-move_x,-move_y) refer_pt=[poly[poly_index][0],poly[poly_index][1]] width=self.width-poly[right_index][0] height=self.height-poly[top_index][1] IFR=[refer_pt,[refer_pt[0]+width,refer_pt[1]],[refer_pt[0]+width,refer_pt[1]+height],[refer_pt[0],refer_pt[1]+height]] return IFR
def getInnerFitRectangleNew(self,poly): ''' 获得IFR,不平移 ''' poly_index=GeoFunc.checkBottom(poly) left_index,bottom_index,right_index,top_index=GeoFunc.checkBound(poly) move_x=poly[left_index][0] move_y=poly[top_index][1] new_poly=GeoFunc.getSlide(poly,-move_x,-move_y) refer_pt=[new_poly[poly_index][0],new_poly[poly_index][1]] width=self.width-new_poly[right_index][0] height=self.height-new_poly[bottom_index][1] IFR=[refer_pt,[refer_pt[0]+width,refer_pt[1]],[refer_pt[0]+width,refer_pt[1]+height],[refer_pt[0],refer_pt[1]+height]] print("计算出结果:",IFR) return IFR
def getBreakPointsList(self, target_edge, edge, _type): if _type == "horizontal": # 两条直线四个组合计算 break_points = [] self.getT(target_edge[0], edge, 0, 1, break_points) self.getT(target_edge[1], edge, 0, 1, break_points) self.getT(edge[0], target_edge, 0, -1, break_points) self.getT(edge[1], target_edge, 0, -1, break_points) # 必须是有两个交点 if len(break_points) < 2: return # 开始计算具体参数 t1 = min(break_points[0], break_points[1]) t2 = max(break_points[0], break_points[1]) target_slide1 = [[target_edge[0][0] + t1, target_edge[0][1]], [target_edge[1][0] + t1, target_edge[1][1]]] # 平移后的结果 target_slide2 = [[target_edge[0][0] + t2, target_edge[0][1]], [target_edge[1][0] + t2, target_edge[1][1]]] # 平移后的结果 pt1 = GeoFunc.intersection(target_slide1, edge) # 可能为Tuple pt2 = GeoFunc.intersection(target_slide2, edge) # 可能为Tuple pt3 = self.getHoriVerInter(pt1, target_slide2, 0) # 计算A1 B1 C1 ratio = (LineString([pt1, pt2]).length) / (t2 - t1) # 两条边的比例 sin_theta = abs(pt1[1] - pt2[1]) / (LineString([pt1, pt2]).length ) # 直线与水平的角度 A1 = 0.5 * ratio * sin_theta B1 = -2 * t1 * A1 C1 = t1 * t1 * A1 # 计算A2 B2 C2 A2 = 0 B2 = abs(pt1[1] - pt2[1]) # 平行四边形的高度 C2 = Polygon([pt1, pt2, pt3]).area - B2 * t2 # 三角形面积 return [[t1, A1, B1, C1], [t2, -A1, B2 - B1, C2 - C1]] if _type == "vertical": pass
def getFeasibleByBottom(polys): polyList = [] for poly in polys: bottom = poly[GeoFunc.checkBottom(poly)] polyList.append({ "poly": poly, "bottom_x": bottom[0], "bottom_y": bottom[1] }) sorted(polyList, key=lambda poly: poly["bottom_y"]) sequence = [] for item in polyList: sequence.append(item["poly"]) pp = BottomLeftFill(1500, sequence) return pp.polygons
def MinimizeOverlap(self, oris, v, o): ''' oris: 允许旋转的角度集合 v: 多边形位置 实际已通过self.polygons得到 o: 旋转的角度 后期可考虑把多边形封装成类 ''' n_polys = self.n_polys it = 0 fitness = 999999 while it < self.n_mo: Q = np.random.permutation(range(n_polys)) for i in range(n_polys): curPoly = self.polygons[Q[i]] # 记录原始位置 top_index = GeoFunc.checkTop(curPoly) top = list(curPoly[top_index]) F = self.evaluate(Q[i]) # 以后考虑旋转 print('F of', Q[i], ':', F) v_i = self.CuckooSearch(Q[i]) self.evaluate(Q[i], v_i) F_new = v_i.getF() print('new F of', Q[i], ':', F) if F_new < F: print('polygon', Q[i], v_i.getXY()) else: # 平移回原位置 GeoFunc.slideToPoint(curPoly, curPoly[top_index], top) fitness_new = self.evaluateAll() if fitness_new == 0: return it # 可行解 elif fitness_new < fitness: fitness = fitness_new it = 0 self.updatePenalty() it = it + 1 return it
def combinateTestData(self): shapes = pd.read_csv("/Users/sean/Documents/Projects/Packing-Algorithm/euro_data/train_test/blaz_vec.csv") for i in range(0,60): index=[random.randint(0,6),random.randint(0,6),random.randint(0,6),random.randint(0,6)] shape1=json.loads(shapes["poly"][index[0]]) shape2=json.loads(shapes["poly"][index[1]]) shape3=json.loads(shapes["poly"][index[2]]) shape4=json.loads(shapes["poly"][index[3]]) GeoFunc.normData(shape1,150) GeoFunc.normData(shape2,150) GeoFunc.normData(shape3,150) GeoFunc.normData(shape4,150) with open("/Users/sean/Documents/Projects/Packing-Algorithm/euro_data/train_test/blaz_trian_test.csv","a+") as csvfile: writer = csv.writer(csvfile) x_8=self.normVec(json.loads(shapes["vec_8"][index[0]])+json.loads(shapes["vec_8"][index[1]])+json.loads(shapes["vec_8"][index[2]])+json.loads(shapes["vec_8"][index[3]])) x_16=self.normVec(json.loads(shapes["vec_16"][index[0]])+json.loads(shapes["vec_16"][index[1]])+json.loads(shapes["vec_16"][index[2]])+json.loads(shapes["vec_16"][index[3]])) x_32=self.normVec(json.loads(shapes["vec_32"][index[0]])+json.loads(shapes["vec_32"][index[1]])+json.loads(shapes["vec_32"][index[2]])+json.loads(shapes["vec_32"][index[3]])) x_64=self.normVec(json.loads(shapes["vec_64"][index[0]])+json.loads(shapes["vec_64"][index[1]])+json.loads(shapes["vec_64"][index[2]])+json.loads(shapes["vec_64"][index[3]])) x_128=self.normVec(json.loads(shapes["vec_128"][index[0]])+json.loads(shapes["vec_128"][index[1]])+json.loads(shapes["vec_128"][index[2]])+json.loads(shapes["vec_128"][index[3]])) x_256=self.normVec(json.loads(shapes["vec_256"][index[0]])+json.loads(shapes["vec_256"][index[1]])+json.loads(shapes["vec_256"][index[2]])+json.loads(shapes["vec_256"][index[3]])) writer.writerows([[i,time.asctime(time.localtime(time.time())),index[0],index[1],index[2],index[3],shape1,shape2,shape3,shape4,x_8,x_16,x_32,x_64,x_128,x_256]])
def updateOverlap(self): # 计算重叠情况 self.overlap_pair = [[0] * len(self.cur_polys) for i in range(len(self.cur_polys))] self.overlap_each = [0 for i in range(len(self.cur_polys))] for i in range(0, len(self.cur_polys) - 1): for j in range(i + 1, len(self.cur_polys)): Pi = Polygon(self.cur_polys[i]) Pj = Polygon(self.cur_polys[j]) overlap_area = GeoFunc.computeInterArea(Pi.intersection(Pj)) if overlap_area > precision_error: self.overlap_pair[i][ j] = self.overlap_pair[i][j] + overlap_area self.overlap_pair[j][i] = self.overlap_pair[i][j] self.overlap_each[i] = self.overlap_each[i] + overlap_area self.overlap_each[j] = self.overlap_each[j] + overlap_area # 计算修正后的参考值,同时修正Phi max_miu_pair = 0 max_miu_pair_indx = [0, 0] for i in range(0, len(self.cur_polys)): for j in range(0, len(self.cur_polys)): miu = self.overlap_pair[i][j] / (1 + self.phi[i][j]) self.miu_each[i] = self.miu_each[i] + miu if miu > max_miu_pair: max_miu_pair_indx = [i, j] self.phi[max_miu_pair_indx[0]][max_miu_pair_indx[0]] += 1 # 获得最大的Miu及其Index self.max_miu = 0 self.max_miu_index = -1 for index, miu in enumerate(self.miu_each): if miu > self.max_miu: self.max_miu = miu self.max_miu_index = index # 更新是否重叠 self.overlap = False for area in self.overlap_each: if area > 0: self.overlap = True
def slidePolytoMe(self, poly): top_index = GeoFunc.checkTop(poly) top = poly[top_index] GeoFunc.slideToPoint(poly, top, self.getXY())