deal with shapes (like squares and cubes)
This commit is contained in:
parent
c4cfd0b298
commit
5e3bf28e7e
@ -174,7 +174,7 @@ class Coordinate:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def generate(from_x: int, to_x: int, from_y: int, to_y: int,
|
def generate(from_x: int, to_x: int, from_y: int, to_y: int,
|
||||||
from_z: int = None, to_z: int = None) -> List[Coordinate]:
|
from_z: int = None, to_z: int = None) -> List[Coordinate]:
|
||||||
if from_z is None and to_z is None:
|
if from_z is None or to_z is None:
|
||||||
return [Coordinate(x, y) for x in range(from_x, to_x + 1) for y in range(from_y, to_y + 1)]
|
return [Coordinate(x, y) for x in range(from_x, to_x + 1) for y in range(from_y, to_y + 1)]
|
||||||
else:
|
else:
|
||||||
return [
|
return [
|
||||||
@ -183,3 +183,84 @@ class Coordinate:
|
|||||||
for y in range(from_y, to_y + 1)
|
for y in range(from_y, to_y + 1)
|
||||||
for z in range(from_z, to_z + 1)
|
for z in range(from_z, to_z + 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Shape:
|
||||||
|
top_left: Coordinate
|
||||||
|
bottom_right: Coordinate
|
||||||
|
mode_3d: bool
|
||||||
|
|
||||||
|
def __init__(self, top_left: Coordinate, bottom_right: Coordinate):
|
||||||
|
"""
|
||||||
|
in 2D mode: top_left is the upper left corner and bottom_right the lower right
|
||||||
|
(top_left.x <= bottom_right.x and top_left.y <= bottom_right.y)
|
||||||
|
in 3D mode: same logic applied, just for 3D Coordinates
|
||||||
|
top_left is the upper left rear corner and bottom_right the lower right front
|
||||||
|
(top_left.x <= bottom_right.x and top_left.y <= bottom_right.y and top_left.z <= bottom_right.z)
|
||||||
|
"""
|
||||||
|
self.top_left = top_left
|
||||||
|
self.bottom_right = bottom_right
|
||||||
|
self.mode_3d = top_left.z is not None and bottom_right.z is not None
|
||||||
|
|
||||||
|
def size(self):
|
||||||
|
if not self.mode_3d:
|
||||||
|
return (self.bottom_right.x - self.top_left.x + 1) * (self.bottom_right.y - self.top_left.y + 1)
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
(self.bottom_right.x - self.top_left.x + 1)
|
||||||
|
* (self.bottom_right.y - self.top_left.y + 1)
|
||||||
|
* (self.bottom_right.z - self.top_left.z + 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
def intersection(self, other: Shape) -> Union[Shape, None]:
|
||||||
|
"""
|
||||||
|
returns a Shape of the intersecting part, or None if the Shapes don't intersect
|
||||||
|
"""
|
||||||
|
if self.mode_3d != other.mode_3d:
|
||||||
|
raise ValueError("Cannot calculate intersection between 2d and 3d shape")
|
||||||
|
|
||||||
|
if not self.mode_3d:
|
||||||
|
intersect_top_left = Coordinate(
|
||||||
|
self.top_left.x if self.top_left.x > other.top_left.x else other.top_left.x,
|
||||||
|
self.top_left.y if self.top_left.y > other.top_left.y else other.top_left.y,
|
||||||
|
)
|
||||||
|
intersect_bottom_right = Coordinate(
|
||||||
|
self.bottom_right.x if self.bottom_right.x < other.bottom_right.x else other.bottom_right.x,
|
||||||
|
self.bottom_right.y if self.bottom_right.y < other.bottom_right.y else other.bottom_right.y,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
intersect_top_left = Coordinate(
|
||||||
|
self.top_left.x if self.top_left.x > other.top_left.x else other.top_left.x,
|
||||||
|
self.top_left.y if self.top_left.y > other.top_left.y else other.top_left.y,
|
||||||
|
self.top_left.z if self.top_left.z > other.top_left.z else other.top_left.z,
|
||||||
|
)
|
||||||
|
intersect_bottom_right = Coordinate(
|
||||||
|
self.bottom_right.x if self.bottom_right.x < other.bottom_right.x else other.bottom_right.x,
|
||||||
|
self.bottom_right.y if self.bottom_right.y < other.bottom_right.y else other.bottom_right.y,
|
||||||
|
self.bottom_right.z if self.bottom_right.z < other.bottom_right.z else other.bottom_right.z,
|
||||||
|
)
|
||||||
|
|
||||||
|
if intersect_top_left <= intersect_bottom_right:
|
||||||
|
return self.__class__(intersect_top_left, intersect_bottom_right)
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
return self.intersection(other)
|
||||||
|
|
||||||
|
def __rand__(self, other):
|
||||||
|
return self.intersection(other)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s(%s, %s)" % (self.__class__.__name__, self.top_left, self.bottom_right)
|
||||||
|
|
||||||
|
|
||||||
|
class Square(Shape):
|
||||||
|
def __init__(self, top_left, bottom_right):
|
||||||
|
super().__init__(top_left, bottom_right)
|
||||||
|
self.mode_3d = False
|
||||||
|
|
||||||
|
|
||||||
|
class Cube(Shape):
|
||||||
|
def __init__(self, top_left, bottom_right):
|
||||||
|
if top_left.z is None or bottom_right.z is None:
|
||||||
|
raise ValueError("Both Coordinates need to be 3D")
|
||||||
|
super().__init__(top_left, bottom_right)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user