Title | Draw a fractal that is generated by applying rules to prime numbers in Visual Basic .NET |
Description | This example shows how to draw a fractal that is generated by applying rules to prime numbers in Visual Basic .NET. |
Keywords | graphics, fractals, primes, prime numbers, Visual Basic .NET, VB.NET |
Categories | Graphics, Graphics, VB.NET |
|
|
(For information and discussion of this idea, see The prime-explosion Bergot graph at The Prime Puzzles & Problem Connection.)
The program draws the image by following these rules:
- Start at the point (0, 0) corresponding to the prime 2.
- Go to the next prime.
- If the prime is 5, ignore it. Otherwise the prime has one of these forms:
- 5n + 1: Move up 1 pixel
- 5n + 2: Move right 1 pixel
- 5n + 3: Move down 1 pixel
- 5n + 4: Move left 1 pixel
- Repeat at step 2 until bored.
Periodically the program makes a bitmap where the colors of the pixels indicate the number of times each point was visited. The image shown here was generated by plotting 4 million points.
The form's Load event handler creates a Hits array to record the number of times a pixel is visited.
|
|
Private Const Wid As Integer = 800
Private Const Hgt As Integer = 800
Private Const XOff As Integer = 150
Private Const YOff As Integer = 200
Private Hits(Wid, Hgt) As Integer
Private CurrentPoint As Point
Private CurrentPrime As Long
' Initialize data structures.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal _
e As System.EventArgs) Handles MyBase.Load
CurrentPoint = New Point(0, 0)
CurrentPrime = 1
End Sub
|
|
When you select the File menu's Start item, the following code executes.
|
|
' Start or stop.
Private Running As Boolean = False
Private Sub mnuFileStart_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles mnuFileStart.Click
If (mnuFileStart.Text = "&Start") Then
' Start.
Running = True
mnuFileStart.Text = "&Stop"
DrawFractal()
' Clean up after we finish running.
mnuFileStart.Enabled = True
mnuFileStart.Text = "&Start"
Else
' Stop.
Running = False
mnuFileStart.Enabled = False
End If
End Sub
|
|
If the menu item currently says Start, the program starts calculating. It sets Running to true so it knows it's running, changes the menu item's text to Stop, and calls the DrawFractal method. After that method returns, the code enables the menu item and resets its text to Start.
If the menu item currently doesn't say Start, then the program is currently drawing the fractal. In that case the code sets Running to false and disables the menu item.
The following code shows the DrawFractal method.
|
|
' Add points to the fractal.
Private NumPoints As Integer = 0
Private Sub DrawFractal()
Const points_per_loop As Integer = 10000
Do While (Running)
' Generate a bunch of points.
For i As Integer = 1 To points_per_loop
' Find the next prime.
CurrentPrime = FindNextPrime(CurrentPrime)
' See which kind of prime it is.
Select (CurrentPrime Mod 5)
Case 1
CurrentPoint.Y -= 1
Case 2
CurrentPoint.X += 1
Case 3
CurrentPoint.Y += 1
Case 4
CurrentPoint.X -= 1
End Select
' Record the hit.
Dim ix As Integer = CurrentPoint.X + XOff
Dim iy As Integer = CurrentPoint.Y + YOff
If (ix >= 0 AndAlso iy >= 0 AndAlso ix < Wid _
AndAlso iy < Hgt) Then
Hits(ix, iy) += 1
End If
Next i
' Build the image.
BuildImage()
' Display the point count.
NumPoints += points_per_loop
lblNumPoints.Text = NumPoints.ToString()
lblPrime.Text = CurrentPrime.ToString()
' Process button clicks if there were any.
Application.DoEvents()
Loop
End Sub
|
|
This code enters a loop that executes as long as Running is true. Inside that loop, the code executes another loop to plot a bunch of points.
The inner loop calls FindNextPrime to get the next prime number. It then uses a switch statement to decide which rule to use and updates the current point accordingly. It then updates the new point's Hits count.
After the inner loop finishes, the program calls BuildImage to display the fractal so far. It then updates a couple labels and calls Application.DoEvents to allow the program to process Windows events. That allows the Start/Stop menu item's event handler to execute if the user selected the item to stop running. That event handler sets Running to false so the outer loop stops.
The FindNextPrime method is straightforward.
|
|
' Find the next prime after this one.
Private Function FindNextPrime(ByVal value As Long) As Long
' Cheat a little for speed.
'if (value = 1) return 2
'if (value = 2) return 3
Dim i As Long = value + 2
Do
If (IsPrime(i)) Then Return i
i += 2
Loop
End Function
|
|
The BuildImage method is also straightforward. It creates a bitmap and uses the Hits array to set its pixel values. See the code for the details.
The only non-trivial part of this method is the fact that it uses the MapRainbowColor method to assign colors to the pixels based on their hit values. For a description of this method, see Map numeric values to colors in a rainbow in Visual Basic .NET.
Finally, the File menu's Save command saves the current picture's image in a file. It calls the SaveBitmapUsingExtension method to save the file using an appropriate file form. For information on that method, see Write a method that saves images in an appropriate format depending on the file name's extension in Visual Basic .NET.
|
|
' Save the file.
Private Sub mnuFileSave_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles mnuFileSave.Click
If (sfdFractal.ShowDialog() = DialogResult.OK) Then
Dim bm As Bitmap = DirectCast(picFractal.Image, _
Bitmap)
SaveBitmapUsingExtension(bm, sfdFractal.FileName)
End If
End Sub
|
|
|
|
|
|
|