Introduction
Hello, and welcome to today’s installment of my math-related articles that I have been doing for the past few months. As you know, I have become a math nerd by chance and haven’t had formal training. Yes, I did math in school, but let’s not talk about that today!
Trigonometry
The word trigonometry originates from the Greek trigōnon (“triangle”) and metron (“measure”). Trigonometry is a branch of mathematics that studies relationships involving lengths and angles of triangles.
Trigonometric Functions
The most familiar trigonometric functions are as follows:
- sine: The sine of an angle is the ratio of the length of the opposite side to the length of the hypotenuse
- cosine: The cosine of an angle is the ratio of the length of the adjacent side to the length of the hypotenuse
- tangent: The tangent of an angle is the ratio of the length of the opposite side to the length of the adjacent side
- cotangent: The cotangent of an angle is the reciprocal of its tangent (the ratio of the length of the adjacent side to the length of the opposite side)
- secant: The secant of an angle is the reciprocal of its cosine (the ratio of the length of the hypotenuse to the length of the adjacent side)
- cosecant: The cosecant of an angle is the reciprocal of its sine (the ratio of the length of the hypotenuse to the length of the opposite side)
Stop me before I get into formulas…
Our Project
Today’s project will demonstrate the three more popular trigonometric functions (sine, cosine, tangent) to draw circles and waves. Hopefully, in a follow-up article, I can delve deeper into the cotangent, secant, and cosecant functions.
Start Visual Studio and create either a C# or Visual Basic Windows Forms project.
Once the project has loaded, design your form as shown in Figure 1. Make sure of the following at design time:
- Your PictureBox is quite big
- Your PictureBox is Docked completely
- Your PictureBox has a background color
- You have a Timer
- The Timer is Enabled
- The Timer’s Interval is set to a relatively small number
- You have two buttons: one labeled ‘Circle’ and the other labeled ‘Wave’
- You keep in mind that my object names might differ from yours
Figure 1: Design
Code
Add two Boolean fields to keep track of which button was clicked.
C#
bool Wave; bool Circle; float Delta = 0; int X = 0;
VB.NET
Dim Wave As Boolean Dim Circle As Boolean
Add the code for the buttons:
C#
private void btnWaveMarquee_Click(object sender, EventArgs e) { Wave = true; Circle = false; } private void btnCircleMarquee_Click(object sender, EventArgs e) { Circle = true; Wave = false; }
VB.NET
Private Sub btnWaveMarquee_Click(sender As Object, e As _ EventArgs) Handles btnWaveMarquee.Click Wave = True Circle = False End Sub Private Sub btnCircleMarquee_Click(sender As Object, e As _ EventArgs) Handles btnCircleMarquee.Click Circle = True Wave = False End Sub
In each button, you set the corresponding flag to True. This is so that we can make use of a simple If statement inside the Timer’s Tick event to draw the correct effect.
Add the Timer’s code:
C#
private void tmrTime_Tick(object sender, EventArgs e) { string strMarquee = "I love Trig!"; double Xx; double Yy; X = -(strMarquee.Length * 20 + 25); X += 3; if (X > ClientSize.Width) X = -(strMarquee.Length * 20 + 25); Delta += 2; if (Delta > picCanvas.Width) Delta = 0; using (Bitmap bmpMarquee = new Bitmap(this.ClientSize.Width, this.ClientSize.Height)) { using (Graphics g = Graphics.FromImage(bmpMarquee)) { { var withBlock = g; withBlock.Clear(Color.Black); withBlock.TextRenderingHint = System.Drawing.Text.TextRenderingHint .AntiAlias; for (var i = 1; i <= strMarquee.Length; i++) { if (Wave) { Xx = X + (i * 27); Yy = 75 + (float)(20 * Math.Cos(Xx / (double)29)); g.DrawString(strMarquee.Substring(1, i), new Font("Tahoma", 20), Brushes.Green, (float)Xx, (float)Yy); } else if (Circle) { float Radius = 100; float d = Delta + (i * 19); Xx = (Radius * Math.Cos(d / 71.23)) + (this.ClientSize.Width / (double)2); Yy = (Radius * Math.Sin(d / 71.23)) + (this.ClientSize.Height / (double)2); withBlock.ResetTransform(); withBlock.TranslateTransform((float)Xx, (float)Yy); withBlock.RotateTransform(d + 100); withBlock.TranslateTransform((float)-Xx, (float)-Yy); withBlock.DrawString(strMarquee .Substring(1, i), new Font("Tahoma", 20), Brushes.Blue, (float)Xx, (float)Yy); } } picCanvas.Image = (Image)bmpMarquee.Clone(); picCanvas.Invalidate(); } } } }
VB.NET
Private Sub tmrTime_Tick(sender As Object, e As EventArgs) _ Handles tmrTime.Tick Dim strMarquee As String = "I love Trig!" Dim Xx As Single Dim Yy As Single Static X As Integer = -(strMarquee.Length * 20 + 25) Static Delta As Single X += 3 If X > ClientSize.Width Then X = -(strMarquee.Length * _ 20 + 25) Delta += 2 If Delta > picCanvas.Width Then Delta = 0 Using bmpMarquee As Bitmap = New _ Bitmap(Me.ClientSize.Width, _ Me.ClientSize.Height) Using g As Graphics = Graphics.FromImage(bmpMarquee) With g .Clear(Color.Black) .TextRenderingHint = _ Drawing.Text.TextRenderingHint.AntiAlias For i = 1 To strMarquee.Length If Wave Then Xx = X + (i * 27) Yy = 75 + (20 * Math.Cos(Xx / 29)) g.DrawString(Mid(strMarquee, i, 1), New _ Font("Tahoma", 20), Brushes.Green, Xx, Yy) ElseIf Circle Then Dim Radius As Single = 100 Dim d As Single = Delta + (i * 19) Xx = (Radius * Math.Cos(d / 71.23)) + _ (Me.ClientSize.Width / 2) Yy = (Radius * Math.Sin(d / 71.23)) + _ (Me.ClientSize.Height / 2) .ResetTransform() .TranslateTransform(Xx, Yy) .RotateTransform(d + 100) .TranslateTransform(-Xx, -Yy) .DrawString(Mid(strMarquee, i, 1), New _ Font("Tahoma", 20), Brushes.Blue, Xx, Yy) End If Next picCanvas.Image = bmpMarquee.Clone picCanvas.Invalidate() End With End Using End Using End Sub
First, you need the width of the canvas. The canvas in this case is obviously the PictureBox. You then create an in-memory graphics object with which to draw. Making use of the in-memory graphics object, you create a string with the font style and color and text to draw, depending on which button was clicked.
After all the objects are set up, you make use of the Cos and Sin methods inside the System.Math namespace to draw the string you created earlier in the Wave form or in Circle form. Because the calculations happen inside the Timer’s Tick event, the string continuously loops according to the desired shape.
Figures 2 and 3 show the results.
Figure 2: Circle
Figure 3: Wave
Conclusion
In today’s article, you have learned about trigonometry in general as well as how to make use of the sine, cosine, and tangent functions to create funky, loopy text. I hope you have enjoyed this article. Hopefully, in another installment, I can speak about cotangent, secant, and cosecant functions. Until then, happy coding!