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: Pickover Popcorn

Author: Mitch Richling
Updated: 2022-12-10

topimg_45.png

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:

pickoverPopcornCOL_20.png

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.