Jump to my Home Page Send me a message Check out stuff on GitHub Check out my photography on Instagram Check out my profile on LinkedIn Check out my profile on reddit Check me out on Facebook

Mitch Richling: Mandelbrot Biomorph

Author: Mitch Richling
Updated: 2022-10-11

mandelbrot_biomorphA_3.png mandelbrot_biomorphE_3.png mandelbrot_biomorphK_3.png mandelbrot_biomorphL_3.png mandelbrot_biomorphM_3.png mandelbrot_biomorphN_3.png

Table of Contents

1. Introduction

I'm calling this the Mandelbrot Biomorph Fractal, but I made that name up! It's really just the Mandelbrot Set with color schemes and iteration stop conditions inspired by biomorph fractals.

In the traditional Mandelbrot set, iteration stops when \(\vert z\vert > 2\). In the code, iteration stops when \(\vert\Re(z)\vert \ge 10\) and \(\vert\Im(z)\vert \ge 10\). As for the color schemes, we have six of them. Only the first one uses just the iteration count. The rest use \(z\) or the next to last \(z\) value.

2. Algorithm & Code

#include "ramCanvas.hpp"

typedef mjr::ramCanvas3c8b::colorType ct;
typedef ct::csIntType cit;

int main(void) {
  std::chrono::time_point<std::chrono::system_clock> startTime = std::chrono::system_clock::now();
  const int    NUMITR = 1024;
  const int    IMXSIZ = 7680/2;
  const int    IMYSIZ = 7680/2;
  const int    LIM    = 10;

  mjr::ramCanvas3c8b theRamCanvasA(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);
  mjr::ramCanvas3c8b theRamCanvasE(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);
  mjr::ramCanvas3c8b theRamCanvasK(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);
  mjr::ramCanvas3c8b theRamCanvasL(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);
  mjr::ramCanvas3c8b theRamCanvasM(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);
  mjr::ramCanvas3c8b theRamCanvasN(IMXSIZ, IMYSIZ, -2.75, 2.75, -2.75, 2.75);

  for(int y=0;y<theRamCanvasA.getNumPixY();y++) {
    for(int x=0;x<theRamCanvasA.getNumPixX();x++) {
      std::complex<double> c = theRamCanvasA.int2real(x, y);
      std::complex<double> z(0.0, 0.0);
      std::complex<double> zL(0.0, 0.0);
      int count = 0; 
      while( ((std::abs(std::real(z))<LIM) || (std::abs(std::imag(z))<LIM)) && (count<NUMITR) ) {
        zL = z;
        z=std::pow(z, 2) + c;
        count++;
      }
      if(count < NUMITR) {
        // A
        theRamCanvasA.drawPoint(x, y, ct::csCColdeRainbow::c(static_cast<cit>(count*500)));
        // E
        if(std::abs(std::real(z))<std::abs(std::imag(z)))
          theRamCanvasE.drawPoint(x, y, ct("red"));
        else
          theRamCanvasE.drawPoint(x, y, ct("blue"));
        // K
        theRamCanvasK.drawPoint(x, y, ct::csCColdeRainbow::c(static_cast<cit>((std::arg(z)+3.14)*255)));
        // L
        if(std::abs(std::real(z))<std::abs(std::imag(z)))
          theRamCanvasL.drawPoint(x, y, ct::csCCu0R::c(mjr::intClamp(static_cast<cit>(std::abs(std::real(z))*15), ct::csCCu0R::numC-1)));
        else
          theRamCanvasL.drawPoint(x, y, ct::csCCu0B::c(mjr::intClamp(static_cast<cit>(std::abs(std::imag(z))*15), ct::csCCu0B::numC-1)));
        // M
        if(std::abs(std::real(zL)) < LIM)
          theRamCanvasM.drawPoint(x, y, ct::csCCfractalYB::c(std::abs(std::real(zL))/LIM));
        else if(std::abs(std::imag(zL)) < LIM)
          theRamCanvasM.drawPoint(x, y, ct::csCCfractalYR::c(std::abs(std::imag(zL))/LIM));
        else
          theRamCanvasM.drawPoint(x, y, "white");
        // N
        if(std::abs(std::real(zL)) < LIM)
          theRamCanvasN.drawPoint(x, y, ct::csCCdiag01::c(std::abs(std::real(zL))/LIM));
        else if(std::abs(std::imag(zL)) < LIM)
          theRamCanvasN.drawPoint(x, y, ct::csCCdiag10::c(std::abs(std::imag(zL))/LIM));
        else
          theRamCanvasN.drawPoint(x, y, "white");
      }
    }
  }
  theRamCanvasA.writeTIFFfile("mandelbrot_biomorphA.tiff");
  theRamCanvasE.writeTIFFfile("mandelbrot_biomorphE.tiff");
  theRamCanvasK.writeTIFFfile("mandelbrot_biomorphK.tiff");
  theRamCanvasL.writeTIFFfile("mandelbrot_biomorphL.tiff");
  theRamCanvasM.writeTIFFfile("mandelbrot_biomorphM.tiff");
  theRamCanvasN.writeTIFFfile("mandelbrot_biomorphN.tiff");
  std::chrono::duration<double> runTime = std::chrono::system_clock::now() - startTime;
  std::cout << "Total Runtime " << runTime.count() << " sec" << std::endl;
}

The above program will generate all of the images in the gallery below.

4. References

Check out the fractals section of my reading list.

All the code used to generate everything on this page may be found on github.