Mitch Richling: Pickover Popcorn
Author: | Mitch Richling |
Updated: | 2024-10-31 |
Table of Contents
1. Pickover Popcorn Fractals
Clifford Pickover's fractal popcorn is an an orbit-fractal traditionally using the following functions:
\[\begin{eqnarray} x & = & x - h \cdot \sin\left(y + \tan(a \cdot y)\right) \\ y & = & y - h \cdot \sin\left(x + \tan(b \cdot x)\right) \end{eqnarray}\]
Typical parameter choices are: \(a=0.3\), \(b=0.3\), and \(h=0.05\). The orbits tend to densely cover regions of the plane with swirling patterns.
Over time people have started calling any orbit fractal of similar form a Pickover Popcorn Fractal. Common modifications include replacing one or more of the trig functions with other trig functions.
2. Algorithms & Code
Note the code uses hstRamCanvas
to count the number of times each pixel is hit – the counters are 16-bit unsigned integers. Then we use writeTIFFfile
with a converter object to color the counts, and produce a nice image. Both the count and color image are saved – so you can load the counts image up in
something like ImageJ
and recolor it to your heart's content.
#include "ramCanvas.hpp" // This is *identical* to what we did in sic.cpp -- just way shorter. typedef mjr::ramCanvas1c16b::rcConverterColorScheme<mjr::ramCanvas1c16b, mjr::color3c8b, mjr::color3c8b::csCCfractal0RYBCW, true, 10, 0> g2rgb8; int main(void) { std::chrono::time_point<std::chrono::system_clock> startTime = std::chrono::system_clock::now(); const int IMXSIZ = 7680/2; const int IMYSIZ = 4320/2; const int NUMITR = 100; const int spanx = 1; const int spany = 1; const double h = 0.05; const double a = 3.0; const double b = 3.0; mjr::ramCanvas1c16b hstRamCanvas(IMXSIZ, IMYSIZ, -4.0, 4.0, -2.25, 2.25); for(int y=0;y<hstRamCanvas.getNumPixY();y+=spany) { if ((y%100)==0) std::cout << y << std::endl; for(int x=0;x<hstRamCanvas.getNumPixX();x+=spanx) { double zx = hstRamCanvas.int2realX(x); double zy = hstRamCanvas.int2realY(y); for(int i=0; i<NUMITR; i++) { double tmpx = zx - h * std::sin(zy + std::tan(a * zy)); double tmpy = zy - h * std::sin(zx + std::tan(b * zx)); zx = tmpx; zy = tmpy; int ix = hstRamCanvas.real2intX(zx); int iy = hstRamCanvas.real2intY(zy); if (hstRamCanvas.isOnCanvas(ix, iy)) hstRamCanvas.getPxColorRefNC(ix, iy).tfrmAdd(1); } } } hstRamCanvas.writeTIFFfile("pickoverPopcornCNT.tiff"); g2rgb8 rcFilt(hstRamCanvas); hstRamCanvas.writeTIFFfile("pickoverPopcornCOL.tiff", rcFilt, false); std::chrono::duration<double> runTime = std::chrono::system_clock::now() - startTime; std::cout << "Total Runtime " << runTime.count() << " sec" << std::endl; return 0; }
The above program will generate this picture: