Sympy 延长线段的长度

问题描述 投票:0回答:2

我正在尝试使用 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

python geometry sympy
2个回答
2
投票

取由点定义的线段

>>> 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

1
投票

改变线的长度意味着什么?新的起点和终点在哪里?

我假设您希望保持

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))
© www.soinside.com 2019 - 2024. All rights reserved.