我正在尝试测量线段和矩形之间的重叠。例如,线段表示为2点:
!important
和一个4点的矩形:
line = [(x1, y1), (x2, y2)]
有没有一种有效的方法来衡量两者之间重叠的长度(如果有的话)?
这是一个简单的图表:
编辑:为了澄清,线段可能与矩形部分相交,甚至根本不相交。
答案 0 :(得分:3)
从图片
我们有
P := (x2,y2) - (x1,y1) = (x2-x1, y2-y1)
Q := (x4,y4) - (x3,y3) = (x4-x3, y4-y3)
cos(α) := dotProduct(P,Q)/norm(P)norm(Q)
h := dist((x4,y4),(x5,y5))
,其中
dotProduct((px,py),(qx,qy)) := px*qx + py*qy
norm(a,b) := sqrt(squared(a)+squared(b))
dist(A,B) = norm(B-A)
然后d
可以计算为
d := h/sin(α) = h/(sqrt(1-squared(cos(α)))
答案 1 :(得分:2)
找到仿射变换以使矩形轴对齐。它只是按角度旋转
fi = -atan2(y4-y3, x4-x3)
使用此旋转矩阵
转换线段末端的坐标和一些矩形坐标 x' = x * Cos(fi) - y * Sin(fi)
y' = x * Sin(fi) + y * Cos(fi)
请注意,现在矩形只需要两个x坐标和两个y坐标(left=x3', right=x4', bottom=y3', top=y6'
)
应用任何l ine-clipping algorithm
我建议使用Liang-Barsky(description with code)
计算后,夹点或段末端之间的距离在矩形内
(无限线与矩形相交且结果参数t0
和/或t1
超出0..1
范围的情况)
答案 2 :(得分:0)
我只是在数学部分,没有编码
找到交点(upperx,uppery)(lowerx,lowery)
找到从上点到右上角的距离
找到从下点到右上角的距离
A =减去一个与另一个的距离
B =找到直肠右上角和右下角的距离
你现在有A和B的公式a ^ 2 + b ^ 2 = c ^ 2
享受
答案 3 :(得分:0)
我将这个答案分解为三个部分:
我还将使用matplotlib
来查看示例。
这wikipedia article给出了一个公式,用于计算坐标描述的两条直线之间交点的坐标:
使用共同坐标 :(x1, y1)
,(x2, y2)
,(x3, y3)
和(x4, y4)
。
如果他们不相交,那么分母:
(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
将是0
。
所以,使用这个公式,我们可以创建一个函数来返回两行之间的交点,或 False
意味着它们不相交:
def intersection(x1, y1, x2, y2, x3, y3, x4, y4):
d = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
if not d:
return False
return (((x1*y2-y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4))/d,
((x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4))/d)
我们可以看到可以使用两个测试:
>>> intersection(0, 0, 8, 8, 0, 8, 8, 0)
(4.0, 4.0)
>>> intersection(6, 0, 6, 8, 7, 0, 7, 8)
False
您可以使用matplotlib
图表来显示这些:
我们还需要能够计算两点之间的距离。这可以使用毕达哥拉斯定理来确定三角形斜边的长度:
a^2 + b^2 = c^2
和以前一样,让我们把它放到辅助函数中:
def distance(x1, y1, x2, y2):
return ((x2-x1)**2 + (y2-y1)**2) ** 0.5
我们可以测试:
>>> distance(0, 0, 3, 4)
5.0
我们现在可以创建主函数,它将实现上面定义的两个函数。
这方面的步骤很简单:
False
,如果没有)False
- 表示该行不与矩形相交现在用Python实现这个:
#first 2 points describe the line, last 4 the rectangle
def length_inside(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6):
intersects = [intersection(x1, y1, x2, y2, x3, y3, x4, y4),
intersection(x1, y1, x2, y2, x4, y4, x5, y5),
intersection(x1, y1, x2, y2, x5, y5, x6, y6),
intersection(x1, y1, x2, y2, x6, y6, x3, y3)]
intersects = [i for i in intersects if i]
if len(intersects) == 2:
return distance(*intersects[0], *intersects[1])
return False
并测试它:
>>> length_inside(2, 6, 5, 0, 1, 3, 2, 1, 6, 3, 5, 5)
2.23606797749979
>>> length_inside(0, 1, 0, 5, 1, 3, 2, 1, 6, 3, 5, 5)
False
通过情节的帮助可以看出是正确的:
答案 4 :(得分:0)
您没有排除外部库,所以这里是shapely,专为此类任务而设计。用C语言写成,Numpy array interface。
from shapely.geometry import LineString, Polygon
line_list = [(0, 0), (5, 5)]
rect_list = [(1, 1), (1, 3), (3, 3), (3, 1)]
line_in_rect = Polygon(rect_list).intersection(LineString(line_list))
if line_in_rect:
print(line_in_rect.length)
else:
print("no intersection")
但是,如果是矩形,或者重叠只是部分,则不测试。