Welcome to the second post of the series where I develop an app that displays the Mandelbrot set using the Go programming language.

## Objectives

In this post I will describe how to put into practice the theory behind the Mandelbrot set.
Then I will write a first version of the app that displays the
set in the **Command Line Interface** (or CLI).

## Requirements

- If you want to follow the steps of this tutorial, install the Go environment.
- An
**IDE**will help you with autocompletions, formatting, incorrect types… I decided to try GitHub’s Atom editor, but you can use your favorite one. Check the official Go docs for plugins and tips. - Also, the code of the app is hosted on GitHub, so if you decide to follow the progress of this project install git and clone the repository:

## Configure the Mandelbrot set

As we saw in the last post, the Mandelbrot set consists of **complex numbers** that comply with some rules.
These complex numbers are numbers like `-1.2 + 0.5i`

, where `-1.2`

is the real part and `0.5i`

is the imaginary part.
To display the Mandelbrot set in a two dimensional cartesian plane like an image, we will use the real part as
the `X`

axis and the imaginary part and the `Y`

axis. Both axis will be delimited by maximum and minimum values.

However in a digital image the `X`

and `Y`

axis are not measured by complex numbers but by **pixels**!
That’s why we are going to need some method to know which complex number `c`

is represented by `pixel(x, y)`

.

## From pixel to complex number

A good starting point for our app can be developing the next two methods:

`toReal(xPixel)`

calculates the real part of a complex number.`toImag(yPixel)`

calculates the imaginary part of a complex number.

Let’s think of a real case scenario: we want to generate a `11x11`

pixels image of a Mandelbrot set
which limits are `[-2.5, 2.5]`

for the real part (`X`

axis)
and `[-1.0, 1.0]`

for the imaginary part (`Y`

axis).

Looking at the image, it’s easy to spot some cases that will help us check if our transformation is correct:

Pixel coordinate | Expected complex number |
---|---|

`(0, 0)` |
`-2.5 + 1.0i` |

`(10, 10)` |
`2.5 - 1.0i` |

`(5, 5)` |
`0 + 0i` |

`(11, 4)` |
Error! `x` is out of bounds |

`(-1, 0)` |
Error! `x` is out of bounds |

`(0, 11)` |
Error! `y` is out of bounds |

`(0, -1)` |
Error! `y` is out of bounds |

For the transformation, we need to know the **boundaries of both real and imaginary parts** of the Mandelbrot set.
We will also need the **width** and **height** of the resulting image in pixels.
Let’s create a type `Config`

that groups all these values:

Now let’s add the `toReal(xPixel)`

and `toImag(yPixel)`

methods:

Nice! The app is now able to transform every pixel of our image into a complex number. The next step will be detecting if these numbers are part of the Mandelbrot set.

## Is this number inside the Mandelbrot set?

To verify if a complex number is inside the set, we need to iterate the function we saw in the previous post:

To program the iteration, we must know the math behind complex numbers. A good tip: we will use
the **perfect square formula**: `(a + b)² = a² + 2 * a * b + b²`

Let’s see an example with `c=-0.75 + 0.75i`

:

But, **when do we stop**? For a complex number `c`

, in every iteration of the function we need to check the
**absolute value** of z (`|z|`

):

`|z| = |(a + bi)| = sqrt(a² + b²)`

- If
`|z|`

is greater than 2, then`c`

is not part of the set. - If after a maximum number of iterations
`|z|`

is not bigger than 2, then`c`

is part of the set.

Let’s see how the absolute value of some complex numbers varies through iterations:

`n=0` |
`n=1` |
`n=2` |
`n=3` |
`n=4` |
`n=5` |
||
---|---|---|---|---|---|---|---|

A: |
`-1.0 + 0.0i` |
`0.00` |
`1.00` |
`0.00` |
`1.00` |
`0.00` |
`1.00` |

B: |
`-2.5 + 1.0i` |
`0.00` |
`2.69` |
||||

C: |
`-0.75 + 0.75i` |
`0.00` |
`1.06` |
`0.84` |
`1.35` |
`2.37` |

For some complex numbers (like *A*) its absolute value never gets bigger than 2. But in other cases,
like *B* and *C*, the continuous iteration makes them diverge at some point. Depending of the iteration,
the complex number is part of the set or not. This is why defining a correct **threshold** is so important.

Let’s create a `type`

that is responsible for verifying if a complex number remains bounded after
some iterations:

Nice, we are almost there!

## Loop and print

Now all we need to do is loop through all the pixels of our “image” and print the result in the CLI. Let’s edit the main method:

And now, let’s build the project and run the generated executable file:

If you execute this code in your machine, the result should be what you see in the next image:

## Custom parameters

Unfortunately, the parameters of this Mandelbrot set are hardcoded inside the app.
Let’s add **command-line flags** to customize the result!

Remember to rebuild the app:

Now the app accepts **custom values** entered from the command line:

## Testing and Refactoring

If you take a look at the source code of the app, you’ll find tests for most part of the code
(look for `*_test.go`

files). I’ve been following a **Test Driven Development** (TDD) approach,
which means writing tests before actually writing the code itself.
These tests provide a *safety net* to refactor the code without breaking things by accident.

Check the `cc79a24`

commit (and the following ones) if you want to see a step-by-step TDD approach
of how I’ve developed the `toReal(x)`

method.

## Next

There are many improvements that could make the code clearer and more robust, but
**at this point the app is good enough**: it does what we want (prints the Mandelbrot set in the CLI)
and does is correctly. In the next post I will enhance the app while adding the ability
to generate images in black and white.