def point_maker(pre_point): if isinstance(pre_point, Point): return pre_point elif isinstance(pre_point, tuple): return Point(pre_point[0], pre_point[1]) else: raise ValueError("Invalid input for Point") class ShapeBase(object): def __init__(self): pass def show(self): pass def move(self, dx, dy): pass def set_color(self, color): pass def get_color(self): pass class Shape2D(ShapeBase): def __init__(self, **kwargs): super(Shape2D, self).__init__() self.color = kwargs.get("color", "white") self.fill = kwargs.get("fill", False) self.width = kwargs.get("width", 1) class Point(Shape2D): def __init__(self, x, y): super(Point, self).__init__() self._x = x self._y = y @property def x(self): return self._x @property def y(self): return self._y class Line(Shape2D): def __init__(self, point1, point2, **kwargs): super(Line, self).__init__(**kwargs) self.point1 = point_maker(point1) self.point2 = point_maker(point2) def contains(self, point, allow_on_extended=False): """判断点`point`是否在线段上 Args: point (Point or tuple): 需要判断的点 allow_on_extended (bool, optional): 是否允许点在线段的延长线上. Defaults to False. Returns: _type_: boolean """ point = point_maker(point) f = self.function() if allow_on_extended: return f(point.x) == point.y else: return f(point.x) == point.y and ( (point.x >= min(self.point1.x, self.point2.x) and point.x <= max(self.point1.x, self.point2.x))) # 通过关键字`in`判断点是否在线段上 def __contains__(self, point): return self.contains(point) # 该线段所在直线的纵截距 def y_intercept(self): if self.point1.x == self.point2.x: return 0 return ((self.point1.y * self.point2.x) \ - (self.point1.x * self.point2.y)) \ / (self.point2.x - self.point1.x) # 该线段的斜率 def slope(self): if self.point1.x - self.point2.x == 0: return float("inf") else: return (self.point1.y - self.point2.y) / (self.point1.x - self.point2.x) # 该线段所在直线的函数方程 def function(self): a = self.slope() b = self.y_intercept() return lambda x: a * x + b # 该线段的函数式 def equation(self): if self.point1.x - self.point2.x == 0: return "y = " + str(self.point1.y) else: a = self.slope() b = self.y_intercept() return f"y = {a}x{' + ' if b != 0 else ''}{b if b != 0 else ''}" # 该线段的长度 def length(self): return ( (self.point1.x - self.point2.x) ** 2 + (self.point1.y - self.point2.y) ** 2 ) ** 0.5 # 该线段与另一线段的交点 def intersection(self, other): if isinstance(other, Line): if self.slope() == other.slope(): return None else: x = ( self.slope() * other.point1.x - self.point1.y + other.slope() * self.point1.x - other.point1.y ) / (self.slope() - other.slope()) y = self.slope() * (x - self.point1.x) + self.point1.y return Point(x, y) else: raise ValueError("Invalid input for Line") class Rectangle(Shape2D): def __init__(self, point1, point2): super(Rectangle, self).__init__() if isinstance(point1, Point) and isinstance(point2, Point): self.point1 = point1 self.point2 = point2 elif isinstance(point1, tuple) and isinstance(point2, tuple): self.point1 = Point(point1[0], point1[1]) self.point2 = Point(point2[0], point2[1]) else: raise ValueError("Invalid input for Rectangle")