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.
|
' Draw the Buddhabrot until stopped or
' we plot the desired number of points.
Private Sub DrawBrot()
' Get parameters.
Dim wid As Integer = Val(txtWidth.Text)
Dim hgt As Integer = Val(txtHeight.Text)
Dim cut_r As Integer = Val(txtRedCutoff.Text)
Dim cut_g As Integer = Val(txtGreenCutoff.Text)
Dim cut_b As Integer = Val(txtBlueCutoff.Text)
Dim stop_after As Integer = Val(txtStopAfter.Text)
Dim draw_every As Integer = Val(txtDrawEvery.Text)
If wid <= 0 OrElse hgt <= 0 Then
MessageBox.Show("Invalid parameter", "Error", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation)
Exit Sub
End If
' Make hit count arrays.
Dim hit_r(wid - 1, hgt - 1) As Integer
Dim hit_g(wid - 1, hgt - 1) As Integer
Dim hit_b(wid - 1, hgt - 1) As Integer
' Make the bitmap.
m_Bitmap = New Bitmap(wid, hgt)
picCanvas.Image = m_Bitmap
Me.ClientSize = New Size( _
picCanvas.Left + picCanvas.Width + 8, _
System.Math.Max( _
btnDraw.Top + btnDraw.Height, _
picCanvas.Top + picCanvas.Height) + 8)
mnuFileSave.Enabled = True
' Start drawing.
Dim start_time As Date = Now
Dim stop_time As Date
Dim elapsed As TimeSpan
m_Drawing = True
' Build the hit counts.
Dim dx As Double = (Wxmax - Wxmin) / hgt
Dim dy As Double = (Wymax - Wymin) / wid
Dim max_r, max_g, max_b, hits, total_hits As Integer
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 += hits
hits = 0
DisplayBrot(wid, hgt, max_r, max_g, max_b, _
hit_r, hit_g, hit_b)
stop_time = Now
elapsed = stop_time.Subtract(start_time)
Me.Text = elapsed.TotalSeconds.ToString("0.00") _
& " sec, " & _
total_hits.ToString & " hits"
Application.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, ByVal hits(,) As Integer, ByVal _
cutoff As Integer, ByRef num_hits As Integer)
Const ESCAPING As Double = 4D
' Pick C.
Dim cx As Double = Wxmin + m_Rand.NextDouble() * (Wxmax _
- Wxmin)
Dim cy As Double = Wymin + m_Rand.NextDouble() * (Wymax _
- Wymin)
' Zet Z0.
Dim x, xx, y, yy As Double
x = cx
y = cy
xx = x * x
yy = y * y
' Iterate.
For i As Integer = 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 As Integer = 1 To cutoff
Dim ix As Integer = CInt((x - Wxmin) / dx)
Dim iy As Integer = CInt((y - Wymin) / dy)
If (ix >= 0) AndAlso (ix < hgt) AndAlso (iy >= _
0) AndAlso (iy < wid) Then
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 += 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, ByVal hit_r(,) As _
Integer, ByVal hit_g(,) As Integer, ByVal hit_b(,) As _
Integer)
Dim gr As Graphics = Graphics.FromImage(m_Bitmap)
gr.Clear(Color.Black)
Dim scale_r As Double = 255 * 2.5 / max_r
Dim scale_g As Double = 255 * 2.5 / max_g
Dim scale_b As Double = 255 * 2.5 / max_b
For y As Integer = 0 To hgt - 1
For x As Integer = 0 To wid - 1
Dim r As Integer = CInt(hit_r(x, y) * scale_r)
If r > 255 Then r = 255
Dim g As Integer = CInt(hit_g(x, y) * scale_g)
If g > 255 Then g = 255
Dim b As Integer = CInt(hit_b(x, y) * scale_b)
If b > 255 Then b = 255
m_Bitmap.SetPixel(x, y, Color.FromArgb(255, r, _
g, b))
Next x
Next y
picCanvas.Refresh()
End Sub
|