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

所以我的问题是,有人能建议这样做的方法吗?也许使用不同的技术(可能是GraphViz)或算法?

有帮助吗?

解决方案

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 <!> lt; = a <!> lt; = 1且0 <!> lt; = b <!> lt; = 1,则交点位于两者上线段,由点

给出
x1 + a * v1

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

x1 + a*v1 = x2 + b*v2

通过将此等式的点积乘以v1,并用v2,我们得到两个等式:

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的等式。

其他提示

如果你旋转你的参考框架以与第一个线段对齐(所以原点现在是第一条线的起点,第一条线的矢量沿着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   |

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

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

C运算符正确定义了齐次坐标(在这种情况下从3个空间到2个空间的投影)。现在剩下的就是检查并查看Y点击X轴的位置,这与解决t x C.V.Y = 0的参数方程C.V.X一侧相同:

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

如果<=>在0到1的范围内,则<=>点击线段内的X轴。它落在X轴上的位置由<=>:

的参数方程的X侧给出
x = C.O.X + t * C.V.X

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

p = A.O + A.V * x

您当然必须首先检查是否有任何线段长度为零。此外,如果<=>您有平行线段。如果<=>也为零,则您有共线线段。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top