我需要找出两条线是否重叠。我已经有了交点代码,如果两条线平行则返回0。但是我需要知道这两条平行线是否重叠。
编辑:
A C B D
-----------------------------------------------
第1行:A-B
第2行:C-D
我需要找出第1行和第2行是否有重叠部分,但两行都可以具有斜率>0。
我需要找出两条线是否重叠。我已经有了交点代码,如果两条线平行则返回0。但是我需要知道这两条平行线是否重叠。
编辑:
A C B D
-----------------------------------------------
第1行:A-B
第2行:C-D
我需要找出第1行和第2行是否有重叠部分,但两行都可以具有斜率>0。
D < A
B < C
如果任一情况为真,则行不重叠。否则必须存在重叠。 要确定它们是否不重叠,您将进行最少数量的比较。否则,将需要进行更多比较。B >= C && A <= D
。更多有关德摩根定律的信息,请参阅:https://en.wikipedia.org/wiki/De_Morgan's_laws。 - Caleb Bertrand只需要计算三角形ACB和CBD的面积即可。如果面积为0,则这些点共线,如果两个面积都是0,则这些线重叠。
您可以使用以下公式来计算三角形ABC的面积:
2 * 面积(ABC) = (bx - ax)(cy - ay) - (cx - ax)(by - ay);
既然你知道它们都是平行的,那么只需检查线段CD是否包含第一条线段的任一端点(点A和点B)。
线性方程是无限线的方向,通过找到斜率或截距,你不能对它们做任何事情(即使水平线没有斜率),我建议使用在线上的点。因此AB是你的线[(x,y),(x,y)],C是线上的一个点(x,y),然后你需要检查点是否在线上。
检查点是否在直线上
对于不一定轴对齐的两个共线线段:
两条线段在同一直线上的特征被称为共线性,可以通过计算一个线段的端点和另一个线段的端点所形成的两个三角形的面积来进行测试。如果该面积接近于零或低于某个阈值,则这两条线段是共线的。
public static bool AreSegmentsCollinear(Segment a, Segment b, double epsilon)
{
return IsPointCollinear(a, b.Left, epsilon) && IsPointCollinear(a, b.Right, epsilon);
}
public static bool IsPointCollinear(Segment a, Vector2D p, double epsilon)
{
return Math.Abs(GetSignedTriangleArea2(a, p)) <= epsilon;
}
/// <returns>The squared signed area of the triangle formed with endpoints
/// of segment a and point p</returns>
public static double GetSignedTriangleArea2(Segment a, Vector2D p)
{
return (p - a.Left) ^ (a.Right - a.Left);
}
/// <summary>Cross product of vectors in 2D space. NB: it returns a
/// magnitude (scalar), not a vector</summary>
/// <returns>The area of the parallelogram formed with u, v as the edges</returns>
public static Double operator ^(Vector2D u, Vector2D v)
{
return u.X * v.Y - u.Y * v.X;
}
给定以下形式的线段l1
和l2
[x1,y1,x2,y2]
,下面的Python代码将给出任何斜率的共线线段的交点。
intersection = line_intersect(l1, l2)
def line_intersect(l1, l2):
"""Find the intersection of two line segments"""
x1, y1, x2, y2 = l1
x3, y3, x4, y4 = l2
x_inter = component_intersect(x1, x2, x3, x4)
y_inter = component_intersect(y1, y2, y3, y4)
return math.sqrt(x_inter**2 + y_inter**2)
def component_intersect(c1, c2, c3, c4):
"""Calculate intersection in one dimension/component"""
# find left endpoints
cl1 = min(c1, c2)
cl2 = min(c3, c4)
# find right endpoints
cr1 = max(c1, c2)
cr2 = max(c3, c4)
# find endpoints of intersection
c_inter_l = max(cl1, cl2)
c_inter_r = min(cr1, cr2)
# calcuate intersection
c_inter = c_inter_r - c_inter_l
c_inter = max(c_inter, 0)
return c_inter
我们有两条线段:
AB = 从点 (Ax,Ay) 到点 (Bx,By) 的线段
CD = 从点 (Cx,Cy) 到点 (Dx,Dy) 的线段
斜率相同。
还存在一些特殊情况:
这些结果导致单个交点。我不确定您的系统是否可能出现其中任何一个,但如果是,您必须决定是否将其视为“重叠”,并添加特殊情况检查。
为了澄清答案中存在的一些混淆,所提出的问题如下。给定两个二维线段A和B,如何确定以下两个条件是否都成立:
请注意,这两个问题都涉及到公差,即A和B需要多接近平行,以及它们需要重叠多少才能被认为是重叠的?
我认为,为了稳健地处理这样的公差,最好的算法是将线段视为薄矩形,其中矩形的厚度是一个公差参数t1
。让t2
成为另一个被认为是平行的斜率的公差参数。然后算法变为:
如果A的斜率和B的斜率相差超过t2
,则返回false。为了清晰地处理垂直线,可以将斜率表示为单位向量,并测试两个单位向量之间的欧几里得距离是否小于t2
。
将A和B表示为(非轴对齐)矩形R1和R2。其中R1以明显的方式包围A,即它的长度为length(A) + t1
个单位,宽度为t1
个单位,A居中在其中,类似地,R2包围B。
确定R1和R2是否相交。这可以通过将每个矩形视为两个三角形的并集,并在所有A三角形和B三角形的组合中测试三角形-三角形相交来相对高效地完成。如果有交点,则返回true;否则返回false。