From 97e0e3c39cb0de5b4cfa3bf3b46aeff8116de6aa Mon Sep 17 00:00:00 2001 From: songsenand Date: Sat, 27 Jan 2024 01:29:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(toydesigner/objects.py):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=B8=B8=E8=A7=812D=E5=9B=BE=E5=BD=A2=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- toydesigner/__init__.py | 0 toydesigner/objects.py | 142 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 toydesigner/__init__.py create mode 100644 toydesigner/objects.py diff --git a/toydesigner/__init__.py b/toydesigner/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/toydesigner/objects.py b/toydesigner/objects.py new file mode 100644 index 0000000..2a8ecf4 --- /dev/null +++ b/toydesigner/objects.py @@ -0,0 +1,142 @@ +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")