Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy
- import pprint
- class ImageLayer(object):
- """
- Represents a layer of an image
- """
- def __init__(self, x_shape, y_shape, fill_character, left_x, top_y, right_x, bottom_y):
- self.x_shape = x_shape
- self.y_shape = y_shape
- self.fill_character = fill_character
- self.canvas = self._build_canvas(left_x, top_y, right_x, bottom_y)
- def _verify_coords(self, x, y):
- # Check that the co-ordinates are valid
- if x<0 or x>=self.x_shape or y<0 or y>=self.y_shape:
- raise ValueError(f'[{x}, {y}] is outside the bounds')
- def _build_canvas(self, left_x, top_y, right_x, bottom_y):
- self._verify_coords(left_x, top_y)
- self._verify_coords(right_x, bottom_y)
- # Create the initial canvas for the layer
- canvas = numpy.zeros(shape=(self.x_shape, self.y_shape))
- canvas[left_x:right_x+1, top_y:bottom_y+1] = numpy.ones(shape=(right_x-left_x+1, bottom_y-top_y+1))
- return canvas
- def erase_area(self, left_x, top_y, right_x, bottom_y):
- """
- Erase a section of the layer
- """
- self._verify_coords(left_x, top_y)
- self._verify_coords(right_x, bottom_y)
- self.canvas[left_x:right_x+1, top_y:bottom_y+1] = numpy.zeros(shape=(right_x-left_x+1, bottom_y-top_y+1))
- def hit(self, select_x, select_y):
- """
- Check if the layer has any content at these co-ordinates
- """
- self._verify_coords(select_x, select_y)
- return self.canvas[select_x, select_y] == 1
- def drag_and_drop(self, move_x, move_y):
- """
- Roll the canvas to move the position of the rectangle
- """
- # This will wrap rectanges around the maximums
- self.canvas = numpy.roll(self.canvas, move_x, axis=0)
- self.canvas = numpy.roll(self.canvas, move_y, axis=1)
- class Image(object):
- """
- Represents an image with multiple layers
- """
- def __init__(self, x_shape=10, y_shape=6):
- self.x_shape = x_shape
- self.y_shape = y_shape
- self.layers = []
- def draw_rectangle(self, fill_character, left_x, top_y, right_x, bottom_y):
- """
- Creates a new layer on top with the specified rectangle on it
- """
- new_layer = ImageLayer(
- self.x_shape,
- self.y_shape,
- fill_character,
- left_x,
- top_y,
- right_x,
- bottom_y
- )
- self.layers = [new_layer] + self.layers
- def erase_area(self, left_x, top_y, right_x, bottom_y):
- """
- Erase the area on all layers
- """
- for layer in self.layers:
- layer.erase_area(left_x, top_y, right_x, bottom_y)
- def drag_and_drop(self, select_x, select_y, release_x, release_y):
- """
- Move the top layer
- """
- for layer in self.layers:
- if layer.hit(select_x, select_y):
- layer.drag_and_drop(release_x-select_x, release_y-select_y)
- return
- def bring_to_front(self, select_x, select_y):
- """
- Move the selected layer to the top of the stack
- """
- for i, layer in enumerate(self.layers):
- if layer.hit(select_x, select_y):
- self.layers.pop(i)
- self.layers = [layer] + self.layers
- return
- def print_canvas(self):
- """
- Return an array of arrays with the rendered content
- """
- canvas = numpy.zeros(shape=(self.x_shape, self.y_shape)).tolist()
- for layer in reversed(self.layers):
- for i in range(self.x_shape):
- for j in range(self.y_shape):
- if layer.canvas[i, j] == 1:
- canvas[i][j] = layer.fill_character
- # This can probably done when initializing the canvas.
- # The solution is somewhere in the numpy docs.
- for i in range(self.x_shape):
- for j in range(self.y_shape):
- if canvas[i][j] == 0:
- canvas[i][j] = ' '
- return canvas
- def command_parser():
- # Parses the file in to the format:
- # ["COMMAND", [*command_args]]
- # BELOW IS HARDCODED EXAMPLE I USED FOR DEBUGGING:
- return [
- ['DRAW_RECTANGLE',['L',1,1,4,4]],
- ['DRAW_RECTANGLE',['R',2,1,4,4]],
- ['PRINT_CANVAS',[]],
- ['ERASE_AREA',[3,2,3,3]],
- ['PRINT_CANVAS',[]],
- ['DRAW_RECTANGLE',['#',1,3,8,4]],
- ['DRAG_AND_DROP',[2,2,6,2]],
- ['PRINT_CANVAS',[]],
- ['BRING_TO_FRONT',[1,2]],
- ['BRING_TO_FRONT',[6,2]],
- ['PRINT_CANVAS',[]],
- ['DRAG_AND_DROP',[3,3,3,2]],
- ['PRINT_CANVAS',[]],
- ]
- def main():
- # Parse the command list
- command_list = command_parser()
- # create an empty image
- image = Image(10, 6)
- # For each command apply it to the command list
- for command, command_args in command_list:
- if command == 'DRAW_RECTANGLE':
- image.draw_rectangle(*command_args)
- elif command == 'ERASE_AREA':
- image.erase_area(*command_args)
- elif command == 'DRAG_AND_DROP':
- image.drag_and_drop(*command_args)
- elif command == 'BRING_TO_FRONT':
- image.bring_to_front(*command_args)
- elif command == 'PRINT_CANVAS':
- pprint.pprint(image.print_canvas())
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement