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
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()
71
/**
* 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);
}
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;
}
}
11 回答
变换所有四个角的坐标
找到所有四个x中最小的x为
min_x
找到所有四个x中最大的一个并称之为
max_x
与y同上
你的边界框是
(min_x,min_y), (min_x,max_y), (max_x,max_y), (max_x,min_y)
AFAIK,没有任何皇家之路可以让你快得多 .
如果您想知道如何变换坐标,请尝试:
其中(x0,y0)是您旋转的中心 . 您可能需要修改这个,具体取决于您的三角函数(他们希望度数或弧度)坐标系的感觉/符号与指定角度的方式等 .
我意识到你要求ActionScript,但是,如果有人来到这里寻找iOS或OS-X答案,它是这样的:
如果您的操作系统为您提供了所有艰苦的工作,那就试试吧! :)
迅速:
MarkusQ概述的方法非常有效,但请记住,如果已经有A点,则不需要转换其他三个角 .
另一种更有效的方法是测试旋转角度所在的象限,然后直接计算答案 . 这样做效率更高,因为你只有两个if语句的最坏情况(检查角度),而另一个方法的最差情况是12个(当检查其他三个角以查看它们是否大于当前时,每个组件为6个)我认为最大或小于当前最小值 .
基本算法仅使用了毕达哥拉斯定理的一系列应用,如下所示 . 我用theta表示了旋转角度,并以度为单位表示检查,因为它是伪代码 .
这种方法假定你拥有你所拥有的,即点A和θ的值,它位于[-180,180]的范围内 . 我还假设theta在顺时针方向上增加,因为图中旋转了30度的矩形似乎表明你正在使用,我不确定右边的部分是什么意思 . 如果这是错误的方法,那么只需交换对称子句以及st术语的符号 .
如果你正在使用GDI,你可以创建一个新的GrpaphicsPath - >添加任何点或形状 - >应用旋转变换 - >使用GraphicsPath.GetBounds(),它将返回一个界定旋转形状的矩形 .
(编辑)VB.Net示例
结束子
虽然Code Guru声明了GetBounds()方法,但我注意到这个问题被标记为3,flex,所以这里有一个as3片段来说明这个想法 .
我注意到有两种方法似乎做同样的事情:getBounds()和getRect()
将旋转矩阵应用于角点 . 然后分别使用获得的x,y坐标的最小值/最大值来定义新的边界框 .
以下是我的开源库中的三个函数 . 这些函数在Java中经过全面测试,但公式可以很容易地翻译成任何语言 .
签名是:
public static float getAngleFromPoint(最终Point centerPoint,最终Point touchPoint)
public static float getTwoFingerDistance(float firstTouchX,float firstTouchY,float secondTouchX,float secondTouchY)
点getPointFromAngle(最终双角,最终双半径)
该解决方案假设像素密度均匀分布 . 在旋转对象之前,请执行以下操作:
使用getAngleFromPoint计算从中心到右上角的角度(假设它返回20度),这意味着upp左角是-20度或340度 .
使用getTwoFingerDistance返回中心点和右上角之间的对角线距离(此距离应与所有角落相同,此距离将在下一次计算中使用) .
现在让我们说旋转物体顺时针旋转30度 . 我们现在知道右上角必须是50度,左上角是10度 .
您现在应该能够在左上角和右上角使用getPointFromAngle函数 . 使用从步骤2返回的半径 . 从右上角乘以2的X位置应该为您提供新的宽度,左上角的Y位置乘以2应该给出新的高度 .
以上4个步骤应根据您旋转物体的距离进行调整,否则您可以将高度作为宽度返回高度,将宽度作为高度返回 .
请记住,角度函数用因子0-1而不是0-360表示(只要在适当的位置乘以或除以360):
//从两个点获取一个角度,表示为因子0 -1(0表示0/360,0.25表示90度等)
//测量两点之间的对角线距离
//从给定半径的角度获取XY坐标(角度表示为0-1 0因子为0/360度,0.75为270等)
这些代码片段来自我的开源库:https://bitbucket.org/warwick/hgdialrepo和https://bitbucket.org/warwick/hacergestov2 . 一个是Android的手势库,另一个是Android的拨号控件 . 拨号控件还有一个OpenGLES 2.0实现:https://bitbucket.org/warwick/hggldial
我不确定我理解,但是复合变换矩阵会为所有相关点提供新的坐标 . 如果您认为矩形可能会在转换后溢出可成像区域,则应用剪切路径 .
如果您不熟悉矩阵的确切定义,请查看here .
我使用Region for First旋转矩形然后使用该旋转区域来检测该矩形
现在检测那个矩形