Subtract CGRect from CGRect -- largest piece of one not containing the other

anonymous picture anonymous · Jan 27, 2011 · Viewed 9.7k times · Source

How I can substract one CGRect from another? I want the result R1 - R2 to be the largest subrectangle of R1 that does not intersect R2.

Example 1:

+----------------------------------+
| +--------+                       |
| |   R2   |                       |
| |        |                       |
| +--------+      R1               |
|                                  |
|                                  |
|                                  |
+----------------------------------+

R3 = CGRectSubstract(R2,R1);

            +----------------------+
            |                      |
            |                      |
            |                      |
            |          R3          |
            |                      |
            |                      |
            |                      |
            +----------------------+

Example 2:

+-----------------------+----------+
|                       |          |
|                       |    R2    |
|                       |          |
|                 R1    +----------+
|                                  |
|                                  |
|                                  |
+----------------------------------+

R3 = CGRectSubstract(R2,R1);

+-----------------------+
|                       |
|                       |
|                       |
|          R3           |
|                       |
|                       |
|                       |
+-----------------------+

Example 3:

+----------------------------------+
|                                  |
|                                  |
|                                  |
|                 R1               |
|         +---------+              |
|         |         |              |
|         |   R2    |              |
+---------+---------+--------------+

R3 = CGRectSubstract(R2,R1);

+----------------------------------+
|                                  |
|                                  |
|              R3                  |
|                                  |
+----------------------------------+



Answer

cobbal picture cobbal · Jan 27, 2011

Your definition is fairly ambiguous, what says whether the subtraction is horizontal or vertical? I recommend using a combination of CGRectIntersection and CGRectDivide, along with specifying a direction to remove ambiguity.

(not tested, or even compiled)

CGRect rectSubtract(CGRect r1, CGRect r2, CGRectEdge edge) {
    // Find how much r1 overlaps r2
    CGRect intersection = CGRectIntersection(r1, r2);

    // If they don't intersect, just return r1. No subtraction to be done
    if (CGRectIsNull(intersection)) {
        return r1;
    }

    // Figure out how much we chop off r1
    float chopAmount = (edge == CGRectMinXEdge || edge == CGRectMaxXEdge)
                       ? intersection.size.width
                       : intersection.size.height;

    CGRect r3, throwaway;
    // Chop
    CGRectDivide(r1, &throwaway, &r3, chopAmount, edge);
    return r3;
}