在另一条线的一点上绘制固定长度的垂直线

时间:2019-07-16 20:37:29

标签: python geometry shapely

我有两个点A(10,20)和B(15,30)。这些点生成线AB。我需要在B点上画一条垂直线CD,长度为6(每个方向3个单位),在Python中。

我已经使用以下代码获得了AB行的某些属性:

from scipy import stats
x = [10,15]
y = [20,30]
slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)

如何计算C和D的位置。我需要它们的X和Y值。 enter image description here

使用Shapely库将C和D的值用于完成另一个目标。

3 个答案:

答案 0 :(得分:1)

如果slope是AB的斜率,则CD的斜率是-1/slope。这等于垂直变化高于水平变化:dy/dx = -1/slope。这给出了dx = -slope*dx。根据毕达哥拉斯定理,您有3**2 = dy**2+dx**2。替换为dx,您将获得

3**2 = (-slope*dy)**2+dy**2
3**2 = (slope**2 + 1)*dy**2
dy**2 = 3**2/(slope**2+1)
dy = math.sqrt(3**2/(slope**2+1))

然后您将获得dx = -slope*dy。最后,您可以使用dxdy来获得C和D。因此代码如下:

import math
dy = math.sqrt(3**2/(slope**2+1))
dx = -slope*dy
C[0] = B[0] + dx
C[1] = B[1] + dy
D[0] = B[0] - dx
D[1] = B[1] - dy

(请注意,尽管math.sqrt仅返回一个数字,但通常会有一个正负平方根。C对应于正平方根,D对应于负数)。

答案 1 :(得分:0)

您可能应该使用向量来计算点的位置。

  • 创建vector AB
  • 计算其normalized perpendicular
  • 将此值加或减3倍到B

借助简单,可重复使用的Vector class,该计算是微不足道的,并且读起来像英语:

找到与AB相距3的{​​{1}}垂直的点:
B P1 = B + (B-A).perp().normalized() * 3

P2 = B + (B-A).perp().normalized() * 3

输出:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    def dot(self, other):
        return self.x * other.x + self.y * other.y
    def norm(self):
        return self.dot(self)**0.5
    def normalized(self):
        norm = self.norm()
        return Vector(self.x / norm, self.y / norm)
    def perp(self):
        return Vector(1, -self.x / self.y)
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    def __str__(self):
        return f'({self.x}, {self.y})'


A = Vector(10, 20)
B = Vector(15, 30)

AB = B - A  
AB_perp_normed = AB.perp().normalized()
P1 = B + AB_perp_normed * 3
P2 = B - AB_perp_normed * 3

print(f'Point{P1}, and Point{P2}')

答案 2 :(得分:0)

由于您对使用Shapely感兴趣,因此获得我能想到的垂直线的最简单方法是使用parallel_offset方法将两条平行线连接到AB,并将其端点连接起来:

from shapely.geometry import LineString

a = (10, 20)
b = (15, 30)
cd_length = 6

ab = LineString([a, b])
left = ab.parallel_offset(cd_length / 2, 'left')
right = ab.parallel_offset(cd_length / 2, 'right')
c = left.boundary[1]
d = right.boundary[0]  # note the different orientation for right offset
cd = LineString([c, d])

enter image description here

和CD的坐标:

>>> c.x, c.y
(12.316718427000252, 31.341640786499873)
>>> d.x, d.y
(17.683281572999746, 28.658359213500127)