Python 计算给定直线起点(x,y)终点(x,y)上的投影点位置(x,y)

Python 计算给定直线起点(x,y)终点(x,y)上的投影点位置(x,y),python,numpy,Python,Numpy,如果我有三个点P1,P2,P3及其坐标(x,y) P1(x,y)和P3(x,y)是直线(起点、终点)的坐标,P3是需要投影的点 如何找到点r(x,y)的坐标,即P3在P1和P2上的投影 适用于2D和3D的Numpy代码(基于): 更新 绘图: 更新2 如果您需要该点属于该段,则需要进行一个小的修改 def point_on_line(a, b, p): ap = p - a ab = b - a t = np.dot(ap, ab) / np.dot(ab, ab)

如果我有三个点P1,P2,P3及其坐标(x,y)

P1(x,y)和P3(x,y)是直线(起点、终点)的坐标,P3是需要投影的点

如何找到点r(x,y)的坐标,即P3在P1和P2上的投影

适用于2D和3D的Numpy代码(基于):

更新

绘图:

更新2

如果您需要该点属于该段,则需要进行一个小的修改

def point_on_line(a, b, p):
    ap = p - a
    ab = b - a
    t = np.dot(ap, ab) / np.dot(ab, ab)
    # if you need the the closest point belonging to the segment
    t = max(0, min(1, t))
    result = a + t * ab
    return result

此解决方案扩展到具有任何几何尺寸(2D、3D、4D等)的点。它假定所有点都是一维numpy阵列(或具有一维形状1的二维阵列)。我不确定你们是否要求投影落在线段或线段的延伸上,所以我将两者都包括在内。您可以选择最适合您问题的选项:

#distance between p1 and p2
l2 = np.sum((p1-p2)**2)
if l2 == 0:
  print('p1 and p2 are the same points')

#The line extending the segment is parameterized as p1 + t (p2 - p1).
#The projection falls where t = [(p3-p1) . (p2-p1)] / |p2-p1|^2

#if you need the point to project on line extention connecting p1 and p2
t = np.sum((p3 - p1) * (p2 - p1)) / l2

#if you need to ignore if p3 does not project onto line segment
if t > 1 or t < 0:
  print('p3 does not project onto p1-p2 line segment')

#if you need the point to project on line segment between p1 and p2 or closest point of the line segment
t = max(0, min(1, np.sum((p3 - p1) * (p2 - p1)) / l2))

projection = p1 + t * (p2 - p1)
p1和p2之间的距离 l2=np.和((p1-p2)**2) 如果l2==0: 打印('p1和p2是相同的点') #延伸线段的线被参数化为p1+t(p2-p1)。 #投影位于t=[(p3-p1)。(p2-p1)]/| p2-p1 | 2处 #如果需要点投影连接p1和p2的在线延伸 t=np.和((p3-p1)*(p2-p1))/l2 #如果p3未投影到线段上,则需要忽略 如果t>1或t<0: 打印('p3未投影到p1-p2线段') #如果需要将点投影到p1和p2之间的线段或线段的最近点上 t=最大值(0,最小值(1,np.和((p3-p1)*(p2-p1))/l2)) 投影=p1+t*(p2-p1)
这是否回答了您的问题?不,这是不同的,它使用Microsoft.Maps.Location API,我希望在Python中解决它,而NumpyIt将它移植到Python是微不足道的-使用我在这里检查的点的表示,因为我需要对它进行矢量化。我有数千点需要预测。我没有提到我的点是3d(x,y,z),因为简单。在你的问题中,你说P1(x,y)和P3(x,y),这清楚地定义了@D点,而不是你说你需要3d解决方案。下定决心:)我以前试过,它没有显示投影点检查这个笔记本我看了一下你的笔记本,你有两个错误:1:你叫投影=ClosestPointOnLine(a,P,B),而它需要投影=ClosestPointOnLine(a,B,P)。2> 您以错误的方式绘制,我们如何使其垂直于直线参见更新如何使其属于直线。请注意,接受的答案基本上是使用更基本函数的相同算法:
np.sum((p1-p2)**2)
等于
np.dot(ab,ab)
etc.lol。这与答案完全相同:D.检查
ab!=0
以避免以零错误进行除法。是的,这就是我要找的,非常感谢much@MSallal不客气。如果它解决了你的问题,请接受答案,以帮助其他人发现它有用。谢谢。我不确定我是否理解这个问题。在我的文章中使用t的第一个方程会导致在基本上垂直于它的延长线/线段上的投影。
def point_on_line(a, b, p):
    ap = p - a
    ab = b - a
    t = np.dot(ap, ab) / np.dot(ab, ab)
    # if you need the the closest point belonging to the segment
    t = max(0, min(1, t))
    result = a + t * ab
    return result
#distance between p1 and p2
l2 = np.sum((p1-p2)**2)
if l2 == 0:
  print('p1 and p2 are the same points')

#The line extending the segment is parameterized as p1 + t (p2 - p1).
#The projection falls where t = [(p3-p1) . (p2-p1)] / |p2-p1|^2

#if you need the point to project on line extention connecting p1 and p2
t = np.sum((p3 - p1) * (p2 - p1)) / l2

#if you need to ignore if p3 does not project onto line segment
if t > 1 or t < 0:
  print('p3 does not project onto p1-p2 line segment')

#if you need the point to project on line segment between p1 and p2 or closest point of the line segment
t = max(0, min(1, np.sum((p3 - p1) * (p2 - p1)) / l2))

projection = p1 + t * (p2 - p1)