【问题标题】:Get the bounding rectangle of multiple rectangles获取多个矩形的边界矩形
【发布时间】:2014-10-21 14:01:00
【问题描述】:

我在图像上最多有 4 个矩形,对于每个矩形,我都知道它们的左上角 X、Y 坐标和宽度、高度。我想创建一个 Int32Rect ,其尺寸从最左上角的矩形到最右下角的矩形。主要问题是您只能使用 x,y,width,height 参数创建 System.Windows.Int32Rect。有什么想法可以用我目前已知的值来实现吗?

编辑: 试图澄清,我想创建一个 Int32Rect ,它是我图像上所有其他“矩形”的尺寸。所以一个大的 Int32Rect 从图像左上角的“矩形”开始,延伸到图像右下角的“矩形”。

以下是对单个矩形执行此操作的一些代码:

var topLeftOfBox = new Point(centerOfBoxRelativeToImage.X - Box.Width/2,
                centerOfBoxRelativeToImage.Y - Box.Height/2);
return new CroppedBitmap(originalBitmap, new Int32Rect(topLeftOfBox.X, topLeftOfBox.Y, Box.Width, Box.Height));

感谢大家的帮助和想法,我发现 Aybe 的答案最适合我。

【问题讨论】:

  • 你说你有顶部、左侧、X、Y 和宽度和高度。我没有看到问题,因为您可以将 X、Y、Width 和 Height 参数传递给 Int32Rect。
  • 这似乎是一个相当简单的最小/最大计算。你能发布你的最佳尝试和问题描述吗?
  • @AaronHawkins 我可以为单个矩形执行此操作,但我想为多个矩形执行此操作。
  • @nvoigt 查看问题更新,看看是否有帮助

标签: c# rectangles


【解决方案1】:

您需要获取每个矩形的 x/y mins/maxs 并用这些值构建一个矩形:

using System.Linq;
using System.Windows;

internal class Class1
{
    public Class1()
    {
        var rect1 = new Int32Rect(10, 10, 10, 10);
        var rect2 = new Int32Rect(30, 30, 10, 10);
        var rect3 = new Int32Rect(50, 50, 10, 10);
        var rect4 = new Int32Rect(70, 70, 10, 10);

        var int32Rects = new[] { rect1, rect2, rect3, rect4 };
        var int32Rect = GetValue(int32Rects);
    }

    private static Int32Rect GetValue(Int32Rect[] int32Rects)
    {
        int xMin = int32Rects.Min(s => s.X);
        int yMin = int32Rects.Min(s => s.Y);
        int xMax = int32Rects.Max(s => s.X + s.Width);
        int yMax = int32Rects.Max(s => s.Y + s.Height);
        var int32Rect = new Int32Rect(xMin, yMin, xMax - xMin, yMax - yMin);
        return int32Rect;
    }
}

结果:

{10,10,70,70}

【讨论】:

  • 您也可以使用 Right、Top、Bottom,例如:您可以使用 s.Right 代替 s.X + s.Width。
【解决方案2】:

这个问题有点不清楚,所以我将首先说明我对您正在寻找的内容的理解。当我阅读您的问题时,您有一个矩形集合,并且正在寻找包含集合中所有矩形的最小矩形。

为了做到这一点,您需要了解以下内容:

  • 矩形的左上角是(X, Y),右下角是(X+Width, Y+Height)
  • 矩形的宽度由Right - Left 给出。高度由Bottom - Top 给出。

现在您可以在这些数量之间进行转换,剩下的就很容易了。找到最小顶部值、最小左侧值、最大右侧值和最大底部值。将这些值输入到上面第二个要点中的方程式中,您就完成了。

【讨论】:

  • 是的,David H.,您的解决方案似乎与我标记答案的解决方案基本相同。 -谢谢
【解决方案3】:

您可以节省一些精力,并避免担心“世界知识”中的 Rectangle 是最底部/顶部。最左侧/最右侧:

public static class RectangleExtensions
{
    public static Rectangle RectsGetBounds(this Rectangle rect, params Rectangle[] rects)
    {
        Rectangle rbase = rect;

        for (int i = 0; i < rects.Length; i++)
        {
            rbase = Rectangle.Union(rbase, rects[i]);
        }

        return rbase;
    }

    public static Rectangle ControlsGetBounds(this Control cntrl, params Control[] cntrls)
    {
        return RectsGetBounds(cntrl.Bounds, cntrls.Select(c => c.Bounds).ToArray());
    }
}

【讨论】: