def rotatedFilledCells(self, angle):
        half_size_x = self.block_size_x // 2
        half_size_y = self.block_size_y // 2

        corners = [(0, 0)] * 4

        # Top left, top right, bottom right, bottom left (clockwise ordering of points)
        # Corners of the block centered at 0,0
        corners[0] = (-half_size_x, -half_size_y)
        corners[1] = (half_size_x, -half_size_y)
        corners[2] = (half_size_x, half_size_y)
        corners[3] = (-half_size_x, half_size_y)

        for i in range(4):
            x, y = corners[i]
            rotated_x = x * math.cos(angle) + y * math.sin(angle)
            rotated_y = -x * math.sin(angle) + y * math.cos(angle)
            corners[i] = (int(round(rotated_x, 0)), int(round(rotated_y, 0)))

        # Add bounding polygon cells to a set
        cells = set()
        cells.update(raytrace(*corners[0], *corners[1]))
        cells.update(raytrace(*corners[3], *corners[2]))
        cells.update(raytrace(*corners[0], *corners[3]))
        cells.update(raytrace(*corners[1], *corners[2]))

        # breadth first search from 0,0 the remaining cells
        bfs = deque([(0, 0)])
        while len(bfs) > 0:
            current_cell = bfs.popleft()

            # If previously visited then skip
            if current_cell in cells:
                continue
            else:
                cells.add(current_cell)

            # Search the neighbours
            for nbr in [(current_cell[0] + 1, current_cell[1]),
                        (current_cell[0] - 1, current_cell[1]),
                        (current_cell[0], current_cell[1] + 1),
                        (current_cell[0], current_cell[1] - 1)]:
                if nbr not in cells:
                    bfs.append(nbr)

        # DEBUGGING
        # longest_edge = max(self.block_size_x, block_size_y)
        # test = np.zeros((30, 30))
        # for i,j in cells:
        #   x = i + 15
        #   y = j + 15
        #   print(x,y)
        #   test[x, y] = 1

        # plt.imshow(test)
        # plt.show()

        return list(cells)
Esempio n. 2
0
    def rotatedFilledCells(self, angle, size_x=None, size_y=None):

        if size_x is None and size_y is None:
            half_size_x = self.block_size_x // 2
            half_size_y = self.block_size_y // 2
        else:
            half_size_x = size_x // 2
            half_size_y = size_y // 2

        corners = [(0, 0)] * 4

        # Top left, top right, bottom right, bottom left (clockwise ordering of points)
        # Corners of the block centered at 0,0
        corners[0] = (-half_size_x, -half_size_y)
        corners[1] = (half_size_x, -half_size_y)
        corners[2] = (half_size_x, half_size_y)
        corners[3] = (-half_size_x, half_size_y)

        for i in range(4):
            x, y = corners[i]
            rotated_x = x * math.cos(angle) - y * math.sin(angle)
            rotated_y = x * math.sin(angle) + y * math.cos(angle)
            # print(rotated_x, rotated_y)
            corners[i] = (int(round(rotated_x, 0)), int(round(rotated_y, 0)))

        cells = set()

        cells.update(raytrace(*corners[0], *corners[1]))
        cells.update(raytrace(*corners[3], *corners[2]))
        cells.update(raytrace(*corners[0], *corners[3]))
        cells.update(raytrace(*corners[1], *corners[2]))

        # breadth first search from 0,0 the remaining cells
        bfs = deque([(0, 0)])
        while len(bfs) > 0:
            current_cell = bfs.popleft()

            # If previously visited then skip
            if current_cell in cells:
                continue
            else:
                cells.add(current_cell)

            # Search the neighbours
            for nbr in [(current_cell[0] + 1, current_cell[1]),
                        (current_cell[0] - 1, current_cell[1]),
                        (current_cell[0], current_cell[1] + 1),
                        (current_cell[0], current_cell[1] - 1)]:
                if nbr not in cells:
                    bfs.append(nbr)

        return list(cells)
Esempio n. 3
0
    def process_path(self, path):
        final_path = []

        prev_pos_x, prev_pos_y, prev_layer = path[0]
        prev_pos = (prev_pos_x, prev_pos_y)
        for pos_x, pos_y, layer in path:
            pos = (pos_x, pos_y)

            # Check if we need to interpolate between two points
            if abs(pos[0] - prev_pos[0]) > 1 or abs(pos[1] - prev_pos[1]) > 1:
                layer_at_cell = self.interpolatePath(prev_pos, prev_layer, pos,
                                                     layer)

                assert layer_at_cell != None, "Could not find an intermediate path"

                cells = raytrace(*prev_pos, *pos)

                for c in cells:
                    final_path.append((*c, layer_at_cell[c]))
            else:
                final_path.append((*pos, layer))

            prev_pos = pos
            prev_layer = layer

        return final_path
Esempio n. 4
0
  def endLayer(self, current_pos, current_layer, goal_pos):
    # Need to check if we can move from current pos to goal pos
    # In order for two adjacent cells to be pathable
    # the cells must have an unoccupied layer 1 shift apart

    # Thus for a path to be valid all adjacent cells must satisfy the above

    # No possible orientations can be reached at goal
    if self.oriented_occ_grid[goal_pos] == 255:
      return None

    # Get the direct path from current to goal
    traversed_cells = raytrace(*current_pos, *goal_pos)

    # Create this structure so we can efficiently get the next cell
    next_cell = dict()

    for num, cell in enumerate(traversed_cells[:-1]):
      next_cell[cell] = traversed_cells[num + 1]


    # depth first search through the path to find a suitable path
    dfs = []
    dfs.append((current_pos, current_layer))
    visited = set()

    while len(dfs) > 0:
      pos, layer = dfs.pop()

      if (pos, layer) in visited:
        continue
      else:
        visited.add((pos, layer))
      
      # Return True if we have reached the goal
      if pos == goal_pos:
        return layer

      # Skip if layer is completely blocked
      if self.oriented_occ_grid[pos] == 255:
        continue

      next_pos = next_cell[pos]
        
      # Check adjacent and current layers of next position to see if it can be reached from here
      for i in [-1, 1, 0]:
        next_layer = (layer + i) % 8
        
        if self.oriented_occ_grid[next_pos] & 2**next_layer == 0:
          # print(pos, layer, next_pos, next_layer)
          dfs.append((next_pos, next_layer))

    # dfs didnt find a suitable path so return false
    return None
Esempio n. 5
0
    def interpolatePath(self, current_pos, current_layer, goal_pos,
                        goal_layer):
        # Get the direct path from current to goal
        traversed_cells = raytrace(*current_pos, *goal_pos)

        # Create this structure so we can efficiently get the next cell
        next_cell = dict()

        for num, cell in enumerate(traversed_cells[:-1]):
            next_cell[cell] = traversed_cells[num + 1]

        # depth first search through the path to find a suitable path
        dfs = []
        dfs.append((current_pos, current_layer))
        visited = set()
        layer_at_cell = dict()

        while len(dfs) > 0:
            pos, layer = dfs.pop()

            if (pos, layer) in visited:
                continue
            else:
                visited.add((pos, layer))

            layer_at_cell[pos] = layer

            # Return True if we have reached the goal
            if pos == goal_pos and layer == goal_layer:
                return layer_at_cell

            next_pos = next_cell[pos]

            # Check adjacent and current layers of next position to see if it can be reached from here
            for i in [-1, 1, 0]:
                next_layer = (layer + i) % 8

                if self.oriented_occ_grid[next_pos] & 2**next_layer == 0:
                    # print(pos, layer, next_pos, next_layer)
                    dfs.append((next_pos, next_layer))

        # dfs didnt find a suitable path so return false
        return None