数学问题关于.Net中的点旋转

时间:2010-06-23 12:07:07

标签: c# .net vb.net math rotation

我有一个部分答案。从:

开始

newHeight =高度* cos(弧度)+宽度* sin(弧度)
newWidth =高度* sin(弧度)+宽度* cos(弧度)

我可以反转方程式得到:

temp = sqr(cos(弧度)) - sqr(sin(弧度))
高度= newHeight * cos(弧度) - newWidth * sin(弧度)/ temp
Width = newWidth * cos(弧度) - newHeight * sin(弧度)/ temp

上述等式仅适用于0-28,62-90,180-208和242-270的角度范围。在这些范围之外,计算的边界太大并导致在45,135,225和315处溢出 我认为我需要检测我所在的象限并略微修改方程式。有任何想法吗?


我很难明确我在这个问题中究竟要求的是什么,所以希望下面的例子能够解决问题。
该示例的作用是采用100x100的正方形,将其旋转12度并将宽度加100。我想要做的是找出一个矩形的尺寸,当旋转12度时将产生相同的矩形,而不会在之后添加100宽度:

绘制的矩形是旋转形状的边界,而不是形状本身:

    Dim radAngle = Math.PI * 12 / 180.0R
    Dim widthChange = 100

    Dim b2 = New RectangleF(200, 200, 100, 100)
    b2 = GetBoundsAfterRotation(b2, radAngle)
    b2.Width += widthChange
    g.DrawRectangle(Pens.Red, ToRectangle(b2))

    Dim offsetY = 21
    Dim offsetX = -7
    b2 = New RectangleF(200, 200, 100 + widthChange - offsetX, 100 - offsetY)
    b2 = GetBoundsAfterRotation(b2, radAngle)
    b2.X += CInt(offsetX / 2)
    b2.Y += CInt(offsetY / 2)
    g.DrawRectangle(Pens.Green, ToRectangle(b2))

通过跟踪和错误,我发现了offsetX和offsetY的值,这将导致这个特殊情况的相同矩形:一个100x100的正方形旋转12度,100加到宽度。我确定它涉及到罪恶,cos或者两者兼而有之,但大脑冻结阻止我建立公式。

ETA:在这种情况下,我增加宽度,但我需要宽度,高度或两者都改变​​的一般解决方案。

ETA2:对于这种情况,结果矩形边界的大小为218.6 x 118.6。要在旋转12度后获得这些边界,起始矩形边界约为207 x 79.


原件:

我使用以下标准例程来获取图像在旋转指定角度后的中心位置。边界是偏移的,因此图像的中心始终位于相同的位置:

Public Function GetBoundsAfterRotation(ByVal imageBounds As RectangleF, ByVal radAngle As Double) As RectangleF

    Dim w = imageBounds.Width
    Dim h = imageBounds.Height
    Dim rotationPoints As PointF() = {New PointF(0, 0), New PointF(w, 0), New PointF(0, h), New PointF(w, h)}
    RotatePoints(rotationPoints, New PointF(w / 2.0F, h / 2.0F), radAngle)
    Dim newBounds = GetBoundsF(rotationPoints)
    Dim x = imageBounds.X + newBounds.X  //Offset the location to ensure the centre point remains the same
    Dim y = imageBounds.Y + newBounds.Y
    Return New RectangleF(New PointF(x, y), newBounds.Size)

End Function

//

Public Shared Sub RotatePoints(ByVal pnts As PointF(), ByVal origin As PointF, ByVal radAngle As Double)
    For i As Integer = 0 To pnts.Length - 1
        pnts(i) = RotatePoint(pnts(i), origin, radAngle)
    Next
End Sub  

//

Public Shared Function RotatePoint(ByVal pnt As PointF, ByVal origin As PointF, ByVal radAngle As Double) As PointF
    Dim newPoint As New PointF()
    Dim deltaX As Double = pnt.X - origin.X
    Dim deltaY As Double = pnt.Y - origin.Y
    newPoint.X = CSng((origin.X + (Math.Cos(radAngle) * deltaX - Math.Sin(radAngle) * deltaY)))
    newPoint.Y = CSng((origin.Y + (Math.Sin(radAngle) * deltaX + Math.Cos(radAngle) * deltaY)))
    Return newPoint
End Function  

//

Public Shared Function GetBoundsF(ByVal pnts As PointF()) As RectangleF
    Dim left As Single = pnts(0).X
    Dim right As Single = pnts(0).X
    Dim top As Single = pnts(0).Y
    Dim bottom As Single = pnts(0).Y

    For i As Integer = 1 To pnts.Length - 1
        If pnts(i).X < left Then
            left = pnts(i).X
        ElseIf pnts(i).X > right Then
            right = pnts(i).X
        End If

        If pnts(i).Y < top Then
            top = pnts(i).Y
        ElseIf pnts(i).Y > bottom Then
            bottom = pnts(i).Y
        End If
    Next

    Return New RectangleF(left, top, CSng(Math.Abs(right - left)), CSng(Math.Abs(bottom - top)))
End Function  

我的问题是:

我有一些BoundsAfterRotation围绕其中心旋转一个角度。我改变了边界的宽度和/或高度。我如何向后工作以找到原本会创建BoundsAfterRotation的imageBounds?

3 个答案:

答案 0 :(得分:1)

将它向后旋转相同的角度,为负。请注意,您可以考虑使用System.Drawing.Matrix类。它有一个RotateAt()方法。使用TransformPoints()方法应用旋转。并使用Invert()方法创建一个将点映射回来的矩阵。

答案 1 :(得分:0)

您可以从图像转到旋转,但不能从旋转转换为图像。这是因为当你旋转时,你必须围绕像素位置,新图像看起来有点不同。

因此,您必须始终保持原始图像并为每个动作制作图像副本。

简单地向后旋转将会加倍舍入。

答案 2 :(得分:0)

我没有时间给出完整的答案,但请考虑以下内容:如果您从以pi / 2旋转的方块开始,那么它看起来像<>,并让alpha为角度在连接正方形中心与其最右边和x轴的直线之间,然后非常基本的三角学告诉你,旋转方形的宽度是cos(alpha)*d,d是正方形的对角线,如果alpha介于-pi / 4和pi / 4之间。

现在,你“只需”从你的角度计算alpha,检查哪些边缘是重要的知道宽度,并计算对角线的“未旋转”宽度。