def oneLoop(self, stdrt): self.sizes = dict() l_straight = self.L_work if self.data['Воздушная завеса']: l_straight += (stdrt["minEntr"][1] * 2 + 2 * (int(self.data['numAir']) * stdrt["airСurtain"][1])) l_straight = round(l_straight * 2 + 499, -3) // 2 #кратно 500 self.sizes.update({"totalLenght": l_straight}) width = (stdrt["minWallEntr"][1] + stdrt["thicknessSandwich"][1]) * 2 +\ self.unit_whl["w"] width = round(width + 99, -2) #кратно 100 minWidth = stdrt["minWidthElectro"][1] if self.data[ 'Электронагрев'] else stdrt["minWidth"][1] width = minWidth if width < minWidth else width self.sizes.update({"width": width}) #TODO здесь округляю с заданной кратностью. Сделать настройку кратности путем чтения ее из JSON файла # Расчет координат входа/выхода относительно start_point ''' s ----------------------------------- L ----- Y | | IN Dryer/Oven OUT | | W ----------------------------------- f | | X ''' self.sizes.update({"In": Coordinate(self.sizes["width"] / 2, 0)}) # in_point self.sizes.update({ "Out": Coordinate(self.sizes["width"] / 2, self.sizes["totalLenght"]) }) # out_point return self.sizes
def _getFigures(self): offset = self.templates["CoordSys"] figures = copy.deepcopy(self.data["Figures"]) for f in figures: f.start_point += Coordinate(offset[0], offset[1]) f.finish_point += Coordinate(offset[0], offset[1]) return figures
def _getImaginaryCell(self, figure, point): if point.y < figure.start_point.y: return Coordinate(point.x, figure.start_point.y)#слева elif point.y >= figure.finish_point.y: return Coordinate(point.x, figure.finish_point.y)#справа elif point.x >= figure.finish_point.x: return Coordinate(figure.finish_point.x - 1, point.y)#снизу elif point.x < figure.start_point.x: return Coordinate(figure.start_point.x, point.y)#сверху
def _scaleFigures(self): for i, f in enumerate(self.data["Figures"]): coord = f.start_point self.data["Figures"][i].start_point = Coordinate(coord.x * self.scaledCellSize, coord.y * self.scaledCellSize) coord = f.finish_point self.data["Figures"][i].finish_point = Coordinate(coord.x * self.scaledCellSize, coord.y * self.scaledCellSize)
def _quadrant4(self, global_Cord): r = self.radius p1 = Coordinate(0, self.scale / 2) p1_1 = Coordinate(self.scale / 2 - r, self.scale / 2) p2 = Coordinate(self.scale / 2, 0) p2_2 = Coordinate(self.scale / 2, self.scale / 2 - r) x = global_Cord.x * self.scale y = global_Cord.y * self.scale if self.mode == "line": return ["line", p1.x + x, p1.y + y, p2.x + x, p2.y + y] pR = Coordinate(p1_1.x, p2_2.y) return [["line", p1.x + x, p1.y + y, p1_1.x + x, p1_1.y + y], \ ["line", p2.x + x, p2.y + y, p2_2.x + x, p2_2.y + y], \ ["arc", APoint(pR.x + x, pR.y + y), r, math.pi * 3/2, math.pi * 2]]
def __init__(self, start_point, finish_point, name, loc_coordinate_from, loc_coordinate_to, neighbor_name): self.start_point = start_point self.finish_point = finish_point self.name = name self.neighbor_name = neighbor_name self.figures_queue = [] # Поля для связи конвейера с фигурами # TODO пока в ручном режиме задую I/O агрегатов, в placement pins заранее известны self.in_point = Coordinate(start_point.x + loc_coordinate_from.x, start_point.y + loc_coordinate_from.y - 1) self.out_point = Coordinate(start_point.x + loc_coordinate_to.x, start_point.y + loc_coordinate_to.y - 1)
def _quadrant1(self, global_Cord): r = self.radius p1 = Coordinate(self.scale, self.scale / 2) # TODO необязательно линия должна идти от середины p1_1 = Coordinate(self.scale / 2 + r, self.scale / 2) p2 = Coordinate(self.scale / 2, 0) p2_2 = Coordinate(self.scale / 2, self.scale / 2 - r) x = global_Cord.x * self.scale y = global_Cord.y * self.scale if self.mode == "line": return ["line", p1.x + x, p1.y + y, p2.x + x, p2.y + y] # TODO фигово. Сделать нормально pR = Coordinate(p1_1.x, p2_2.y) return [["line", p1.x + x, p1.y + y, p1_1.x + x, p1_1.y + y], \ ["line", p2.x + x, p2.y + y, p2_2.x + x, p2_2.y + y], \ ["arc", APoint(pR.x + x, pR.y + y), r, 0, math.pi / 2]]
def _read(self): initialLayout = dict() tempBoundaries = list() tempObstacles = list() #iteration will consider only polyline type. Other objects will be ignored for obj in self.acad.iter_objects("Polyline"): try: if obj.layer == "Границы Цеха": tempBoundaries.extend(list(obj.coordinates)) #use extend because will be 1 list elif obj.layer == "Препятствия": tempObstacles.append(list(obj.coordinates)) #use append because can be several lists except Exception: print(f"Exception: ошибка при итерации по файлу {self.path2dwg}") continue # At first, we find base point, width and height of initial Layout boundary = self._getBPoint_W_H(tempBoundaries) self.data["Ширина Размещения"][0] = boundary[1] # обновляем значение ширины размещения после парсинга файла self.data["Высота Размещения"][0] = boundary[2] # обновляем значение высоты размещения после парсинга файла #at final, we find base point, width and height of all obstacles obstacles = list() for obstacle in tempObstacles: templist = self._getBPoint_W_H(obstacle) local_base_point = Coordinate(abs(boundary[0].x - templist[0].x), abs(boundary[0].y - templist[0].y)) obstacles.append([local_base_point, templist[1], templist[2]]) self.data.update({"Obstacles" : obstacles}) """ Печать лок координат препятствий, их ширины и высоты
def _getBPoint_W_H(self, listCoordinates): maxindexes = [i * 2 + 1 for i, j in enumerate(listCoordinates[1::2]) if j == max( listCoordinates[1::2])] # возвращает индексы максимальных элементов по Y координате ( поэтому я указал отсчет со 2 элемента) minindexes = [i * 2 for i, j in enumerate(listCoordinates[0::2]) if j == min(listCoordinates[0::2])] #теперь находим все минимальные indexbP = [i for i in maxindexes if (i - 1) in minindexes] # find index of Y of base Point indexbP = [indexbP[0] - 1] + indexbP # find index of X of base Point basePoint = Coordinate(listCoordinates[indexbP[0]], listCoordinates[indexbP[1]]) # object, consist of x and y width = max(listCoordinates[0::2]) - basePoint.x # calculate width of layout height = basePoint.y - min(listCoordinates[1::2]) # calculate height of layout return [basePoint, width, height]
def twoLoop(self, stdrt): ''' s -------------------- L ----- Y | | IN | | Dryer/Oven | OUT | | | W -------------------- f | | X ''' self.sizes = dict() l_straight = (self.L_work - np.pi*float(self.data['Radius']))/2 + stdrt["minEntr"][1] +\ (int(self.data['numAir'])*stdrt["airСurtain"][1]) totalLenght = l_straight + float(self.data['Radius']) + self.EF totalLenght = round(totalLenght * 2 + 499, -3) // 2 # кратно 500 self.sizes.update({"totalLenght": totalLenght}) width = self.unit_whl["w"] + 2 * (float(self.data['Radius']) + stdrt["minWallEntr"][1] + stdrt["thicknessSandwich"][1]) width = round(width + 99, -2) # кратно 100 minWidth = stdrt["minWidthElectro"][1] if self.data[ 'Электронагрев'] else stdrt["minWidth"][ 1] #проверка на миним ширину width = minWidth if width < minWidth else width self.sizes.update({"width": width}) # TODO здесь округляю с заданной кратностью. Сделать настройку кратности путем чтения ее из JSON файла # Расчет координат входа/выхода относительно start_point inx = stdrt["minWallEntr"][1] + stdrt["thicknessSandwich"][ 1] + self.unit_whl["w"] / 2 outx = inx + 2 * self.data['Radius'] self.sizes.update({"In": Coordinate(inx, 0)}) # in_point self.sizes.update({"Out": Coordinate(outx, 0)}) # out_point return self.sizes
def snake(self, stdrt): ''' s -------------------- L ----- Y IN | OUT | | Dryer/Oven | | | W -------------------- f | | X ''' self.sizes = dict() l_straight = (self.L_work + 2 * (stdrt["minEntr"][1] + int(self.data['numAir']) * stdrt["airСurtain"][1])+\ 5*self.EF - float(self.data['Radius']) - stdrt["minBtwProducts"][1] - \ 3 * np.pi * float(self.data['Radius']))/4 totalLenght = l_straight + float(self.data['Radius']) + self.EF totalLenght = round(totalLenght * 2 + 499, -3) // 2 # кратно 500 self.sizes.update({"totalLenght": totalLenght}) width = self.unit_whl["w"]*2 + 2 * (stdrt["minWallEntr"][1] + stdrt["thicknessSandwich"][1]) + \ 4 * float(self.data['Radius']) + stdrt["minBtwProducts"][1] width = round(width + 99, -2) # кратно 100 minWidth = stdrt["minWidthElectro"][1] if self.data[ 'Электронагрев'] else stdrt["minWidth"][1] width = minWidth if width < minWidth else width # проверка на миним ширину self.sizes.update({"width": width}) inx = stdrt["minWallEntr"][1] + stdrt["thicknessSandwich"][ 1] + self.unit_whl["w"] / 2 outx = inx + self.unit_whl["w"] + stdrt["minBtwProducts"][1] self.sizes.update({"In": Coordinate(inx, 0)}) # in_point self.sizes.update({"Out": Coordinate(outx, 0)}) # out_point return self.sizes
def getBlocks_mm(self): nA, ahpp = self.ahppCalc() nD, dryers = self.dryerCalc() nO, ovens = self.polymerizCalc() for numD, dryer in enumerate(dryers): for numO, oven in enumerate(ovens): nameDryer = nD + str(numD) nameOven = nO + str(numO) package = { 1: [ ahpp['totalLenght'], ahpp['width'], nA, ahpp["In"], ahpp["Out"], nameDryer ], 2: [ dryer['totalLenght'], dryer['width'], nameDryer, dryer["In"], dryer["Out"], "Кабина" ], 3: [ 11500, 6800, "Кабина", Coordinate(3400, 0), Coordinate(3400, 11500), nameOven ], 4: [ oven['totalLenght'], oven['width'], nameOven, oven["In"], oven["Out"], "Зона Разгрузки" ], # TODO зона разгрузки и погрузки может быть объеденена (как в проекте Брендфорд). Спрашивать об этом можно на этапе задания параметров 5: [ 5000, 1000, "Зона Разгрузки", Coordinate(500, 0), Coordinate(500, 5000), "Зона Загрузки" ], 6: [ 5000, 1000, "Зона Загрузки", Coordinate(500, 0), Coordinate(500, 5000), nA ], } ''' package = { 1 : [ahpp['totalLenght'], ahpp['width'], nA, Coordinate(0, 0), Coordinate(0, 0), nameDryer], 2 : [dryer['totalLenght'], dryer['width'], nameDryer, Coordinate(0, 0), Coordinate(0, 0), "Кабина"], 3 : [11500, 6800, "Кабина", Coordinate(0, 0), Coordinate(0, 0), nameOven], 4 : [oven['totalLenght'], oven['width'], nameOven, Coordinate(0, 0), Coordinate(0, 0), "Зона Разгрузки"], # TODO зона разгрузки и погрузки может быть объеденена (как в проекте Брендфорд). Спрашивать об этом можно на этапе задания параметров 5 : [5000, 1000, "Зона Разгрузки", Coordinate(0, 0), Coordinate(0, 0), "Зона Загрузки"], 6 : [5000, 1000, "Зона Загрузки", Coordinate(0, 0), Coordinate(0, 0), nA], } ''' self.packages_mm.append(package)
def _getFinConv(self, conveyor): if len(conveyor[0]) == 0: return [] finConveyor = copy.deepcopy(conveyor[0]) offset = Coordinate(self.templates["CoordSys"][0], self.templates["CoordSys"][1]) for i in [1,2]: for f in self.data["Figures"]: if conveyor[i] == f.name: figure = f point = conveyor[0][0 if i == 1 else -1] print(point.x, point.y, point) point += offset print(point.x, point.y, point) break if i == 1: finConveyor.insert(0, self._getImaginaryCell(figure, point)) else: finConveyor.append(self._getImaginaryCell(figure, point)) return finConveyor
def get_blocks(self): self.getBlocks_mm() self.packages = copy.deepcopy( self.packages_mm) #копирование всех конфигураций с объектами for i, package in enumerate(self.packages): for key in package.keys(): for j, elem in enumerate(package[key]): if not isinstance(elem, str) and not isinstance( elem, Coordinate): self.packages[i][key][j] = int( round(elem / float(self.data['CellSize']))) if isinstance(elem, Coordinate): # здесь я округляю в меньшую сторону. Может случиться проблема при большом размере клетки. Тогда вход и выход будут одной клеткой. # TODO в будущем подумать над тем, чтобы задать конвейер не одной клеткой, а несколькими клетками. self.packages[i][key][j] = Coordinate( int( math.floor(elem.x / float(self.data['CellSize']))), int( math.floor(elem.y / float(self.data['CellSize']))))
def get(self, data): self.unit_whl = { "w": float(data["Ширина"]), "l": float(data['Длина']), "h": float(data['Высота']) } self.speed = float(data['Скорость конвейера']) self.sizes = dict() self.numOfBath = 0 # 2.1.1Входная зона self.sizes.update({ "entranceArea": int(round(self.unit_whl["l"] * 1.2 * 2, -2) // 2) }) # кратно 50 if self.sizes[ "entranceArea"] < 2000: # Чтобы округлить до 50, можно умножить на 2 и округлить до 100: self.sizes["entranceArea"] = 2000 # 2.1.2.Зона перехода # TODO добавить выбор зоны по 2 расчетам - либо по умножению, либо по времени 1 мин self.sizes.update({ "transitionArea": int(round(self.unit_whl["l"] * 1.25 * 2, -2) // 2) }) if self.sizes["transitionArea"] < 2000: self.sizes["transitionArea"] = 2000 # 2.1.3.Выходная зона # TODO добавить выбор зоны по 2 расчетам - либо по умножению, либо по времени 1 мин self.sizes.update( {"outputArea": int(round(self.unit_whl["l"] * 1.5 * 2, -1) // 2)}) if self.sizes["outputArea"] < 2000: self.sizes["outputArea"] = 2000 # 2.1.5.Ширина АХПП self.sizes.update({"width": self.unit_whl["w"] + 1000}) if self.sizes["width"] < 1200: self.sizes["width"] = 1200 # 2.1.6Высота АХПП self.sizes.update({"height": self.unit_whl["h"] + 900}) # Длинны ван for i in range( 6): # в baths хранятся исходные данные о продолжительности ТО curBath = "Ванна №" + str( i + 1) #текущй ключ к словарю данных data try: if data[curBath] == "" or float(data[curBath]) < 1: continue except ValueError: continue length = int(self.speed * (float(data[curBath]) / 60) * 1000) # V_конв * t * 1000мм if length < 600: length = 600 self.sizes.update({curBath: [float(data[curBath])]}) self.sizes[curBath].append(length) self.sizes[curBath].append(self.sizes["width"] + 750) self.numOfBath += 1 # self.sizes["1bath"] >>[150.0, 'сек', 'Обезжиривание', 7500, 2450.0] # 2.3. Расстояние от АХПП до печи сушки – # не менее 600 мм при параллельном расположении, # не менее 1000 мм при последовательном self.restrictionParalel = 600 self.restrictionSeqence = 1000 # 2.1.4.Длинна АХПП кратна self.totalLenght = (self.sizes["entranceArea"] + self.sizes["transitionArea"] * (self.numOfBath - 1) + self.sizes["outputArea"]) for i in range(self.numOfBath): curBath = "Ванна №" + str(i + 1) # текущй ключ к словарю self.size self.totalLenght += self.sizes[curBath][ 1] #прибавляем длинну каждой ванны self.sizes.update({"totalLenght": self.totalLenght}) #Расчет координат входа/выхода относительно start_point ''' s ----------------------------------- x ----- y | | IN AHPP OUT | | x ----------------------------------- f | | x ''' self.sizes.update({"In": Coordinate(self.sizes["width"] / 2, 0)}) # in_point self.sizes.update({ "Out": Coordinate(self.sizes["width"] / 2, self.sizes["totalLenght"]) }) # out_point return self.sizes
def _vertic(self, global_Cord): p1 = Coordinate(0, self.scale / 2) p2 = Coordinate(self.scale, self.scale / 2) x = global_Cord.x * self.scale y = global_Cord.y * self.scale return [["line", p1.x + x, p1.y + y, p2.x + x, p2.y + y]]
def _horiz(self, global_Cord): p1 = Coordinate(self.scale / 2, 0) p2 = Coordinate(self.scale / 2, self.scale) x = global_Cord.x * self.scale y = global_Cord.y * self.scale return [["line", p1.x + x, p1.y + y, p2.x + x, p2.y + y]]
height2 = 8660//gr + 1 # 3_Печь width3 = 24320//gr + 1 height3 = 4820//gr +1 # 4_Кабина width4 = 5000 // gr + 1 height4 = 5000//gr + 1 # 5_Зона Загрузки/Выгрузки width5 = 10000//gr + 1 height5 = 2 area = (700000//gr, 500000//gr) wid_hei_dict = { 1: [height1, width1, '1_АХПП', Coordinate(0, 0), Coordinate(height1 - 1, width1 + 1), '2_Печь'], 2: [height2, width2, '2_Печь', Coordinate(0, 0), Coordinate(height2 - 1, width2 + 1), '3_Печь_2'], 3: [height3, width3, '3_Печь_2', Coordinate(0, 0), Coordinate(height3 - 1, width3 + 1), '4_Кабина'], 4: [height4, width4, '4_Кабина', Coordinate(0, 0), Coordinate(height4 - 1, width4 + 1), '5_Зона Загрузки/Выгрузки'], 5: [height5, width5, '5_Зона Загрузки/Выгрузки', Coordinate(0, 0), Coordinate(0, width5 + 1), '6_Зона Загрузки/Выгрузки_2'], 6: [height5, width5, '6_Зона Загрузки/Выгрузки_2',Coordinate(0, 0), Coordinate(0, width5 + 1), '1_АХПП'], } X = [1, 3, 4, 5, 2, 6] Y = [3, 4, 1, 2, 5, 6] ''' wid_hei_dict = { 1: [height1, width1, '1_АХПП', Coordinate(0, 0), Coordinate(height1 - 1, width1 + 1), '2_Печь'], 2: [height2, width2, '2_Печь', Coordinate(0, 0), Coordinate(height2 - 1, width2 + 1), '3_Печь_2'], 3: [height3, width3, '3_Печь_2', Coordinate(0, 0), Coordinate(height3 - 1, width3 + 1), '4_Кабина'],