def make_coordinates_by_size(size: Size) -> Coordinates: """Makes only coordinates object with starting point at 0,0.""" return Coordinates( tl=Point(x=0, y=0), tr=Point(x=size.w - 1, y=0), br=Point(x=size.w - 1, y=size.h - 1), bl=Point(x=0, y=size.h - 1), )
def load(self, config: Configuration, file_name: str) -> None: file_path = self._resolve_file(file_name) try: with file_path.open('r') as config_file: data = json.load(fp=config_file) scale = data['scale'] if scale != config.map_scale: error_text = f'Map and screen resolution scales mismatch. ' \ f'You try to load map with scale {scale} ' \ f'on screen with scale {config.map_scale}.' log.error(error_text) raise ConfigurationLoadError(error_text) serialized_map = data['map'] actor_on_map_pos = Point(**data['actor_on_map_pos']) actor_scene_center_offset = Size( **data['actor_scene_center_offset']) serialized_scene_on_map_coords = data['scene_on_map_coords'] scene_is_most_top = data['scene_is_most_top'] scene_is_most_bottom = data['scene_is_most_bottom'] scene_is_most_right = data['scene_is_most_right'] scene_is_most_left = data['scene_is_most_left'] except KeyError as error: raise ConfigurationLoadError('Invalid file.') from error except json.JSONDecodeError as error: raise ConfigurationLoadError( 'Unable to decode file content.') from error parsed_map = [] for row in serialized_map: parsed_map.append([Tile(**tile) for tile in row]) scene_on_map_coords = Coordinates( **{ key: Point(**value) for key, value in serialized_scene_on_map_coords.items() }) # Restores map config.map = parsed_map config.surface = data['surface'] # Restores actor position config.actor_on_map_pos = actor_on_map_pos config.actor_scene_center_offset = actor_scene_center_offset config.scene_on_map_coords = scene_on_map_coords config.scene_is_most_top = scene_is_most_top config.scene_is_most_bottom = scene_is_most_bottom config.scene_is_most_right = scene_is_most_right config.scene_is_most_left = scene_is_most_left
def get_actor_on_scene_coords(self) -> Point: scene_center = self.get_scene_center() return Point( y=scene_center.y + self.cf.actor_scene_center_offset.h, x=scene_center.x + self.cf.actor_scene_center_offset.w, )
def create_marker_from_region(lbl: scipy.ndarray, i: int) -> Marker: """Returns position and radius of the marker in region i of the given label image.""" x_arr, y_arr = scipy.where(lbl == i) assert len(x_arr) == len(y_arr) pixel_count = len(x_arr) points = scipy.array([x_arr, y_arr]) m = scipy.mean(points, axis=1) distances = points - scipy.repeat(m.reshape(len(m), 1), pixel_count, 1) distances = scipy.linalg.norm(distances, axis=0) max_index = scipy.argmax(distances) max_distance = distances[max_index] return Marker( position=Point(m[0], m[1]), radius=max_distance )
def get_scene_center(self) -> Point: rx = self.cf.scene_pad_coords.tr.x lx = self.cf.scene_pad_coords.tl.x ty = self.cf.scene_pad_coords.tl.y by = self.cf.scene_pad_coords.bl.y sc = Point( x=(rx - lx) // 2 + (rx - lx) % 2, y=(by - ty) // 2 + (by - ty) % 2, ) if self.cf.square_tiles: sc.x -= 1 return sc
def update_actor_location(self) -> bool: actor_on_scene_coords = self.get_actor_on_scene_coords() actor_location_x = actor_on_scene_coords.x + self.cf.scene_on_map_coords.tl.x if self.cf.square_tiles: actor_location_x = actor_location_x // 2 actor_on_map_coords = Point( x=actor_location_x, y=actor_on_scene_coords.y + self.cf.scene_on_map_coords.tl.y, ) if self.cf.actor_on_map_pos != actor_on_map_coords: self.cf.actor_on_map_pos = actor_on_map_coords return True return False
def path_between_two_dots(p1: Point, p2: Point) -> t.Generator[Point, None, Point]: """ # Linear interpolation algorithm implementation. Finds path between two points in XY matrix. # "long", X-axis oriented paths tests: # Y axis increasing >>> [p for p in path_between_two_dots(Point(x=1,y=2), Point(x=11, y=7))] [Point(x=2, y=2), Point(x=3, y=3), Point(x=4, y=4), Point(x=5, y=4), Point(x=6, y=4), Point(x=7, y=5), Point(x=8, y=6), Point(x=9, y=6), Point(x=10, y=6)] >>> [p for p in path_between_two_dots(Point(x=10,y=2), Point(x=3, y=9))] [Point(x=9, y=3), Point(x=8, y=4), Point(x=7, y=5), Point(x=6, y=6), Point(x=5, y=7), Point(x=4, y=8)] # Y axis decreasing >>> [p for p in path_between_two_dots(Point(x=1,y=9), Point(x=11, y=1))] [Point(x=2, y=8), Point(x=3, y=7), Point(x=4, y=7), Point(x=5, y=6), Point(x=6, y=5), Point(x=7, y=4), Point(x=8, y=3), Point(x=9, y=3), Point(x=10, y=2)] >>> [p for p in path_between_two_dots(Point(x=10,y=8), Point(x=3, y=2))] [Point(x=9, y=7), Point(x=8, y=6), Point(x=7, y=5), Point(x=6, y=5), Point(x=5, y=4), Point(x=4, y=3)] # Y axis stalled (difference by Y is 0) >>> [p for p in path_between_two_dots(Point(x=1,y=9), Point(x=10, y=1))] [Point(x=2, y=8), Point(x=3, y=7), Point(x=4, y=6), Point(x=5, y=5), Point(x=6, y=5), Point(x=7, y=4), Point(x=8, y=3), Point(x=9, y=2)] >>> [p for p in path_between_two_dots(Point(x=9,y=8), Point(x=1, y=8))] [Point(x=8, y=8), Point(x=7, y=8), Point(x=6, y=8), Point(x=5, y=8), Point(x=4, y=8), Point(x=3, y=8), Point(x=2, y=8)] # "tall", Y-axis oriented paths tests: # X axis increasing >>> [p for p in path_between_two_dots(Point(x=3,y=2), Point(x=9, y=12))] [Point(x=4, y=3), Point(x=4, y=4), Point(x=5, y=5), Point(x=5, y=6), Point(x=6, y=7), Point(x=7, y=8), Point(x=7, y=9), Point(x=8, y=10), Point(x=8, y=11)] >>> [p for p in path_between_two_dots(Point(x=3,y=12), Point(x=9, y=3))] [Point(x=4, y=11), Point(x=4, y=10), Point(x=5, y=9), Point(x=6, y=8), Point(x=6, y=7), Point(x=7, y=6), Point(x=8, y=5), Point(x=8, y=4)] # X axis decreasing >>> [p for p in path_between_two_dots(Point(x=8,y=2), Point(x=1, y=12))] [Point(x=7, y=3), Point(x=7, y=4), Point(x=6, y=5), Point(x=5, y=6), Point(x=4, y=7), Point(x=4, y=8), Point(x=3, y=9), Point(x=2, y=10), Point(x=2, y=11)] >>> [p for p in path_between_two_dots(Point(x=9,y=4), Point(x=2, y=14))] [Point(x=8, y=5), Point(x=8, y=6), Point(x=7, y=7), Point(x=6, y=8), Point(x=6, y=9), Point(x=5, y=10), Point(x=4, y=11), Point(x=3, y=12), Point(x=3, y=13)] # X axis stalled (difference by X is 0) >>> [p for p in path_between_two_dots(Point(x=8,y=2), Point(x=8, y=12))] [Point(x=8, y=3), Point(x=8, y=4), Point(x=8, y=5), Point(x=8, y=6), Point(x=8, y=7), Point(x=8, y=8), Point(x=8, y=9), Point(x=8, y=10), Point(x=8, y=11)] >>> [p for p in path_between_two_dots(Point(x=6,y=13), Point(x=6, y=4))] [Point(x=6, y=12), Point(x=6, y=11), Point(x=6, y=10), Point(x=6, y=9), Point(x=6, y=8), Point(x=6, y=7), Point(x=6, y=6), Point(x=6, y=5)] """ if p1 == p2: return p1 y_diff = p2.y - p1.y x_diff = p2.x - p1.x move_op = operator.add if abs(y_diff) > abs(x_diff): move_over_x = False if y_diff < 0: move_op = operator.sub slope = x_diff / y_diff else: move_over_x = True if x_diff < 0: move_op = operator.sub slope = y_diff / x_diff steps = max(abs(x_diff), abs(y_diff)) for step in range(1, steps): if move_over_x: x = move_op(p1.x, step) y = round(p1.y + slope * (x - p1.x)) else: y = move_op(p1.y, step) x = round(p1.x + slope * (y - p1.y)) yield Point(x=x, y=y)