I am drawing an image rotated with Graphics transform, but I am unable to get the position and size of the rotated image.
Paint event:
graphics.TranslateTransform(BaseX, BaseY);
graphics.RotateTransform((float)Rotation);
graphics.DrawImage(Image, X - BaseX, Y - BaseY, Image.Width, Image.Height);
ToRectangle method:
public Rectangle ToRotatedRectangle() {
// Code here to rotate X, Y, Image.Width and Image.Height values
return new Rectangle(rotatedX, rotatedY, rotatedWidth, rotatedHeight);
}
I have seen several other posts that can get the rotated size, but none of them include the X and Y values. I have attempted rotating them individually but the location is not correct.
CodePudding user response:
Be careful: 'graphics.RotateTransform(X)' rotates image clockwise X degrees whereas 'Math.Cos(X)' and 'Math.Sin(X)' calculate based on X radians.
Based on your translation/rotation, we can calculate the sin and cos values using trig.
graphics.TranslateTransform(BaseX, BaseY);
graphics.RotateTransform((float)Rotation);
...
var sin = Math.Sin(Rotation * Math.PI / 180.0);
var cos = Math.Cos(Rotation * Math.PI / 180.0);
the resultant graphics matrix is multiplied into any given (X,Y) using linear algebra as follows
// (X, Y) =>
// | cos -sin BaseX | | X | | X*cos-Y*sin BaseX |
// | sin cos BaseY | | Y | = | X*sin Y*cos BaseY |
// | 0 0 1 | | 1 | | 1 |
// => (X*cos-Y*sin BaseX, X*sin Y*cos BaseY)
the 4 corner points as drawn on graphics are:
var (x1, y1) = (X-BaseX, Y-BaseY);
var (x2, y2) = (X-BaseX Image.Width, Y-BaseY);
var (x3, y3) = (X-BaseX, Y-BaseY Image.Height);
var (x4, y4) = (X-BaseX Image.Width, Y-BaseY Image.Height);
thus, after translation/rotation, they become
var (X1, Y1) = (cos*(X-BaseX)-sin*(Y-BaseY) BaseX, sin*(X-BaseX) cos*(Y-BaseY) BaseY);
var (X2, Y2) = (cos*(X-BaseX Image.Width)-sin*(Y-BaseY) BaseX, sin*(X-BaseX Image.Width) cos*(Y-BaseY) BaseY);
var (X3, Y3) = (cos*(X-BaseX)-sin*(Y-BaseY Image.Height) BaseX, sin*(X-BaseX) cos*(Y-BaseY Image.Height) BaseY);
var (X4, Y4) = (cos*(X-BaseX Image.Width)-sin*(Y-BaseY Image.Height) BaseX, sin*(X-BaseX Image.Width) cos*(Y-BaseY Image.Height) BaseY);
To get the top, left corner, you would need the smallest from each X and Y value. The width and height would be the difference between the largest and smallest X's and Y's, which can be simplified as shown below.
var (X, Y) = (Math.Min(Math.Min(X1, X2), Math.Min(X3, X4)), Math.Min(Math.Min(Y1, Y2), Math.Min(Y3, Y4)));
var (Width, Height) = (Math.Abs(cos*Image.Width) Math.Abs(sin*Image.Height), Math.Abs(sin*Image.Width) Math.Abs(cos*Image.Height));