Rectangle overlap (intersection)
1. Introduction
Consider rectangles whose sides are parallel to the X and Y axes. Let a rectangle be defined by 4 fields: the X and Y coordinate of its bottom-left corner, and its width and height.
For a diagram of the various kinds of overlap we can expect, see (Aziz et al., 2018, p. 39).
2. Problem statement
Write a function which checks if two rectangles have a nonempty overlap; if the overlap is nonempty, return the rectangle formed by their overlap (Aziz et al., 2018, p. 39). Two rectangles are considered to be overlapping if they share the same side.
3. Insights
Enumerating all the ways in which two rectangles can overlap is rather difficult. Instead we can just check if there is no overlap horizontally and vertically, separately.
4. Solution
First just consider horizontal overlap. The check to see if there is no
overlap is simple: if the rightmost point of Rect A is less than the leftmost
point of Rect B, there is no overlap. We can encode this as a_R < b_L
. Of
course, it may be the case that Rect A is further right on the X axis than
Rectnagle B, in which case the roles are reversed and we have to check if Rect
A's leftmost point is indeed greater than the rightmost point of Rect B (a_L >
b_R
). These two conditions form the basis of no_horizontal_overlap()
below.
By symmetry, the code for no_vertical_overlap()
is rather similar.
The code in (Aziz et al., 2018, p. 40) actually does the opposite to check for overlap
(instead of no-overlap). And so they use a_R >= b_L and a_L <= b_R
instead.
However that code is a tiny bit slower because of the use of and
instead of
or
as we've done here.
Now that we can check if there is no overlap, we can proceed to calculating the actual overlapping (smaller) rectangle.
Now that we have all of our points defined, first consider the \((X, Y)\)
coordinate (lower-left corner) of the overlapping rectangle (let's call this
rectangle v
). What is the leftmost side of v
? It's just the max of either
a
or b
, because we already know that they overlap:
aaaaaaa bbbb | `- this point, b_L, is what we want
Again, we have to account for the case where the rectangles are reversed, where Rect B is on the left:
bbbbbbb aaaa | `- this point, a_L, is what we want
So we need to get either a_L
or b_L
. In both cases, this value is max(a_L,
b_L)
. For the Y axis, similar logic follows and we need to use max(a_B, b_B)
.
What about width the width? The width is the rightmost point subtracted by the
leftmost point. We already know the leftmost point of v
, v_x
. So we just
need to calculate the rightmost point. We can get the rightmost point by taking
the minimum of the rightmost points of either a
or b
. Using the same
examples from above, we have
,- this point, a_R, is what we want | aaaaaaa bbbb
and also the reversed case
,- this point, b_R, is what we want | bbbbbbb aaaa
where in both cases, the value is min(a_R, b_R)
. Then we can just subtract
v_x
from it to get the width. By symmetry, the calculation of vheight is
essentially the same.