У меня есть частичный ответ. Начиная с:
newHeight = Высота * cos (радианы) + Ширина * sin (радианы)
newWidth = Высота * sin (радианы) + Ширина * cos (радианы)
Я могу перевернуть уравнения, чтобы получить:
temp = sqr (cos (радианы)) - sqr (sin (радианы))
Высота = newHeight * cos (радианы) - newWidth * sin (радианы) / temp
Ширина = newWidth * cos (радианы) - newHeight * sin (радианы) / темп
Приведенные выше уравнения действуют только для диапазонов углов 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 к ширине. Я уверен, что это связано с грехом, потому что или с тем и другим вместе, но замораживание мозгов не позволяет мне построить формулу.
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, которые были повернуты на угол вокруг своего центра. Я меняю ширину и / или высоту границ. Как я могу работать в обратном направлении, чтобы найти исходный imageBounds, который создал бы BoundsAfterRotation?