views:

375

answers:

2

I am drawing an image from MetaFile (emf) and then apply some rotation transformations to it all within the OnPaint of a UserControl. After applying those transformation how can I calculate the normal untransformed rectangular bounding box of this in screen coordinates? I need this to be able to resize the rotated image to the size of the UserControl.

protected override void OnPaint(PaintEventArgs e)
{
 // rotate around the center of this UserControl
 e.Graphics.TranslateTransform(this.Width / 2.0f, this.Height / 2.0f);
 e.Graphics.RotateTransform(this.Rotation);
 e.Graphics.TranslateTransform(this.Width / -2.0f, this.Height / -2.0f);

 // TODO: now scale so the image so it fits exactly into this UserControl

 // draw the image at the center of this UserControl
 float left = (this.Width - ResourceManager.MyDrawingMetaFile.Width) / 2.0f;
 float top = (this.Height - ResourceManager.MyDrawingMetaFile.Height) / 2.0f;
 e.Graphics.DrawImage(Resources.MyDrawingMetaFile, left, top);
}

The whole idea behind this is that I want to display rotated .emf File in a UserControl and have the emf drawing allways fill the available space in the UserControl. Maybe there is a better approach?

The fillmode/stretchmode I am after is Uniform and UniformToFill (like in WPF's Viewbox). The emf should not be distorted an in Uniform mode the emf completely fills the usercontrol at least in one dimension, nothing is cropped. In UniformToFill the emf filles the UserControl in both dimensions and if the aspectratios do not match, the emf is cropped in one dimension.

A: 

The way it would be done with GDI is :

BeginPath()
// Draw stuff
EndPath()
PathToRegion()
GetRgnBox()

GDI+ has equivalents - The GraphicsPath and Region classes can do the above

rep_movsd
My drawing comes from a Metafile so I think GraphicsPath would not apply.
bitbonk
A metafile is just a serialization of GDI calls, so it should work with GraphicsPath.Anyway the MetaFile class has a GetMetafileHeader method, you can get the metafile bounding box and use triginometry to get the rotated size.
rep_movsd
Well GraphicsPath does not have a AddMetaFile or AddDrawing or similar method.
bitbonk
Also because the drawing is not rectangular (it can be a circle or complex path) to get the correct bounding box I would need to get the boundingbox AFTER the transformations have been applied. Using trigonometry to recalcualte the size of the rotated boundingbox is not enough.
bitbonk
+1  A: 

If I understand you correctly - you need to figure out how the rotation affects the bounding box of your image, so that you can scale it accordingly.

Then you can do like this:

  1. Stuff the four coordinates of your bounding box in a Point[].
  2. Set up a Matrix with your rotation (.RotateAt)
  3. Let the matrix transform the four points.
  4. Sort the four transformed X coordinates and compare the width of the new bounding box (pts[3].X - pts[0].X after sort).
  5. Now you know how to scale the width for a perfect fit.
  6. Repeat step 4 for the height as well.
danbystrom
My drawings are not necessarily rectangular. For example if the drawing is a circle the rotation itself would not affect the scale factor.
bitbonk
Then you need to do the above for every *corner* in the image. A circle will have to be approximated, of course, and thought of as being made up of a number of line segments.
danbystrom
I wonder, how WPF (probably in DWM layer somewhere) does this.
bitbonk