py-tools/grid.py
Stefan Harmuth 8221403ed0 grids \o/
2021-10-22 18:46:28 +02:00

106 lines
3.1 KiB
Python

from __future__ import annotations
from .coordinate import Coordinate
from typing import Union
OFF_STATES = [False, 0, None]
OFF = False
ON = True
class Grid:
def __init__(self, default=False):
self.__default = default
self.__grid = {}
self.__minX = 0
self.__minY = 0
self.__maxX = 0
self.__maxY = 0
def __trackBoundaries(self, pos: Coordinate):
if pos.x < self.__minX:
self.__minX = pos.x
if pos.y < self.__minY:
self.__minY = pos.y
if pos.x > self.__maxX:
self.__maxX = pos.x
if pos.y > self.__maxY:
self.__maxY = pos.y
def toggle(self, pos: Coordinate):
if pos in self.__grid:
del self.__grid[pos]
else:
self.__trackBoundaries(pos)
self.__grid[pos] = not self.__default
def set(self, pos: Coordinate, value: any):
if value in OFF_STATES and pos in self.__grid:
del self.__grid[pos]
elif value not in OFF_STATES:
self.__trackBoundaries(pos)
self.__grid[pos] = value
def getState(self, pos: Coordinate) -> bool:
if pos not in self.__grid:
return False
else:
return self.__grid[pos] not in OFF_STATES
def getValue(self, pos: Coordinate) -> any:
if pos not in self.__grid:
return self.__default
else:
return self.__grid[pos]
def getOnCount(self):
return len(self.__grid)
def isSet(self, pos: Coordinate) -> bool:
return pos in self.__grid
def isCorner(self, pos: Coordinate) -> bool:
return pos in [
Coordinate(self.__minX, self.__minY),
Coordinate(self.__minX, self.__maxY),
Coordinate(self.__maxX, self.__minY),
Coordinate(self.__maxX, self.__maxY),
]
def add(self, pos: Coordinate, value: Union[float, int] = 1):
if pos in self.__grid:
self.__grid[pos] += value
else:
self.__trackBoundaries(pos)
self.__grid[pos] = self.__default + value
def sub(self, pos: Coordinate, value: Union[float, int] = 1):
if pos in self.__grid:
self.__grid[pos] -= value
else:
self.__trackBoundaries(pos)
self.__grid[pos] = self.__default - value
def getSum(self, includeNegative: bool = True):
grid_sum = 0
for value in self.__grid.values():
if includeNegative or value > 0:
grid_sum += value
return grid_sum
def getNeighbourSum(self, pos: Coordinate, includeNegative: bool = True, includeDiagonal: bool = True) \
-> Union[float, int]:
neighbour_sum = 0
for neighbour in pos.getNeighbours(
includeDiagonal=includeDiagonal,
minX=self.__minX, minY=self.__minY,
maxX=self.__maxX, maxY=self.__maxY):
if neighbour in self.__grid:
if includeNegative or self.__grid[neighbour] > 0:
neighbour_sum += self.__grid[neighbour]
return neighbour_sum