Assuming rectangle 2 is contained in rectangle 1
(if not, use the intersection of both rectangles as the rectangle 2):
-------------------------
| rectangle 1 |
| |
| ------------- |
| |rectangle 2| |
| ------------- |
| |
| |
-------------------------
If you subtract rectangle 2 from rectangle 1, you will get an area with a hole:
-------------------------
| |
| |
| ------------- |
| | hole | |
| ------------- |
| |
| |
-------------------------
This area can be decomposed into 4 rectangles:
-------------------------
| A |
| |
|-----------------------|
| B | hole | C |
|-----------------------|
| |
| D |
-------------------------
If rectangle 1 and rectangle 2 are three sides coincident, you will get 1 rectangle from the subtracted area (which is your case). In general, you will get at most 4 rectangles.
The implementation in objective-c (sorry, don't have visual studio at this moment):
// returns the rectangles which are part of rect1 but not part of rect2
NSArray* rectSubtract(CGRect rect1, CGRect rect2)
{
if (CGRectIsEmpty(rect1)) {
return @[];
}
CGRect intersectedRect = CGRectIntersection(rect1, rect2);
// No intersection
if (CGRectIsEmpty(intersectedRect)) {
return @[[NSValue valueWithCGRect:rect1]];
}
NSMutableArray* results = [NSMutableArray new];
CGRect remainder;
CGRect subtractedArea;
subtractedArea = rectBetween(rect1, intersectedRect, &remainder, CGRectMaxYEdge);
if (!CGRectIsEmpty(subtractedArea)) {
[results addObject:[NSValue valueWithCGRect:subtractedArea]];
}
subtractedArea = rectBetween(remainder, intersectedRect, &remainder, CGRectMinYEdge);
if (!CGRectIsEmpty(subtractedArea)) {
[results addObject:[NSValue valueWithCGRect:subtractedArea]];
}
subtractedArea = rectBetween(remainder, intersectedRect, &remainder, CGRectMaxXEdge);
if (!CGRectIsEmpty(subtractedArea)) {
[results addObject:[NSValue valueWithCGRect:subtractedArea]];
}
subtractedArea = rectBetween(remainder, intersectedRect, &remainder, CGRectMinXEdge);
if (!CGRectIsEmpty(subtractedArea)) {
[results addObject:[NSValue valueWithCGRect:subtractedArea]];
}
return results;
}
// returns the area between rect1 and rect2 along the edge
CGRect rectBetween(CGRect rect1, CGRect rect2, CGRect* remainder, CGRectEdge edge)
{
CGRect intersectedRect = CGRectIntersection(rect1, rect2);
if (CGRectIsEmpty(intersectedRect)) {
return CGRectNull;
}
CGRect rect3;
float chopAmount = 0;
switch (edge) {
case CGRectMaxYEdge:
chopAmount = rect1.size.height - (intersectedRect.origin.y - rect1.origin.y);
if (chopAmount > rect1.size.height) { chopAmount = rect1.size.height; }
break;
case CGRectMinYEdge:
chopAmount = rect1.size.height - (CGRectGetMaxY(rect1) - CGRectGetMaxY(intersectedRect));
if (chopAmount > rect1.size.height) { chopAmount = rect1.size.height; }
break;
case CGRectMaxXEdge:
chopAmount = rect1.size.width - (intersectedRect.origin.x - rect1.origin.x);
if (chopAmount > rect1.size.width) { chopAmount = rect1.size.width; }
break;
case CGRectMinXEdge:
chopAmount = rect1.size.width - (CGRectGetMaxX(rect1) - CGRectGetMaxX(intersectedRect));
if (chopAmount > rect1.size.width) { chopAmount = rect1.size.width; }
break;
default:
break;
}
CGRectDivide(rect1, remainder, &rect3, chopAmount, edge);
return rect3;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…