Compare commits
3 Commits
f832238900
...
97e0e3c39c
| Author | SHA1 | Date |
|---|---|---|
|
|
97e0e3c39c | |
|
|
86c1f27e38 | |
|
|
d77f119c63 |
|
|
@ -18,6 +18,7 @@ ezdxf = "^1.1.4"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
commitizen = "^3.13.0"
|
commitizen = "^3.13.0"
|
||||||
|
pytest = "^7.4.4"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# import sys
|
||||||
|
|
||||||
|
# sys.path.append('/home/songsenand/Project/ToyDesigner/')
|
||||||
|
|
||||||
|
from toydesigner.objects import *
|
||||||
|
|
||||||
|
|
||||||
|
def test_line():
|
||||||
|
line1 = Line((1, 3), (1, 4))
|
||||||
|
assert line1.slope() == float("inf")
|
||||||
|
assert line1.y_intercept() == 0
|
||||||
|
line2 = Line((1, 1), (2, 2))
|
||||||
|
assert line2.slope() == 1
|
||||||
|
assert line2.y_intercept() == 0
|
||||||
|
assert line2.equation() == "y = 1.0x"
|
||||||
|
line3 = Line((37, 5), (7, 29))
|
||||||
|
assert line3.slope() == -0.8
|
||||||
|
assert line3.y_intercept() == 34.6
|
||||||
|
assert line3.equation() == "y = -0.8x + 34.6"
|
||||||
|
assert (12, 25) in line3
|
||||||
|
assert (12, 12) not in line3
|
||||||
|
assert (3, 32.2) not in line3
|
||||||
|
assert line3.contains((6, 29.8), allow_on_extended=True) == True
|
||||||
|
assert line3.length()**2 == (37 - 7) ** 2 + (5 - 29) ** 2
|
||||||
|
|
@ -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")
|
||||||
Loading…
Reference in New Issue