Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Use Transformations to Draw Your Own Great Graphs : Page 5

Use .NET to build your own graphing control that displays bar, line, and point data either on its own surface, in a printout, or in an image file.




Application Security Testing: An Integral Part of DevOps

Drawing Labels
The code divides the previous and next vectors' components by their lengths to get vectors of length 1. It then averages these unit vectors to get a new vector pointing halfway between the original vectors. To complete the operation, the code divides this vector's components by its length and multiplies by half the desired tick mark width. The result is a vector that the program can use to draw a tick mark at this point.

The DrawLabels method shown in the following code also uses GetTickVector; however this code draws text, so it has some special needs. The Graphics object uses transformations to make drawing the data relatively straightforward. In particular, it scales the drawing to flip Y coordinates. That allows world coordinates to start with (0, 0) in the lower left corner and increase upwards as you normally expect on a graph. Unfortunately that means that any text you draw on the Graphics object appears flipped upside down. To fix this, the DrawLabels method adds another transformation to flip the text right-side up:

Private Sub DrawLabels(ByVal gr As Graphics) If Labels Is Nothing Then Exit Sub ' Save the original transformation. Dim old_transform As Matrix = gr.Transform ' Flip the transformation vertically. gr.ScaleTransform(1, -1, MatrixOrder.Prepend) ' Draw the labels. For i As Integer = 0 To Points.Length - 1 ' Get the tick mark direction vector. Dim tx, ty As Single GetTickVector(i, tx, ty) ' Lengthen the tick mark vector to ' add extra room for the text. Dim lbl_size As SizeF = _ gr.MeasureString(Labels(i), LabelFont) Dim extra_len As Single = 0.375 * _ Sqrt(lbl_size.Width * lbl_size.Width + _ lbl_size.Height * lbl_size.Height) Dim tick_len As Single = Sqrt(tx * tx + ty * ty) tx *= (1 + extra_len / tick_len) ty *= (1 + extra_len / tick_len) ' Draw the label. Using sf As New StringFormat() sf.Alignment = StringAlignment.Center sf.LineAlignment = StringAlignment.Center Dim x, y As Single If LabelsOnLeft Then x = Points(i).X + tx y = -(Points(i).Y + ty) Else x = Points(i).X - tx y = -(Points(i).Y - ty) End If gr.DrawString(Labels(i), _ LabelFont, LabelBrush, x, y, sf) End Using Next i ' Restore the original transformation. gr.Transform = old_transform End Sub

The method starts by saving the Graphics object's current transformation matrix in the variable old_transform. It then adds a scaling transformation at the beginning of the Graphics object's sequence of transformations to flip all Y coordinates. Now, when the code draws text, this transformation flips the text upside down. Then the original transformations that map world coordinates to device coordinates flip the text right-side up again.

After adding the new transformation, the code loops through the object's data points. For each point, it calls GetTickVector to find the tick mark vector for the point. It measures the point's label text and uses the size to add some extra length to the vector to make room for the label.

The code then draws the label. To draw on the right side of the data, the code switches the sign of the lengthened tick mark vector. Because the newly added scaling transformation flips Y coordinates, the code also switches the sign of the label's target Y position so it appears in its correct location. The new transformation flips the Y coordinate, inverting the string and placing it at the desired location in world coordinates. Then the Graphics object's original transformations map the new point to its correct final destination in device coordinates, flipping the text back in the process.

Finally DrawLabels restores the Graphics object's original transformation so other DataSeries objects can correctly map from world to device coordinates when drawing their data.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date