Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subtract a rectangle from another?

Tags:

c#

math

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.

like image 631
Chris Thompson Avatar asked Sep 21 '10 23:09

Chris Thompson


1 Answers

A simple solution in C#

Here is fast, deferred execution, easy to understand, cross platform and easy portable to other languages solution in C#.

Еdit: Fix the case of (subtrahend.IsEmpty) so the code do not return zero area rectangles. See comments for scenarios where touching rectangles are returned

    //-------------------------
    //|          A            |
    //|-----------------------|
    //|  B  |   hole    |  C  |
    //|-----------------------|
    //|          D            |
    //-------------------------
    public static IEnumerable<Rectangle> Subtract(this 
        Rectangle minuend,
        Rectangle subtrahend)
    {
        subtrahend.Intersect(minuend);
        //if (subtrahend.IsEmpty)
        //if (subtrahend.Size.IsEmpty)
        if ((subtrahend.Width | subtrahend.Height) == 0)
        {
            yield return minuend;
            yield break;
        }

        //A
        var heightA = subtrahend.Top - minuend.Top;
        if (heightA > 0)
            yield return new Rectangle(
                minuend.Left,
                minuend.Top,
                minuend.Width,
                heightA);

        //B
        var widthB = subtrahend.Left - minuend.Left;
        if (widthB > 0)
            yield return new Rectangle(
                minuend.Left,
                subtrahend.Top,
                widthB,
                subtrahend.Height);

        //C
        var widthC = minuend.Right - subtrahend.Right;
        if (widthC > 0)
            yield return new Rectangle(
                subtrahend.Right,
                subtrahend.Top,
                widthC,
                subtrahend.Height);

        //D
        var heightD = minuend.Bottom - subtrahend.Bottom;
        if (heightD > 0)
            yield return new Rectangle(
                minuend.Left,
                subtrahend.Bottom,
                minuend.Width,
                heightD);
    }
like image 189
Valentin Vasilev Avatar answered Sep 30 '22 13:09

Valentin Vasilev