Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Actionscript 3 从旋转的矩形计算边界框坐标_Actionscript 3_Math_Geometry_Rotation_Bounding Box - Fatal编程技术网

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

Actionscript 3 从旋转的矩形计算边界框坐标,actionscript-3,math,geometry,rotation,bounding-box,Actionscript 3,Math,Geometry,Rotation,Bounding Box,我有一个矩形左上角点的坐标,还有它的宽度,高度和旋转角度,从0到180,-0到-180 我试图得到矩形周围实际长方体的边界坐标 计算边界框坐标的简单方法是什么 最小y,最大y,最小x,最大x A点并不总是在最小y边界上,它可以在任何地方 如果需要,我可以使用as3中的矩阵转换工具包。我不确定我是否理解,但复合转换矩阵将为您提供所有相关点的新坐标。如果您认为矩形可能会在变换后溢出可成像区域,请应用剪裁路径 如果您不熟悉矩阵的确切定义,请查看。将旋转矩阵应用于角点。然后分别使用获得的x、y坐标的

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

我试图得到矩形周围实际长方体的边界坐标

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

  • 最小y,最大y,最小x,最大x
A点并不总是在最小y边界上,它可以在任何地方


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

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


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

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

  • 变换所有四个角的坐标
  • 找到所有四个x中最小的一个,如
    min\u x
  • 找到四个x中最大的一个,并将其命名为
    max\u x
  • y的也一样
  • 您的边界框是
    (minux,minuy),(minux,max\y),(max\ux,max\uy),(max\ux,minuy)
好了,没有哪条皇家大道能让你更快到达那里

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

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

其中(x0,y0)是旋转的中心。您可能需要根据您的三角函数(它们是否期望度或弧度)、坐标系的感觉/符号以及指定角度的方式等对其进行修补。

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

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

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

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;
    }
}
ct=cos(θ);
st=sin(θ);
hct=h*ct;
wct=w*ct;
hst=h*st;
wst=w*st;
如果(θ>0)
{
如果(θ<90度)
{
//0<θ<90
y_min=A_y;
y_max=A_y+hct+wst;
x_min=A_x-hst;
x_max=A_x+wct;
}
其他的
{

//90如果您使用的是GDI+,您可以创建一个新的GrpaphicsPath->向其添加任何点或形状->应用旋转变换->使用GraphicsPath.GetBounds(),它将返回一个矩形,该矩形将限制您旋转的形状

(编辑)VB.Net示例
End Sub

尽管代码专家声明了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()

我知道你在要求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)
}

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

签名如下:

公共静态浮点getAngleFromPoint(终点中心点,终点接触点)

公共静态浮点getTwoFingerDistance(浮点firstTouchX、浮点firstTouchY、浮点secondTouchX、浮点secondTouchY)

点getPointFromAngle(最终双角度,最终双半径)

此解决方案假定像素密度的间隔均匀。 旋转对象之前,请执行以下操作:

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

  • 使用getTwoFingerDistance返回中心点和右上角之间的对角线距离(该距离显然应与所有角相同,该距离将在下一次计算中使用)

  • 现在让我们把物体顺时针旋转30度,我们现在知道右上角必须是50度,左上角是10度

  • 现在,您应该能够在左上角和右上角使用getPointFromAngle函数。使用从步骤2返回的半径。 从右上角开始,X位置乘以2将得到新的宽度,从左上角开始,Y位置乘以2将得到新的高度

  • 以上4个步骤应根据您旋转对象的距离设定条件,否则您可以将高度作为宽度,将宽度作为高度

    请记住,角度函数以0-1而不是0-360的系数表示(在适当情况下,只需乘以或除以360):

    //从两个点获取一个角度,表示为因子0-1(0表示0/360,0.25表示90度等)

    这些代码片段来自我的开源库:和。
    一个是Android的手势库,另一个是Android的拨号控制。还有一个OpenGLES 2.0实现的拨号控制:

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

            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;
            }
    
        }
    
    现在去侦查
    func boundingRectAfterRotatingRect(rect: CGRect, toAngle radians: CGFloat) -> CGRect {
        let xfrm = CGAffineTransformMakeRotation(radians)
        return CGRectApplyAffineTransform (rect, xfrm)
    }
    
    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;
    
    }
    
    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)
    
    }
    
    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;
    
    }
    
            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;
            }
    
        }