【问题标题】:How do I determine the intersection point of two lines in GDI+?如何确定 GDI+ 中两条线的交点?
【发布时间】:2026-01-25 14:40:01
【问题描述】:

我正在使用 .NET 制作具有绘图表面的应用程序,类似于 Visio。 UI 用 Graphics.DrawLine 连接屏幕上的两个对象。这个简单的实现效果很好,但是随着表面变得越来越复杂,我需要一种更健壮的方式来表示对象。这些强大的要求之一是确定两条线的交点,以便我可以通过某种图形指示分离。

所以我的问题是,任何人都可以提出一种方法来做到这一点吗?也许使用不同的技术(也许是 GraphViz)或算法?

【问题讨论】:

  • 你是指线还是线段?我正在为此在 C# 中寻找一个健壮的实现,我正在关注这些关于 SO 的问题,我注意到很多人说“线”时他们的意思是“线段”。前者是 x,y 平面上更简单的 b/c 情况,任何 2 条非平行线都保证在某处相交,但大多数编程应用程序使用线段,而不是线。
  • 我的问题是7年前的问题,所以我不知道。

标签: c# .net graphics geometry gdi+


【解决方案1】:

用 y = mx + c 表示线对于计算机图形来说是有问题的,因为垂直线要求 m 是无限的。

此外,计算机图形中的线有起点和终点,不像数学线的范围是无限的。如果交叉点位于所讨论的两条线段上,人们通常只对线的交叉感兴趣。

如果你有两条线段,一个从向量 x1 到 x1+v1,一个从向量 x2 到 x2+v2,那么定义:

a = (v2.v2 v1.(x2-x1) - v1.v2 v2.(x2-x1)) / ((v1.v1)(v2.v2) - (v1.v2)^2)
b = (v1.v2 v1.(x2-x1) - v1.v1 v2.(x2-x1)) / ((v1.v1)(v2.v2) - (v1.v2)^2)

对于向量 p=(px,py), q=(qx,qy),p.q 是点积 (px * qx + py * qy)。首先检查 (v1.v1)(v2.v2) = (v1.v2)^2 - 如果是,则线平行且不交叉。

如果它们不平行,那么如果0

x1 + a * v1

编辑 a 和 b 方程的推导如下。交点满足向量方程

x1 + a*v1 = x2 + b*v2

通过将这个方程与v1v2 相乘,我们得到两个方程:

v1.v1*a - v2.v1*b = v1.(x2-x1)
v1.v2*a - v2.v2*b = v2.(x2-x1)

为 a 和 b 形成两个线性方程。求解这个系统(通过将第一个方程乘以 v2.v2 并将第二个方程乘以 v1.v1 并减去,或以其他方式)给出 a 和 b 的方程。

【讨论】:

    【解决方案2】:

    【讨论】:

    • 肯定比dr.evil提供更多信息,感谢您的链接!
    【解决方案3】:

    如果您旋转参考系以与第一条线段对齐(因此原点现在是第一条线的起点,第一条线的矢量沿 X 轴延伸)问题就变成了,在哪里第二条线在新坐标系中击中 X 轴。这是一个更容易回答的问题。如果第一行称为A,并且由A.O 定义为线的起点,'A.V' 是线的矢量,因此A.O + A.V 是线的终点。参照系可以通过矩阵来定义:

        | A.V.X   A.V.Y   A.O.X |
    M = | A.V.Y  -A.V.X   A.O.Y |
        |   0       0       1   |
    

    在齐次坐标中,此矩阵为将线 A 映射到 X 轴上的 0 到 1 的参考系提供了基础。我们现在可以将转换后的线 B 定义为:

    C.O = M*(B.O)
    C.V = M*(B.O + B.V) - C.O
    

    * 运算符为齐次坐标正确定义的位置(在这种情况下是从 3 个空间到 2 个空间的投影)。现在剩下的就是检查C 在X 轴上的位置,这与为t 求解C 的参数方程的Y 一侧相同:

    C.O.Y + t * C.V.Y = 0
         -C.O.Y
    t = --------
          C.V.Y
    

    如果 t 在 0 到 1 的范围内,则 C 命中线段内的 X 轴。它落在 X 轴上的位置由 C 的参数方程的 X 侧给出:

    x = C.O.X + t * C.V.X
    

    如果 x 在 0 到 1 的范围内,则交点位于 A 线段上。然后我们可以在原始坐标系中找到该点:

    p = A.O + A.V * x
    

    您当然必须先检查任一线段的长度是否为零。此外,如果C.V.Y = 0 您有平行线段。如果C.V.X 也为零,则您有共线线段。

    【讨论】: