Thursday, May 23, 2019

Mandelbrot and Julia Fractals

The Mandelbrot set and the Julia sets are very similar in the way they're defined. Both are generated iteratively by the equation:

$z_{n+1} = z_{n}^2 + c$

Where $z$ and $c$ are complex numbers.

The Mandelbrot set is generated by starting with $z_{0}=0$ and varying $c$. Each $c$ that causes the iteration to converge to some complex number is part of the set, while each $c$ that causes it to diverge is not part of the set.

The Julia sets are similar to the Mandelbrot set, except $z_{0}$ is varied, and $c$ is constant. Each $c$ will create a unique Julia set.

Both sets can be visualized by treating each pixel in an image as a complex number where the horizontal axis is the real component of a complex number, and the vertical axis is the imaginary component. Each pixel will represent $c$ in the Mandelbrot set and $z_{0}$ in the Julia sets.

Here is an image of the Mandelbrot set that I generated using a small program I wrote in C++



Here is the most relevant function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
std::vector<unsigned char> generateMandelbrot(const unsigned width, const unsigned height, int iterations, double scale, double realAnim, double imagAnim) {
 int offset{ -static_cast<int>(width) / 4 };
 int maxX{ static_cast<int>(width / 2) + offset }, minX{ -static_cast<int>(width / 2) + offset };
 int maxY{ static_cast<int>(height / 2) }, minY{ -maxY };
 std::vector<unsigned char> img(width * height * 4, 255);

 for (int y{ minY }; y < maxY; ++y)
  for (int x{ minX }; x < maxX; ++x) {
   Complex z{ realAnim, imagAnim };
   Complex c{ x / (scale * 500), y / (scale * 500) };
   int i;
   for (i = 0; i < iterations; ++i)
   {
    z = z * z + c;
    if (complexLength(z) > 2)
     break;
   }
   unsigned index{ 4 * width * (y + height / 2) + 4 * (x + width / 2 - offset) };
   addRGBA(img, index, static_cast<double>(i) / iterations);
  }
 return img;
}


Here are two Julia fractals:



And here's the function I wrote for the Julia fractals:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
std::vector<unsigned char> generateJulia(const unsigned width, const unsigned height, int iterations, double scale, int offset, const Complex& c) {
 int maxX{ static_cast<int>(width / 2) + offset }, minX{ -static_cast<int>(width / 2) + offset };
 int maxY{ static_cast<int>(height / 2) }, minY{ -maxY };
 std::vector<unsigned char> img(width * height * 4, 255);

 for (int y{ minY }; y < maxY; ++y)
  for (int x{ minX }; x < maxX; ++x) {
   Complex z{ x / (scale * 500), y / (scale * 500) };
   int i;
   for (i = 0; i < iterations; ++i)
   {
    z = z * z + c;
    if (complexLength(z) > 2)
     break;
   }
   unsigned index{ 4 * width * (y + height / 2) + 4 * (x + width / 2 - offset) };
   addRGBA(img, index, static_cast<double>(i) / iterations);
  }
 return img;
}

I was curious what it would look like to vary some of the parameters for Mandelbrot and Julia fractals so I made an animation of it and put it on my new YouTube channel. It turned out pretty cool, take a look:




No comments:

Post a Comment