我正在尝试在MatPlotLib中绘制一条线,并根据斜率找到线上方或下方的所有点。
阅读此post后,阅读Cross Product,我相信这是检查要点的最佳方法。
我不确定在python中实现它的最佳方式是什么。
v1 = {x2-x1, y2-y1} # Vector 1
v2 = {x2-xA, y2-yA} # Vector 2
xp = v1.x*v2.y - v1.y*v2.x # Cross product
有没有人尝试过类似的东西?
我是否有其他方法可以找到地块上的点是否高于或低于MatPlotLib中的一行?
答案 0 :(得分:7)
如所见在this question中,十字产品确实可用于确定一个点位于由两个点定义的线之上还是之下。
因此,让a
和b
为定义一条线的两个点,p
一个(一组)点,我们想知道它们与线的相对位置。然后,如果
numpy.cross(p-a, b-a) < 0
True
点位于线上方。
为了准确起见,“上方”表示从点a
向点b
看,点p
位于该行的左侧。
这可以用来对散点图中的点进行不同的着色,具体取决于它们是在线的上方还是下方,如下所示:
import numpy as np
import matplotlib.pyplot as plt
isabove = lambda p, a,b: np.cross(p-a, b-a) < 0
a = np.array([1,1])
b = np.array([4,3])
p1 = np.array([2,4])
p2 = np.array([3,1])
p = np.array([p1,p2])
fig, (ax,ax2) = plt.subplots(ncols=2, sharex=True, sharey=True)
ax.plot([a[0],b[0]],[a[1],b[1]], marker="o", color="k")
ax.scatter(p[:,0],p[:,1], c=isabove(p,a,b), cmap="bwr", vmin=0, vmax=1)
p = np.random.rand(10,2)*5
ax2.plot([a[0],b[0]],[a[1],b[1]], marker="o", color="k")
ax2.scatter(p[:,0],p[:,1], c=isabove(p,a,b), cmap="bwr", vmin=0, vmax=1)
ax.set_xlim(0,6)
ax.set_ylim(0,6)
plt.show()
答案 1 :(得分:0)
一种肮脏的方法-对带有叉积(How to tell whether a point is to the right or left side of a line)的左/右方法使用该方法,然后评估该线的斜率。如果斜率为负,则线的任何点在该线的上方,如果斜率为正,则线的任何点在该线的下方。如果该点在右边,则将它们颠倒。 (显然,答案取决于y轴的方向,例如,在我的示例中,up为负,down为正。)此方法要求对垂直和水平线进行特殊编程。对于水平线,叉积法将为您提供线上方的点的位置。对于垂直线,没有真正的答案,但是我们指向isLeftOfLine。
C ++代码:
bool Point::isLeftOfLine(Line cmp)
{
return ((cmp.p2.x - cmp.p1.x) * (y - cmp.p1.y) > (cmp.p2.y - cmp.p1.y) * (x - cmp.p1.x));
}
bool Point::isTopOfLine(Line cmp)
{
if(cmp.p1.x == cmp.p2.x || cmp.p1.y == cmp.p2.y)
{
return isLeftOfLine(cmp);
}
return isLeftOfLine(cmp) == cmp.slope() < 0;
}
double Line::slope()
{
return (p2.y - p1.y) / (p2.x - p1.x);
}