我正在尝试使用 Sympy 来计算沿延长线段的点。
所以首先我在 point_a 和 point_b 之间设置一条线
Segment
:
from sympy import Point, Segment
point_a = (4, 1)
point_b = (10, 3)
p1, p2 = Point(point_a), Point(point_b)
seg = Segment(p1, p2)
在此示例中,线段的长度约为
6.32455532034
我希望能够将
point_a
保留在原处,但将 point_b
延伸出来,以便该段的长度为 20
(而不是 6.32
)
seg.length = 20
new_end_point = seg.points[1]
但是它不允许像这样改变线的长度。有没有简单的方法可以做到这一点?
注1:我正在尝试使用 Sympy 来实现此目的,以保持代码对非数学人员(例如我自己)可读
注2:
20
是与p1和p2之间的起始距离无关的任意长度
感谢@smichr的回答,我添加了他所说内容的简化版本:
from sympy import Point, Ray, Circle
point_a = (4, 1)
point_b = (10, 3)
extend = 20
p1, p2 = Point(point_a), Point(point_b)
ray = Ray(p1, p2)
c = Circle(p1, extend).intersection(ray)
# The resulting point
result = c[0].evalf().coordinates
取由点定义的线段
>>> p1=(0,0)
>>> p2=(1,0)
>>> s=Segment(p1,p2)
将其投射到射线并查看它与以 p1 为中心的所需半径的圆相交的位置。它只会在一个点相交,因此请将该点用于您的新线段:
>>> from sympy.abc import t
>>> from sympy import Ray, Circle
>>> Circle(p1, 20).intersection(Ray(*s.args))[0]
Point(20, 0)
>>> new_segment = Segment(p1, _)
你可以将其包装成这样的函数:
>>> def directed_segment(line, length):
... from sympy import Circle, Ray
... p3 = Ray(*line.args).intersection(Circle(line.p1, length))[0]
... return line.func(line.p1, p3)
...
>>> directed_segment(s,20)
Segment2D(Point2D(0, 0), Point2D(20, 0))
最简单的方法是在所需点的两个方向上缩放线段(在您的情况下是第一个参数)。比例因子将是您所需的长度
l
除以当前长度。下面定义了一个名为 new_seg
的辅助函数,用于将 3,4,5 斜边延长到 10 的长度,同时保持线段的初始点:
new_seg=lambda s,l : s.scale(*[l/s.length]*2, s.args[0])
>>> new_seg(Segment((1,2),(4,6)), 10)
Segment2D(Point2D(1, 2), Point2D(7, 10))
>>> assert _.length == 10
如果您使用
s.midpoint
而不是 s.args[0]
,则线段的中点将保持不变。例如,要在保持中点的同时将长度加倍,
>>> t=s.scale(2,2,s.midpoint)
>>> assert t.length = 2*s.length and t.midpoint == s.midpoint
改变线的长度意味着什么?新的起点和终点在哪里?
我假设您希望保持
p1
不变,但移动 p2
,使其与 p1
的距离增加两倍,但方向与从 p1
到 p2
的方向相同:
In [12]: p1, p2 = Point2D(4, 1), Point2D(10, 3)
In [13]: p3 = p1 + 2*(p2 - p1)
In [14]: p3
Out[14]: Point2D(16, 5)
In [15]: Segment2D(p1, p3)
Out[15]: Segment2D(Point2D(4, 1), Point2D(16, 5))
或者,您可以使多个符号化,然后替换不同的值:
In [16]: x = symbols('x')
In [17]: line = Segment2D(p1, p1 + x*(p2 - p1))
In [18]: line
Out[18]: Segment2D(Point2D(4, 1), Point2D(6*x + 4, 2*x + 1))
In [19]: line.subs(x, 2)
Out[19]: Segment2D(Point2D(4, 1), Point2D(16, 5))