Anchor the rectangles at their center, not one of the four vertices.
You'll have an hierarchical structure:
- a collection with a translation (the position of the center of the collection)
- for each element in the collection you'll have a relative position to the collection's center
At that point, you'll have to rotate the position of the rectangles and the rectangles themselves this way:
- rotate element at origin (before translation)
- rotate relative position
- add absolute position and relative position
- translate rectangle
This is a little diagram:
+-----+-----+
| | |
| e | e |
| | |
+-----C-----+
| | |
| e | e |
| | |
+-----+-----+
C is the center of the collection, e are the centers of the elements. The relative position is the vector e-C. This is pretty basic stuff, it may sound difficult but it's just a matter of adding/subtracting vectors (positions) and rotating them by angles in the right order.
The order of translating/rotating the elements/collection is very important.
To rotate around the center of the rectangle:
RotateAboutOrigin(new Vector2(test1.Width / 2, test1.Height / 2), Vector2.zero, rotation)
At this point translate by the relative position, which is one of these (one line for each rectangle):
Vector2 p1 = new Vector2(+test1.Width / 2, +test1.Height / 2)
Vector2 p2 = new Vector2(+test2.Width / 2, -test2.Height / 2)
Vector2 p3 = new Vector2(-test3.Width / 2, +test3.Height / 2)
Vector2 p4 = new Vector2(-test4.Width / 2, -test4.Height / 2)
The actual mapping of relative translations to the rectangles has to be determined, here I just try to give an idea. By changing the actual lines up/down the right combination will be easy to find.
Finally, translate by the center of the cluster:
p1 + c // c is also a Vector2
All this code can afterwards be corrected and optimized by removing a lot of excess code and saving vectors in appropriate places. Especially the CreateRotationZ()
inside RotateAboutOrigin
should be cached, like this:
Matrix[] rot = new Matrix[64];
for(phi = 0; phi < 64; phi++)
{
rot[phi] = Matrix.CreateRotationZ(phi / 64 * 2 * Math.PI);
}
In the example above you'll then have 64 matrices and a 64 step-wise rotation. You can then rotate only by discrete multiples of the minimum angle 1 / 64 * 2 * Math.PI
. This will make the function much faster.