Fascinating World of Fractals - Exploring the Beauty of Mathematics

Fractals are like alien worlds, strange yet familiar. You can zoom into fractals endlessly, producing fascinating patterns of colour.

By Tim Trott | Legacy Code | May 8, 2003
1,553 words, estimated reading time 6 minutes.

Most mathematical formulas can be graphed to generate wave-like lines, curves, arcs, and other simple patterns. Graphs are something that almost everyone is familiar with. Fractals, on the other hand, generate extraordinarily complex and colourful patterns. They frequently appear natural, emulating patterns found in nature such as ferns or coastlines. They are fairly simple to programme, despite their seeming complexity.

What are Fractals?

Fractals are "the adventures of a small number in a complex plane." Fractals are weird, dense graphs created by a mathematical process. The fundamental formulas are short and very straightforward, even though the graphs are infinitely complex. You can use a chart or plot to visualise the relationship between numbers and mathematical expressions. A basic plot of distance versus elevation is presented below.

A simple elevation plot showing distance in the x-axis and elevation in the y-axis
A simple elevation plot showing distance in the x-axis and elevation in the y-axis

You can see how the height of various sites changes with distance by moving down the line from left to right. Mathematicians do not always utilise numbers that we are familiar with. For example, to convert waveforms to audio or evaluate radio signals, "imaginary" numbers must be used.

What are Imaginary Numbers and Complex Numbers?

You square any integer when you multiply it by itself. For instance, 4 * 4 equals 16. This relationship can also be expressed in the inverse - 4 is the square root of 16. There is a square root for every number. For thousands of years, squares and roots have been employed. However, mathematicians began attempting to find the square root of -1 in the 16th century. What is -1's square root? When you square a positive number, the result is always positive. When a negative number is multiplied by another negative number, a positive number is obtained. As a result, the number multiplied by itself to get -1 cannot be positive or negative. It's a contradiction. 1In other terms, it is an imaginary number as opposed to a genuine number.

When you combine imaginary and real numbers, you get grid points. The horizontal axis is described by real numbers, whereas the vertical axis is described by imaginary numbers. This results in a complex number, which is an important notion used in practically every discipline of mathematics and applied research, including speech processing, image compression, radar analysis, and even seismic monitoring.

Fractals are created pixel by pixel by repeating the transformation of a complex number. When you multiply a complex number by itself, several things can happen.

  1. If it is a real number larger than 1, it will grow towards infinity.
  2. If it is less than one (a fraction) it will shrink towards zero, but never reach zero.
  3. If it is exactly one, it will remain one since 1 * 1 is 1 and always will be.

The Mandelbrot Fractals Set

The Mandelbrot set is arguably the most well-known fractal with which most people are familiar. The Mandelbrot set is a collection of numbers that remain bounded when entered into the Mandelbrot equation. That is, they do not reach infinity. The traditional Mandelbrot shape is formed by numbers that trend towards zero or oscillate.

z = z^2 + c

We'd want to draw these fractals on the screen and see if we can find a fractal pattern. Consider the complex plane to be a grid, with real numbers displayed horizontally and imaginary numbers displayed vertically.

To calculate the Mandelbrot set, we must first draw a zone within the grid. We assign the matching complex number to c for each point in this area and, beginning with z = 0, we perform the transformation against this value enough times to determine whether or not this particular place will escape to infinity. If it does, we colour it white to indicate that it is not part of the Mandelbrot set. If it is unable to escape, we colour it black to indicate that it is a component of the set. The number of iterations is the number of times we execute this test.

The Mandelbrot set is the complicated shape that results. The boundary between the two attractors (infinity and zero) is the uneven line connecting the black and white sections. As you can see, it is far from simple as a circle.

Classic Black and White Mandelbrot Fractals Set
Classic Black and White Mandelbrot Fractals Set

Programming the Mandelbrot Fractals Set

Let's first start with the black and white Mandelbrot set. The only parameters to define are:

  1. The area of the complex plane (xMin, xMax, yMin, yMax)
  2. The resolution of the image (nx, ny)
  3. The maximum iterations required to determine if the value escapes or is bounded (maxIter)

Thirty-two iterations is a good starting point. Larger values produce more accurate results, however, require more calculation time.

I know this is in VisualBasic, it's the language I was using at the time. Later examples use Delphi and Pascal.

basic
Sub GenerateMandelbrot ()
  BLACK = RGB(0,0,0): WHITE = RGB(255,255,255)
  Dim X As Double, Y As Double
  Dim ix As Integer, iy As Integer 
  Dim MaxIter As Integer
  
  ' Define picture resolution
  nx = 256
  ny = 256

  ' Select the area of the complex plane to map
  xmin = -1.5
  xmax = .5
  ymin = -1
  ymax = 1
 
  ' Maximum number of iterations
  MaxIter = 32

  ' For each point in the selected area
  For iy = 0 To ny - 1
    Y = (ymin + iy * (ymax - ymin) / (ny - 1))

    For ix = 0 To nx - 1
      X = (xmin + ix * (xmax - xmin) / (nx - 1))
      ' Now check if it escapes to infinity
      M - Mandelbrot(X, Y, MaxIter)
      If M = MaxIter Then
        Picture1.PSet(ix,iy), BLACK
      Else
        Picture1.PSet(ix,iy), WHITE
      End If
    Next
    DoEvents
  Next
End Sub

Function Mandelbrot (ByVal cx As Double, ByVal cy As Double, ByVal MaxIter As Integer) As Integer
  Dim x2 As Double, y2 As Double
  Dim temp As Double
  Dim X As Double, Y As Double

  X = 0
  Y = 0
  x2 = 0
  y2 = 0
  iter = 0

  While ((iter < MaxIter) And (Abs(x2) + Abs(y2) < 100000))
    temp = x2 - y2 + cx
    Y = 2 * X * Y + cy
    X = temp
    x2 = X * X
    y2 = Y * Y
    iter = iter + 1
  Wend
  Mandelbrot = iter
End Function

The first function essentially goes through each pixel in the complex plain and runs the Mandelbrot calculation. If the value returned from this function does not escape to infinity it assigns that pixel the black colour, while if it does escape to infinity it is assigned the WHITE colour.

The actual calculation is done by the Mandelbrot function. The loop tests to see if the calculated value from the Mandelbrot equation escapes to infinity before the maximum iterations is reached. If it is, it returns the number of iterations, if it doesn't then it returns the max iterations. For this example, the value of 100000 is good enough to represent infinity.

Colouring Fractals

Black and White fractals are all well and good, but coloured fractals are often breathtaking. Where does the colour come from?

Different colours represent different escape velocities. That is, the calculation not only tests to see if a point escapes to infinity, it also tests how fast it escapes. These mysterious variations of escape velocity give fractals their beauty and complexity.

These code examples show code written in Borland Delphi. The fully working example can be downloaded at the end of the article.

pascal
procedure TfrmMain.DrawMandel;
var
   x,y: real;
   ix,iy,nx,ny,ipx,px: integer;
   aColor: TColor;
begin
     nx := frmMain.FractalImage.Width;
     ny := frmMain.FractalImage.Height;
     DRAWINGF := TRUE;
     px := 0;
     begin
       nx := frmMain.FractalImage.Width;
       ny := frmMain.FractalImage.Height;
       for iy := 0 to ny-1 do
       begin
            if STOPNOW = TRUE then break;
            Y := (ymin +iy * (ymax -ymin) / (ny - 1));
            for ix := 0 to nx-1 do
            begin
                   X := (xmin + ix * (xmax - xmin) / (nx - 1));
                   aColor := CalcColorMandel(X,Y,maxiter);
                   frmMain.FractalImage.Canvas.Pixels[ix,iy] := aColor;
                   frmMain.Progress.Progress := trunc(((iy/frmMain.FractalImage.Height)*100)+1);
                   frmMain.ProgressShow.Progress := frmMain.Progress.Progress;
            end;
            Application.ProcessMessages;
       end;
     end;
     DRAWINGF := FALSE;
     STOPNOW := FALSE;
     btnStop.Visible := FALSE;
     btnDraw.Visible := TRUE;
     px := 64;
end;

function TfrmMain.CalcColorMandel(cx,cy: double; maxiter: integer): TColor;
var
   x2,y2,temp,x,y : double;
   iter: integer;
begin
     x := 0;
     y := 0;
     x2 := 0;
     y2 := 0;
     iter := 0;
     while ((iter < maxiter) and ((abs(x2) + abs(y2)) < 100000)) do
     begin
          temp := x2 - y2 + cx;
          y := (2 * x * y) + cy;
          x := temp;
          x2 := x * x;
          y2 := y * y;
          inc(iter);
     end;
     if PaletteType = 2 then result := trunc((iter+80)*colorFactor);
     if PaletteType = 1 then
     begin
          if ((iter > 60) AND (iter < maxiter)) then result := 255 * 255 * 255
          else if ((iter < 56) AND (iter > 53)) then result := 240 * 255 * 255
          else if ((iter < 52) AND (iter > 47)) then result := 244 * 255 * 255
          else if ((iter < 48) AND (iter > 45)) then result := 192 * 255 * 255
          else if ((iter < 44) AND (iter > 41)) then result := 176 * 255 * 255
          else if ((iter < 40) AND (iter > 37)) then result := 160 * 255 * 255
          else if ((iter < 36) AND (iter > 33)) then result := 144 * 255 * 255
          else if ((iter < 32) AND (iter > 29)) then result := 128 * 255 * 255
          else if ((iter < 28) AND (iter > 25)) then result := 112 * 255 * 255
          else if ((iter < 24) AND (iter > 21)) then result := 96 * 255 * 255
          else if ((iter < 20) AND (iter > 17)) then result := 80 * 255 * 255
          else if ((iter < 16) AND (iter > 13)) then result := 64 * 255 * 255
          else if ((iter < 12) AND (iter > 9)) then result  := 32 * 255 * 255
          else if ((iter < 8) AND (iter > 5)) then result   := 16 * 255 * 255
          else if (iter < 4) then result  :=     0
          else result := 0;
     end;
end;

What we see here is the colour method testing how many iterations were needed before the value escapes to infinity. Based on this it assigns a colour value (R*G*B)

FractalGenerator in Delphi by Tim Trott

You can download the code from GitHub

Download from GitHub 

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

There are no comments yet. Why not get the discussion started?

We respect your privacy, and will not make your email public. Learn how your comment data is processed.