我加入了以下问题/答案启发的社区:Line intersection with AABB Rectangle?
在那里,原始海报要求一种方法来检测线和矩形之间的交叉点。其中一个答案提到使用Cohen-Sutherland算法比进行4个线到线交叉要快得多。然而,关于如何做的解释是缺席的(或者至多是模糊的),虽然我可以找到关于该定理的信息,但我没有找到关于如何使其适应手头问题的任何进一步解释/代码示例。
所以,我来找你问一个慈善的灵魂,以获得更多信息,可能是C#,JavaScript或伪代码示例,如何使用Cohen-Sutherland算法有效地检测线和矩形之间的交集。如果还有其他快速的方法可以使用我不知道的其他算法,我会欢迎启蒙。
非常感谢
答案 0 :(得分:0)
我最喜欢的解决方案不是经典的。它依赖于Minkowski sum的概念,即扩张。
主要思想是检测矩形与线段的交叉点与检测矩形和线段之和中的段端点的包含相同。 (在扩大矩形的同时,您会沿着线的方向侵蚀线段)。
如您所见,总和是一个轴对齐的六边形,可以看作是一个更大的矩形(原始窗口按片段边界框的大小放大),两个三角形被切除。
通过二分法,您可以通过三次测试来确定点是否在六边形内部(检查通过相对顶点的线的哪一侧;六边形=>四边形= >三角形)。这不是首选方式,因为大多数这些线是倾斜的并且具有完整的等式。
通常最好首先检查较大矩形的内部性,这样可以在四次比较中快速拒绝,然后与三角形的两个连字符进行比较。
对于细分AB
和窗口[X0,X1]x[Y0,Y1]
,讨论将类似于
if Xb > Xa and Yb > Ya:
# NW-SE segment
Dx= Xb - Xa; Dy= Yb - Ya
if Xb < X0 or X1 + Dx < Xb or Yb < X0 or Y1 + Dy < Yb:
# No intersection (no overlap between the bounding boxes)
else
if LeftOf(Xb, Yb, X0, Y0, X1 + Dx, Y0 + Dy):
# No intersection, inside the NE triangle
else if LeftOf(Xb, Yb, Dx, Y1 + Dy, X0, Y1):
# No intersection, inside the SW triangle
else:
# Intersection, inside the hexagon
...
函数LeftOf
计算由三个点组成的三角形区域的符号(众所周知的行列式公式)。
必须对所有象限继续讨论,并且可以对水平/垂直段进行简化。另请注意
X1 + Dx < Xb
只是
X1 < xa
答案 1 :(得分:0)
当我等待更多的答案时,我想我应该带来我自己已经实施的解决方案。我并非100%确定它能完美运行(即它处理所有情况),但到目前为止它似乎对我有用。请注意,这是一个非常简单的解决方案,所以欢迎批评。
设r [1:4]为矩形的顶点,p [1:2]为线段的顶点。然后,在C#中:
bool DoLineRecIntersect(Vector2 p1, Vector2 p2, Vector2 r1, Vector2 r2, Vector2 r3, Vector2 r4)
{
if(p1.x > r1.x && p1.x > r2.x && p1.x > r3.x && p1.x > r4.x && p2.x > r1.x && p2.x > r2.x && p2.x > r3.x && p2.x > r4.x ) return false;
if(p1.x < r1.x && p1.x < r2.x && p1.x < r3.x && p1.x < r4.x && p2.x < r1.x && p2.x < r2.x && p2.x < r3.x && p2.x < r4.x ) return false;
if(p1.y > r1.y && p1.y > r2.y && p1.y > r3.y && p1.y > r4.y && p2.y > r1.y && p2.y > r2.y && p2.y > r3.y && p2.y > r4.y ) return false;
if(p1.y < r1.y && p1.y < r2.y && p1.y < r3.y && p1.y < r4.y && p2.y < r1.y && p2.y < r2.y && p2.y < r3.y && p2.y < r4.y ) return false;
float f1 = (p2.y-p1.y)*r1.x + (p1.x-p2.x)*r1.y + (p2.x*p1.y-p1.x*p2.y);
float f2 = (p2.y-p1.y)*r2.x + (p1.x-p2.x)*r2.y + (p2.x*p1.y-p1.x*p2.y);
float f3 = (p2.y-p1.y)*r3.x + (p1.x-p2.x)*r3.y + (p2.x*p1.y-p1.x*p2.y);
float f4 = (p2.y-p1.y)*r4.x + (p1.x-p2.x)*r4.y + (p2.x*p1.y-p1.x*p2.y);
if(f1<0 && f2<0 && f3<0 && f4<0) return false;
if(f1>0 && f2>0 && f3>0 && f4>0) return false;
return true;
}