从旋转的矩形计算边界框坐标

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从旋转的矩形计算边界框坐标相关的知识,希望对你有一定的参考价值。

我有一个矩形左上角的坐标,以及从0到180和-0到-180的宽度,高度和旋转。

我试图获取矩形周围的实际框的边界坐标。

什么是计算边界框坐标的简单方法

  • 最小值,最大值,最小值x,最大值x?

A点并不总是在最小值上,它可以在任何地方。

如果需要,我可以在as3中使用矩阵变换工具包。

答案
  • 变换所有四个角的坐标
  • 找到所有四个x中最小的一个作为min_x
  • 找到所有四个x中最大的x并称之为max_x
  • 与y同上
  • 你的边界框是(min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)

AFAIK,没有任何皇家之路可以让你快得多。

如果您想知道如何变换坐标,请尝试:

x2 = x0+(x-x0)*cos(theta)+(y-y0)*sin(theta)
y2 = y0-(x-x0)*sin(theta)+(y-y0)*cos(theta)

其中(x0,y0)是您旋转的中心。您可能需要修改这个,具体取决于您的三角函数(他们希望度数或弧度)坐标系的感觉/符号与指定角度的方式等。

另一答案

我不确定我理解,但是复合变换矩阵将为所有相关点提供新的坐标。如果您认为矩形可能会在转换后溢出可成像区域,则应用剪切路径。

如果您不熟悉矩阵的确切定义,请查看here

另一答案

我使用Region for First旋转矩形然后使用该旋转区域来检测该矩形

        r = new Rectangle(new Point(100, 200), new Size(200, 200));         
        Color BorderColor = Color.WhiteSmoke;
        Color FillColor = Color.FromArgb(66, 85, 67);
        int angle = 13;
        Point pt = new Point(r.X, r.Y);
        PointF rectPt = new PointF(r.Left + (r.Width / 2),
                               r.Top + (r.Height / 2));
       //declare myRegion globally 
        myRegion = new Region(r);

        // Create a transform matrix and set it to have a 13 degree

        // rotation.
        Matrix transformMatrix = new Matrix();
        transformMatrix.RotateAt(angle, pt);

        // Apply the transform to the region.
        myRegion.Transform(transformMatrix);
        g.FillRegion(Brushes.Green, myRegion);
        g.ResetTransform();

现在检测那个矩形

        private void panel_MouseMove(object sender, MouseEventArgs e)
    {


        Point point = e.Location;
        if (myRegion.IsVisible(point, _graphics))
        {
            // The point is in the region. Use an opaque brush.
            this.Cursor = Cursors.Hand;
        }
        else {
            this.Cursor = Cursors.Cross;
        }

    }
另一答案

我意识到你要求ActionScript,但是,如果有人来到这里寻找ios或OS-X答案,它是这样的:

+ (CGRect) boundingRectAfterRotatingRect: (CGRect) rect toAngle: (float) radians
{
    CGAffineTransform xfrm = CGAffineTransformMakeRotation(radians);
    CGRect result = CGRectApplyAffineTransform (rect, xfrm);

    return result;
}

如果您的操作系统为您提供了所有艰苦的工作,那就试试吧! :)

迅速:

func boundingRectAfterRotatingRect(rect: CGRect, toAngle radians: CGFloat) -> CGRect {
    let xfrm = CGAffineTransformMakeRotation(radians)
    return CGRectApplyAffineTransform (rect, xfrm)
}
另一答案

MarkusQ概述的方法非常有效,但请记住,如果已经有A点,则不需要转换其他三个角。

另一种更有效的方法是测试旋转角度所在的象限,然后直接计算答案。这样做效率更高,因为你只有两个if语句的最坏情况(检查角度),而另一个方法的最差情况是12个(当检查其他三个角以查看它们是否大于当前时,每个组件为6个)我认为最大或小于当前最小值。

基本算法仅使用了毕达哥拉斯定理的一系列应用,如下所示。我用theta表示了旋转角度,并以度为单位表示检查,因为它是伪代码。

ct = cos( theta );
st = sin( theta );

hct = h * ct;
wct = w * ct;
hst = h * st;
wst = w * st;

if ( theta > 0 )
{
    if ( theta < 90 )
    {
        // 0 < theta < 90
        y_min = A_y;
        y_max = A_y + hct + wst;
        x_min = A_x - hst;
        x_max = A_x + wct;
    }
    else
    {
        // 90 <= theta <= 180
        y_min = A_y + hct;
        y_max = A_y + wst;
        x_min = A_x - hst + wct;
        x_max = A_x;
    }
}
else
{
    if ( theta > -90 )
    {
        // -90 < theta <= 0
        y_min = A_y + wst;
        y_max = A_y + hct;
        x_min = A_x;
        x_max = A_x + wct - hst;
    }
    else
    {
        // -180 <= theta <= -90
        y_min = A_y + wst + hct;
        y_max = A_y;
        x_min = A_x + wct;
        x_max = A_x - hst;
    }
}

这种方法假定你拥有你所拥有的,即点A和θ的值,它位于[-180,180]的范围内。我还假设theta在顺时针方向上增加,因为在图中旋转了30度的矩形似乎表明你正在使用,我不确定右边的部分试图表示什么。如果这是错误的方法,那么只需交换对称子句以及st术语的符号。

另一答案
    fitRect: function( rw,rh,radians ){
            var x1 = -rw/2,
                x2 = rw/2,
                x3 = rw/2,
                x4 = -rw/2,
                y1 = rh/2,
                y2 = rh/2,
                y3 = -rh/2,
                y4 = -rh/2;

            var x11 = x1 * Math.cos(radians) + y1 * Math.sin(radians),
                y11 = -x1 * Math.sin(radians) + y1 * Math.cos(radians),
                x21 = x2 * Math.cos(radians) + y2 * Math.sin(radians),
                y21 = -x2 * Math.sin(radians) + y2 * Math.cos(radians), 
                x31 = x3 * Math.cos(radians) + y3 * Math.sin(radians),
                y31 = -x3 * Math.sin(radians) + y3 * Math.cos(radians),
                x41 = x4 * Math.cos(radians) + y4 * Math.sin(radians),
                y41 = -x4 * Math.sin(radians) + y4 * Math.cos(radians);

            var x_min = Math.min(x11,x21,x31,x41),
                x_max = Math.max(x11,x21,x31,x41);

            var y_min = Math.min(y11,y21,y31,y41);
                y_max = Math.max(y11,y21,y31,y41);

            return [x_max-x_min,y_max-y_min];
        }
另一答案

如果你正在使用GDI +,你可以创建一个新的GrpaphicsPath - >添加任何点或形状 - >应用旋转变换 - >使用GraphicsPath.GetBounds(),它将返回一个界定旋转形状的矩形。

(edit) VB.Net Sample

Public Shared Sub RotateImage(ByRef img As Bitmap, degrees As Integer)
' http://stackoverflow.com/questions/622140/calculate-bounding-box-coordinates-from-a-rotated-rectangle-picture-inside#680877
'
Using gp As New GraphicsPath
  gp.AddRectangle(New Rectangle(0, 0, img.Width, img.Height))

  Dim translateMatrix As New Matrix
  translateMatrix.RotateAt(degrees, New PointF(img.Width  2, img.Height  2))
  gp.Transform(translateMatrix)

  Dim gpb = gp.GetBounds

  Dim newwidth = CInt(gpb.Width)
  Dim newheight = CInt(gpb.Height)

  ' http://www.codeproject.com/Articles/58815/C-Image-PictureBox-Rotations
  '
  Dim rotatedBmp As New Bitmap(newwidth, newheight)

  rotatedBmp.SetResolution(img.HorizontalResolution, img.VerticalResolution)

  Using g As Graphics = Graphics.FromImage(rotatedBmp)
    g.Clear(Color.White)
    translateMatrix = New Matrix
    translateMatrix.Translate(newwidth  2, newheight  2)
    translateMatrix.Rotate(degrees)
    translateMatrix.Translate(-img.Width  2, -img.Height  2)
    g.Transform = translateMatrix
    g.DrawImage(img, New PointF(0, 0))
  End Using
  img.Dispose()
  img = rotatedBmp
End Using

结束子

另一答案

虽然Code Guru声明了GetBounds()方法,但我注意到这个问题被标记为3,flex,所以这里有一个as3片段来说明这个想法。

var box:Shape = new Shape();
box.graphics.beginFill(0,.5);
box.graphics.drawRect(0,0,100,50);
box.graphics.endFill();
box.rotation = 20;
box.x = box.y = 100;
addChild(box);

var bounds:Rectangle = box.getBounds(this);

var boundingBox:Shape = new Shape();
boundingBox.graphics.lineStyle(1);
boundingBox.graphics.drawRect(bounds.x,bounds.y,bounds.width,bounds.height);
addChild(boundingBox);

我注意到有两种方法似乎做同样的事情:getBounds()和getRect()

另一答案
/**
     * Applies the given transformation matrix to the rectangle and returns
     * a new bounding box to the transformed rectangle.
     */
    public static function getBoundsAfterTransformation(bounds:Rectangle, m:Matrix):Rectangle {
        if (m == null) return bounds;

        var topLeft:Point = m.transformPoint(bounds.topLeft);
        var topRight:Point = m.transformPoint(new Point(bounds.right, bounds.top));
        var bottomRight:Point = m.transformPoint(bounds.bottomRight);
        var bottomLeft:Point = m.transformPoint(new Point(bounds.left, bounds.bottom));

        var left:Number = Math.min(topLeft.x, topRight.x, bottomRight.x, bottomLeft.x);
        var top:Number = Math.min(topLeft.y, topRight.y, bottomRight.y, bottomLeft.y);
        var right:Number = Math.max(topLeft.x, topRight.x, bottomRig

以上是关于从旋转的矩形计算边界框坐标的主要内容,如果未能解决你的问题,请参考以下文章

查找覆盖原始矩形的旋转矩形的大小

如何计算围绕其中心旋转的矩形的边界框?

如何计算围绕其角旋转的矩形的边界框?

如何在 C++ 中获取边界框(矩形)内的像素值和坐标?有啥方法吗?

Mapbox矩形线从两点的边界

ruby Ruby:获取旋转矩形的边界框的尺寸