# Container classes for points and lines import math class Point: IDX_X = 0 IDX_Y = 1 def __init__(self, x, y): self._x = x self._y = y def get_cartesian(self) -> tuple: return self.get_x(), self.get_y() def get_polar(self) -> tuple: pass def get_x(self) -> float: return self._x def get_y(self) -> float: return self._y def get_r(self) -> float: pass def get_theta(self) -> float: pass def apply_polar_shift(self, r, theta) -> None: pass def apply_cartesian_shift(self, x, y) -> None: pass def distance_from_point(self, point) -> float: # Euclidian distance distance = math.sqrt((self.get_x() - point.get_x())**2 + (self.get_y() - point.get_y())**2) return distance class PointWithID(Point): IDX_WALLID = 3 def __init__(self, x, y, wall_id): super().__init__(x, y) self._wall_id = wall_id def get_wallid(self): return self._wall_id class StraightLine: IDX_M = 0 IDX_B = 1 def __init__(self, p1: PointWithID, p2: PointWithID): self.wall_id = p1.get_wallid() self.m, self.b = self.__find_line(p1, p2) v = ValueError() if not self.__matching_wall_ids(p1, p2): raise WallIDMismatch('Wall ID for points does not match') def __find_line(self, p1:PointWithID, p2:PointWithID) -> tuple: try: m = (p2.get_y() - p1.get_y()) / (p2.get_x() - p1.get_x()) except ZeroDivisionError: m = None # Using p1 to find b b = p1.get_y() - (m*p1.get_x()) # y = mx + b # b = y - mx return m, b def __matching_wall_ids(self, p1, p2) -> bool: if p1.get_wallid() == p2.get_wallid(): return True return False """ Return slope for non-virtical line. None for virtical lines """ def get_m(self)-> float: return self.m def get_b(self) -> float: return self.b def get_wall_id(self) -> str: return self.wall_id def intercept(self, line) -> Point: # Basically when the two lines have the same cords (x,y) # As a formula x = (b2 - b1)/ (m1 + m2) to find X, then apply y = mx + b on any line x = (line.get_b() - self.get_b()) / (line.get_m() + line.get_m()) y = self.get_m()*x + self.get_b() # Inline to reduce overhead return Point(x, y) def intercept_list(self, lines) -> list: # May return a sorted list based on distance # Consider vectorized (SIMD) implmentaion with numpy pass class WallIDMismatch (RuntimeError): ... # Helper methods def polar_to_cart(r, theta_deg) -> tuple: #print('polar to cart ',r, theta_deg) x = r * math.cos(deg_to_rad(theta_deg)) y = r * math.sin(deg_to_rad(theta_deg)) return x,y def deg_to_rad(theta_deg) -> float: return theta_deg*(math.pi/180) def point_from_polar(r, theta, wall_id) -> PointWithID: x, y = polar_to_cart(r, theta) return PointWithID(x, y, wall_id)