Mitch Richling: Mandelbrot Wave
Author: | Mitch Richling |
Updated: | 2024-10-31 |
Table of Contents
1. Introduction
Iterate \(f(x)=z^5+a\cdot z+c\) as one would \(f(z)=z^2+c\) to render a Mandelbrot Set. Vary the parameter \(a\) by moving it around the unit circle, and drop out an image for each \(a\).
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 = 255; const int NUMFRM = 24*16; // Full circle animation //const int NUMFRM = 24*4; // Wave animation const int IMXSIZ = 7680/2; const int IMYSIZ = 7680/2; const int MAXZSQ = 10; const double ANGMIN = 0.0; // Full circle animation const double ANGMAX = std::numbers::pi*2; // Full circle animation // const double ANGMIN = 3.04341788317; // Wave animation // const double ANGMAX = 3.23976742401; // Wave animation for(int frame=0; frame<NUMFRM; frame++) { mjr::ramCanvas3c8b theRamCanvas(IMXSIZ, IMYSIZ, -1.5, 1.5, -1.5, 1.5); // Full circle animation // mjr::ramCanvas3c8b theRamCanvas(IMXSIZ, IMYSIZ, -0.7, 0.1, -0.7, 0.1); // Wave animation theRamCanvas.clrCanvasToBlack(); std::cout << "Frame: " << frame << " of " << NUMFRM << std::endl; double angle = frame*(ANGMAX-ANGMIN)/NUMFRM+ANGMIN; std::complex<double> a(std::cos(angle), std::sin(angle)); # pragma omp parallel for schedule(static,1) for(int y=0;y<theRamCanvas.getNumPixY();y++) { for(int x=0;x<theRamCanvas.getNumPixX();x++) { std::complex<double> c(theRamCanvas.int2realX(x), theRamCanvas.int2realY(y)); std::complex<double> z(0.0, 0.0); int count = 0; while((std::norm(z)<MAXZSQ) && (count<=NUMITR)) { z = std::pow(z, 5) + a * z + c; count++; } if(count < NUMITR) theRamCanvas.drawPoint(x, y, ct::csCColdeFireRamp::c(static_cast<ct::csIntType>(count*20))); } } theRamCanvas.scaleDownMean(8); // Another good choice: theRamCanvas.scaleDownMax(8); theRamCanvas.writeTIFFfile("mandelbrot_wave_" + mjr::math::str::fmt_int(frame, 3, '0') + ".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 frames for a movie which may be rendered into a GIF:
If we use the scaleDownMax
option, then we get the following:
Lastly, if we use the "wave" code, we get the following: