예제 #1
0
    def createAndAddNewGrid(self,
                            width,
                            article_name='default',
                            material='kokos',
                            brand='kokos',
                            color='naturel'):
        if self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 100:
            grid_height = 1230
        elif self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 200:
            grid_height = 605
        else:
            grid_height = 980

        try:
            grid = Grid(width=width,
                        height=grid_height,
                        article_name=article_name,
                        material=material,
                        name=self.grids[-1].getName() + 1,
                        brand=brand,
                        color=color,
                        stacked_rectangles=[])
            self.grids.append(grid)

            self.db_manager.addGrid(grid)
            print("Created and added new grid to database")

        except IndexError:
            grid = Grid(width=200, height=grid_height, name=1)
            self.grids.append(grid)
            self.db_manager.addGrid(grid)
            print("Created and added initial grid to database")
    def getGrid(self, grid_number, for_cutting=False):
        """ 
        Parameters 
        ----------
        for_cutting: get the rectangles with the exact sizes (in mm)
        """

        query = {"name": grid_number}

        cursor = self.grids_collection.find(query)
        for document in cursor:
            grid = Grid(width=document['width'],
                        height=document['height'],
                        article_name=document['article_name'],
                        brand=document['brand'],
                        material=document['material'],
                        color=document['color'],
                        name=document['name'],
                        is_cut=document['isCut'])
            if for_cutting == True:
                rectangles = self.getRectangles(grid, for_cutting)
            else:
                rectangles = self.getRectangles(grid)

            grid.setStackedRectangles(rectangles)

        return grid
    def getGridsCutByWidthBrandColor(self,
                                     width=100,
                                     brand='kokos',
                                     color='naturel'):
        grids = []
        query = {}
        if brand != 'all':
            query["brand"] = brand
        if color != 'all':
            query["color"] = color
        if grid_width != 'all':
            query["grid_width"] = grid_width

        cursor = self.grids_collection.find(query)
        for document in cursor:
            grid = Grid(width=document['width'],
                        height=document['height'],
                        article_name=document['article_name'],
                        material=document['material'],
                        brand=document['brand'],
                        color=document['color'],
                        name=document['name'],
                        is_cut=document['isCut'])
            rectangles = self.getRectangles(grid)
            grid.setStackedRectangles(rectangles)

            if grid.isCut():
                print("Loaded grid " + str(document["name"]) +
                      " from database")

                grids.append(grid)

        return grids
예제 #4
0
    def setUp(self):

        self.rectangle_4 = Rectangle(50, 80, 4)
        self.rectangle_5 = Rectangle(50, 80, 5)

        self.grid_1 = Grid(200, 1500, 1)
        self.grid_2 = Grid(100, 100, 2)
        self.grid_3 = Grid(100, 80, 3)
예제 #5
0
    def testIsValidPosition(self):
        self.grid_2 = Grid(100, 100, 2)

        self.rectangle_4.setPosition([25, 40])
        self.rectangle_5.setPosition([24, 40])

        self.grid_2.addRectangle(self.rectangle_4)
        self.assertFalse(self.grid_2.isValidPosition(self.rectangle_5))

        self.rectangle_5.setPosition([76, 40])
        self.assertFalse(self.grid_2.isValidPosition(self.rectangle_5))
    def getGridsNotFull(self, width=100, brand='kokos', color='naturel'):
        try:
            grids = []
            query = {"width": width, "brand": brand, "color": color}

            cursor = self.grids_collection.find(query)

            for document in cursor:
                print("Loaded grid " + str(document["name"]) +
                      " from database")
                grid = Grid(width=document['width'],
                            height=document['height'],
                            article_name=document['article_name'],
                            material=document['material'],
                            brand=document['brand'],
                            color=document['color'],
                            name=document['name'],
                            is_cut=document['isCut'])
                rectangles = self.getRectangles(grid)
                grid.setStackedRectangles(rectangles)

                grid.checkAndSetFull()
                if not grid.isFull():
                    grids.append(grid)
        except:
            pass

        return grids
    def getGridsNotCut(self, sort=False):
        grids = []

        cursor = self.grids_collection.find({})
        for document in cursor:
            print("getGridsNotCut material = " + str(document['material']))
            grid = Grid(width=document['width'],
                        height=document['height'],
                        name=document['name'],
                        article_name=document['article_name'],
                        material=document['material'],
                        color=document['color'],
                        brand=document['brand'],
                        is_cut=document['isCut'])
            rectangles = self.getRectangles(grid)
            grid.setStackedRectangles(rectangles)

            if not grid.isCut():
                print("Loaded grid " + str(document["name"]) +
                      " from database")
                grids.append(grid)

        if sort == True:
            grids = sorted(grids, key=lambda g: g.getWidth(), reverse=True)

        print("Grid widths are " + str([grid.getWidth() for grid in grids]))
        print("Grid heights are " + str([grid.getHeight() for grid in grids]))

        return grids
예제 #8
0
    def __init__(self, data_logger=DataLogger()):
        self.db_manager = DatabaseManager()
        self.setStandardSizesToFill([])
        self.setFillOrdersWithSmallerGridWidths(False)

        self.rectangles = []
        self.is_stacking = False

        # current rectangle to stack in current grid
        self.rectangle = Rectangle()
        self.grid = Grid()
        self.setDataLogger(data_logger)

        # stacking position of current rectangle
        self.stacking_position = []

        # stacking position of current rectangle rotated
        self.stacking_position_rotated = []
    def getAllGrids(self):
        grids = []
        cursor = self.grids_collection.find({})

        for document in cursor:
            print("Loaded grid " + str(document["name"]) + " from database")
            grid = Grid(width=document['width'],
                        height=document['height'],
                        article_name=document['article_name'],
                        brand=document['brand'],
                        material=document['material'],
                        color=document['color'],
                        name=document['name'],
                        is_cut=document['isCut'])
            rectangles = self.getRectangles(grid)
            grid.setStackedRectangles(rectangles)
            grids.append(grid)

        return grids
예제 #10
0
class GridTest(unittest.TestCase):
    def setUp(self):

        self.rectangle_4 = Rectangle(50, 80, 4)
        self.rectangle_5 = Rectangle(50, 80, 5)

        self.grid_1 = Grid(200, 1500, 1)
        self.grid_2 = Grid(100, 100, 2)
        self.grid_3 = Grid(100, 80, 3)

    def tearDown(self):
        pass

    def testIsOutOfGrid(self):
        self.rectangle_4.setPosition([25, 40])
        self.assertFalse(self.grid_2.isOutOfGrid(self.rectangle_4))
        self.grid_2.addRectangle(self.rectangle_4)

        self.rectangle_5.setPosition([75, 40])
        self.assertFalse(self.grid_2.isOutOfGrid(self.rectangle_5))

        self.rectangle_5.setPosition([76, 40])
        self.assertTrue(self.grid_2.isOutOfGrid(self.rectangle_5))

        self.rectangle_5.setPosition([75, 40])
        self.assertFalse(self.grid_3.isOutOfGrid(self.rectangle_5))

        self.rectangle_5.setPosition([75, 41])
        self.assertTrue(self.grid_3.isOutOfGrid(self.rectangle_5))

    def testIsValidPosition(self):
        self.grid_2 = Grid(100, 100, 2)

        self.rectangle_4.setPosition([25, 40])
        self.rectangle_5.setPosition([24, 40])

        self.grid_2.addRectangle(self.rectangle_4)
        self.assertFalse(self.grid_2.isValidPosition(self.rectangle_5))

        self.rectangle_5.setPosition([76, 40])
        self.assertFalse(self.grid_2.isValidPosition(self.rectangle_5))
예제 #11
0
class Stacker(object):
    """
    Contains the algorithm for stacking rectangles in a grid in 2D. The rectangles are first sorted at centimeter accuracy. First the rectangles are sorted
    using in descending order based on the area, after which they are stacked to the most lower left position. After that the rectangles are shrunken to their exact
    millimeter size and moved left and downwards until they cannot be moved further. The result is a millimeter accuracy stacked grid.
    """
    def __init__(self, data_logger=DataLogger()):
        self.db_manager = DatabaseManager()
        self.setStandardSizesToFill([])
        self.setFillOrdersWithSmallerGridWidths(False)

        self.rectangles = []
        self.is_stacking = False

        # current rectangle to stack in current grid
        self.rectangle = Rectangle()
        self.grid = Grid()
        self.setDataLogger(data_logger)

        # stacking position of current rectangle
        self.stacking_position = []

        # stacking position of current rectangle rotated
        self.stacking_position_rotated = []

    def setDataLogger(self, data_logger):
        self.data_logger = data_logger

    def getDataLogger(self):
        return self.data_logger

    def setRectangle(self, rectangle):
        self.rectangle = rectangle

    def setExcelParser(self, path, file_name):
        self.excel_parser = ExcelParser(data_logger=self.data_logger,
                                        path=path,
                                        file_name=file_name)

    def stackingStopped(self):
        return not self.is_stacking

    def startStacking(self):
        self.is_stacking = True

    def stopStacking(self):
        self.is_stacking = False

    def setGrid(self, grid):
        print("Set grid to " + str(grid.getName()))
        self.grid = grid

    def getGrid(self):
        return self.grid

    def setStandardSizesToFill(self, sizes):
        self.standard_sizes_to_fill = sizes

    def getStandardSizesToFill(self):
        return self.standard_sizes_to_fill

    def setFillOrdersWithSmallerGridWidths(self, should_be_filled):
        self.fill_orders_with_smaller_grid_widths = should_be_filled

    def getFillSmallerGridWidths(self):
        return self.fill_smaller_grid_widths

    def getUnstackedRectangles(self):
        return [
            rectangle for rectangle in self.rectangles
            if not rectangle.isStacked()
        ]

    def setCoupage(self, coupage):
        self.coupage = coupage

    def getCoupage(self):
        return self.coupage

    def start(self, automatic=True):
        """ 
        Starts stacking the current unstacked rectangles from database in self.grid

        Parameters
        -----------
        automatic: Automatically create grids when not available and stack all unstacked rectangles in these grids (loop over all the grids instead of only self.grid)
        When automatic is false, the user should manually set a grid to be used for stacking.
        """

        self.start_time = time.time()
        self.getAndExportCoupages()
        self.is_stacking = True
        # self.loadOrdersAndAddToDatabase()

        self.getAllUnstackedRectanglesFromDatabaseAndSortOnArea()
        total_amount_of_unstacked_rectangles = len(
            self.getUnstackedRectangles())

        while self.anyUnstackedRectangles() and not self.stackingStopped():
            if automatic:
                self.createGridInDatabaseIfNotAvailable()
                self.grids = self.db_manager.getGridsNotCut(sort=True)
            else:
                self.grids = []
                self.grids.append(self.grid)

            for grid in self.grids:
                self.rectangles = []
                self.setGrid(grid)
                self.getUnstackedRectanglesFromDatabaseMatchingAllGridPropertiesSortedOnArea(
                )
                self.stackUnstackedRectanglesInGrid()

                # some grids are empty and should not be exported
                if not grid.isEmpty() and len(
                        self.getUnstackedRectangles()) == 0:
                    if self.fill_orders_with_smaller_grid_widths:
                        self.shrinkGridToHeighestVerticalStackedPoint()
                        self.stackOrdersWithSmallerGridWidths()

                    if len(self.standard_sizes_to_fill
                           ) > 0 and self.grid.getBrand().lower() == "kokos":
                        self.shrinkGridToHeighestVerticalStackedPoint()
                        self.stackStandardRectangles()

                    self.enlargeGridToStandardSize()

                # break out of loop when operator presses stop button
                if self.stackingStopped():
                    break

            self.getAllUnstackedRectanglesFromDatabaseAndSortOnArea()

        self.optimizeOnMillimetersAndExportNonEmptyGrids()
        self.total_time = time.time() - self.start_time
        self.data_logger.setTotalExecutionTime(self.total_time)
        self.data_logger.setSuccessfullyStackedRectangles(
            total_amount_of_unstacked_rectangles)
        self.data_logger.storeData()

    def optimizeOnMillimetersAndExportNonEmptyGrids(self):
        self.grids = self.db_manager.getGridsNotCut(sort=True)
        for grid in self.grids:
            if not grid.isEmpty():
                self.setGrid(grid)
                self.convertRectanglesToMillimetersOptimizeAndExportGrid()

    def stackOrdersWithSmallerGridWidths(self):
        self.getUnstackedRectanglesOfAllSmallerGridWidthsThanOriginalSortedOnArea(
        )
        self.stackUnstackedRectanglesInGrid()

    def shrinkGridToHeighestVerticalStackedPoint(self):
        # set height to heighest point because we only want to stack in the gaps
        # of the stack, not add more at the top
        self.grid.setHeight(self.grid.getHighestVerticalPoint())
        self.db_manager.updateGrid(self.grid)

    def enlargeGridToStandardSize(self):
        if self.grid.getBrand().lower() == 'kokos' and self.grid.getWidth(
        ) == 100:
            grid_height = 1230
        elif self.grid.getBrand().lower() == 'kokos' and self.grid.getWidth(
        ) == 200:
            grid_height = 605
        else:
            grid_height = 980

        self.grid.setHeight(grid_height)
        self.db_manager.updateGrid(self.grid)

    def getUncutAreasOfGrids(self):
        grids = self.db_manager.getGridsNotCut()
        result = []

        for grid in grids:
            if not grid.isEmpty():
                result.append(grid.getUncutArea())

        return result

    def getAndExportCoupages(self):
        coupages = self.db_manager.getUnstackedRectangles(
            for_cutting=True, coupage_batch="coupage")
        for coupage in coupages:
            self.setCoupage(coupage)
            self.rotateCoupageToLargestSideUpwards()
            self.exportAndUpdateCoupage()

    def rotateCoupageToLargestSideUpwards(self):
        _width = self.coupage.getWidth()
        _height = self.coupage.getHeight()

        if _width > _height:
            print("Coupage width is larger than height")
            width, height = Helper.swap(_width, _height)
            print("Width before swap = " + str(self.coupage.getWidth()))
            self.coupage.setWidth(width)
            self.coupage.setHeight(height)
            print("Width after swap = " + str(self.coupage.getWidth()))
            self.db_manager.updateRectangle(self.coupage)

    def exportAndUpdateCoupage(self):
        self.coupage.toDxf(for_prime_center=True)
        self.coupage.toZcc()
        self.coupage.setStacked()
        self.db_manager.updateRectangle(self.coupage)

    def loadOrdersAndAddToDatabase(self):
        try:
            self.rectangles = self.excel_parser.getUnstackedRectangles()
            self.db_manager.addRectangles(self.rectangles)
        except EmptyExcelError:
            print("Excel file is empty!")

    def computeRectangleOrderArea(self, rectangles):
        areas = [x.getArea() for x in rectangles]
        indices_descending_order = sorted(range(len(areas)),
                                          key=lambda k: areas[k])
        rectangles_descending_area_order = []
        for idx in indices_descending_order:
            rectangles_descending_area_order.append(rectangles[idx])

        return list(reversed(rectangles_descending_area_order))

    def stackStandardRectangles(
        self, sizes=Rectangle.getStandardSizesSortedOnMostSold()):
        print("Try stacking standard rectangles")

        for size in self.standard_sizes_to_fill:
            while True:

                if not self.stackingStopped():
                    rectangle = Rectangle(
                        width=size[0],
                        height=size[1],
                        client_name="Voorraad_" + str(size[0]) + "x" +
                        str(size[1]) + "_" + str(uuid.uuid4())[-4:],
                        name="Voorraad_" + str(size[0]) + "x" + str(size[1]) +
                        "_" + str(uuid.uuid4())[-4:],
                        grid_width=self.grid.getWidth(),
                        brand=self.grid.getBrand(),
                        color=self.grid.getColor())

                    self.db_manager.addRectangle(rectangle)
                    self.setRectangle(rectangle)

                    try:
                        print("Grid height = " + str(self.grid.getHeight()))
                        self.stackOriginalOrRotatedRectangleAndUpdateDatabase()
                    except RotatedAndOriginalRectangleDoNotFitError:
                        self.db_manager.removeRectangle(rectangle)
                        break

                else:
                    break

    def getUnstackedRectanglesOfAllSmallerGridWidthsThanOriginalSortedOnArea(
            self):
        self.rectangles = []

        unstacked_rectangles = self.db_manager.getUnstackedRectangles(
            color=self.grid.getColor(),
            brand=self.grid.getBrand(),
            for_cutting=True)

        for rectangle in unstacked_rectangles:
            if rectangle.getGridWidth() <= self.grid.getWidth():
                self.rectangles.append(rectangle)

        self.rectangles = self.computeRectangleOrderArea(self.rectangles)
        for rectangle in self.rectangles:
            rectangle.roundWidth()
            rectangle.roundHeight()

    def anyUnstackedRectangles(self):
        return len(self.getUnstackedRectangles()) > 0

    def createGridInDatabaseIfNotAvailable(self):
        for rectangle in self.rectangles:

            if not self.isGridAvailable(rectangle):
                print("Grid not available")
                print("Create unique grid with material " +
                      str(rectangle.getMaterial()))
                print("Create unique grid with article name " +
                      str(rectangle.getArticleName()))

                if rectangle.getBrand().lower(
                ) == 'kokos' and rectangle.getGridWidth() == 100:
                    grid_height = 1230
                elif rectangle.getBrand().lower(
                ) == 'kokos' and rectangle.getGridWidth() == 200:
                    grid_height = 605
                else:
                    grid_height = 980

                self.db_manager.createUniqueGrid(
                    width=rectangle.getGridWidth(),
                    height=grid_height,
                    article_name=rectangle.getArticleName(),
                    material=rectangle.getMaterial(),
                    color=rectangle.getColor(),
                    brand=rectangle.getBrand())

    def getUnstackedRectanglesFromDatabaseMatchingAllGridPropertiesSortedOnArea(
            self):
        self.rectangles = self.db_manager.getUnstackedRectangles(
            color=self.grid.getColor(),
            brand=self.grid.getBrand(),
            grid_width=self.grid.getWidth(),
            for_cutting=True)

        self.rectangles = self.computeRectangleOrderArea(self.rectangles)
        for rectangle in self.rectangles:
            rectangle.roundWidth()
            rectangle.roundHeight()

    def getUnstackedRectanglesFromDatabaseMatchingGridColorBrandSortedOnArea(
            self):
        self.rectangles = self.db_manager.getUnstackedRectangles(
            color=self.grid.getColor(),
            brand=self.grid.getBrand(),
            for_cutting=True)

        self.rectangles = self.computeRectangleOrderArea(self.rectangles)
        for rectangle in self.rectangles:
            rectangle.roundWidth()
            rectangle.roundHeight()

    def getAllUnstackedRectanglesFromDatabaseAndSortOnArea(self):
        self.rectangles = self.db_manager.getUnstackedRectangles(
            for_cutting=True)
        self.rectangles = self.computeRectangleOrderArea(self.rectangles)
        for rectangle in self.rectangles:
            rectangle.roundWidth()
            rectangle.roundHeight()

    def isGridAvailable(self, rectangle):
        grid_width = rectangle.getGridWidth()
        color = rectangle.getColor()
        brand = rectangle.getBrand()

        print("Is grid available?")
        print("Color: " + rectangle.getColor())
        print("Brand: " + rectangle.getBrand())
        return len(
            self.db_manager.getGridsNotCutByWidthBrandColor(
                width=grid_width, color=color, brand=brand)) > 0

    def rectangleAndGridPropertiesMatch(self):
        return (self.grid.getBrand() == self.rectangle.getBrand()) and (
            self.grid.getColor() == self.rectangle.getColor())

    def createNewGridAndStackRectangle(self):

        if self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 100:
            grid_height = 1230
        elif self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 200:
            grid_height = 605
        else:
            grid_height = 980

        new_grid = self.db_manager.createUniqueGrid(
            width=self.rectangle.getGridWidth(),
            height=grid_height,
            article_name=self.rectangle.getArticleName(),
            material=self.rectangle.getMaterial(),
            brand=self.rectangle.getBrand(),
            color=self.rectangle.getColor())

        self.setGrid(new_grid)

        # for some reason new_grid starts out filled in an iteration
        self.db_manager.emptyGrid(new_grid)

        try:
            self.stackOriginalOrRotatedRectangleAndUpdateDatabase()

        except RotatedAndOriginalRectangleDoNotFitError:
            print(
                "Something went wrong, rectangle does not fit in completely new grid"
            )

    def convertRectanglesToMillimetersOptimizeAndExportGrid(self):
        print("Optimizing grid " + str(self.grid.getName()) +
              " and exporting to DXF...")
        self.getRectanglesExactWidthHeight()

        self.grid.empty()

        # size to move rectangles in x and y direction
        step_size = 0.001

        for exact_rectangle in self.exact_rectangles:

            print("Optimizing " + str(exact_rectangle.getName()) + '.....')
            self.is_optimized_x = False
            self.is_optimized_y = False

            # copy needed because otherwise variables have the same address
            self.optimized_rectangle = copy.deepcopy(exact_rectangle)

            while not self.is_optimized_x:
                self.moveRectangleHorizontally(step_size)

            while not self.is_optimized_y:
                self.moveRectangleVertically(step_size)

            self.db_manager.updateRectangle(self.optimized_rectangle)
            self.grid.addRectangle(self.optimized_rectangle)

        self.grid.toDxf(for_prime_center=True, remove_overlap=True)
        self.grid.toZcc()

    def getRectanglesExactWidthHeight(self):
        self.exact_rectangles = self.db_manager.getRectangles(self.grid,
                                                              for_cutting=True,
                                                              sort=True)
        # self.grid.setStackedRectangles(self.exact_rectangles)

    def moveRectangleHorizontally(self, step_size):
        self.grid.removeRectangle(self.optimized_rectangle)

        x = self.optimized_rectangle.getPosition()[0]
        y = self.optimized_rectangle.getPosition()[1]

        x_new = x - step_size

        self.optimized_rectangle.setPosition([x_new, y])

        if not self.grid.isValidPosition(self.optimized_rectangle):
            print("Cannot optimize further in x direction")
            self.optimized_rectangle.setPosition([x, y])
            print(self.optimized_rectangle)
            self.is_optimized_x = True
        else:
            pass
            # move x to x_new

    def moveRectangleVertically(self, step_size):
        self.grid.removeRectangle(self.optimized_rectangle)

        x = self.optimized_rectangle.getPosition()[0]
        y = self.optimized_rectangle.getPosition()[1]

        y_new = y - step_size

        self.optimized_rectangle.setPosition([x, y_new])

        if not self.grid.isValidPosition(self.optimized_rectangle):
            print("Cannot optimize further in y direction")
            self.optimized_rectangle.setPosition([x, y])
            self.is_optimized_y = True
        else:
            pass
            # move y to y_new

    def createAndAddNewGrid(self,
                            width,
                            article_name='default',
                            material='kokos',
                            brand='kokos',
                            color='naturel'):
        if self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 100:
            grid_height = 1230
        elif self.rectangle.getBrand().lower(
        ) == 'kokos' and self.rectangle.getGridWidth() == 200:
            grid_height = 605
        else:
            grid_height = 980

        try:
            grid = Grid(width=width,
                        height=grid_height,
                        article_name=article_name,
                        material=material,
                        name=self.grids[-1].getName() + 1,
                        brand=brand,
                        color=color,
                        stacked_rectangles=[])
            self.grids.append(grid)

            self.db_manager.addGrid(grid)
            print("Created and added new grid to database")

        except IndexError:
            grid = Grid(width=200, height=grid_height, name=1)
            self.grids.append(grid)
            self.db_manager.addGrid(grid)
            print("Created and added initial grid to database")

    def stackUnstackedRectanglesInGrid(self, smaller=False):
        for rectangle in self.rectangles:
            self.setRectangle(rectangle)

            if self.rectangleAndGridPropertiesMatch(
            ) and not rectangle.isStacked():
                try:
                    self.stackOriginalOrRotatedRectangleAndUpdateDatabase()
                except RotatedAndOriginalRectangleDoNotFitError:
                    print("Both rotated and original do not fit in grid")
                    self.createNewGridAndStackRectangle()
                    continue

                # stop the loop if user presses stop button
                if self.stackingStopped():
                    break

    def stackOriginalOrRotatedRectangleAndUpdateDatabase(self):
        self.chooseOriginalOrRotatedRectangle()
        self.updateUnstackedRectangleInDatabase()

    def chooseOriginalOrRotatedRectangle(self):
        try:
            self.computeRotatedRectangleStackingPosition()
        except RectangleDoesNotFitError:
            print("Rotated rectangle does not fit")
            pass

        try:
            self.computeOriginalRectangleStackingPosition()
        except RectangleDoesNotFitError:
            print("Original rectangle does not fit")
            pass

        if self.isRotatedRectangleMoreOptimal():
            self.updateStackingPositionToRotatedInDatabase()

        if self.stacking_position_rotated[0] == self.grid.getWidth(
        ) and self.stacking_position_rotated[1] == self.grid.getHeight():
            if self.stacking_position[0] == self.grid.getWidth(
            ) and self.stacking_position[1] == self.grid.getHeight():
                raise RotatedAndOriginalRectangleDoNotFitError

    def computeRotatedRectangleStackingPosition(self):
        print("Computing stacking position for rotated rectangle " +
              str(self.rectangle.getName()))

        self.rectangle.rotate()
        self.stacking_position_rotated = self.computeStackingPosition()
        self.rectangle.rotate()

        if self.stacking_position_rotated[0] == self.grid.getWidth(
        ) and self.stacking_position_rotated[1] == self.grid.getHeight():
            raise RectangleDoesNotFitError

    def computeOriginalRectangleStackingPosition(self):
        print("Computing stacking position for original rectangle " +
              str(self.rectangle.getName()))

        self.stacking_position = self.computeStackingPosition()

        if self.stacking_position[0] == self.grid.getWidth(
        ) and self.stacking_position[1] == self.grid.getHeight():
            raise RectangleDoesNotFitError

    def isRotatedRectangleMoreOptimal(self):
        return np.linalg.norm(self.stacking_position_rotated) < np.linalg.norm(
            self.stacking_position)

    def updateStackingPositionToRotatedInDatabase(self):
        self.rectangle.rotate()
        self.stacking_position = copy.deepcopy(self.stacking_position_rotated)

        # get exact width height to update database correctly
        # rotate this rectangle
        rectangle_exact = self.db_manager.getRectangle(
            self.rectangle.getName(), for_cutting=True)
        rectangle_exact.rotate()
        self.db_manager.updateRectangle(rectangle_exact)

    def updateUnstackedRectangleInDatabase(self):
        self.rectangle.setPosition(self.stacking_position)
        self.rectangle.setStacked()
        self.rectangle.setGridNumber(self.grid.getName())

        # get exact rectangle width and height
        rectangle_exact = self.db_manager.getRectangle(
            self.rectangle.getName(), for_cutting=True)

        width_exact = rectangle_exact.getWidth()
        height_exact = rectangle_exact.getHeight()

        # check if rectangle was rotated in start function
        w = int(np.ceil(width_exact))
        # if w % 2 > 0:
        #     w += 1

        if w == self.rectangle.getHeight():
            t = height_exact
            height_exact = width_exact
            width_exact = t

        # set rectangle width height back to the exact ones
        self.rectangle.setWidth(width_exact)
        self.rectangle.setHeight(height_exact)

        for rectangle in self.rectangles:
            if rectangle.getName() == self.rectangle.getName():
                rectangle.setStacked()

        self.grid.addRectangle(self.rectangle)
        self.db_manager.updateRectangle(self.rectangle)

        self.db_manager.updateGrid(self.grid)

    def computeStackingPosition(self):
        stacking_position = [self.grid.getWidth(), self.grid.getHeight()]

        if self.grid.getWidth() > self.rectangle.getWidth():
            for x in self.getHorizontalLoopRange():
                for y in self.getVerticalLoopRange():
                    position = np.array([x, y])
                    self.rectangle.setPosition(position)
                    if self.grid.isValidPosition(
                            self.rectangle) and np.linalg.norm(
                                position) < np.linalg.norm(stacking_position):
                        stacking_position = position

        elif self.grid.getWidth() == self.rectangle.getWidth():
            x = self.rectangle.getWidth() / 2
            for y in self.getVerticalLoopRange():
                position = np.array([x, y])
                self.rectangle.setPosition(position)
                if self.grid.isValidPosition(
                        self.rectangle) and np.linalg.norm(
                            position) < np.linalg.norm(stacking_position):
                    stacking_position = position

        return stacking_position

    def getHorizontalLoopRange(self):
        if self.rectangle.getWidth() % 2 > 0:
            width = self.rectangle.getWidth() + 1
        else:
            width = self.rectangle.getWidth()

        return reversed(
            range(int(width / 2),
                  int(self.grid.getWidth() - width / 2) + 1))

    def getVerticalLoopRange(self):
        if self.rectangle.getHeight() % 2 > 0:
            height = self.rectangle.getHeight() + 1
        else:
            height = self.rectangle.getHeight()

        return reversed(
            range(int(height / 2),
                  int(self.grid.getHeight() - height / 2) + 1))
    def createUniqueGrid(self,
                         width,
                         height=None,
                         article_name='',
                         material='kokos',
                         brand='kokos',
                         color='naturel'):

        brand_lower_case = brand.lower()
        material_lower_case = material.lower()

        # only do this when the height is not specified
        if height == None:
            if brand_lower_case == 'kokos' and width == 100:
                height = 1225
            elif brand_lower_case == 'kokos' and width == 200:
                height = 600

            # ambiant except lobby
            elif brand_lower_case == 'ambiant' and material_lower_case.split(
            )[1] != 'lobby' and width == 123:
                height = 975
            elif brand_lower_case == 'ambiant' and material_lower_case.split(
            )[1] != 'lobby' and width == 193:
                height = 600

            # ambiant lobby
            elif brand_lower_case == 'ambiant' and material_lower_case.split(
            )[1] == 'lobby' and width == 123:
                height = 975
            elif brand_lower_case == 'ambiant' and material_lower_case.split(
            )[1] == 'lobby' and width == 200:
                height = 600

            # forbo
            elif brand_lower_case.split()[0] == 'forbo' and width == 98:
                height = 975
            elif brand_lower_case.split()[0] == 'forbo' and width == 148:
                height = 975
            elif brand_lower_case.split()[0] == 'forbo' and width == 198:
                height = 600

            # zeno protect
            elif brand_lower_case.split()[0] == 'zeno' and width == 98:
                height = 975
            elif brand_lower_case.split()[0] == 'zeno' and width == 198:
                height = 600

            # ondervloer
            elif brand_lower_case == 'ondervloer 5 mm' and width == 135:
                height = 700
            elif brand_lower_case == 'ondervloer 3,6 mm' and width == 130:
                height = 1100

            elif brand_lower_case.split()[0] == 'squid' and width == 137:
                height = 1500

            # TODO: might want to throw an exception here
            else:
                height = 980

        try:
            used_names = self.listUsedGridNames()
            sorted_names = sorted(used_names)
            unique_name = int(sorted_names[-1] + 1)
            print("Creating unique grid with number: " + str(unique_name))
            grid = Grid(width=width,
                        height=height,
                        name=unique_name,
                        article_name=article_name,
                        material=material,
                        brand=brand,
                        color=color)
            self.addGrid(grid)

        except IndexError:
            print("No grids available yet")
            print("Creating first grid")

            grid = Grid(width=width,
                        height=height,
                        name=1,
                        article_name=article_name,
                        material=material,
                        brand=brand,
                        color=color)
            print(grid.color)
            print(grid.brand)
            self.addGrid(grid)

        return grid
예제 #13
0
from rectangle_packing.grid import Grid
from rectangle_packing.stacker import Stacker
from rectangle_packing.rectangle import Rectangle
from rectangle_packing.excel_parser import ExcelParser
from rectangle_packing.database_manager import DatabaseManager

import cProfile

if __name__ == "__main__":
    stacker = Stacker()
    excel_parser = ExcelParser("./example/paklijsten/", "paklijst.xlsx")
    grid = Grid(name="0",
                width=130,
                height=1500,
                brand="Ambiant",
                color="2400.0205")
    grid.setDxfDrawing("./example/grids/", "example.dxf")
    db_manager = DatabaseManager()

    prof = cProfile.Profile()

    db_manager.clearDatabase()
    rectangles = excel_parser.getUnstackedRectangles()
    db_manager.addRectangles(rectangles)
    stacker.setGrid(grid)

    prof.enable()
    stacker.start(automatic=False)
    prof.disable()

    prof.print_stats()