简体   繁体   English

如何确定GDI +中两条线的交点?

[英]How do I determine the intersection point of two lines in GDI+?

I'm using .NET to make an application with a drawing surface, similar to Visio. 我正在使用.NET来创建一个具有绘图表面的应用程序,类似于Visio。 The UI connects two objects on the screen with Graphics.DrawLine. UI使用Graphics.DrawLine连接屏幕上的两个对象。 This simple implementation works fine, but as the surface gets more complex, I need a more robust way to represent the objects. 这个简单的实现工作正常,但随着表面变得更复杂,我需要一种更健壮的方式来表示对象。 One of these robust requirements is determining the intersection point for two lines so I can indicate separation via some kind of graphic. 这些强大要求之一是确定两条线的交叉点,因此我可以通过某种图形指示分离。

So my question is, can anyone suggest a way to do this? 所以我的问题是,有人可以提出一种方法吗? Perhaps with a different technique (maybe GraphViz) or an algorithm? 也许使用不同的技术(可能是GraphViz)或算法?

The representation of lines by y = mx + c is problematic for computer graphics, because vertical lines require m to be infinite. 由y = mx + c表示的线对于计算机图形是有问题的,因为垂直线要求m是无穷大的。

Furthermore, lines in computer graphics have a start and end point, unlike mathematical lines which are infinite in extent. 此外,计算机图形中的线条具有起点和终点,而不像数学线条在范围上是无限的。 One is usually only interested in a crossing of lines if the crossing point lies on both the line segments in question. 如果交叉点位于所讨论的两个线段上,则通常只对线交叉感兴趣。

If you have two line segments, one from vectors x1 to x1+v1, and one from vectors x2 to x2+v2, then define: 如果你有两个线段,一个从向量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)

where for the vectors p=(px,py), q=(qx,qy), pq is the dot product (px * qx + py * qy). 其中,对于矢量p =(px,py),q =(qx,qy),pq是点积(px * qx + py * qy)。 First check if (v1.v1)(v2.v2) = (v1.v2)^2 - if so, the lines are parallel and do not cross. 首先检查是否(v1.v1)(v2.v2)=(v1.v2)^ 2 - 如果是,则线是平行的并且不交叉。

If they are not parallel, then if 0<=a<=1 and 0<=b<=1, the intersection point lies on both of the line segments, and is given by the point 如果它们不是平行的,那么如果0 <= a <= 1且0 <= b <= 1,则交点位于两个线段上,并由点给出

x1 + a * v1

Edit The derivation of the equations for a and b is as follows. 编辑 a和b的等式的推导如下。 The intersection point satisfies the vector equation 交点满足矢量方程

x1 + a*v1 = x2 + b*v2

By taking the dot product of this equation with v1 , and with v2 , we get two equations: 通过将该等式的点积与v1v2 ,我们得到两个等式:

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

which form two linear equations for a and b. 它形成了a和b的两个线性方程。 Solving this system (by multiplying the first equation by v2.v2 and the second by v1.v1 and subtracting, or otherwise) gives the equations for a and b. 求解该系统(通过将第一个等式乘以v2.v2,将第二个等式乘以v1.v1并减去或以其他方式)得到a和b的等式。

If you rotate your frame of reference to align with the first line segment (so the origin is now the start of the first line, and the vector for the first line extends along the X-axis) the question becomes, where does the second line hit the X-axis in the new coordinate system. 如果旋转参照系以与第一个线段对齐(因此原点现在是第一条线的起点,第一条线的矢量沿X轴延伸)问题就变成了,第二条线在哪里在新坐标系中击中X轴。 This is a much easier question to answer. 这是一个更容易回答的问题。 If the first line is called A and it is defined by AO as the origin of the line and 'AV' being the vector of the line so that AO + AV is the end point of the line. 如果第一行被称为A并且它被AO定义为行的原点而'AV'是该行的向量,那么AO + AV是该行的终点。 The frame of reference can be defined by the matrix: 参考框架可以由矩阵定义:

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

In homogeneous coordinates this matrix provides a basis for the frame of reference that maps the line A to 0 to 1 on the X-axis. 在齐次坐标系中,该矩阵为在X轴上将线A映射到0到1的参考系提供了基础。 We can now define the transformed line B as: 我们现在可以将变换后的线B定义为:

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

Where the * operator properly defined for homogeneous coordinates (a projection from 3 space onto 2 space in this case). *运算符正确定义为齐次坐标(在这种情况下从3个空间到2个空间的投影)。 Now all that remains is to check and see where C hits the X-axis which is the same as solving Y side of the parametric equation of C for t : 现在剩下的工作就是检查,看看C打X轴是相同的解决Y的参数方程的侧Ct

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

If t is in the range 0 to 1, then C hits the X-axis inside the line segment. 如果t在0到1的范围内,则C命中线段内的X轴。 The place it lands on the X-axis is given by the X side of the parametric equation for C : 它落在X轴上的位置由C的参数方程的X侧给出:

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

If x is in the range 0 to 1 then the intersection is on the A line segment. 如果x在0到1的范围内,则交点位于A线段上。 We can then find the point in the original coordinate system with: 然后我们可以在原始坐标系中找到以下点:

p = A.O + A.V * x

You would of course have to check first to see if either line segment is zero length. 您当然必须首先检查是否有任何线段长度为零。 Also if CVY = 0 you have parallel line segments. 此外,如果CVY = 0您有平行线段。 If CVX is also zero you have colinear line segments. 如果CVX也为零,则您有共线线段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM