USING TRIG TO DRAW A SIN WAVE

Since my last article on the Unit Circle was such a hit I decided to continue. In this example we move from using sin and cos to calculate points on the perimeter of a circle to making a "sin" wave.

# Introduction

If you watch the values of sin as the angle moves around the circle, you may spot that the values are changing rapidly at 0 and slowly at 90 degrees. That is because at Delta = 0 you are near the X axis where the value of Y is changing rapidly as the angle delta moves at a uniform rate. At Delta = 90 you are on the top of the circle where it is flat and the y value, the sin, changes slowly until it reaches the maximum at 1. Unit Circle showing flat and steep areas.

# CODING A SIN WAVE GRAPH

Lets make a graph that plots the value of the sin in the Y direction. In the X direction we will plot the angle delta. Can you guess what the graph will look like? Its going to be steep in the area around Delta = 0 and flat around Delta = 90.

You can see in this next example 2 we use the sin function to get the value of y at the angle delta. We simply plot delta along the x axis:  (x, y)  = (delta, sin(delta)) where x is delta and y is sin(delta). See the red sin wave? Note we adjusted the x values so they fit the circle. Any scale could have been used for the x axis.

`Public` `Class` ``` Form4```

`    ``'Using Trigonometry to draw graphic curves in VB.NET part 2, Example 2`
`    ``'draws sin wave on unit circle`
`    ``Private` `WithEvents` ``` timer1 ````As` ``` New``` `Windows.Forms.Timer ``With` `{.Interval = 500}`
`    ``Private` `Delta ``As` `Single`
`    ``Private` `DeltaStep ``As` `Single` ``` = 15```

`    ``Private` `Sub` ``` Form4_Paint(sender ````As` `Object````, e ````As` ``` PaintEventArgs) ````Handles` `Me``.Paint`
`        ``Dim` `Scale ``As` `Single` ``` = 4     ````'create a scale of 2 units across the width of the form`
`        ``Dim` `ScaleRatio ``As` `Single` ``` = ````Me````.ClientRectangle.Width / Scale         ````'pixels/unit`
`        ``Dim` `r ``As` `Single` ``` = 1         ````'set radius to 1 for the "Unit Circle"`
`        ``Dim` `fntheight ``As` `Single` ``` = Scale / 25```
`        ``Dim` `x, y, x1, y1 ``As` `Single`

`        ``With` `e.Graphics`
`            ````Using p ````As` ``` New``` `Pen(Color.LightBlue, Scale / 1000)`
`                ````Using br ````As` ``` New``` `SolidBrush(Color.Black)`
`                    ````Using f ````As` ``` New``` `Font(``"Arial"``, fntheight)`
`                        ``.Clear(Color.White)`
`                        ``.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias`

`                        ````'scale the window ```
`                        ``.ScaleTransform(ScaleRatio, ScaleRatio)`
`                        ``'move the 0,0 coordinate to the center of the window`
`                        ``.TranslateTransform(Scale / 2, Scale / 2)`

`                        ``'draw the axes`
`                        ``For` `x = -Scale ``To` `Scale`
`                            ``.DrawLine(p, x, -Scale / 2, x, Scale / 2)`
`                            ``.DrawString(x.ToString, f, br, x, -Scale / 2)`
`                            ``.DrawLine(p, -Scale / 2, x, Scale / 2, x)`
`                            ``.DrawString(x.ToString, f, br, -Scale / 2, x)`
`                        ``Next`

`                        ``'draw the unit circle perimeter`
`                        ``p.Width = Scale / 200`
`                        ``p.Color = Color.Blue`
`                        ``Dim` `rectf ``As` `RectangleF = ``New` `RectangleF(-r, -r, 2 * r, 2 * r)`
`                        ``.DrawArc(p, rectf, 0, 360)`

`                        ``'draw the sine wave to the current delta`
`                        ``p.Color = Color.Red`
`                        ``p.Width = Scale / 150`
`                        ``p.EndCap = Drawing2D.LineCap.DiamondAnchor`
`                        ``x1 = -r`
`                        ``y1 = 0`

`                        ``For` `d = 0 ``To` `Delta ``Step` `DeltaStep`
`                            ````'calculate the y coordinate on the circle at the angle delta. ```
`                            ``'Convert degress to radians for sin function`
`                            ``'use delta for the x value`
`                            ``x = (0.4 * d / ScaleRatio) - 1`
`                            ``y = r * Math.Sin(d / 57.3)`

`                            ``.DrawLine(p, x, y, x1, y1)`

`                            ``x1 = x`
`                            ``y1 = y`
`                        ``Next`

`                        ``'draw the radius line at the current angle set in the timer`
`                        ``p.Color = Color.Blue`
`                        ``p.Width = 0.05`
`                        ``x = r * Math.Cos(Delta / 57.3)`
`                        ``y = r * Math.Sin(Delta / 57.3)`
`                        ``.DrawLine(p, 0, 0, x, y)`

`                        ````'draw the values ```
`                        ``x = -0.3 * Scale`
`                        ``y = -0.4 * Scale`
`                        ``.DrawString(``"Delta: "` `& Delta.ToString, f, br, x, y)`
`                        ``Dim` `t ``As` `String` ``` = ````"Cos: "` `& Math.Cos(Delta / 57.3).ToString(``"f3"````) & ````"  Sin: "` `& Math.Sin(Delta / 57.3).ToString(``"f3"``)`
`                        ``.DrawString(t, f, br, x, y + (2 * fntheight))`
`                    ``End` `Using`
`                ``End` `Using`
`            ``End` `Using`
`        ``End` `With`
`    ``End` `Sub`

`    ``Private` `Sub` ``` timer1_Tick(sender ````As` `Object````, e ````As` ``` EventArgs) ````Handles` ``` timer1.Tick```
`        ``Delta += DeltaStep`
`        ``If` `Delta > 360 ``Then` `Delta -= 360`
`        ``Me``.Invalidate()`
`    ``End` `Sub`

`    ``Private` `Sub` ``` Form4_Load(sender ````As` ``` Object````, e ``As` `EventArgs) ``Handles` `MyBase``.Load`
`        ``Me````.DoubleBuffered = ````True`
`        ``timer1.Start()`
`    ``End` `Sub`

`    ``Private` `Sub` ``` Form4_Click(sender ````As` `Object````, e ````As` ``` EventArgs) ````Handles` ``` Me````.Click`
`        ````timer1.Enabled = ````Not` ``` timer1.Enabled```
`    ``End` `Sub`

`    ``Private` `Sub` ``` Form4_Resize(sender ````As` `Object````, e ````As` ``` EventArgs) ````Handles` ``` Me````.Resize`
`        ``Me``.Invalidate()`
`    ``End` `Sub`
`End` `Class`

# Coding a Fancy SIN Wave and Unit Circle

Now in example 3 we will get fancy and put the last two examples to work. The code produces a marquee effect with text by placing the text either around a circle (similar to example 1) or along a sin wave (similar to example 2).

In the sin wave example we just place the text at the y values calculated with the sin function y = sin(Delta). The X axis of the graph shows the Delta angle.

However, in the circle marquee we add the step of rotating the text around the circle. In this case, to rotate the text we simply use the value of the delta angle for the text rotation angle. Then we calculate the (x, y) point on the circle where the text is placed using our favorite sin and cos functions.

Example 3: drawing text as Circle or Wave (cick for animation).

`Public` `Class` ``` DrawTextMarquee```
`    ``'Using Trigonometry to draw graphic curves in VB.NET part 2, Example 3`
`    ``'draws marquee style text animation - wave, circle`
`    ``Private` `WithEvents` ``` Timer1 ````As` ``` New``` `System.Windows.Forms.Timer ``With` `{.Interval = 30}`

`    ``Private` `Sub` ``` DrawTextMarquee_Load(sender ````As` `Object````, e ````As` ``` EventArgs) ````Handles` ``` MyBase````.Load`
`        ``Me``.BackgroundImageLayout = ImageLayout.None`
`        ``Me````.DoubleBuffered = ````True`
`        ````RadioButton1.Checked = ````True`
`        ``Timer1.Start()`
`    ``End` `Sub`

`    ``Private` `Sub` ``` Timer1_Tick(sender ````As` `Object````, e ````As` ``` EventArgs) ````Handles` ``` Timer1.Tick```
`        ``Dim` `theText ``As` `String` ``` = ````"Fancy Marquee"`
`        ``Dim` `y2, x2 ``As` `Single`
`        ``Static` `x1 ``As` `Integer` ``` = -(theText.Length * 15 + 20)```
`        ``x1 += 3`
`        ``If` `x1 > ``Me````.ClientSize.Width ````Then` ``` x1 = -(theText.Length * 15 + 20)```

`        ``Static` `delta ``As` `Single`
`        ``delta += 2`
`        ``If` `delta > 359 ``Then` `delta = 0`

`        ``'draw the scene on a the memory bitmap and copy to the form background`
`        ````Using bmp ````As` ``` Bitmap = ````New` ``` Bitmap(````Me````.ClientSize.Width, ````Me``.ClientSize.Height)`
`            ````Using g ````As` ``` Graphics = Graphics.FromImage(bmp)```
`                ``With` `g`
`                    ``.Clear(Color.Black)`
`                    ``.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias`

`                    ``For` `i = 1 ``To` `theText.Length`
`                        ``If` `RadioButton1.Checked ``Then`
`                            ``'wave`
`                            ``x2 = x1 + (i * 24)`
`                            ``y2 = 65 + (20 * Math.Cos(x2 / 26))`
`                            ````g.DrawString(Mid(theText, i, 1), ````New` ``` Font(````"Arial"``, 18), Brushes.Red, x2, y2)`
`                        ``Else`
`                            ``'circle`
`                            ``Dim` `r ``As` `Single` ``` = 100```
`                            ``Dim` `d ``As` `Single` ``` = delta + (i * 16)```
`                            ``x2 = (r * Math.Cos(d / 57.3)) + (``Me````.ClientSize.Width / 2)```
`                            ``y2 = (r * Math.Sin(d / 57.3)) + (``Me````.ClientSize.Height / 2)```
`                            ``.ResetTransform()`
`                            ``.TranslateTransform(x2, y2)`
`                            ``.RotateTransform(d + 100)`
`                            ``.TranslateTransform(-x2, -y2)`
`                            ````.DrawString(Mid(theText, i, 1), ````New` ``` Font(````"Arial"``, 18), Brushes.Red, x2, y2)`
`                        ``End` `If`
`                    ``Next`
`                    ``Me``.BackgroundImage = bmp.Clone`
`                    ``Me``.Invalidate()`
`                ``End` `With`
`            ``End` `Using`
`        ``End` `Using`
`    ``End` `Sub`
`End` `Class`