I am wondering how to get the Set Subtraction between two rectangles with "parallel edges" in an efficient way. Thank you in advance for you help!
Problem: We know that each rectangle can be encoded by four parameters. Now, assume that we have 2 rectangles region1 and region2 and we want to get the set subtraction (a.k.a set complement, set difference see wiki) region1 - region2, which is a union of some smaller rectangles. How can we encoded these resulting rectangles efficiently?
My efforts:
At the beginning, I did it by considering all the possible positions of the two rectangles (there are at least 10 main cases by fixing
region1and movingregion2and many sub-cases). But of course, this is not a good strategy.I found a similar post here but it is not exactly the problem I consider here and the code provided is in
C#(which I don't know) and the answer there has no explanation.I then post my question in Math Stack Exchange and got a promising answer as follows:
There are four x-coordinates and four y-coordinates involved, which together determine a total of 9 sub-rectangles; and you can just check their centers one by one to see whether they are in
region1and not inregion2.
I then try to program it using python (I just know Python). Here is my code. But I think it is unclean, unclear and unreadable. In addition, it is not very efficient since the rectangles with common edges have not been merged.
def substraction(region1, region2):
# return region1 \ region2
# region = [(x1,x2), (y1,y2)]
assert(len(region1) == 2 and len(region2) == 2)
(r1x1, r1x2), (r1y1, r1y2) = region1
(r2x1, r2x2), (r2y1, r2y2) = region2
x1, x2, x3, x4 = sorted([r1x1, r1x2, r2x1, r2x2])
y1, y2, y3, y4 = sorted([r1y1, r1y2, r2y1, r2y2])
out=[]
for x in [(x1, x2), (x2, x3), (x3, x4)]:
for y in [(y1, y2), (y2, y3), (y3, y4)]:
xm, ym = (x[0]+x[1])/2, (y[0]+y[1])/2
bool1_x = xm>r1x1 and xm<r1x2
bool1_y = ym>r1y1 and ym<r1y2
bool2_x = xm<=r2x1 or xm>=r2x2
bool2_y = ym<=r2y1 or ym>=r2y2
if (bool1_x and bool1_y) and (bool2_x or bool2_y):
out += [ [x, y] ]
return out
def test():
region1=[(0., 1.), (0., 1.)]
region2=[(0.4, 1.5), (0.4, 0.6)]
list_rects=substraction(region1, region2)
print(list_rects)
test()
Could anyone give an idea how to improve my code. A new efficient solution is also welcome! Thank you!