在此讨论的求取两个矩形的相交区域问题中的矩形的边是平行于坐标轴的情况,不平行的暂时无讨论。
因为工作的需要求取两个矩形的相交区域面积的python程序,当时在网上找呀找,要么是说的云里雾里的,要么代码不是python的,其实主要是矩形相交判断条件,有的说的那叫一个复杂呀,还好在查找过程中找到了两篇不错的博客
blog1:https://blog.csdn.net/qianchenglenger/article/details/50484053
blog2:https://blog.csdn.net/dreamd1987/article/details/7656858
我在参考这两篇博客的基础上做有些整理和汇总,最终形成了本文,感谢上述博主的分享。
由于代码注解的比较详细,一看便知,故在此不多赘述其他。
#2018/07/29 by DQ
import matplotlib.pyplot as plt
import random
#画一个矩形框,我使用Pyplot 自带的Rectangle函数没画出来指定大小(边长大于1)的矩形,后面会顺便说一下,
#虽然matlab用的很熟练,两者也有好些相似之处,实在没法子,因此只有自立根生,再造轮子吧,还好不难
def DrawRect(Rect,LineCor):
(x1,y1,x2,y2)=Rect
x3,y3=x2,y1
x4,y4=x1,y2
plt.plot([x1,x3,x2,x4,x1],[y1,y3,y2,y4,y1],'-',color=LineCor,linewidth=1)
plt.text(x1+1,y1+1,str((x1,y1)),color=LineCor)
plt.text(x2+1,y2+1,str((x2,y2)),color=LineCor)
#求取两个矩形相交的程序主要参考了下面两个blogs
#blog1:https://blog.csdn.net/qianchenglenger/article/details/50484053
#blog2:https://blog.csdn.net/dreamd1987/article/details/7656858
def RectOverlap(Rect1,Rect2):
(x11,y11,x12,y12)=Rect1 #矩形1左上角(x11,y11)和右下角(x12,y12)
(x21,y21,x22,y22)=Rect2 #矩形2左上角(x21,y21)和右下角(x22,y22)
#我们在此假想一个大矩形,它正好把坐标轴区域上矩形1和矩形2包围起来,我们称它为外包框
StartX=min(x11,x21) #外包框在x轴上左边界
EndX=max(x12,x22) #外包框在x轴上右边界
StartY=min(y11,y21)#外包框在y轴上上边界
EndY=max(y12,y22)#外包框在y轴上下边界
#相交矩形区域的宽度和高度,因为这两个矩形的边都是平行与坐标轴的,因此他们的相交区域也是矩形
#那什么条件下才能形成相交区域啦,矩形是二维的,只有x,y方向都有交集时,他们才能形成相交区域
#记住上面提到过得外包框,就比较容易理解相交的条件了,blog1中的逆向思维也是不错的,不过感觉还是有些麻烦不直观,
#因此在这里多解释一下
CurWidth=(x12-x11)+(x22-x21)-(EndX-StartX)#(EndX-StartX)表示外包框的宽度
CurHeight=(y12-y11)+(y22-y21)-(EndY-StartY)#(Endy-Starty)表示外包框的高度
if CurWidth<=0 or CurHeight<=0:#不相交
return []
else:#相交
X1=max(x11,x21)#有相交则相交区域位置为:小中取大为左上角,大中取小为右下角
Y1=max(y11,y21)
X2=min(x12,x22)
Y2=min(y12,y22)
Area=CurWidth*CurHeight#相交区域面积
IntersectRect=(X1,Y1,X2,Y2,Area)
return IntersectRect
#标示出相交区域位置
def DrawIntersectLoc(IntersectRect):
(X1,Y1,X2,Y2)=tuple(IntersectRect)
plt.plot(X1,Y1,'*',color='cyan')
plt.plot(X2,Y2,'*',color='cyan')
plt.text(X1,Y1,str((X1,Y1)),color='r')
plt.text(X2,Y2,str((X2,Y2)),color='r')
#为了避免手动修改矩形,因此写了个随机生成矩形的的程序,
#matlab有个randperm可以产生一个随机序列,pyhon还不太知道怎么搞
def GetRandRect(RandLow=2,RandUp=100):
Seq=range(RandLow,RandUp)#产生一个有序序列
random.shuffle(Seq)#打乱这个序列
#print Seq
X1X2=[Seq[1],Seq[2]]#随机抽取x方向坐标值
Y1Y2=[Seq[95],Seq[96]]#随机抽取y方向坐标值
X1X2.sort()#随机抽取x方向坐标值排个序,要求x2>x1
Y1Y2.sort()#随机抽取y方向坐标值排个序,要求y2>y1
#print X1X2
#print Y1Y2
Rect=(X1X2[0],Y1Y2[0],X1X2[1],Y1Y2[1])#组成一个矩形
return Rect
plt.close('all')#我擦,为啥在linux下sublime中每次运行程序,这条语句不起作用???
plt.clf()#也不起作用??? 刚接触matplotlib 不久,虽然matlab用的熟练,他们有许多相似之处但还是没搞定
#Rect1=(12,36,38,86) #手动设置矩形1
Rect1=GetRandRect() #随机产生一个矩形1
LineCor='b' #蓝色
DrawRect(Rect1,LineCor)
#Rect2=(41,16,81,77) #手动设置矩形2
Rect2=GetRandRect()#随机产生一个矩形2
LineCor='g' #绿色
DrawRect(Rect2,LineCor)
IntersectRect=RectOverlap(Rect1,Rect2)#求解矩形1和矩形2可能相交的位置和面积
if IntersectRect:
X1,Y1,X2,Y2=IntersectRect[:-1]
"""
plt.plot(X1,Y1,'*',color='cyan')#相交区域的左上角
plt.plot(X2,Y2,'*',color='cyan')#相交区域的右下角
plt.text(X1,Y1,str((X1,Y1)),color='r')#相交区域的左上角坐标显示
plt.text(X2,Y2,str((X2,Y2)),color='r')#相交区域的右下角坐标显示
"""
DrawIntersectLoc(IntersectRect[:-1])
IntersectArea=IntersectRect[-1] #相交面积
TitleStr='the two rectangels intersect,Area={}'.format(IntersectArea)
print IntersectArea
else:
print 'no intersect'
TitleStr='the two rectangels not intersect'
plt.title(TitleStr,loc='center')#标题居中,一定要放在plt.show()之前
ax = plt.gca() #获取坐标轴句柄
#ax.xaxis.set_ticks_position('top') #本来有这句的,但是把x坐标轴放在区域上方,有碍title的显示,故还是放在下面好些
ax.yaxis.set_ticks_position('left') #y坐标轴从上到下,符合搞图像处理或计算视觉人的习惯和风格
ax.invert_yaxis()
plt.show()
在结束之前我说一下在此过程终于到的几个问题,请允许我这个刚入python和matplotlib的小白:
1、plt.close('all')#为啥在linux下sublime中每次运行程序,这条语句不起作用???我运行几次后就有好几个窗口
plt.clf()#也不起作用???
2、使用下面的代码画一个矩形可以,为啥把坐标x,y设为大于1就不行了,难道坐标轴默认采取的是归一化的方式,郁闷
import matplotlib.pyplot as plt
import matplotlib.patches as patches
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(
patches.Rectangle(
(0.1, 0.1), # (x,y)
0.5, # width
0.5, # height
)
)
上述情况有知道的朋友麻烦告知一声不甚感激。
最后上几张显示图吧:
1、相交的情况
2 不相交的情况