py-tools/coordinate.py
Stefan Harmuth fc0178288e Coordinate.generate(): get list of coordinates from x1,y1 to x2,y2
Grid(): expose boundaries
Grid.isWithinBoundaries(): check if Coordinate is within boundaries
Grid.getActiveCells(): get all Coordinates within Grid() with a value
2021-11-29 16:40:01 +01:00

69 lines
2.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from math import sqrt, inf
from typing import Union, List
@dataclass(frozen=True, order=True)
class Coordinate:
x: int
y: int
def getDistanceTo(self, target: Coordinate, mode: int = 1, includeDiagonals: bool = False) -> Union[int, float]:
"""
Get distance to target Coordinate
:param target:
:param mode: Calculation Mode (0 = Manhattan, 1 = Pythagoras)
:param includeDiagonals: in Manhattan Mode specify if diagonal movements are allowed (counts as 1.4)
:return: Distance to Target
"""
assert isinstance(target, Coordinate)
assert mode in [0, 1]
assert isinstance(includeDiagonals, bool)
if mode == 1:
return sqrt(abs(self.x - target.x) ** 2 + abs(self.y - target.y) ** 2)
elif mode == 0:
if not includeDiagonals:
return abs(self.x - target.x) + abs(self.y - target.y)
else:
x_dist = abs(self.x - target.x)
y_dist = abs(self.y - target.y)
o_dist = max(x_dist, y_dist) - min(x_dist, y_dist)
return o_dist + 1.4 * min(x_dist, y_dist)
def getNeighbours(self, includeDiagonal: bool = True, minX: int = -inf, minY: int = -inf,
maxX: int = inf, maxY: int = inf) -> list[Coordinate]:
"""
Get a list of neighbouring coordinates
:param includeDiagonal: include diagonal neighbours
:param minX: ignore all neighbours that would have an X value below this
:param minY: ignore all neighbours that would have an Y value below this
:param maxX: ignore all neighbours that would have an X value above this
:param maxY: ignore all neighbours that would have an Y value above this
:return: list of Coordinate
"""
neighbourList = []
if includeDiagonal:
nb_list = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
else:
nb_list = [(-1, 0), (1, 0), (0, -1), (0, 1)]
for dx, dy in nb_list:
tx = self.x + dx
ty = self.y + dy
if tx < minX or tx > maxX or ty < minY or ty > maxY:
continue
neighbourList.append(Coordinate(tx, ty))
return neighbourList
@staticmethod
def generate(from_x: int, to_x: int, from_y: int, to_y: int) -> List[Coordinate]:
return [Coordinate(x, y) for x in range(from_x, to_x + 1) for y in range(from_y, to_y + 1)]