Compare commits
3 Commits
f22c3bd798
...
2de9725adb
| Author | SHA1 | Date | |
|---|---|---|---|
| 2de9725adb | |||
| 32c07d2913 | |||
| 0408432e3d |
@ -30,11 +30,11 @@ class Coordinate(tuple):
|
|||||||
return self[2]
|
return self[2]
|
||||||
|
|
||||||
def is3D(self) -> bool:
|
def is3D(self) -> bool:
|
||||||
return self.z is not None
|
return self[2] is not None
|
||||||
|
|
||||||
def getDistanceTo(
|
def getDistanceTo(
|
||||||
self,
|
self,
|
||||||
target: Coordinate,
|
target: Coordinate | tuple,
|
||||||
algorithm: DistanceAlgorithm = DistanceAlgorithm.EUCLIDEAN,
|
algorithm: DistanceAlgorithm = DistanceAlgorithm.EUCLIDEAN,
|
||||||
includeDiagonals: bool = False,
|
includeDiagonals: bool = False,
|
||||||
) -> Union[int, float]:
|
) -> Union[int, float]:
|
||||||
@ -48,40 +48,40 @@ class Coordinate(tuple):
|
|||||||
:return: Distance to Target
|
:return: Distance to Target
|
||||||
"""
|
"""
|
||||||
if algorithm == DistanceAlgorithm.EUCLIDEAN:
|
if algorithm == DistanceAlgorithm.EUCLIDEAN:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return sqrt(abs(self.x - target.x) ** 2 + abs(self.y - target.y) ** 2)
|
return sqrt(abs(self[0] - target[0]) ** 2 + abs(self[1] - target[1]) ** 2)
|
||||||
else:
|
else:
|
||||||
return sqrt(
|
return sqrt(
|
||||||
abs(self.x - target.x) ** 2
|
abs(self[0] - target[0]) ** 2
|
||||||
+ abs(self.y - target.y) ** 2
|
+ abs(self[1] - target[1]) ** 2
|
||||||
+ abs(self.z - target.z) ** 2
|
+ abs(self[2] - target[2]) ** 2
|
||||||
)
|
)
|
||||||
elif algorithm == DistanceAlgorithm.CHEBYSHEV:
|
elif algorithm == DistanceAlgorithm.CHEBYSHEV:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return max(abs(target.x - self.x), abs(target.y - self.y))
|
return max(abs(target[0] - self[0]), abs(target[1] - self[1]))
|
||||||
else:
|
else:
|
||||||
return max(
|
return max(
|
||||||
abs(target.x - self.x),
|
abs(target[0] - self[0]),
|
||||||
abs(target.y - self.y),
|
abs(target[1] - self[1]),
|
||||||
abs(target.z - self.z),
|
abs(target[2] - self[2]),
|
||||||
)
|
)
|
||||||
elif algorithm == DistanceAlgorithm.MANHATTAN:
|
elif algorithm == DistanceAlgorithm.MANHATTAN:
|
||||||
if not includeDiagonals:
|
if not includeDiagonals:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return abs(self.x - target.x) + abs(self.y - target.y)
|
return abs(self[0] - target[0]) + abs(self[1] - target[1])
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
abs(self.x - target.x)
|
abs(self[0] - target[0])
|
||||||
+ abs(self.y - target.y)
|
+ abs(self[1] - target[1])
|
||||||
+ abs(self.z - target.z)
|
+ abs(self[2] - target[2])
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
dist = [abs(self.x - target.x), abs(self.y - target.y)]
|
dist = [abs(self[0] - target[0]), abs(self[1] - target[1])]
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
o_dist = max(dist) - min(dist)
|
o_dist = max(dist) - min(dist)
|
||||||
return o_dist + 1.4 * min(dist)
|
return o_dist + 1.4 * min(dist)
|
||||||
else:
|
else:
|
||||||
dist.append(abs(self.z - target.z))
|
dist.append(abs(self[2] - target[2]))
|
||||||
d_steps = min(dist)
|
d_steps = min(dist)
|
||||||
dist.remove(min(dist))
|
dist.remove(min(dist))
|
||||||
dist = [x - d_steps for x in dist]
|
dist = [x - d_steps for x in dist]
|
||||||
@ -97,13 +97,13 @@ class Coordinate(tuple):
|
|||||||
minZ: int = -inf,
|
minZ: int = -inf,
|
||||||
maxZ: int = inf,
|
maxZ: int = inf,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return minX <= self.x <= maxX and minY <= self.y <= maxY
|
return minX <= self[0] <= maxX and minY <= self[1] <= maxY
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
minX <= self.x <= maxX
|
minX <= self[0] <= maxX
|
||||||
and minY <= self.y <= maxY
|
and minY <= self[1] <= maxY
|
||||||
and minZ <= self.z <= maxZ
|
and minZ <= self[2] <= maxZ
|
||||||
)
|
)
|
||||||
|
|
||||||
def getCircle(
|
def getCircle(
|
||||||
@ -118,9 +118,9 @@ class Coordinate(tuple):
|
|||||||
maxZ: int = inf,
|
maxZ: int = inf,
|
||||||
) -> list[Coordinate]:
|
) -> list[Coordinate]:
|
||||||
ret = []
|
ret = []
|
||||||
if self.z is None: # mode 2D
|
if self[2] is None: # mode 2D
|
||||||
for x in range(self.x - radius * 2, self.x + radius * 2 + 1):
|
for x in range(self[0] - radius * 2, self[0] + radius * 2 + 1):
|
||||||
for y in range(self.y - radius * 2, self.y + radius * 2 + 1):
|
for y in range(self[1] - radius * 2, self[1] + radius * 2 + 1):
|
||||||
target = Coordinate(x, y)
|
target = Coordinate(x, y)
|
||||||
if not target.inBoundaries(minX, minY, maxX, maxY):
|
if not target.inBoundaries(minX, minY, maxX, maxY):
|
||||||
continue
|
continue
|
||||||
@ -133,9 +133,9 @@ class Coordinate(tuple):
|
|||||||
ret.append(target)
|
ret.append(target)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for x in range(self.x - radius * 2, self.x + radius * 2 + 1):
|
for x in range(self[0] - radius * 2, self[0] + radius * 2 + 1):
|
||||||
for y in range(self.y - radius * 2, self.y + radius * 2 + 1):
|
for y in range(self[1] - radius * 2, self[1] + radius * 2 + 1):
|
||||||
for z in range(self.z - radius * 2, self.z + radius * 2 + 1):
|
for z in range(self[2] - radius * 2, self[2] + radius * 2 + 1):
|
||||||
target = Coordinate(x, y)
|
target = Coordinate(x, y)
|
||||||
if not target.inBoundaries(minX, minY, maxX, maxY, minZ, maxZ):
|
if not target.inBoundaries(minX, minY, maxX, maxY, minZ, maxZ):
|
||||||
continue
|
continue
|
||||||
@ -171,7 +171,7 @@ class Coordinate(tuple):
|
|||||||
:param maxZ: ignore all neighbours that would have an Z value above this
|
:param maxZ: ignore all neighbours that would have an Z value above this
|
||||||
:return: list of Coordinate
|
:return: list of Coordinate
|
||||||
"""
|
"""
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
if includeDiagonal:
|
if includeDiagonal:
|
||||||
nb_list = [
|
nb_list = [
|
||||||
(-1, -1),
|
(-1, -1),
|
||||||
@ -187,8 +187,8 @@ class Coordinate(tuple):
|
|||||||
nb_list = [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
nb_list = [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||||
|
|
||||||
for dx, dy in nb_list:
|
for dx, dy in nb_list:
|
||||||
if minX <= self.x + dx <= maxX and minY <= self.y + dy <= maxY:
|
if minX <= self[0] + dx <= maxX and minY <= self[0] + dy <= maxY:
|
||||||
yield self.__class__(self.x + dx, self.y + dy)
|
yield self.__class__(self[0] + dx, self[1] + dy)
|
||||||
else:
|
else:
|
||||||
if includeDiagonal:
|
if includeDiagonal:
|
||||||
nb_list = [
|
nb_list = [
|
||||||
@ -210,19 +210,19 @@ class Coordinate(tuple):
|
|||||||
|
|
||||||
for dx, dy, dz in nb_list:
|
for dx, dy, dz in nb_list:
|
||||||
if (
|
if (
|
||||||
minX <= self.x + dx <= maxX
|
minX <= self[0] + dx <= maxX
|
||||||
and minY <= self.y + dy <= maxY
|
and minY <= self[1] + dy <= maxY
|
||||||
and minZ <= self.z + dz <= maxZ
|
and minZ <= self[2] + dz <= maxZ
|
||||||
):
|
):
|
||||||
yield self.__class__(self.x + dx, self.y + dy, self.z + dz)
|
yield self.__class__(self[0] + dx, self[1] + dy, self[2] + dz)
|
||||||
|
|
||||||
def getAngleTo(self, target: Coordinate, normalized: bool = False) -> float:
|
def getAngleTo(self, target: Coordinate | tuple, normalized: bool = False) -> float:
|
||||||
"""normalized returns an angle going clockwise with 0 starting in the 'north'"""
|
"""normalized returns an angle going clockwise with 0 starting in the 'north'"""
|
||||||
if self.z is not None:
|
if self[2] is not None:
|
||||||
raise NotImplementedError() # which angle?!?!
|
raise NotImplementedError() # which angle?!?!
|
||||||
|
|
||||||
dx = target.x - self.x
|
dx = target[0] - self[0]
|
||||||
dy = target.y - self.y
|
dy = target[1] - self[1]
|
||||||
if not normalized:
|
if not normalized:
|
||||||
return degrees(atan2(dy, dx))
|
return degrees(atan2(dy, dx))
|
||||||
else:
|
else:
|
||||||
@ -232,77 +232,77 @@ class Coordinate(tuple):
|
|||||||
else:
|
else:
|
||||||
return 180.0 + abs(angle)
|
return 180.0 + abs(angle)
|
||||||
|
|
||||||
def getLineTo(self, target: Coordinate) -> List[Coordinate]:
|
def getLineTo(self, target: Coordinate | tuple) -> List[Coordinate]:
|
||||||
diff = target - self
|
diff = target - self
|
||||||
|
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
steps = gcd(diff.x, diff.y)
|
steps = gcd(diff[0], diff[0])
|
||||||
step_x = diff.x // steps
|
step_x = diff[0] // steps
|
||||||
step_y = diff.y // steps
|
step_y = diff[1] // steps
|
||||||
return [
|
return [
|
||||||
self.__class__(self.x + step_x * i, self.y + step_y * i)
|
self.__class__(self[0] + step_x * i, self[1] + step_y * i)
|
||||||
for i in range(steps + 1)
|
for i in range(steps + 1)
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
steps = gcd(diff.x, diff.y, diff.z)
|
steps = gcd(diff[0], diff[1], diff[2])
|
||||||
step_x = diff.x // steps
|
step_x = diff[0] // steps
|
||||||
step_y = diff.y // steps
|
step_y = diff[1] // steps
|
||||||
step_z = diff.z // steps
|
step_z = diff[2] // steps
|
||||||
return [
|
return [
|
||||||
self.__class__(
|
self.__class__(
|
||||||
self.x + step_x * i, self.y + step_y * i, self.z + step_z * i
|
self[0] + step_x * i, self[1] + step_y * i, self[2] + step_z * i
|
||||||
)
|
)
|
||||||
for i in range(steps + 1)
|
for i in range(steps + 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
def reverse(self) -> Coordinate:
|
def reverse(self) -> Coordinate:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return self.__class__(-self.x, -self.y)
|
return self.__class__(-self[0], -self[1])
|
||||||
else:
|
else:
|
||||||
return self.__class__(-self.x, -self.y, -self.z)
|
return self.__class__(-self[0], -self[1], -self[2])
|
||||||
|
|
||||||
def __add__(self, other: Coordinate) -> Coordinate:
|
def __add__(self, other: Coordinate | tuple) -> Coordinate:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return self.__class__(self.x + other.x, self.y + other.y)
|
return self.__class__(self[0] + other[0], self[1] + other[1])
|
||||||
else:
|
else:
|
||||||
return self.__class__(self.x + other.x, self.y + other.y, self.z + other.z)
|
return self.__class__(self[0] + other[0], self[1] + other[1], self[2] + other[2])
|
||||||
|
|
||||||
def __sub__(self, other: Coordinate) -> Coordinate:
|
def __sub__(self, other: Coordinate | tuple) -> Coordinate:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return self.__class__(self.x - other.x, self.y - other.y)
|
return self.__class__(self[0] - other[0], self[1] - other[1])
|
||||||
else:
|
else:
|
||||||
return self.__class__(self.x - other.x, self.y - other.y, self.z - other.z)
|
return self.__class__(self[0] - other[0], self[1] - other[1], self[2] - other[2])
|
||||||
|
|
||||||
def __mul__(self, other: int) -> Coordinate:
|
def __mul__(self, other: int) -> Coordinate:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return self.__class__(self.x * other, self.y * other)
|
return self.__class__(self[0] * other, self[1] * other)
|
||||||
else:
|
else:
|
||||||
return self.__class__(self.x * other, self.y * other, self.z * other)
|
return self.__class__(self[0] * other, self[1] * other, self[2] * other)
|
||||||
|
|
||||||
def __floordiv__(self, other) -> Coordinate:
|
def __floordiv__(self, other: int | float) -> Coordinate:
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return self.__class__(self.x // other, self.y // other)
|
return self.__class__(self[0] // other, self[1] // other)
|
||||||
else:
|
else:
|
||||||
return self.__class__(self.x // other, self.y // other, self.z // other)
|
return self.__class__(self[0] // other, self[1] // other, self[2] // other)
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other: int | float) -> Coordinate:
|
||||||
return self // other
|
return self // other
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return "(%d,%d)" % (self.x, self.y)
|
return "(%d,%d)" % (self[0], self[1])
|
||||||
else:
|
else:
|
||||||
return "(%d,%d,%d)" % (self.x, self.y, self.z)
|
return "(%d,%d,%d)" % (self[0], self[1], self[2])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.z is None:
|
if self[2] is None:
|
||||||
return "%s(x=%d, y=%d)" % (self.__class__.__name__, self.x, self.y)
|
return "%s(x=%d, y=%d)" % (self.__class__.__name__, self[0], self[1])
|
||||||
else:
|
else:
|
||||||
return "%s(x=%d, y=%d, z=%d)" % (
|
return "%s(x=%d, y=%d, z=%d)" % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self.x,
|
self[0],
|
||||||
self.y,
|
self[1],
|
||||||
self.z,
|
self[2],
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from collections import deque
|
|
||||||
from collections.abc import Callable
|
|
||||||
|
|
||||||
from .aoc_ocr import convert_array_6
|
from .aoc_ocr import convert_array_6
|
||||||
from .coordinate import Coordinate, DistanceAlgorithm, Shape
|
from .coordinate import Coordinate, DistanceAlgorithm, Shape
|
||||||
|
from collections import deque
|
||||||
|
from collections.abc import Callable
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from heapq import heappop, heappush
|
from heapq import heappop, heappush
|
||||||
from math import inf
|
from math import inf
|
||||||
@ -50,19 +48,19 @@ class Grid:
|
|||||||
|
|
||||||
def __trackBoundaries(self, pos: Coordinate):
|
def __trackBoundaries(self, pos: Coordinate):
|
||||||
if self.minX is None:
|
if self.minX is None:
|
||||||
self.minX, self.maxX, self.minY, self.maxY = pos.x, pos.x, pos.y, pos.y
|
self.minX, self.maxX, self.minY, self.maxY = pos[0], pos[0], pos[1], pos[1]
|
||||||
else:
|
else:
|
||||||
self.minX = pos.x if pos.x < self.minX else self.minX
|
self.minX = pos[0] if pos[0] < self.minX else self.minX
|
||||||
self.minY = pos.y if pos.y < self.minY else self.minY
|
self.minY = pos[1] if pos[1] < self.minY else self.minY
|
||||||
self.maxX = pos.x if pos.x > self.maxX else self.maxX
|
self.maxX = pos[0] if pos[0] > self.maxX else self.maxX
|
||||||
self.maxY = pos.y if pos.y > self.maxY else self.maxY
|
self.maxY = pos[1] if pos[1] > self.maxY else self.maxY
|
||||||
|
|
||||||
if self.mode3D:
|
if self.mode3D:
|
||||||
if self.minZ is None:
|
if self.minZ is None:
|
||||||
self.minZ = self.maxZ = pos.z
|
self.minZ = self.maxZ = pos[2]
|
||||||
else:
|
else:
|
||||||
self.minZ = pos.z if pos.z < self.minZ else self.minZ
|
self.minZ = pos[2] if pos[2] < self.minZ else self.minZ
|
||||||
self.maxZ = pos.z if pos.z > self.maxZ else self.maxZ
|
self.maxZ = pos[2] if pos[2] > self.maxZ else self.maxZ
|
||||||
|
|
||||||
def recalcBoundaries(self) -> None:
|
def recalcBoundaries(self) -> None:
|
||||||
self.minX, self.maxX, self.minY, self.maxY, self.minZ, self.maxZ = (
|
self.minX, self.maxX, self.minY, self.maxY, self.minZ, self.maxZ = (
|
||||||
@ -125,7 +123,7 @@ class Grid:
|
|||||||
self.toggle(Coordinate(x, y, z))
|
self.toggle(Coordinate(x, y, z))
|
||||||
|
|
||||||
def set(self, pos: Coordinate, value: Any = True) -> Any:
|
def set(self, pos: Coordinate, value: Any = True) -> Any:
|
||||||
if pos.z is not None:
|
if pos[2] is not None:
|
||||||
self.mode3D = True
|
self.mode3D = True
|
||||||
|
|
||||||
if (value == self.__default) and pos in self.__grid:
|
if (value == self.__default) and pos in self.__grid:
|
||||||
@ -159,13 +157,13 @@ class Grid:
|
|||||||
return self.set(pos, self.get(pos) / value)
|
return self.set(pos, self.get(pos) / value)
|
||||||
|
|
||||||
def add_shape(self, shape: Shape, value: int | float = 1) -> None:
|
def add_shape(self, shape: Shape, value: int | float = 1) -> None:
|
||||||
for x in range(shape.top_left.x, shape.bottom_right.x + 1):
|
for x in range(shape.top_left[0], shape.bottom_right[0] + 1):
|
||||||
for y in range(shape.top_left.y, shape.bottom_right.y + 1):
|
for y in range(shape.top_left[1], shape.bottom_right[1] + 1):
|
||||||
if not shape.mode_3d:
|
if not shape.mode_3d:
|
||||||
pos = Coordinate(x, y)
|
pos = Coordinate(x, y)
|
||||||
self.set(pos, self.get(pos) + value)
|
self.set(pos, self.get(pos) + value)
|
||||||
else:
|
else:
|
||||||
for z in range(shape.top_left.z, shape.bottom_right.z + 1):
|
for z in range(shape.top_left[2], shape.bottom_right[2] + 1):
|
||||||
pos = Coordinate(x, y, z)
|
pos = Coordinate(x, y, z)
|
||||||
self.set(pos, self.get(pos) + value)
|
self.set(pos, self.get(pos) + value)
|
||||||
|
|
||||||
@ -207,29 +205,29 @@ class Grid:
|
|||||||
def isWithinBoundaries(self, pos: Coordinate, pad: int = 0) -> bool:
|
def isWithinBoundaries(self, pos: Coordinate, pad: int = 0) -> bool:
|
||||||
if self.mode3D:
|
if self.mode3D:
|
||||||
return (
|
return (
|
||||||
self.minX + pad <= pos.x <= self.maxX - pad
|
self.minX + pad <= pos[0] <= self.maxX - pad
|
||||||
and self.minY + pad <= pos.y <= self.maxY - pad
|
and self.minY + pad <= pos[1] <= self.maxY - pad
|
||||||
and self.minZ + pad <= pos.z <= self.maxZ - pad
|
and self.minZ + pad <= pos[2] <= self.maxZ - pad
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
self.minX + pad <= pos.x <= self.maxX - pad
|
self.minX + pad <= pos[0] <= self.maxX - pad
|
||||||
and self.minY + pad <= pos.y <= self.maxY - pad
|
and self.minY + pad <= pos[1] <= self.maxY - pad
|
||||||
)
|
)
|
||||||
|
|
||||||
def getActiveCells(
|
def getActiveCells(
|
||||||
self, x: int = None, y: int = None, z: int = None
|
self, x: int = None, y: int = None, z: int = None
|
||||||
) -> List[Coordinate]:
|
) -> Iterable[Coordinate]:
|
||||||
if x is not None or y is not None or z is not None:
|
if x is not None or y is not None or z is not None:
|
||||||
return [
|
return (
|
||||||
c
|
c
|
||||||
for c in self.__grid.keys()
|
for c in self.__grid.keys()
|
||||||
if (c.x == x if x is not None else True)
|
if (c[0] == x if x is not None else True)
|
||||||
and (c.y == y if y is not None else True)
|
and (c[1] == y if y is not None else True)
|
||||||
and (c.z == z if z is not None else True)
|
and (c[2] == z if z is not None else True)
|
||||||
]
|
)
|
||||||
else:
|
else:
|
||||||
return list(self.__grid.keys())
|
return self.__grid.keys()
|
||||||
|
|
||||||
def getActiveRegion(
|
def getActiveRegion(
|
||||||
self,
|
self,
|
||||||
@ -273,7 +271,7 @@ class Grid:
|
|||||||
pos: Coordinate,
|
pos: Coordinate,
|
||||||
includeDefault: bool = False,
|
includeDefault: bool = False,
|
||||||
includeDiagonal: bool = True,
|
includeDiagonal: bool = True,
|
||||||
) -> List[Coordinate]:
|
) -> Iterable[Coordinate]:
|
||||||
neighbours = pos.getNeighbours(
|
neighbours = pos.getNeighbours(
|
||||||
includeDiagonal=includeDiagonal,
|
includeDiagonal=includeDiagonal,
|
||||||
minX=self.minX,
|
minX=self.minX,
|
||||||
@ -314,47 +312,47 @@ class Grid:
|
|||||||
if mode == GridTransformation.ROTATE_X:
|
if mode == GridTransformation.ROTATE_X:
|
||||||
shift_z = self.maxY
|
shift_z = self.maxY
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.x, c.z, -c.y), v)
|
self.set(Coordinate(c[0], c[2], -c[1]), v)
|
||||||
self.shift(shift_z=shift_z)
|
self.shift(shift_z=shift_z)
|
||||||
elif mode == GridTransformation.ROTATE_Y:
|
elif mode == GridTransformation.ROTATE_Y:
|
||||||
shift_x = self.maxX
|
shift_x = self.maxX
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(-c.z, c.y, c.x), v)
|
self.set(Coordinate(-c[2], c[1], c[0]), v)
|
||||||
self.shift(shift_x=shift_x)
|
self.shift(shift_x=shift_x)
|
||||||
elif mode == GridTransformation.ROTATE_Z:
|
elif mode == GridTransformation.ROTATE_Z:
|
||||||
shift_x = self.maxX
|
shift_x = self.maxX
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(-c.y, c.x, c.z), v)
|
self.set(Coordinate(-c[1], c[0], c[2]), v)
|
||||||
self.shift(shift_x=shift_x)
|
self.shift(shift_x=shift_x)
|
||||||
elif mode == GridTransformation.COUNTER_ROTATE_X:
|
elif mode == GridTransformation.COUNTER_ROTATE_X:
|
||||||
shift_y = self.maxY
|
shift_y = self.maxY
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.x, -c.z, c.y), v)
|
self.set(Coordinate(c[0], -c[2], c[1]), v)
|
||||||
self.shift(shift_y=shift_y)
|
self.shift(shift_y=shift_y)
|
||||||
elif mode == GridTransformation.COUNTER_ROTATE_Y:
|
elif mode == GridTransformation.COUNTER_ROTATE_Y:
|
||||||
shift_z = self.maxZ
|
shift_z = self.maxZ
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.z, c.y, -c.x), v)
|
self.set(Coordinate(c[2], c[1], -c[0]), v)
|
||||||
self.shift(shift_z=shift_z)
|
self.shift(shift_z=shift_z)
|
||||||
elif mode == GridTransformation.COUNTER_ROTATE_Z:
|
elif mode == GridTransformation.COUNTER_ROTATE_Z:
|
||||||
shift_y = self.maxY
|
shift_y = self.maxY
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.y, -c.x, c.z), v)
|
self.set(Coordinate(c[1], -c[0], c[2]), v)
|
||||||
self.shift(shift_y=shift_y)
|
self.shift(shift_y=shift_y)
|
||||||
elif mode == GridTransformation.FLIP_X:
|
elif mode == GridTransformation.FLIP_X:
|
||||||
shift_x = self.maxX
|
shift_x = self.maxX
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(-c.x, c.y, c.z), v)
|
self.set(Coordinate(-c[0], c[1], c[2]), v)
|
||||||
self.shift(shift_x=shift_x)
|
self.shift(shift_x=shift_x)
|
||||||
elif mode == GridTransformation.FLIP_Y:
|
elif mode == GridTransformation.FLIP_Y:
|
||||||
shift_y = self.maxY
|
shift_y = self.maxY
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.x, -c.y, c.z), v)
|
self.set(Coordinate(c[0], -c[1], c[2]), v)
|
||||||
self.shift(shift_y=shift_y)
|
self.shift(shift_y=shift_y)
|
||||||
elif mode == GridTransformation.FLIP_Z:
|
elif mode == GridTransformation.FLIP_Z:
|
||||||
shift_z = self.maxZ
|
shift_z = self.maxZ
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
self.set(Coordinate(c.x, c.y, -c.z), v)
|
self.set(Coordinate(c[0], c[1], -c[2]), v)
|
||||||
self.shift(shift_z=shift_z)
|
self.shift(shift_z=shift_z)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(mode)
|
raise NotImplementedError(mode)
|
||||||
@ -370,9 +368,9 @@ class Grid:
|
|||||||
self.__grid = {}
|
self.__grid = {}
|
||||||
for c, v in coords.items():
|
for c, v in coords.items():
|
||||||
if self.mode3D:
|
if self.mode3D:
|
||||||
nc = Coordinate(c.x + shift_x, c.y + shift_y, c.z + shift_z)
|
nc = Coordinate(c[0] + shift_x, c[1] + shift_y, c[2] + shift_z)
|
||||||
else:
|
else:
|
||||||
nc = Coordinate(c.x + shift_x, c.y + shift_y)
|
nc = Coordinate(c[0] + shift_x, c[1] + shift_y)
|
||||||
self.set(nc, v)
|
self.set(nc, v)
|
||||||
|
|
||||||
def shift_zero(self, recalc: bool = True):
|
def shift_zero(self, recalc: bool = True):
|
||||||
@ -684,17 +682,5 @@ class Grid:
|
|||||||
|
|
||||||
return grid
|
return grid
|
||||||
|
|
||||||
def __eq__(self, other: Grid) -> bool:
|
def __hash__(self):
|
||||||
if not isinstance(other, Grid):
|
return hash(frozenset(self.__grid.items()))
|
||||||
return False
|
|
||||||
|
|
||||||
other_active = set(other.getActiveCells())
|
|
||||||
for c, v in self.__grid.items():
|
|
||||||
if other.get(c) != v:
|
|
||||||
return False
|
|
||||||
other_active.remove(c)
|
|
||||||
|
|
||||||
if other_active:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user