如何从另一个中减去一个矩形?

Chr*_*son 6 c# math

我正在尝试确定桌面的工作区域,即使隐藏任务栏也是如此.

我有两个矩形,屏幕的边界和任务栏的界限.我需要从屏幕矩形中减去任务栏的边界Rectangle,以确定桌面的可用工作区域.基本上,我想提出Screen.WorkingArea,除非隐藏任务栏.

说屏幕矩形X,Y,W,H = 0,0,1680,1050和任务栏X,Y,W,H is 0,1010,1680,40.我需要从第一个中减去第二个来确定工作区域0,0,1680,1010.

任务栏可以位于屏幕四边之一,我知道必须有一个更好的方法,而不是确定任务栏的位置,然后有一个单独的代码行为四个可能位置中的每一个生成一个新的矩形.

Hai*_*Kao 8

假设矩形2包含在矩形1中(如果不包含,则使用两个矩形的交集作为矩形2):

-------------------------
|      rectangle 1      |
|                       |
|     -------------     |
|     |rectangle 2|     |
|     -------------     |
|                       |
|                       |
-------------------------
Run Code Online (Sandbox Code Playgroud)

如果从矩形1中减去矩形2,则会得到一个带孔的区域:

-------------------------
|                       |
|                       |
|     -------------     |
|     |    hole   |     |
|     -------------     |
|                       |
|                       |
-------------------------
Run Code Online (Sandbox Code Playgroud)

该区域可以分解为4个矩形:

-------------------------
|          A            |
|                       |
|-----------------------|
|  B  |   hole    |  C  |
|-----------------------|
|                       |
|          D            |
-------------------------
Run Code Online (Sandbox Code Playgroud)

如果矩形1和矩形2的三边重合,则从减去的区域得到1个矩形(这是你的情况).通常,您最多可以获得4个矩形.

在objective-c中实现(对不起,此刻没有visual studio):

// 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;
}
Run Code Online (Sandbox Code Playgroud)


Val*_*lev 6

C# 中的一个简单解决方案

\n

这是快速、延迟执行、易于理解、跨平台且易于移植到其他语言的 C# 解决方案。

\n

\xd0\x95dit:修复 (subtrahend.IsEmpty) 的情况,以便代码不返回零面积矩形。请参阅返回触摸矩形的场景的注释

\n
    //-------------------------\n    //|          A            |\n    //|-----------------------|\n    //|  B  |   hole    |  C  |\n    //|-----------------------|\n    //|          D            |\n    //-------------------------\n    public static IEnumerable<Rectangle> Subtract(this \n        Rectangle minuend,\n        Rectangle subtrahend)\n    {\n        subtrahend.Intersect(minuend);\n        //if (subtrahend.IsEmpty)\n        //if (subtrahend.Size.IsEmpty)\n        if ((subtrahend.Width | subtrahend.Height) == 0)\n        {\n            yield return minuend;\n            yield break;\n        }\n\n        //A\n        var heightA = subtrahend.Top - minuend.Top;\n        if (heightA > 0)\n            yield return new Rectangle(\n                minuend.Left,\n                minuend.Top,\n                minuend.Width,\n                heightA);\n\n        //B\n        var widthB = subtrahend.Left - minuend.Left;\n        if (widthB > 0)\n            yield return new Rectangle(\n                minuend.Left,\n                subtrahend.Top,\n                widthB,\n                subtrahend.Height);\n\n        //C\n        var widthC = minuend.Right - subtrahend.Right;\n        if (widthC > 0)\n            yield return new Rectangle(\n                subtrahend.Right,\n                subtrahend.Top,\n                widthC,\n                subtrahend.Height);\n\n        //D\n        var heightD = minuend.Bottom - subtrahend.Bottom;\n        if (heightD > 0)\n            yield return new Rectangle(\n                minuend.Left,\n                subtrahend.Bottom,\n                minuend.Width,\n                heightD);\n    }\n
Run Code Online (Sandbox Code Playgroud)\n


cas*_*nca 1

我不确定还有比你提到的更好的方法。问题是,在一般情况下,从另一个矩形区域中减去一个矩形区域会在两者之间留下一个洞,因此结果并不是真正的矩形。在您的情况下,您知道任务栏恰好适合屏幕矩形的一侧,因此“最佳”方法确实是找出它是哪一侧并从该一侧减去宽度/高度。