Mitch Richling: Burning Ship Fractal
Author: | Mitch Richling |
Updated: | 2024-10-31 |
Table of Contents
1. Introduction
The Burning Ship Fractal is a bit of a Mandelbrot'alike in that its generating function is a minor modification of the one used for the Mandelbrot Set:
\[\begin{eqnarray} f(z) & = & z^2+c & \,\,\,\,\,\,\mathrm{Mandelbrot} \\ f(z) & = & \left(\vert\Re(z)\vert + i\cdot\vert\Im(z)\vert\right)^2 +c & \,\,\,\,\,\,\mathrm{Burning\,\,Ship} \\ \end{eqnarray}\]
Granted, these two functions are not visually similar in the standard form written above; however, we can remedy that by rewriting the equations using explicit real and imaginary parts. We use \(x+yi\) instead of \(z\) for the following two equations:
\[\begin{eqnarray} f(z) & = & ( & \,x & + & \,y & i & )^2 & + & c & \,\,\,\,\,\,\mathrm{Mandelbrot} \\ f(z) & = & ( & \vert x\vert & + & \vert y\vert & i & )^2 & + & c & \,\,\,\,\,\,\mathrm{Burning\,\,Ship} \\ \end{eqnarray}\]
So the equations are identical except for the signs of the real and imaginary parts – i.e. at each step in the Burning Ship Fractal we make the parts positive.
2. Algorithms
We render the Burning Ship Fractal using the \(L\) function just like we did with the Mandelbrot Set. The general idea is to map an array of pixels making up the raster image to a rectangular region of the complex plane, and color each pixel of the image based upon a color scale for the computed value of the \(L\) function. Coding up this idea leads to the following C++ program:
#include "ramCanvas.hpp" typedef mjr::color3c8b::csCC_tpl<mjr::color3c8b::cornerColorEnum::BLUE, mjr::color3c8b::cornerColorEnum::RED, mjr::color3c8b::cornerColorEnum::YELLOW, mjr::color3c8b::cornerColorEnum::WHITE> csCCbs; int main(void) { std::chrono::time_point<std::chrono::system_clock> startTime = std::chrono::system_clock::now(); const int NUMITR = 1024; const int MAXMAG = 15; const int IMGSIZ = 7680/4; //mjr::ramCanvas3c8b escRamCanvas(IMGSIZ, IMGSIZ, -1.5, 2.7, -1.25, 2.49); // Entire fractal //mjr::ramCanvas3c8b escRamCanvas(IMGSIZ, IMGSIZ, 1.6, 1.9, -0.089, 0.2); // The horizon zoom mjr::ramCanvas3c8b escRamCanvas(IMGSIZ, IMGSIZ, 1.715, 1.795, -0.022, 0.086); // The classic zoom //mjr::ramCanvas3c8b escRamCanvas(IMGSIZ, IMGSIZ, 1.802, 1.80287, -0.002, 0.002); // Columns to heaven //mjr::ramCanvas3c8b escRamCanvas(IMGSIZ, IMGSIZ, -0.3743, -0.3735, -0.0876, -0.0866); // Deep zoom. BATS! for(int y=0;y<escRamCanvas.getNumPixY();y++) { for(int x=0;x<escRamCanvas.getNumPixX();x++) { double cx = escRamCanvas.int2realX(x), cy = escRamCanvas.int2realY(y); double zx = 0.0, zy = 0.0; double t; int count = 0; while(((zx*zx+zy*zy)<MAXMAG) && (count<=NUMITR)) { count++; t = zx*zx - zy*zy - cx; zy = std::abs(2*zx*zy) - cy; zx = t; } if(count < NUMITR) escRamCanvas.drawPoint(x, y, csCCbs::c(static_cast<mjr::ramCanvas3c8b::csIntType>(count*10))); } } // Escape Time Coloring escRamCanvas.writeTIFFfile("BurningShip.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 this picture: