Esempio n. 1
0
def calculate_above(block: Block, blocks: List[Block]) -> Set[Block]:
    """
    Calculated which of a given blocks are strictly above this given sample block.
    :param block: a single block with a bottom level L
    :param block_state: A full dictionary of blocks organized by thier top levels

    X - Segment of initial block
    A - Above (Suportee) blocks
    N - Non above blocks

                    Front View      |            Side View     |          Top View
                    ----------------------------------------------------------------------
                        AAAAAA      |                A         |      NNNNNN
                    N    X   N      |       NNNNNN XXXXXX      |
                                    |                          |                A
                                    |                          |              XXAXXX
                                    |                          |                A
                                    |                          |              NNANNN

    :return: A list of 1 or more blocks that are strictly above the given block,
            or an empty list if no such blocks exist
    """
    supported = set()

    cells = block.get_cover_cells()
    for potential_supported_block in blocks:
        for cell in cells:
            # Check if this cell is above under a cell from another block
            if cell in potential_supported_block.get_cover_cells():
                supported.add(potential_supported_block)
                break
    return supported
Esempio n. 2
0
def calculate_below(block: Block, blocks: List[Block]) -> Set[Block]:
    """
    Calculated which of a given list of blocks are strictly under this given sample block.
    :param block: a single block with a bottom level L
    :param blocks: A list of blocks, all top level L-1

    X - Segment of initial block
    S - Support blocks
    N - Non support blocks

                    Front View      |            Side View     |          Top View
                    ----------------------------------------------------------------------
                        XXXXXX      |                X         |      NNNNNN
                    N    S   S      |       NNNNNN SSSSSS      |
                                    |                          |                X
                                    |                          |              SSXSSS
                                    |                          |                X
                                    |                          |              SSXSSS

    :return: A list of 1 or more blocks that are strictly under the given block,
            or an empty list if no such blocks exist
    """
    supports = set()

    cells = block.get_cover_cells()
    for potential_support in blocks:
        for cell in cells:
            # Check if this cell is above under a cell from another block
            if cell in potential_support.get_cover_cells():
                supports.add(potential_support)
                break
    return supports
Esempio n. 3
0
    def test_spread(self):
        tower_state = Tower_State()

        #same orientation
        orientation = 'tall_wide'
        block1 = Block(block_mesh, orientation, (0, 0, 0))
        block2 = Block(block_mesh, orientation, (2, 1, 0))

        spread = tower_state.get_spread(block1, block2)
        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        orientation = 'short_wide'
        block1 = Block(block_mesh, orientation, (0, 0, 0))
        block2 = Block(block_mesh, orientation, (5, 5, 0))

        spread = tower_state.get_spread(block1, block2)
        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        orientation = 'flat_thin'
        block1 = Block(block_mesh, orientation, ( 0,  0, 0))
        block2 = Block(block_mesh, orientation, (10, 10, 0))

        spread = tower_state.get_spread(block1, block2)
        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        # differing orientations - must have same top level
        block1 = Block(block_mesh, 'flat_wide', ( 0,  0, 0))
        block2 = Block(block_mesh, 'tall_thin', ( 5, 3, -7))

        spread = tower_state.get_spread(block1, block2)
        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        block1 = Block(block_mesh, 'flat_wide', ( 0,  0, 1))
        block2 = Block(block_mesh, 'short_thin', ( -10, 3, 0))

        spread = tower_state.get_spread(block1, block2)
        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)


        # test commutative quality of spread: ie. my spread with you is the same as yours spread with me.
        block1 = Block(block_mesh, 'flat_wide', ( 0,  0, 1))
        block2 = Block(block_mesh, 'short_thin', ( -15, 5, 0))

        spread1 = tower_state.get_spread(block1, block2)
        spread2 = tower_state.get_spread(block2, block1)

        self.assertEqual(spread1, spread2)

        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread1, spread2], scale=20)

        block1 = Block(block_mesh, (0, 0, 0), (0, 5, 1))
        block2 = Block(block_mesh, (0, 0, 0), (-2, -11, 1))
        block3 = Block(block_mesh, 'flat_wide', (-1, -6, 3))
        tower_state.set_blocks_above(block1, {block3})
        tower_state.set_blocks_above(block2, {block3})
        spread = tower_state.get_spread(block2, block1)

        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        block1 = Block(block_mesh, (0, 0, 0), (0, 9, 1))
        block2 = Block(block_mesh, (0, 0, 0), (-2, -13, 1))
        block3 = Block(block_mesh, 'flat_wide', (-1, -6, 3))
        tower_state.set_blocks_above(block1, {block3})
        tower_state.set_blocks_above(block2, {block3})
        spread = tower_state.get_spread(block2, block1)

        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)

        block1 = Block(block_mesh, 'short_thin', (-8, -1, 1))
        block2 = Block(block_mesh, 'short_thin', (7, 1, 1))
        block3 = Block(block_mesh, 'flat_wide', (0, 0, 3))
        tower_state.set_blocks_above(block1, {block3})
        tower_state.set_blocks_above(block2, {block3})
        spread = tower_state.get_spread(block2, block1)

        if DISPLAY:
            display([block1.render(), block2.render()])
            display_multiple_cells([block1.get_cells(), block2.get_cells()], scale=20)
            display_multiple_grids([block1.get_cover_cells(), block2.get_cover_cells(), spread], scale=20)
Esempio n. 4
0
    def get_spread(self, block1: Block, block2: Block):
        """
        Retrieves the space between two blocks that can support blocks above, should their center of gravity
        sit within them.
        Spread should only be calculated between blocks that have already been recognized as close enough to hold
        another block above them, otherwise behavior is not defined, or in the best case an assertion will fail.
        This is garanteed by only calling get_spread on blocks both directly under the same piece.
        Spread is commutative
        :param block1:
        :param block2:
        :return:
        """

        assert block1.get_top_level() == block2.get_top_level(
        ), str(block1) + str(block1.get_top_level()) + str(block2) + str(
            block2.get_top_level())

        # a spread with yourself it the cells you cover
        if block1 == block2:
            return block1.get_cover_cells()

        ordered_pair = (block1, block2) if block1 < block2 else (block2,
                                                                 block1)
        if ordered_pair in self._spreads_memory:  # shared with father
            return self._spreads_memory[ordered_pair]

        b1_cover_x = {cell[X] for cell in block1.get_cover_cells()}
        b2_cover_x = {cell[X] for cell in block2.get_cover_cells()}

        b1_cover_y = {cell[Y] for cell in block1.get_cover_cells()}
        b2_cover_y = {cell[Y] for cell in block2.get_cover_cells()}

        inter_x = b1_cover_x & b2_cover_x
        inter_y = b1_cover_y & b2_cover_y

        spread = set()
        spread |= block1.get_cover_cells()
        spread |= block2.get_cover_cells()
        if (inter_x):
            union_y = b1_cover_y | b2_cover_y
            min_y = int(min(union_y))
            max_y = int(max(union_y))
            for y in range(min_y, max_y + 1):
                for x in inter_x:
                    spread.add((x, y))

        elif (inter_y):
            union_x = b1_cover_x | b2_cover_x
            min_x = int(min(union_x))
            max_x = int(max(union_x))
            for x in range(min_x, max_x + 1):
                for y in inter_y:
                    spread.add((x, y))

        else:  # no common pieces - skew lines
            """
                                                    X                   XXXXXXX
            XXXXXXX                                 X                               X
                                            or              X       or              X
                    XXXXXXXX                                X                       X


            Relevant for flat pieces only.
            """
            pass
            # See if the candidate blocks above can help increase spread
            candidate_blocks = self.get_blocks_above(
                block1) & self.get_blocks_above(block2)

            if candidate_blocks:
                flat_block = candidate_blocks.pop()
                center_x, center_y, _ = tuple(flat_block.get_cog())
                skew_center = set()
                for cell in spread:
                    new_cell = ((cell[X] + center_x) // 2,
                                (cell[Y] + center_y) // 2)
                    skew_center.add(new_cell)
                spread |= skew_center

        self._spreads_memory[ordered_pair] = spread
        return spread