I'm trying to wrap my head around how to rotate a 2d object around any axis, which could be anywhere, including outside of the shape itself.
The langage I happen to use for this is VBA, but any pseudocode will do.
I am looking for a function similar to this:
function rotate(obj, axisX, axisY, angle)
obj.rotate(angle)
obj.x = ?
obj.y = ?
I'm not sure if that is relevant, but for the sake of simplicity, we can assume the shape is a rectangle.
And the x, y coordinates once the shape is rotated would be that of a square containing the rotated shape.
CodePudding user response:
The common approach to this to divide the operation in three basic steps:
move the object to the local space (also called object space)
rotate around the origin
move the object back (also called world space)
function rotate(obj, axisX, axisY, angle) { // 1. obj.x -= axisX obj.y -= axisY // 2. obj.rotate(angle) // 3. obj.x = axisX obj.y = axisY }
Edit some notes on obj.rotate
: the approach assumes that the rotate
function rotates globally (world space) that is, if the object is not at the origin, it will be rotated in a orbit like fashion. But if rotate
rotates the object locally (object space) the object will always be rotated around its center, regardless where it is in world space. In this case, you need to additionally compute the new position yourself (but with the same principle):
ox = obj.x - axisX
oy = obj.y - axisY
// apply 2D rotation matrix
obj.x = ox * cos(angle) - oy * sin(angle)
obj.y = ox * sin(angle) oy * cos(angle)
obj.x = axisX
obj.y = axisY
CodePudding user response:
Well I can see we already have the general answer, but I had a bit of fun making this so I'll post it anyway.
It shows how all the concepts come together so Might help someone.
Option Explicit
Type ObjLocData
X As Long
Y As Long
End Type
Sub Rotate_Object_About_Axis()
Dim RotObj As Shape
Dim RotLoc1 As ObjLocData
Dim RotLoc2 As ObjLocData
Dim AxisObj As Shape
Dim AxisLoc As ObjLocData
Dim R_Rad As Double
Dim Pi As Double
R_Rad = 0.1
Pi = 3.14159
Set AxisObj = ActiveSheet.Shapes("AxisObj")
AxisLoc = ObjectLocation(AxisObj)
Set RotObj = ActiveSheet.Shapes("RotObj")
RotLoc1 = ObjectLocation(RotObj)
Debug.Print AxisLoc.X
RotLoc2 = RotateCoordinates(AxisLoc.X, AxisLoc.Y, RotLoc1.X, RotLoc1.Y, R_Rad)
With RotObj
.Left = RotLoc2.X - (.Width / 2)
.Top = RotLoc2.Y - (.Height / 2)
.Rotation = .Rotation (R_Rad * 360 / (2 * Pi))
End With
End Sub
Function ObjectLocation(Shp As Object) As ObjLocData
ObjectLocation.X = Shp.Left (Shp.Width / 2)
ObjectLocation.Y = Shp.Top (Shp.Height / 2)
End Function
Function RotateCoordinates(Xa, Ya, X, Y, R) As ObjLocData
RotateCoordinates.X = ((X - Xa) * Cos(R)) - ((Y - Ya) * Sin(R)) Xa
RotateCoordinates.Y = ((X - Xa) * Sin(R)) ((Y - Ya) * Cos(R)) Ya
End Function
'Location Formulas
'X'=(x-p)cos(?)-(y-q)sin(?) p,
'y'=(x-p)sin(?) (y-q)cos(?) q.