【问题标题】:Finding Cross Product to find points above/below a line in MatplotLib查找叉积以在 MatplotLib 中查找线上方/下方的点
【发布时间】:2018-01-27 17:22:11
【问题描述】:

我正在尝试在 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 中的一条线?

【问题讨论】:

  • this answer的第一部分。基本上,如果你有一个x-y 对,你将你的x 值插入你的行的方程中,比如y1=a+b*x 并将结果与​​你的y-值进行比较,即如果y1>y,重点是在线下方,如果 `y1

标签: python matplotlib


【解决方案1】:

如所见,例如在this question 中,叉积确实可以用来确定一个点是位于由两点定义的线的上方还是下方。

所以让ab 是定义一条线的两个点,而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()

【讨论】:

  • 很好的答案,尤其是如果确实想知道点 p 是在方向 a -&gt; b 的线的左侧还是右侧。但是,如果想严格了解该点是高于还是低于线(即在给定x 处更大或更小y 值)与线方程相比仍然要简单得多,因为使用叉积,您仍然需要有一个 if 子句来测试线的方向。
  • @Thomas 您可以简单地确保点a 的x 坐标小于b 的x 坐标,即沿x 轴对点进行排序。这将自动确保“之上”意味着“之上”。哪个解决方案更简单的问题可能更多地取决于您从什么开始。如果您有两个点定义线,叉积是优选的解决方案,如果您有斜率和 y 截距,则在 y 坐标方面相对于线的比较,如this answer。当然,每个都可以相互计算。
  • 嗯,关于订购 x 值的好点。我仍然必须下定决心,如果你有很多点,哪种计算会更有效。当然np.cross 函数使代码看起来很整洁,而且可能也很快......
  • @Thomas 直观地说,我会说评估线方程更快,至于n 点,它涉及n 乘法和n 比较。叉积涉及2n 乘法和n 比较。
【解决方案2】:

一种肮脏的方式 - 使用带叉积的左/右方法 (How to tell whether a point is to the right or left side of a line),然后计算线的斜率。如果斜率为负,则线左侧的任何点都在线上方,如果斜率为正,则线左侧的任何点都在线下方。如果该点在右侧,则它们是相反的。 (显然,答案取决于 y 轴的方向,对于我的示例来说,向上是负数,向下是正数。)这种方法需要对垂直和水平线的特殊情况进行编程。对于水平线,叉积法将为您提供该点在线上方的位置。对于垂直线,没有真正的答案,但我们指向的是 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2018-05-02
    相关资源
    最近更新 更多