import math from typing import List class Pos: def __init__(self, x: float = 0, y: float = 0): self.x_pos = x self.y_pos = y pass def __add__(self, other: 'Pos') -> 'Pos': return Pos(self.x_pos + other.x_pos, self.y_pos + other.y_pos) def __sub__(self, other: 'Pos') -> 'Pos': return Pos(self.x_pos - other.x_pos, self.y_pos - other.y_pos) def __iadd__(self, other: 'Pos') -> 'Pos': self.x_pos += other.x_pos self.y_pos += other.y_pos return self def __isub__(self, other: 'Pos') -> 'Pos': self.x_pos -= other.x_pos self.y_pos -= other.y_pos return self def __mul__(self, t: float) -> 'Pos': return Pos(self.x_pos * t, self.y_pos * t) def __imul__(self, t: float) -> 'Pos': self.x_pos *= t self.y_pos *= t return self def vec_length(self) -> float: return math.sqrt(self.x_pos**2 + self.y_pos**2) def normalized(self) -> 'Pos': dist = self.vec_length() if dist == 0: return Pos(0, 0) return self * (1/dist) def to_text(self) -> str: return f"pos<{self.__hash__()}>{{{self.x_pos}, {self.y_pos}}}" def make_copy(self) -> 'Pos': return Pos(self.x_pos, self.y_pos) class Point: def __init__(self, name:str): self.point_name = name pass def name(self) -> str: return self.point_name def make_copy(self) -> 'Point': return Point(self.point_name) class PositionalPoint(Point, Pos): def __init__(self, name: str, x: float, y: float): Point.__init__(self, name) Pos.__init__(self, x, y) pass def make_copy(self) -> 'PositionalPoint': return PositionalPoint(self.name(), self.x_pos, self.y_pos) class Line: def __init__(self, p0: Point, p1: Point): self.point_set = [p0, p1] pass def points(self) -> List[Point]: return self.point_set def make_copy(self) -> 'Line': return Line(self.points()[0].make_copy(), self.points()[1].make_copy()) class Arrow(Line): def __init__(self, start: Point, end: Point): Line.__init__(self, start, end) pass def start_point(self): return self.point_set[0] def end_point(self): return self.point_set[1]