"""
ManhattanArc3D Class (Not working)
This code defines a class called ManhattanArc3D, which represents a geometric object in a 3D space.
The purpose of this class is to handle operations on points, segments, or regions that are
rotated 45 degrees. It's designed to work with different types of coordinates, such as
integers, floats, or intervals.
The ManhattanArc3D class takes four inputs when creating an object: xcoord, ycoord, zcoord, and wcoord. These
represent the coordinates of the object in the rotated space. The class doesn't produce a
specific output on its own, but it provides various methods to manipulate and interact
with these objects.
The class achieves its purpose by storing the coordinates in a Point object and providing
methods to perform operations like translation, enlargement, intersection, and merging
with other ManhattanArc3D instances. It uses a 45-degree rotated coordinate system, which allows
for easier calculations in certain geometric operations.
"""
from .generic import center, intersection, lower, min_dist, nearest, upper
from .interval import enlarge
from .point import Point
[docs]
class ManhattanArc3D:
"""
Merging point, segment, or region ⛝
"""
[docs]
def __init__(self, w, x, y, z) -> None:
"""
Initialize a ManhattanArc3D object with 4-interval coordinates.
:param w: The w-interval coordinate in the 4-interval space.
:param x: The x-interval coordinate in the 4-interval space.
:param y: The y-interval coordinate in the 4-interval space.
:param z: The z-interval coordinate in the 4-interval space.
Examples:
>>> a = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> print(a)
/12, -4, 2, 6/
"""
self.w_i = w
self.x_i = x
self.y_i = y
self.z_i = z
[docs]
@classmethod
def from_point(cls, pt) -> "ManhattanArc3D":
"""
Create a ManhattanArc3D object from a 3D point.
:param pt: A 3D point.
:type pt: Point
:return: A new ManhattanArc3D object.
:rtype: ManhattanArc3D
"""
xcoord = pt.xcoord.xcoord
ycoord = pt.ycoord
zcoord = pt.xcoord.ycoord
xx = xcoord - ycoord
yy = xcoord + ycoord
w = (yy + zcoord) // 2
x = (xx - zcoord) // 2
y = (xx + zcoord) // 2
z = (yy - zcoord) // 2
return cls(w, x, y, z)
[docs]
@staticmethod
def construct(xcoord, ycoord, zcoord) -> "ManhattanArc3D":
"""
Constructs a ManhattanArc3D object from standard x and y coordinates.
:param xcoord: The x-coordinate.
:param ycoord: The y-coordinate.
:param zcoord: The z-coordinate.
:return: A new ManhattanArc3D object.
Examples:
>>> a = ManhattanArc3D.construct(8, 10, 6)
>>> print(a)
/12, -4, 2, 6/
"""
xx = xcoord - ycoord
yy = xcoord + ycoord
w = (yy + zcoord) // 2
x = (xx - zcoord) // 2
y = (xx + zcoord) // 2
z = (yy - zcoord) // 2
return ManhattanArc3D(w, x, y, z)
[docs]
def __repr__(self) -> str:
"""
The `__repr__` function returns a string representation of an `ManhattanArc3D` object, including the class
name and its x and y coordinates, which is useful for debugging.
:return: The `__repr__` method is returning a string representation of the `ManhattanArc3D` object.
Examples:
>>> a = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> repr(a)
'ManhattanArc3D(12, -4, 2, 6)'
"""
return (
f"{self.__class__.__name__}({self.w_i}, {self.x_i}, {self.y_i}, {self.z_i})"
)
[docs]
def __str__(self) -> str:
"""
The `__str__` function returns a string representation of an object, specifically in the format
"/xcoord, ycoord/".
:return: The method `__str__` returns a string representation of the object. In this case, it
returns a string in the format "/xcoord, ycoord/" where xcoord and ycoord are the x and y
coordinates of the object.
Examples:
>>> a = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> print(a)
/12, -4, 2, 6/
"""
return f"/{self.w_i}, {self.x_i}, {self.y_i}, {self.z_i}/"
[docs]
def __eq__(self, other: object) -> bool:
"""
The `__eq__` function checks if two `ManhattanArc3D` instances have the same `impl` attribute.
:param other: The `other` parameter represents the object that we are comparing with the current object
:return: The `__eq__` method is returning a boolean value.
Examples:
>>> a = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> b = ManhattanArc3D(7 + 9 + 2, 7 - 9 - 2, 7 - 9 + 2, 7 + 9 - 2)
>>> a == b
False
>>> c = ManhattanArc3D.construct(8, 10, 6)
>>> a == c
True
"""
if not isinstance(other, ManhattanArc3D):
return NotImplemented
return (self.w_i, self.x_i, self.y_i, self.z_i) == (
other.w_i,
other.x_i,
other.y_i,
other.z_i,
)
[docs]
def min_dist_with(self, other) -> int:
"""
The `min_dist_with` function calculates the minimum rectilinear distance between two objects.
:param other: The `other` parameter represents another object with which you want to calculate
the minimum rectilinear distance
:return: the minimum rectilinear distance between the two objects.
Examples:
>>> r1 = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> r2 = ManhattanArc3D(7 + 9 + 2, 7 - 9 - 2, 7 - 9 + 2, 7 + 9 - 2)
>>> r1.min_dist_with(r2)
8
"""
w_dist = min_dist(self.w_i, other.w_i)
x_dist = min_dist(self.x_i, other.x_i)
y_dist = min_dist(self.y_i, other.y_i)
z_dist = min_dist(self.z_i, other.z_i)
return int(max([w_dist, x_dist, y_dist, z_dist]))
[docs]
def enlarge_with(self, alpha: int) -> "ManhattanArc3D":
"""
Enlarge the ManhattanArc3D intervals by a given factor.
Expands each coordinate interval by the specified alpha value using the
enlarge function from the interval module.
:param alpha: The expansion factor to enlarge each coordinate interval.
:return: A new ManhattanArc3D object with enlarged coordinates.
Examples:
>>> a = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> r = a.enlarge_with(1)
>>> print(r)
/[11, 13], [-5, -3], [1, 3], [5, 7]/
"""
wcoord = enlarge(self.w_i, alpha)
xcoord = enlarge(self.x_i, alpha)
ycoord = enlarge(self.y_i, alpha)
zcoord = enlarge(self.z_i, alpha)
return ManhattanArc3D(wcoord, xcoord, ycoord, zcoord)
[docs]
def intersect_with(self, other: "ManhattanArc3D") -> "ManhattanArc3D":
"""
Calculate the intersection between two ManhattanArc3D objects.
Computes the coordinate-wise intersection of the intervals stored in both
ManhattanArc3D objects, returning a new ManhattanArc3D with the intersected
coordinates.
:param other: Another ManhattanArc3D object to intersect with.
:return: A new ManhattanArc3D object containing the intersection coordinates.
"""
w_inter = intersection(self.w_i, other.w_i)
x_inter = intersection(self.x_i, other.x_i)
y_inter = intersection(self.y_i, other.y_i)
z_inter = intersection(self.z_i, other.z_i)
return ManhattanArc3D(w_inter, x_inter, y_inter, z_inter)
[docs]
def merge_with(self, other, alpha: int):
"""
The `merge_with` function takes another object as input, calculates the minimum Manhattan distance between
the two objects, enlarges the objects based on the calculated distance, finds the intersection
of the enlarged objects, and returns a new object with the coordinates of the intersection.
:param other: The "other" parameter is an object of the same class as the current object. It
represents another instance of the class that we want to merge with the current instance
:return: The `merge_with` method returns a new `ManhattanArc3D` object with the x-coordinate and
y-coordinate of the intersection of the two objects being merged.
Examples:
>>> r1 = ManhattanArc3D(4 + 5 + 3, 4 - 5 - 3, 4 - 5 + 3, 4 + 5 - 3)
>>> r2 = ManhattanArc3D(7 + 9 + 2, 7 - 9 - 2, 7 - 9 + 2, 7 + 9 - 2)
>>> r1.merge_with(r2, 4)
ManhattanArc3D([14, 16], [-8, 0], [-2, 4], [10, 10])
"""
distance = self.min_dist_with(other)
trr1 = self.enlarge_with(alpha)
trr2 = other.enlarge_with(distance - alpha)
return trr1.intersect_with(trr2)
[docs]
def to_point(self):
"""
Converts the ManhattanArc3D object back to a Point object.
:return: A Point object representing the coordinates of the ManhattanArc3D object.
Examples:
>>> a = ManhattanArc3D(12, -4, 2, 6)
>>> print(a.to_point())
((8, 6), 10)
"""
xx = self.x_i + self.y_i
zz = self.z_i + self.w_i
xcoord = (xx + zz) // 2
ycoord = (-xx + zz) // 2
zcoord = (self.w_i - self.x_i + self.y_i - self.z_i) // 2
return Point(Point(xcoord, zcoord), ycoord)
[docs]
def get_center(self):
"""
Calculates the center of the merging segment
:return: The center of the merging segment.
Examples:
>>> r1 = ManhattanArc3D(40 + 50 + 30, 40 - 50 - 30, 40 - 50 + 30, 40 + 50 - 30)
>>> r2 = ManhattanArc3D(70 + 90 + 20, 70 - 90 - 20, 70 - 90 + 20, 70 + 90 - 20)
>>> r3 = r1.merge_with(r2, 40)
>>> print(r3.get_center())
((110, 50), 140)
"""
wcoord = center(self.w_i)
xcoord = center(self.x_i)
ycoord = center(self.y_i)
zcoord = center(self.z_i)
return ManhattanArc3D(wcoord, xcoord, ycoord, zcoord).to_point()
[docs]
def get_lower_corner(self):
"""
Calculates the lower corner of the merging segment
:return: The lower corner of the merging segment.
Examples:
>>> r1 = ManhattanArc3D(40 + 50 + 30, 40 - 50 - 30, 40 - 50 + 30, 40 + 50 - 30)
>>> r2 = ManhattanArc3D(70 + 90 + 20, 70 - 90 - 20, 70 - 90 + 20, 70 + 90 - 20)
>>> r3 = r1.merge_with(r2, 40)
>>> print(r3.get_lower_corner())
((70, 50), 170)
"""
wcoord = lower(self.w_i)
xcoord = lower(self.x_i)
ycoord = lower(self.y_i)
zcoord = lower(self.z_i)
return ManhattanArc3D(wcoord, xcoord, ycoord, zcoord).to_point()
[docs]
def get_upper_corner(self):
"""
Calculates the upper corner of the merging segment
:return: The upper corner of the merging segment.
Examples:
>>> r1 = ManhattanArc3D(40 + 50 + 30, 40 - 50 - 30, 40 - 50 + 30, 40 + 50 - 30)
>>> r2 = ManhattanArc3D(70 + 90 + 20, 70 - 90 - 20, 70 - 90 + 20, 70 + 90 - 20)
>>> r3 = r1.merge_with(r2, 40)
>>> print(r3.get_upper_corner())
((150, 50), 110)
"""
wcoord = upper(self.w_i)
xcoord = upper(self.x_i)
ycoord = upper(self.y_i)
zcoord = upper(self.z_i)
return ManhattanArc3D(wcoord, xcoord, ycoord, zcoord).to_point()
def _nearest_point_to(self, manhattan_arc):
"""
Calculates the nearest point on the merging segment to another ManhattanArc3D object.
:param manhattan_arc: Another ManhattanArc3D object to which we want to find the nearest point on the merging segment.
:return: The nearest point on the merging segment to the given ManhattanArc3D object.
Examples:
>>> r1 = ManhattanArc3D(40 + 50 + 30, 40 - 50 - 30, 40 - 50 + 30, 40 + 50 - 30)
>>> r2 = ManhattanArc3D(70 + 90 + 20, 70 - 90 - 20, 70 - 90 + 20, 70 + 90 - 20)
>>> r3 = r1.merge_with(r2, 40)
>>> print(r3)
/[140, 160], [-80, 0], [-20, 40], [100, 100]/
>>> print(r3._nearest_point_to(ManhattanArc3D.construct(0, 0, 0)))
((120, 20), 120)
>>> print(ManhattanArc3D(140, 0, 0, 100).to_point())
((120, 20), 120)
"""
wcoord = nearest(self.w_i, manhattan_arc.w_i)
xcoord = nearest(self.x_i, manhattan_arc.x_i)
ycoord = nearest(self.y_i, manhattan_arc.y_i)
zcoord = nearest(self.z_i, manhattan_arc.z_i)
return ManhattanArc3D(wcoord, xcoord, ycoord, zcoord).to_point()
[docs]
def nearest_point_to(self, other):
"""
Calculates the nearest point on the merging segment to another ManhattanArc3D object.
:param manhattan_arc: Another ManhattanArc3D object to which we want to find the nearest point on the merging segment.
:return: The nearest point on the merging segment to the given ManhattanArc3D object.
Examples:
>>> r1 = ManhattanArc3D(40 + 50 + 30, 40 - 50 - 30, 40 - 50 + 30, 40 + 50 - 30)
>>> r2 = ManhattanArc3D(70 + 90 + 20, 70 - 90 - 20, 70 - 90 + 20, 70 + 90 - 20)
>>> r3 = r1.merge_with(r2, 40)
>>> print(r3.nearest_point_to(Point(Point(1000, 1000), 1000)))
((110, 90), 150)
"""
ms = ManhattanArc3D.from_point(other)
return self._nearest_point_to(ms)