|Title||Set a scaling transformation on a Graphics object in VB .NET|
|Keywords||VB.NET, scale, scalemode, scalex, scaley, graph|
VB .NET doesn't have the scale properties and methods (Scale, ScaleX, ScaleMode, and so on) provided by previous version of Visual Basic. However, the Graphics object provides transformation methods you can use to translate, scale, and rotate whatever you draw on it. You can use them to create your own scale system.
The SetScale routine shown here takes as parameters the size of the area you are drawing on (PictureBox, Bitmap, Form, etc.) and parameters giving the coordinates you want the object's left, right, top, and bottom to have. It clears the Graphics object's transformations, and then scales and translates appropriately.
Note: For some weird reason, adding a new transformation to the Graphics object prepends it so it is executed before any existing transformations. That means this code builds a transformation followed by a scaling, which is what we need, rather than the other way around as the code makes it appear. A small silliness in GDI+.
' Set transformations for the Graphics object
' so its coordinate system matches the one specified.
' Return the horizontal scale.
Private Sub SetScale(ByVal gr As Graphics, ByVal gr_width _
As Integer, ByVal gr_height As Integer, ByVal left_x As _
Single, ByVal right_x As Single, ByVal top_y As Single, _
ByVal bottom_y As Single)
' Start from scratch.
' Scale so the viewport's width and height
' map to the Graphics object's width and height.
Dim bounds As RectangleF = gr.ClipBounds
gr_width / (right_x - left_x), _
gr_height / (bottom_y - top_y))
' Translate (left_x, top_y) to the Graphics
' object's origin.
The main program uses this routine to draw in a coordinate system it likes. The following code sets the form's coordinate transformation so it maps (-10, 110)-(110, -10). That makes the coordinates of the point in the lower left corner (-10, -10) and the coordinates of the point in the upper right (110, 110).
The program then draws coordinate axes and a graph in the area (0, 0)-(100, 100). The Graphics object automatically transforms the coordinates so they fit the form properly.
Note that the transformation also applies to pen widths. If you created a pen with width 1 (for example, using Pens.Black), the result would be more than 1 pixel wide because of the scaleing in this example (the form is more than 120 pixels wide and tall). If you create a pen with width 0, however, GDI+ uses a thin line.
' Set viewport (-10, -10) to (110, 110).
Dim gr As Graphics = e.Graphics
SetScale(gr, Me.ClientSize.Width, Me.ClientSize.Height, _
-10, 110, 110, -10)
' Draw coordinate axes.
' make a pen for the axes.
' (Width 0 means a fine line.)
Dim red_pen As Pen = New Pen(Color.Red, 0)
gr.DrawLine(red_pen, -5, 0, 105, 0)
For x As Integer = 10 To 100 Step 10
gr.DrawLine(red_pen, x, -3, x, 3)
gr.DrawLine(red_pen, 0, -5, 0, 105)
For y As Integer = 10 To 100 Step 10
gr.DrawLine(red_pen, -3, y, 3, y)
Dim black_pen As Pen = New Pen(Color.Black, 0)
Dim y0 As Single = F(0)
For x As Single = 0 To 100
gr.DrawLine(black_pen, x - 1, y0, x, F(x))
y0 = F(x)