Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
236 views
in Technique[技术] by (71.8m points)

c# - How to subtract a rectangle from another?

I'm trying to determine the working area of the desktop even when the taskbar is hidden.

I have two Rectangles, the screen's bounds and the taskbar's bounds. I need to subtract the taskbar's bounds Rectangle from the screen Rectangle to determine the available working area of the desktop. Basically, I want to come up with Screen.WorkingArea except when the taskbar is hidden.

Say the screen rectangle X,Y,W,H = 0,0,1680,1050 and the taskbar X,Y,W,H is 0,1010,1680,40. I need to subtract the second from the first to determine that the working area is 0,0,1680,1010.

The taskbar can be on either of the four sides of the screen and I know there's got to be a better method than determining where the taskbar is and then having a separate line of code to generate a new Rectangle for each of the four possible positions.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...