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

时间:2022-08-22 13:54:38

I have the coordinates of the top left point of a rectangle as well as its width, height and rotation from 0 to 180 and -0 to -180.

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

I am trying to get the bounding coordinates of the actual box around the rectangle.

我想要得到矩形周围实际方框的边界坐标。

What is a simple way of calculating the coordinates of the bounding box

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

  • Min y, max y, min x, max x?
  • 最小y,最大y,最小x,最大x?

The A point is not always on the min y bound, it can be anywhere.

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

I can use matrix the transform toolkit in as3 if needed.

如果需要的话,我可以使用as3中的转换工具包。

11 个解决方案

#1


68  

  • Transform the coordinates of all four corners
  • 变换四个角的坐标
  • Find the smallest of all four x's as min_x
  • 求所有四个x中最小的为min_x
  • Find the largest of all four x's and call it max_x
  • 找到所有四个x中最大的一个,并将其命名为max_x
  • Ditto with the y's
  • 与y同上
  • Your bounding box is (min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)
  • 你的边界框是(min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)

AFAIK, there isn't any royal road that will get you there much faster.

阿法伊克,没有任何捷径可以让你更快地到达那里。

If you are wondering how to transform the coordinates, try:

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

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

where (x0,y0) is the center around which you are rotating. You may need to tinker with this depending on your trig functions (do they expect degrees or radians) the sense / sign of your coordinate system vs. how you are specifying angles, etc.

其中(x0,y0)是旋转的中心。您可能需要根据您的三角函数(它们期望的是度数或弧度)、坐标系统的感觉/符号以及您如何指定角度等来修改它。

#2


22  

I realize that you're asking for ActionScript but, just in case anyone gets here looking for the iOS or OS-X answer, it is this:

我知道你在问动作脚本,但是,万一有人来找iOS或OS-X的答案,它是这样的:

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

If your OS offers to do all the hard work for you, let it! :)

如果你的操作系统提供给你所有的努力工作,让它!:)

Swift:

迅速:

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

#3


8  

The method outlined by MarkusQ works perfectly but bear in mind that you don't need to transform the other three corners if you have point A already.

MarkusQ概述的方法可以很好地工作,但是要记住,如果您已经有了点A,就不需要转换其他三个角。

An alternative method, which is more efficient, is to test which quadrant your rotation angle is in and then simply compute the answer directly. This is more efficient as you only have a worst case of two if statements (checking the angle) whereas the other approach has a worst case of twelve (6 for each component when checking the other three corners to see if they are greater than the current max or less than the current min) I think.

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

The basic algorithm, which uses nothing more than a series of applications of Pythagoras' theorem, is shown below. I have denoted the rotation angle by theta and expressed the check there in degrees as it's pseudo-code.

下面展示了基本算法,它只使用了勾股定理的一系列应用。我已经用表示旋转角度的符号来表示它的度作为伪码。

ct = cos( theta );st = sin( theta );hct = h * ct;wct = w * ct;hst = h * st;wst = w * st;if ( theta > 0 ){    if ( theta < 90 degrees )    {        // 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;    }}

This approach assumes that you have what you say you have i.e. point A and a value for theta that lies in the range [-180, 180]. I've also assumed that theta increases in the clockwise direction as that's what the rectangle that has been rotated by 30 degrees in your diagram seems to indicate you are using, I wasn't sure what the part on the right was trying to denote. If this is the wrong way around then just swap the symmetric clauses and also the sign of the st terms.

这个方法假设你有你说的你有,点A和一个在范围内的值[-180,180]。我也假设是顺时针方向的增加这就是在图中旋转了30度的矩形似乎表明你在使用,我不确定右边的部分要表示什么。如果这是错误的方法,那么就交换对称子句和st项的符号。

#4


6  

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

#5


3  

if you are using GDI+ , you can create a new GrpaphicsPath -> Add any points or shapes to it -> Apply rotate transformation -> use GraphicsPath.GetBounds() and it will return a rectangle that bounds your rotated shape.

如果您正在使用GDI+,您可以创建一个新的GrpaphicsPath—>添加任何点或形状—>应用旋转变换—>使用graphicsp . getbounds()(),它将返回一个矩形,它将包围您旋转的形状。

(edit) VB.Net Sample

Public Shared Sub RotateImage(ByRef img As Bitmap, degrees As Integer)' http://*.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 = rotatedBmpEnd Using

End Sub

终止子

#6


2  

Although Code Guru stated the GetBounds() method, I've noticed the question is tagged as3, flex, so here is an as3 snippet that illustrates the idea.

尽管Code Guru声明了GetBounds()方法,但我注意到这个问题被标记为as3, 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);

I noticed that there two methods that seem to do the same thing: getBounds() and getRect()

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

#7


2  

/**     * 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, bottomRight.x, bottomLeft.x);        var bottom:Number = Math.max(topLeft.y, topRight.y, bottomRight.y, bottomLeft.y);        return new Rectangle(left, top, right - left, bottom - top);    }

#8


1  

Apply the rotation matrix to your corner points. Then use the minimum/maximum respectively of the obtained x,y coordinates to define your new bounding box.

将旋转矩阵应用到你的角点上。然后分别使用得到的x、y坐标的最小/最大值来定义新的边界框。

#9


1  

Here are three functions from my open source libraries. The functions are fully tested in Java but the formulae can be easily translated to any language.

下面是我的开源库中的三个函数。函数在Java中得到了充分的测试,但是公式可以很容易地翻译成任何语言。

The signatures are:

签名:

public static float getAngleFromPoint(final Point centerPoint, final Point touchPoint)

公共静态浮点格坦弗罗姆点(终点中心点,终点接触点)

public static float getTwoFingerDistance(float firstTouchX, float firstTouchY, float secondTouchX, float secondTouchY)

公共静态浮动getTwoFingerDistance(float firstTouchX, float firstTouchY, float secondTouchX, float secondTouchY)

Point getPointFromAngle(final double angle, final double radius)

点getPointFromAngle(final double angle, final double radius)

This solution assumes that the pixel density is evenly spaced.Before rotating the object do the following:

这个解假设像素密度是均匀间隔的。在旋转物体之前,要做以下事情:

  1. Use getAngleFromPoint to calculate the angle from the center to the upper right corner (lets say this returns 20 degrees) meaning that the upp left corner is -20 degrees or 340 degrees.

    使用getAngleFromPoint计算从中心到右上角的角度(假设返回20度),这意味着左上角是-20度或340度。

  2. Use the getTwoFingerDistance to return the diagonal distance between the center point and the upper right corner (this distance should obvoiusly be the same to all corners, This distance will be used in the next calculation).

    使用getTwoFingerDistance返回中心点和右上角之间的对角线距离(这个距离对于所有的角应该是完全相同的,这个距离将在下次计算中使用)。

  3. Now lets say we rotate the object clockwise by 30 degrees. We now know that the upper right corner must be at 50 degrees and the upper left corner is at 10 degrees.

    现在假设我们顺时针旋转物体30度。现在我们知道右上角一定是50度,左上角是10度。

  4. You should now be able to use the getPointFromAngle function on the upper left and upper right corner. using the radius returned from step 2.The X position multiplied by 2 from the upper right corner should give you the new width and the Y position times 2 from the upper left corner should give the the new height.

    现在应该可以在左上角和右上角使用getPointFromAngle函数。使用步骤2返回的半径。在右上角X的位置乘以2应该会得到新的宽度,在左上角Y的位置乘以2应该会得到新的高度。

These above 4 steps should be put into conditions based upon how far you have rotated your object other wise you may return the height as the width and the width as the height.

以上4个步骤应该根据你旋转物体的距离来设定,你可以把高度作为宽度,把宽度作为高度。

Bare in mind the angle functions are expressed in factors of 0-1 instead of 0-360 (just multiply or divide by 360 where appropriate):

考虑到角度函数是用0-1而不是0-360的因子来表示的(只要适当地乘以或除以360即可):

//Gets an angle from two points expressed as a factor of 0 -1 (0 being 0/360, 0.25 being 90 degrees etc)

//得到两个点的夹角表示为0 -1(0 = 0/360,0。25 = 90度,等等)

public float getAngleFromPoint(final Point centerPoint, final Point touchPoint) {    float returnVal = 0;    //+0 - 0.5    if(touchPoint.x > centerPoint.x) {        returnVal = (float) (Math.atan2((touchPoint.x - centerPoint.x), (centerPoint.y - touchPoint.y)) * 0.5 / Math.PI);    }    //+0.5    else if(touchPoint.x < centerPoint.x) {        returnVal = (float) (1 - (Math.atan2((centerPoint.x - touchPoint.x), (centerPoint.y - touchPoint.y)) * 0.5 / Math.PI));    }//End if(touchPoint.x > centerPoint.x)    return returnVal;}

//Measures the diagonal distance between two points

//测量两点之间的对角线距离

public float getTwoFingerDistance(final float firstTouchX, final float firstTouchY, final float secondTouchX, final float secondTouchY) {    float pinchDistanceX = 0;    float pinchDistanceY = 0;    if(firstTouchX > secondTouchX) {        pinchDistanceX = Math.abs(secondTouchX - firstTouchX);    }    else if(firstTouchX < secondTouchX) {        pinchDistanceX = Math.abs(firstTouchX - secondTouchX);    }//End if(firstTouchX > secondTouchX)    if(firstTouchY > secondTouchY) {        pinchDistanceY = Math.abs(secondTouchY - firstTouchY);    }    else if(firstTouchY < secondTouchY) {        pinchDistanceY = Math.abs(firstTouchY - secondTouchY);    }//End if(firstTouchY > secondTouchY)    if(pinchDistanceX == 0 && pinchDistanceY == 0) {        return 0;    }    else {        pinchDistanceX = (pinchDistanceX * pinchDistanceX);        pinchDistanceY = (pinchDistanceY * pinchDistanceY);        return (float) Math.abs(Math.sqrt(pinchDistanceX + pinchDistanceY));    }//End if(pinchDistanceX == 0 && pinchDistanceY == 0)}

//Get XY coordinates from an angle given a radius (The angle is expressed in a factor of 0-1 0 being 0/360 degrees and 0.75 being 270 etc)

//从给定半径的角度得到XY坐标(这个角度表示为0-1 0 = 0/360度,0.75 = 270度等等)

public Point getPointFromAngle(final double angle, final double radius) {    final Point coords = new Point();    coords.x = (int) (radius * Math.sin((angle) * 2 * Math.PI));    coords.y = (int) -(radius * Math.cos((angle) * 2 * Math.PI));    return coords;}

These code snippets are from my open source libraries: https://bitbucket.org/warwick/hgdialrepo and https://bitbucket.org/warwick/hacergestov2.One is a gesture library for Android and the other is a dial control for Android. There is also an OpenGLES 2.0 implementation of the dial control at: https://bitbucket.org/warwick/hggldial

这些代码片段来自我的开源库:https://bitbucket.org/warwick/hgdialrepo和https://bitbucket.org/warwick/hacergestov2.一个是Android的手势库,另一个是Android的拨号控件。还有OpenGLES 2.0的拨号控件实现:https://bitbucket.org/warwick/hggldial

#10


0  

I am not sure I understand, but a compound transformation matrix will give you the new co-ordinates for all points concerned. If you think the rectangle may spill over the imagable area post transformation apply a clipping path.

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

In case you are unfamiliar with the exact definition of the matrices take a look here.

如果你不熟悉矩阵的确切定义,在这里看看。

#11


0  

I used Region for First rotating the rectangle and then use that rotated region to detect that rectangle

我使用区域首先旋转矩形,然后使用旋转区域来检测矩形

        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();

now to detecting that rectangle

现在来检测这个矩形

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

#1


68  

  • Transform the coordinates of all four corners
  • 变换四个角的坐标
  • Find the smallest of all four x's as min_x
  • 求所有四个x中最小的为min_x
  • Find the largest of all four x's and call it max_x
  • 找到所有四个x中最大的一个,并将其命名为max_x
  • Ditto with the y's
  • 与y同上
  • Your bounding box is (min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)
  • 你的边界框是(min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)

AFAIK, there isn't any royal road that will get you there much faster.

阿法伊克,没有任何捷径可以让你更快地到达那里。

If you are wondering how to transform the coordinates, try:

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

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

where (x0,y0) is the center around which you are rotating. You may need to tinker with this depending on your trig functions (do they expect degrees or radians) the sense / sign of your coordinate system vs. how you are specifying angles, etc.

其中(x0,y0)是旋转的中心。您可能需要根据您的三角函数(它们期望的是度数或弧度)、坐标系统的感觉/符号以及您如何指定角度等来修改它。

#2


22  

I realize that you're asking for ActionScript but, just in case anyone gets here looking for the iOS or OS-X answer, it is this:

我知道你在问动作脚本,但是,万一有人来找iOS或OS-X的答案,它是这样的:

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

If your OS offers to do all the hard work for you, let it! :)

如果你的操作系统提供给你所有的努力工作,让它!:)

Swift:

迅速:

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

#3


8  

The method outlined by MarkusQ works perfectly but bear in mind that you don't need to transform the other three corners if you have point A already.

MarkusQ概述的方法可以很好地工作,但是要记住,如果您已经有了点A,就不需要转换其他三个角。

An alternative method, which is more efficient, is to test which quadrant your rotation angle is in and then simply compute the answer directly. This is more efficient as you only have a worst case of two if statements (checking the angle) whereas the other approach has a worst case of twelve (6 for each component when checking the other three corners to see if they are greater than the current max or less than the current min) I think.

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

The basic algorithm, which uses nothing more than a series of applications of Pythagoras' theorem, is shown below. I have denoted the rotation angle by theta and expressed the check there in degrees as it's pseudo-code.

下面展示了基本算法,它只使用了勾股定理的一系列应用。我已经用表示旋转角度的符号来表示它的度作为伪码。

ct = cos( theta );st = sin( theta );hct = h * ct;wct = w * ct;hst = h * st;wst = w * st;if ( theta > 0 ){    if ( theta < 90 degrees )    {        // 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;    }}

This approach assumes that you have what you say you have i.e. point A and a value for theta that lies in the range [-180, 180]. I've also assumed that theta increases in the clockwise direction as that's what the rectangle that has been rotated by 30 degrees in your diagram seems to indicate you are using, I wasn't sure what the part on the right was trying to denote. If this is the wrong way around then just swap the symmetric clauses and also the sign of the st terms.

这个方法假设你有你说的你有,点A和一个在范围内的值[-180,180]。我也假设是顺时针方向的增加这就是在图中旋转了30度的矩形似乎表明你在使用,我不确定右边的部分要表示什么。如果这是错误的方法,那么就交换对称子句和st项的符号。

#4


6  

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

#5


3  

if you are using GDI+ , you can create a new GrpaphicsPath -> Add any points or shapes to it -> Apply rotate transformation -> use GraphicsPath.GetBounds() and it will return a rectangle that bounds your rotated shape.

如果您正在使用GDI+,您可以创建一个新的GrpaphicsPath—>添加任何点或形状—>应用旋转变换—>使用graphicsp . getbounds()(),它将返回一个矩形,它将包围您旋转的形状。

(edit) VB.Net Sample

Public Shared Sub RotateImage(ByRef img As Bitmap, degrees As Integer)' http://*.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 = rotatedBmpEnd Using

End Sub

终止子

#6


2  

Although Code Guru stated the GetBounds() method, I've noticed the question is tagged as3, flex, so here is an as3 snippet that illustrates the idea.

尽管Code Guru声明了GetBounds()方法,但我注意到这个问题被标记为as3, 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);

I noticed that there two methods that seem to do the same thing: getBounds() and getRect()

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

#7


2  

/**     * 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, bottomRight.x, bottomLeft.x);        var bottom:Number = Math.max(topLeft.y, topRight.y, bottomRight.y, bottomLeft.y);        return new Rectangle(left, top, right - left, bottom - top);    }

#8


1  

Apply the rotation matrix to your corner points. Then use the minimum/maximum respectively of the obtained x,y coordinates to define your new bounding box.

将旋转矩阵应用到你的角点上。然后分别使用得到的x、y坐标的最小/最大值来定义新的边界框。

#9


1  

Here are three functions from my open source libraries. The functions are fully tested in Java but the formulae can be easily translated to any language.

下面是我的开源库中的三个函数。函数在Java中得到了充分的测试,但是公式可以很容易地翻译成任何语言。

The signatures are:

签名:

public static float getAngleFromPoint(final Point centerPoint, final Point touchPoint)

公共静态浮点格坦弗罗姆点(终点中心点,终点接触点)

public static float getTwoFingerDistance(float firstTouchX, float firstTouchY, float secondTouchX, float secondTouchY)

公共静态浮动getTwoFingerDistance(float firstTouchX, float firstTouchY, float secondTouchX, float secondTouchY)

Point getPointFromAngle(final double angle, final double radius)

点getPointFromAngle(final double angle, final double radius)

This solution assumes that the pixel density is evenly spaced.Before rotating the object do the following:

这个解假设像素密度是均匀间隔的。在旋转物体之前,要做以下事情:

  1. Use getAngleFromPoint to calculate the angle from the center to the upper right corner (lets say this returns 20 degrees) meaning that the upp left corner is -20 degrees or 340 degrees.

    使用getAngleFromPoint计算从中心到右上角的角度(假设返回20度),这意味着左上角是-20度或340度。

  2. Use the getTwoFingerDistance to return the diagonal distance between the center point and the upper right corner (this distance should obvoiusly be the same to all corners, This distance will be used in the next calculation).

    使用getTwoFingerDistance返回中心点和右上角之间的对角线距离(这个距离对于所有的角应该是完全相同的,这个距离将在下次计算中使用)。

  3. Now lets say we rotate the object clockwise by 30 degrees. We now know that the upper right corner must be at 50 degrees and the upper left corner is at 10 degrees.

    现在假设我们顺时针旋转物体30度。现在我们知道右上角一定是50度,左上角是10度。

  4. You should now be able to use the getPointFromAngle function on the upper left and upper right corner. using the radius returned from step 2.The X position multiplied by 2 from the upper right corner should give you the new width and the Y position times 2 from the upper left corner should give the the new height.

    现在应该可以在左上角和右上角使用getPointFromAngle函数。使用步骤2返回的半径。在右上角X的位置乘以2应该会得到新的宽度,在左上角Y的位置乘以2应该会得到新的高度。

These above 4 steps should be put into conditions based upon how far you have rotated your object other wise you may return the height as the width and the width as the height.

以上4个步骤应该根据你旋转物体的距离来设定,你可以把高度作为宽度,把宽度作为高度。

Bare in mind the angle functions are expressed in factors of 0-1 instead of 0-360 (just multiply or divide by 360 where appropriate):

考虑到角度函数是用0-1而不是0-360的因子来表示的(只要适当地乘以或除以360即可):

//Gets an angle from two points expressed as a factor of 0 -1 (0 being 0/360, 0.25 being 90 degrees etc)

//得到两个点的夹角表示为0 -1(0 = 0/360,0。25 = 90度,等等)

public float getAngleFromPoint(final Point centerPoint, final Point touchPoint) {    float returnVal = 0;    //+0 - 0.5    if(touchPoint.x > centerPoint.x) {        returnVal = (float) (Math.atan2((touchPoint.x - centerPoint.x), (centerPoint.y - touchPoint.y)) * 0.5 / Math.PI);    }    //+0.5    else if(touchPoint.x < centerPoint.x) {        returnVal = (float) (1 - (Math.atan2((centerPoint.x - touchPoint.x), (centerPoint.y - touchPoint.y)) * 0.5 / Math.PI));    }//End if(touchPoint.x > centerPoint.x)    return returnVal;}

//Measures the diagonal distance between two points

//测量两点之间的对角线距离

public float getTwoFingerDistance(final float firstTouchX, final float firstTouchY, final float secondTouchX, final float secondTouchY) {    float pinchDistanceX = 0;    float pinchDistanceY = 0;    if(firstTouchX > secondTouchX) {        pinchDistanceX = Math.abs(secondTouchX - firstTouchX);    }    else if(firstTouchX < secondTouchX) {        pinchDistanceX = Math.abs(firstTouchX - secondTouchX);    }//End if(firstTouchX > secondTouchX)    if(firstTouchY > secondTouchY) {        pinchDistanceY = Math.abs(secondTouchY - firstTouchY);    }    else if(firstTouchY < secondTouchY) {        pinchDistanceY = Math.abs(firstTouchY - secondTouchY);    }//End if(firstTouchY > secondTouchY)    if(pinchDistanceX == 0 && pinchDistanceY == 0) {        return 0;    }    else {        pinchDistanceX = (pinchDistanceX * pinchDistanceX);        pinchDistanceY = (pinchDistanceY * pinchDistanceY);        return (float) Math.abs(Math.sqrt(pinchDistanceX + pinchDistanceY));    }//End if(pinchDistanceX == 0 && pinchDistanceY == 0)}

//Get XY coordinates from an angle given a radius (The angle is expressed in a factor of 0-1 0 being 0/360 degrees and 0.75 being 270 etc)

//从给定半径的角度得到XY坐标(这个角度表示为0-1 0 = 0/360度,0.75 = 270度等等)

public Point getPointFromAngle(final double angle, final double radius) {    final Point coords = new Point();    coords.x = (int) (radius * Math.sin((angle) * 2 * Math.PI));    coords.y = (int) -(radius * Math.cos((angle) * 2 * Math.PI));    return coords;}

These code snippets are from my open source libraries: https://bitbucket.org/warwick/hgdialrepo and https://bitbucket.org/warwick/hacergestov2.One is a gesture library for Android and the other is a dial control for Android. There is also an OpenGLES 2.0 implementation of the dial control at: https://bitbucket.org/warwick/hggldial

这些代码片段来自我的开源库:https://bitbucket.org/warwick/hgdialrepo和https://bitbucket.org/warwick/hacergestov2.一个是Android的手势库,另一个是Android的拨号控件。还有OpenGLES 2.0的拨号控件实现:https://bitbucket.org/warwick/hggldial

#10


0  

I am not sure I understand, but a compound transformation matrix will give you the new co-ordinates for all points concerned. If you think the rectangle may spill over the imagable area post transformation apply a clipping path.

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

In case you are unfamiliar with the exact definition of the matrices take a look here.

如果你不熟悉矩阵的确切定义,在这里看看。

#11


0  

I used Region for First rotating the rectangle and then use that rotated region to detect that rectangle

我使用区域首先旋转矩形,然后使用旋转区域来检测矩形

        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();

now to detecting that rectangle

现在来检测这个矩形

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