求解平面中任意两个矩形的重叠面积——python
import numpy as np
import matplotlib.pyplot as plt
from copy import deepcopy
class Rec():
def __init__(self,center,l,w,theta):
self.center=center
self.l=l
self.w=w
self.theta=theta
l_vec=np.array([l/2*np.cos(theta),l/2*np.sin(theta)])
w_vec=np.array([w/2*np.cos(3/2*np.pi+theta),w/2*np.sin(3/2*np.pi+theta)])
self.points=[]
self.points.append(l_vec+w_vec+np.array(self.center))
self.points.append(l_vec-w_vec+np.array(self.center))
self.points.append(-l_vec-w_vec+np.array(self.center))
self.points.append(-l_vec+w_vec+np.array(self.center))
def draw(self):
rec_points = deepcopy(self.points)
rec_points.append(self.points[0])
rec_points=np.array(rec_points)
plt.plot(rec_points[:,0],rec_points[:,1],'-')
def point2rec(point,rec):
rec_points = deepcopy(rec.points)
rec_points.append(rec.points[0])
rec_points = np.array(rec_points)
flag=None
for i in range(4):
tmp=np.cross(rec_points[i+1,:]-rec_points[i,:],point-rec_points[i+1,:])
if flag is None:
flag=tmp
else:
if flag*tmp<-1e-6:
return False
return True
def line2line(line1,line2):
xa,ya = line1[0,0],line1[0,1]
xb,yb = line1[1,0],line1[1,1]
xc,yc = line2[0,0],line2[0,1]
xd,yd = line2[1,0],line2[1,1]
a = np.matrix(
[
[xb-xa,-(xd-xc)],
[yb-ya,-(yd-yc)]
]
)
delta = np.linalg.det(a)
if np.fabs(delta) < 1e-6:
return []
c = np.matrix(
[
[xc-xa,-(xd-xc)],
[yc-ya,-(yd-yc)]
]
)
d = np.matrix(
[
[xb-xa,xc-xa],
[yb-ya,yc-ya]
]
)
lamb = np.linalg.det(c)/delta
miu = np.linalg.det(d)/delta
if lamb <= 1 and lamb >= 0 and miu >= 0 and miu <= 1:
x = xc + miu*(xd-xc)
y = yc + miu*(yd-yc)
return [x,y]
else:
return []
def line2rec(line,rec):
rec_points=deepcopy(rec.points)
rec_points.append(rec.points[0])
rec_points=np.array(rec_points)
cross_points=[]
for i in range(4):
cross_point=line2line(line,rec_points[i:i+2,:])
if len(cross_point) !=0:
cross_points.append([cross_point[0],cross_point[1]])
if len(cross_points)==1:
if point2rec(line[0,:],rec):
cross_points.append(list(line[0,:]))
else:
cross_points.append(list(line[1,:]))
if len(cross_points)==0 and point2rec(line[0,:],rec) and point2rec(line[1,:],rec):
cross_points.append(list(line[0,:]))
cross_points.append(list(line[1, :]))
return cross_points
def rec2rec(rec1,rec2):
rec1_points = deepcopy(rec1.points)
rec1_points.append(rec1.points[0])
rec1_points=np.array(rec1_points)
rec2_points = deepcopy(rec2.points)
rec2_points.append(rec2.points[0])
rec2_points = np.array(rec2_points)
cross_points=[]
for i in range(4):
cross_point=line2rec(rec1_points[i:i+2,:], rec2)
if len(cross_point)!=0:
cross_points.extend(cross_point)
for i in range(4):
cross_point = line2rec(rec2_points[i:i + 2, :], rec1)
if len(cross_point) != 0:
cross_points.extend(cross_point)
return cross_points
def refine_points(points):
if len(points)==0:
return [],0
new_points=np.array([points.pop(0),points.pop(0)])
while np.sum((new_points[-1,:]-new_points[0,:])**2)>1e-6:
tmp_point=new_points[-1,:]
ind=np.nonzero(np.sum((np.array(points)-tmp_point)**2,1)<1e-6)[0]
if ind[0]%2==0:
new_points=np.concatenate((new_points,
np.array(points.pop(ind[0]+1)).reshape((1,-1))),0)
points.pop(ind[0])
else:
new_points = np.concatenate((new_points,
np.array(points.pop(ind[0]-1)).reshape((1,-1))), 0)
points.pop(ind[0]-1)
S=0
for i in range(1,new_points.shape[0]-2):
a=np.linalg.norm(new_points[0,:]-new_points[i,:])
b=np.linalg.norm(new_points[i,:]-new_points[i+1,:])
c=np.linalg.norm(new_points[0,:]-new_points[i+1,:])
S+=tri_area(a,b,c)
return new_points,S
def tri_area(a,b,c):
s = (a + b + c) / 2
area = (s * (s - a) * (s - b) * (s - c)) ** 0.5
return area
Rec1=Rec(center=[1,2],l=5,w=3,theta=0)
Rec2=Rec(center=[2,2],l=3,w=4,theta=np.pi/3)
Rec1.draw()
Rec2.draw()
cross_points=rec2rec(Rec1,Rec2)
points,S=refine_points(cross_points)
if len(points)!=0:
plt.plot(points[:,0],points[:,1],'ro-')
plt.fill(points[:,0],points[:,1], facecolor='r',alpha=0.5)
plt.title('S={:.4f}'.format(S))
plt.axis('equal')
plt.show()