Example #1
0
 def getLengthDecreaing(self):
     length_list = []
     for i, poly in enumerate(self.polys):
         bottom_pt, top_pt = LPAssistant.getBottomPoint(
             poly), LPAssistant.getTopPoint(poly)
         length_list.append([i, top_pt[1] - bottom_pt[1]])
     return length_list
Example #2
0
 def getWidthDecreaing(self, polys):
     width_list = []
     for i, poly in enumerate(self.polys):
         left_pt, right_pt = LPAssistant.getLeftPoint(
             poly), LPAssistant.getRightPoint(poly)
         width_list.append([i, right_pt[0] - left_pt[0]])
     return width_list
 def getPolyDepeth(self, index):
     cur_min_depth, pt = 0, LPAssistant.getTopPoint(self.polys[index])
     for j in range(len(self.polys)):
         if j == index or self.pair_overlap[index][j] == 0:
             continue
         cur_min_depth = cur_min_depth + self.getPairDepenetration(
             pt, index, j)
     return cur_min_depth
 def getNFP(self, j, i):
     # j是固定位置,i是移动位置
     row = j * 192 + i * 16 + self.poly_status[j][2] * 4 + self.poly_status[
         i][2]
     bottom_pt = LPAssistant.getBottomPoint(self.polys[j])
     delta_x, delta_y = bottom_pt[0], bottom_pt[1]
     nfp = GeoFunc.getSlide(json.loads(self.fu_pre["nfp"][row]), delta_x,
                            delta_y)
     return nfp
 def slideToContainer(self):
     # 平移部分形状
     for index, poly in enumerate(self.polys):
         right_pt = LPAssistant.getRightPoint(poly)
         if right_pt[0] > self.cur_length:
             delta_x = self.cur_length - right_pt[0]
             GeoFunc.slidePoly(poly, delta_x, 0)
             top_pt = self.poly_status[index][1]
             self.poly_status[index][1] = [top_pt[0] + delta_x, top_pt[1]]
    def getPrerequisite(self, i, orientation, **kw):
        # 获得全部NFP以及拆分情况
        self.all_nfps,self.all_points_target,self.all_edges_target = [],[],[]
        offline = kw['offline']
        for j, item in enumerate(self.polys):
            # 两个相等的情况,跳过否则会计算错误
            if j == i:
                self.all_nfps.append([])
                self.all_points_target.append([])
                self.all_edges_target.append([])
                continue
            # 预处理的情况
            points_target, edges_target, nfp = [], [], []
            if offline == True:
                row = j * 192 + i * 16 + self.poly_status[j][
                    2] * 4 + orientation
                bottom_pt = LPAssistant.getBottomPoint(self.polys[j])
                delta_x, delta_y = bottom_pt[0], bottom_pt[1]
                nfp = GeoFunc.getSlide(json.loads(self.fu_pre["nfp"][row]),
                                       delta_x, delta_y)
            else:
                nfp = LPAssistant.deleteOnline(
                    self.NFPAssistant.getDirectNFP(
                        self.polys[j], self.polys[i]))  # NFP可能有同一直线上的点
            # 计算对应目标函数
            for pt_index in range(len(nfp)):
                edges_target.append(
                    LPAssistant.getTargetFunction(
                        [nfp[pt_index - 1], nfp[pt_index]]))
                points_target.append([nfp[pt_index][0], nfp[pt_index][1]])
            # 添加上去
            self.all_nfps.append(nfp)
            self.all_edges_target.append(edges_target)
            self.all_points_target.append(points_target)

        # 获取IFR
        self.target_poly = self.all_polygons[i][orientation]
        self.ifr = PackingUtil.getInnerFitRectangle(self.target_poly,
                                                    self.cur_length,
                                                    self.width)
        self.IFR = Polygon(self.ifr)
        self.final_IFR = Polygon(self.ifr)
 def polysOverlapIFR(self, poly1, poly2):
     '''判断两个形状之间是否重叠、重叠区域面积、重叠区域是否与IFR有重叠'''
     P1, P2 = Polygon(poly1), Polygon(poly2)
     inter = P1.intersection(P2)
     overlap, overlap_poly = False, []
     if inter.area > bias:
         new_inter = inter.intersection(self.IFR)
         if new_inter.area > bias:
             overlap, overlap_poly = True, LPAssistant.processRegion(
                 new_inter)  # 相交区域肯定是凸多边形
     return overlap, overlap_poly
    def main(self):
        ration_dec, ration_inc = 0.04, 0.01
        max_time = 2000
        print("执行主程序")
        self.best_length = LPAssistant.getLength(self.polys)  # 最佳状态
        print("初始高度:", self.best_length)
        self.cur_length = self.best_length * (1 - ration_dec)  # 当前的宽度

        self.slideToContainer()  # 把突出去的移进来

        start_time = time.time()
        self.use_ratio.append(self.total_area /
                              (self.best_length * self.width))
        print("当前利用率:", self.total_area / (self.best_length * self.width))

        while time.time() - start_time < max_time:
            # 最小化重叠
            self.minimizeOverlap()
            if LPAssistant.judgeFeasible(self.polys) == True:
                # 更新全部状态
                self.length = self.cur_length
                self.use_ratio.append(self.total_area /
                                      (self.length * self.width))
                print("当前利用率:", self.total_area / (self.length * self.width))
                self.best_polys = copy.deepcopy(self.polys)
                self.best_poly_status = copy.deepcopy(self.poly_status)
                # 收缩边界,并且把突出去的移进来
                self.cur_length = self.length * (1 - ration_dec)
                self.slideToContainer()
            else:
                # 如果不可行就直接拆分
                self.cur_length = self.best_length * (1 + ration_inc)

        end_time = time.time()
        print("最优结果:", self.best_polys)
        self.showPolys()
        self.plotRecord("use ratio:", self.use_ratio)
 def getConstants(self):
     self.W = []  # 最高位置到右侧的距离
     self.W_ = []  # 最高位置到左侧的距离
     self.H = []  # 最高点
     self.Xi = []  # Xi的初始位置
     self.Yi = []  # Yi的初始位置
     self.PLACEMENTPOINT = []
     for i, poly in enumerate(self.polys):
         left, bottom, right, top = LPAssistant.getBoundPoint(poly)
         self.PLACEMENTPOINT.append([top[0], top[1]])
         self.Xi.append(top[0])
         self.Yi.append(top[1])
         self.W.append(right[0] - top[0])
         self.W_.append(top[0] - left[0])
         self.H.append(top[1] - bottom[1])
Example #10
0
    def checkOneSeq(self, one_list):
        new_polys = []
        for item in one_list:
            new_polys.append(self.polys[item[0]])

        packing_polys = BottomLeftFill(
            760, new_polys, NFPAssistant=self.nfp_assistant).polygons
        _len = LPAssistant.getLength(packing_polys)

        ratio = 433200 / (_len * 760)

        res = [[] for i in range(len(new_polys))]
        for i, item in enumerate(one_list):
            res[one_list[i][0]] = packing_polys[i]

        return ratio, res
 def getInitialResult(self):
     index = 6
     blf = pd.read_csv(
         "/Users/sean/Documents/Projects/Packing-Algorithm/record/blf.csv")
     self.total_area = blf["total_area"][index]
     self.polys = json.loads(blf["polys"][index])
     self.best_polys = copy.deepcopy(self.polys)  # 按照index的顺序排列
     self.best_poly_status, self.poly_status = json.loads(
         blf["poly_status"][index]), json.loads(blf["poly_status"][index])
     self.use_ratio = []
     # 在没有的时候全部加载一遍
     if len(self.best_poly_status) == 0:
         for i, poly in enumerate(self.polys):
             top_pt = LPAssistant.getTopPoint(poly)
             self.best_poly_status.append([i, top_pt, 0])  # 分别为序列号、位置及方向
             self.poly_status.append([i, top_pt, 0])  # 分别为序列号、位置及方向
     print("一共", len(self.polys), "个形状")
    def getProblemLP(self):
        # 获得目标区域
        self.ifr_points = []
        self.target_areas = [[], [], [], [], [], [], [], [], []]
        self.last_index = [[], [], [], [], [], [], [], [], []]

        # 获得两个NFP在IFR中重叠的情况
        self.nfp_overlap_pair = [[i] for i in range(len(self.all_nfps))]
        for i in range(len(self.all_nfps) - 1):
            for j in range(i + 1, len(self.all_nfps)):
                overlap, overlap_poly = self.polysOverlapIFR(
                    self.all_nfps[i], self.all_nfps[j])
                if overlap == True:
                    self.nfp_overlap_pair[i].append(j)
                    self.nfp_overlap_pair[j].append(i)
                    self.target_areas[1].append([overlap_poly, i, j])
                    self.last_index[1].append([i, j])  # 分别添加i,j

        # 切去一维重叠情况
        for i, nfp in enumerate(self.all_nfps):
            # 删除与IFR重叠区域
            new_region = Polygon(nfp).intersection(self.IFR)
            self.final_IFR = self.final_IFR.difference(Polygon(nfp))
            # 删除与其他NFP拆分的重叠
            for j in self.nfp_overlap_pair[i][1:]:
                P = Polygon(self.all_nfps[j])
                new_region = new_region.difference(P)
            # 在目标区域增加情况,首先排除点和直线,以及面积过小
            if new_region.is_empty != True and new_region.geom_type != "Point" and new_region.geom_type != "LineString" and new_region.area > bias:
                self.target_areas[0].append(
                    [LPAssistant.processRegion(new_region), i])  # 删除直线/顶点情况
            else:
                self.target_areas[0].append([])
            self.last_index[0].append([])

        # 增加IFR的计算
        if self.final_IFR.is_empty != True and self.final_IFR.geom_type != "Point" and self.final_IFR.geom_type != "LineString" and self.final_IFR.area > bias:
            self.ifr_points = LPAssistant.processRegion(self.final_IFR)

        # 获得后续的重叠
        for i in range(2, len(self.target_areas)):
            # 遍历上一阶段计算的结果
            for j, target_area in enumerate(self.target_areas[i - 1]):
                area, P1 = target_area[0], Polygon(target_area[0])  # 获得当前目标可行解

                all_possible_target = []
                # 如果大于三个,只需要计算最后加入的,否则是第一个
                if i >= 3:
                    all_possible_target = self.nfp_overlap_pair[
                        target_area[-1]]
                else:
                    all_possible_target = self.nfp_overlap_pair[
                        target_area[1]] + self.nfp_overlap_pair[target_area[2]]

                all_possible_target = PolyListProcessor.deleteRedundancy(
                    all_possible_target)

                # 删除所有更小的,保证正序,获得判断这些形状是否会重叠,若有则添加并求解目标区域
                all_possible_target_larger = LPAssistant.deleteTarget(
                    all_possible_target, [
                        i for i in range(
                            0,
                            max(item for item in target_area[1:]) + 1)
                    ])
                for possible_target in all_possible_target_larger:
                    P2 = Polygon(self.all_nfps[possible_target])
                    # 只有相交才进一步计算
                    if P1.intersects(P2):
                        inter = P1.intersection(P2)
                        if inter.area > bias:
                            self.last_index[i].append([j])
                            self.target_areas[i].append(
                                [LPAssistant.processRegion(inter)] +
                                target_area[1:] + [possible_target])

                # 删除已经有的,遍历计算重叠
                all_possible_target_difference = LPAssistant.deleteTarget(
                    all_possible_target, [item for item in target_area[1:]])
                new_region = self.cutFrontRegion(
                    all_possible_target_difference, P1)

                if new_region.is_empty != True and new_region.geom_type != "Point" and new_region.geom_type != "LineString" and new_region.area > bias:
                    target_area[0] = LPAssistant.processRegion(new_region)
                else:
                    self.target_areas[i - 1][j] = []

            # 如果该轮没有计算出重叠则停止
            if self.target_areas[i] == []:
                self.max_overlap = i
                # print("至多",i,"个形状重叠,计算完成")
                break
    def minimizeOverlap(self):
        start_time = time.time()

        # 记录引导检索的相关内容
        self.miu = [[1] * len(self.polys) for _ in range(len(self.polys))]
        self.initialOverlap()

        # 记录重叠变化情况
        self.overlap_reocrd = []

        # 检索次数限制/超出倍数退出
        it, N = 0, 50
        minimal_overlap = self.getTotalOverlap()
        cur_overlap = minimal_overlap
        print("初始重叠:", cur_overlap)

        # 限定计算次数
        print("开始一次检索")
        while it < N:
            print("it:", it)
            # 获得随机序列并逐一检索
            permutation = np.arange(len(self.polys))
            np.random.shuffle(permutation)
            for i in range(len(self.polys)):
                # 选择特定形状
                choose_index = permutation[i]

                # 通过重叠判断是否需要计算
                with_overlap = False
                for item in self.pair_overlap[choose_index]:
                    if item > 0:
                        with_overlap = True
                        break
                if with_overlap == False:
                    continue

                # 获得当前的最小的深度(调整后),如果没有重叠,直接下一个
                self.getPrerequisite(choose_index,
                                     self.poly_status[choose_index][2],
                                     offline=True)
                cur_min_depth = self.getPolyDepeth(choose_index)

                # 记录最优情况,默认是当前情况
                original_position = self.poly_status[choose_index][1]
                best_position, best_orientation, best_depth = self.poly_status[
                    choose_index][1], self.poly_status[choose_index][
                        2], cur_min_depth
                # print("当前最低高度:",best_depth)

                print("测试第", i, "个形状")
                # 遍历四个角度的最优值
                for orientation in [0, 1, 2, 3]:
                    # print("测试角度:",90*orientation,"度")
                    self.getPrerequisite(choose_index,
                                         orientation,
                                         offline=True)
                    self.getProblemLP()
                    new_position, new_depth = self.searchBestPosition(
                        choose_index)  # 获得最优位置
                    if new_depth < best_depth:
                        best_position, best_orientation, best_depth = copy.deepcopy(
                            new_position), orientation, new_depth

                # 如果有变化状态则需要更新overlap以及移动形状
                if best_position != original_position:
                    print("本次检索最低深度:", best_depth)
                    # 更新记录的位置
                    self.poly_status[choose_index][1] = copy.deepcopy(
                        best_position)
                    self.poly_status[choose_index][2] = best_orientation
                    # 获取形状顶部位置并平移过去
                    new_poly = copy.deepcopy(
                        self.all_polygons[choose_index][best_orientation])
                    top_point = LPAssistant.getTopPoint(new_poly)
                    GeoFunc.slidePoly(new_poly,
                                      best_position[0] - top_point[0],
                                      best_position[1] - top_point[1])
                    # 更新形状与重叠情况
                    self.polys[choose_index] = new_poly
                    self.updateOverlap(choose_index)
                    # self.showPolys()

            # 计算新方案的重叠情况
            cur_overlap = self.getTotalOverlap()
            self.overlap_reocrd.append(cur_overlap)
            if cur_overlap < bias:
                print("没有重叠,本次检索结束")
                break
            elif cur_overlap < minimal_overlap:
                minimal_overlap = cur_overlap
                it = 0
            print("\n当前重叠:", cur_overlap, "\n")
            it = it + 1
            self.updateMiu()

        # 超出检索次数
        if it == N:
            print("超出更新次数/超出倍数")
            # self.showPolys()

        end_time = time.time()
        print("本轮耗时:", end_time - start_time)
        print("最终结果:", self.polys)
        print("当前状态:", self.poly_status)

        with open(
                "/Users/sean/Documents/Projects/Packing-Algorithm/record/fu_result.csv",
                "a+") as csvfile:
            writer = csv.writer(csvfile)
            writer.writerows([[
                time.asctime(time.localtime(time.time())),
                end_time - start_time, self.cur_length,
                self.total_area / (self.cur_length * self.width), cur_overlap,
                self.poly_status, self.polys
            ]])

        self.showPolys()
        self.plotRecord("Overlap Record:", self.overlap_reocrd)