Home Search   What's New Index Books Links Q & A Newsletter Banners   Feedback Tip Jar MSDN Visual Basic Community

Title Draw a Buddhabrot fractal in Visual Basic 6 This example shows how to draw a Buddhabrot fractal in Visual Basic 6. fractal, buddhabrot, mandelbrot, iterated system Graphics, Algorithms

The Mandelbrot set iterates the function Z = Z^2 + C in complex numbers for various values of C. It can be shown that, if the magnitude of Z ever grows beyond 2, then the function eventually heads towards infinity. To draw a Mandelbrot set, you iterate the function and see how many iterations it takes for the function to reach magnitude 2. You then color the point C beased on how many iterations it took. For example, if you use N colors and it took M iterations, then you could color the point M mod N.

To draw the Buddhabrot, you iterate Z = Z^2 + C for values of as usual, except you pick the values C randomly. If the function's magnitude exceeds 2 at some point, you go back and iterate the function again. This time you increment a count for each value Z that you come to before the magnitude exceeds 2. When you're done, you set a pixel's brightness to be 255 times its hit count divided by the largest hit count of any pixel.

To get color, you plot three random points, one each for red, green, and blue. When you're finished, you calculate the brightness for each pixel separately and cobine them.

Private Const Wxmin As Double = -2
Private Const Wxmax As Double = 1
Private Const Wymin As Double = -1.5
Private Const Wymax As Double = 1.5

' Draw the Buddhabrot until stopped or
' we plot the desired number of points.
Private Sub DrawBrot()
Dim wid As Integer
Dim hgt As Integer
Dim cut_r As Integer
Dim cut_g As Integer
Dim cut_b As Integer
Dim stop_after As Long
Dim draw_every As Long

' Get parameters.
wid = Val(txtWidth.Text)
hgt = Val(txtHeight.Text)
cut_r = Val(txtRedCutoff.Text)
cut_g = Val(txtGreenCutoff.Text)
cut_b = Val(txtBlueCutoff.Text)
stop_after = Val(txtStopAfter.Text)
draw_every = Val(txtDrawEvery.Text)

If (wid <= 0) Or (hgt <= 0) Then
MsgBox "Invalid parameter", vbOKOnly Or _
vbExclamation, "Error"
Exit Sub
End If

' Make hit count arrays.
Dim hit_r() As Integer
Dim hit_g() As Integer
Dim hit_b() As Integer
ReDim hit_r(wid - 1, hgt - 1)
ReDim hit_g(wid - 1, hgt - 1)
ReDim hit_b(wid - 1, hgt - 1)

' Make the bitmap.
picCanvas.Width = wid + picCanvas.Width - _
picCanvas.ScaleWidth
picCanvas.Height = hgt + picCanvas.Height - _
picCanvas.ScaleHeight

' Start drawing.
Dim start_time As Single
Dim stop_time As Single
Dim elapsed As Single
start_time = Timer
m_Drawing = True

' Build the hit counts.
Dim dx As Double
Dim dy As Double
dx = (Wxmax - Wxmin) / hgt
dy = (Wymax - Wymin) / wid
Dim max_r As Integer
Dim max_g As Integer
Dim max_b As Integer
Dim hits As Long
Dim total_hits As Long

Do While total_hits < stop_after
DrawPoint wid, hgt, dx, dy, max_r, hit_r, cut_r, _
hits
DrawPoint wid, hgt, dx, dy, max_g, hit_g, cut_g, _
hits
DrawPoint wid, hgt, dx, dy, max_b, hit_b, cut_b, _
hits

If hits >= draw_every Then
total_hits = total_hits + hits
hits = 0
DisplayBrot wid, hgt, max_r, max_g, max_b, _
hit_r, hit_g, hit_b

stop_time = Timer
elapsed = stop_time - start_time
Me.Caption = Format\$(elapsed, "0.00") & " sec, " & _
"" & _
Format\$(total_hits) & " hits"

DoEvents
If Not m_Drawing Then Exit Do
End If
Loop
End Sub

' Plot one point.
Private Sub DrawPoint(ByVal wid As Integer, ByVal hgt As _
Integer, ByVal dx As Double, ByVal dy As Double, ByRef _
max_hits As Integer, hits() As Integer, ByVal cutoff As _
Integer, ByRef num_hits As Long)
Const ESCAPING As Double = 4

' Pick C.
Dim cx As Double
Dim cy As Double
cx = Wxmin + Rnd * (Wxmax - Wxmin)
cy = Wymin + Rnd * (Wymax - Wymin)

' Zet Z0.
Dim x, xx, y, yy As Double
x = cx
y = cy
xx = x * x
yy = y * y

' Iterate.
Dim i As Integer
For i = 1 To cutoff
y = 2 * x * y + cy
x = xx - yy + cx
xx = x * x
yy = y * y
If xx + yy >= ESCAPING Then Exit For
Next i

' See if we escaped.
If xx + yy >= ESCAPING Then
' Plot.
x = cx
y = cy
xx = x * x
yy = y * y

' Iterate.
For i = 1 To cutoff
Dim ix As Integer
Dim iy As Integer
ix = CInt((x - Wxmin) / dx)
iy = CInt((y - Wymin) / dy)
If (ix >= 0) And (ix < hgt) And (iy >= 0) And _
(iy < wid) Then
hits(iy, ix) = hits(iy, ix) + 1
If max_hits < hits(iy, ix) Then max_hits = _
hits(iy, ix)
Else
Exit For
End If

y = 2 * x * y + cy
x = xx - yy + cx
xx = x * x
yy = y * y
If xx + yy >= ESCAPING Then Exit For
Next i

num_hits = num_hits + 1
End If
End Sub

' Draw the current image.
Private Sub DisplayBrot(ByVal wid As Integer, ByVal hgt As _
Integer, ByVal max_r As Integer, ByVal max_g As _
Integer, ByVal max_b As Integer, hit_r() As Integer, _
hit_g() As Integer, hit_b() As Integer)
picCanvas.Cls

Dim scale_r As Double
Dim scale_g As Double
Dim scale_b As Double
scale_r = 255 * 2.5 / max_r
scale_g = 255 * 2.5 / max_g
scale_b = 255 * 2.5 / max_b

Dim x As Integer
Dim y As Integer
Dim r As Integer
Dim g As Integer
Dim b As Integer
For y = 0 To hgt - 1
For x = 0 To wid - 1
r = CInt(hit_r(x, y) * scale_r)
If r > 255 Then r = 255
g = CInt(hit_g(x, y) * scale_g)
If g > 255 Then g = 255
b = CInt(hit_b(x, y) * scale_b)
If b > 255 Then b = 255

picCanvas.PSet (x, y), RGB(r, g, b)
Next x
Next y

picCanvas.Refresh
End Sub