Reputation: 2964
I'm trying to implement a small tool that draws sin and cos functions. The program is supposed to draw from the center of the form, so that the history will extend to the right. Imagine the following gif but with the right end of the line moving up and down, and the path to the left "showing the trace"
What I would like to do is, every time a timer elapses, draw a point (via Graphics.FillRectangle
) in the center of a PictureBox
. In the next timer fire move the graphics one pixel to the left, and draw the next pixel. This is what I have so far:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bmp = New Drawing.Bitmap(PictureBox1.Size.Width, PictureBox1.Size.Height)
g1 = Graphics.FromImage(bmp)
MathTimer = New Timers.Timer(30)
AddHandler MathTimer.Elapsed, AddressOf OnTimedEvent
MathTimer.Enabled = True
MathTimer.Start()
End Sub
Private Sub OnTimedEvent(source As Object, e As System.Timers.ElapsedEventArgs)
g1.FillRectangle(Brushes.Red, PictureBox1.Size.Width \ 2, PictureBox1.Size.Height \ 2, 1, 1)
g1.TranslateTransform(-1, 0)
PictureBox1.Image = bmp
End Sub
However, this doesn't achieve the desired effect, since the canvas of the graphics object g1
is moved to the left with this. Eventually it's not drawing anymore. (No wonder, since with this I'm drawing "with the left end of the line")
Anybody have a better idea that achieves the desired effect?
Upvotes: 0
Views: 130
Reputation: 5324
For i As Integer = 0 To pointsToDraw.Count - 2
Dim p As Point = pointsToDraw(i)
Dim xPos As Integer = (pctrBxSinCosDraw.Width / 2) + p.X - currentTick
e.Graphics.FillRectangle(Brushes.Black, xPos, CInt(p.Y + pctrBxSinCosDraw.Height / 2), 1, 1)
If xPos <= 0 Then
pointsToDraw.RemoveAt(i)
End If
Next
Where currentTick
is set by a Timer
, which on Tick
, calculates the x/y values:
Dim yVal As Double
If useSinCalc Then
yVal = Math.Sin(DegreeToRadian(currentTick)) * (180 / Math.PI)
Else
yVal = Math.Cos(DegreeToRadian(currentTick)) * (180 / Math.PI)
End If
pointsToDraw.Add(New Point(currentTick, yVal))
currentTick += 1
pctrBxSinCosDraw.Invalidate()
And DegreeToRadian
simply does (as it states):
Private Function DegreeToRadian(ByVal angle As Double)
DegreeToRadian = Math.PI * angle / 180.0
End Function
And pointsToDraw
is List(Of Point)
A sample project can be found on my download page.
Upvotes: 1