The Graphics object's RotateTransform
method takes one parameter that indicates the angle in degrees clockwise that future drawing should be rotated around the origin (0, 0). The following code draws a red rectangle and an orange line from the origin to the rectangle's upper left corner. It then uses ScaleTransform
to rotate future drawing by 30 degrees and redraws the rectangle and line in green and blue respectively:
|Figure 3. RotateTransform Results: The RotateTransform method rotates a drawing.|
e.Graphics.DrawRectangle(Pens.Red, 20, 20, 200, 100)
e.Graphics.DrawLine(Pens.Orange, 0, 0, 20, 20)
e.Graphics.DrawRectangle(Pens.Green, 20, 20, 200, 100)
e.Graphics.DrawLine(Pens.Blue, 0, 0, 20, 20)
shows the result. Notice that the blue line still starts at the origin (0, 0), the same place the orange line started. All rotation is around the origin so that's the only point in the drawing that looks the same both before and after the rotation. This little detail is important when you want to rotate around some point other than the origin, and I'll say more about it later.
Translation, scaling, and rotation are mathematics, not magic. With a little work, you could write code to transform the corners of a rectangle and draw them without bothering with the Graphics object's transformation methods. You could use the same code to transform any drawing made up of straight lines. With more work, you might even be able to "manually" transform curves such as ellipses and arcs.
However, transforming text and images is a lot tougher. You can't simply transform the corners of an image and expect the interior points to be transformed, as well. It takes some special algorithms to transform every point in an image smoothly and, while the calculations are interesting, they're time consuming.
|Figure 4. Transform All Output: Transformation methods apply to both images and text.|
Fortunately, when you use the Graphics object's transformation methods, any images or text that you draw are transformed as well. The TransformImage
program shown in Figure 4
uses transformations to rotate both the image and text.
One of the coolest features of transformations (actually the whole reason for implementing them as matrices) is that you can easily combine them to represent a series of graphical operations. To represent a series of transformations represented by matrices as a single matrix, you simply multiply together the individual transformation matrices.
For example, suppose you want to translate, scale, rotate, and translate a set of drawing commands. Suppose the transformation matrices T1
, and T2
represent these operations. Then you can represent this complicated series of transformations with a single transformation matrix T
that is the product of the matrices representing the separate transformations:
T = T1 * S * R * T2
The Graphics object's transformation methods automatically add the new transformation to any previously selected one. For example, the following code prepares a Graphics object named gr
to draw with a translation, scaling, and rotation:
Unfortunately, for some bizarre reason these routines add their transformations before
any previously defined transformations. In this example, that means the Graphics object will actually first rotate the drawing, then scale it, and finally translate the result, the opposite of what you might expect.
In other words, what you should remember from this is that the order of transformations is very important (in general, a rotation followed by a translation is not the same as a translation followed by a rotation) so it's important to build the combined transformation in the correct order.
While the default behavior for these methods is to have operations invoked last occur first (this is so counterintuitive that it still weirds me out), you can change this behavior by adding a final argument to the method calls. In the following code, the new parameters tell the Graphics object to apply the transformations in the order: translate, scale, rotate:
gr.TranslateTransform(100, 100, Drawing2D.MatrixOrder.Append)
Usually when I run som transformation code and don't see the image I expect to see, it's because I forgot that new transformations are added after
existing ones by default and I didn't include the Append
parameter. If things look wrongparticularly if you see no drawing at allrecheck your code and make sure the transformations are being applied in the order you want.