Fractal Spirographs

Inspiration

Daniel Shiffman has been making YouTube movies for some time now. His videos focus on programming and include coding challenges in which he writes code for a target idea from scratch. If you are a coder I recommend Dan’s videos for entertainment and inspiration.

His latest live stream focused on Fractal Spirographs.

If you prefer to watch a shorter edited version, here it is.

He was inspired by the following image from the Benice Equation blog.

Fractal Spirograph

Fractal Spirographs (aka Fractal Routlette) are generated by tracking a series (or chain) of circles rotating around each other as shown in the above gif animation. You track the chain of 10 or so circles and plot the path the final smallest circle takes. Changing the number of circles, the size ratio between circles, the speed of angle change, and the constant “k” changes the resulting plots and images.

How I Coded It

As I watched Daniel’s video I coded my own version. For my code (Delphi/pascal) I used a dynamic array of records to hold the details of each circle/orbit. This seemed the simplest approach to me for keeping track of a list of the linked circles.

  
type orbit=record
     x,y:double;
     radius:double;
     angle:double;
     speed:double;
end;

Before the main loop you fill the array;

     
//parent orbit
orbits[0].x:=destimage.width/2;
orbits[0].y:=min(destimage.width,destimage.height)/2;
orbits[0].radius:=orbits[0].y/2.5;
orbits[0].angle:=0;
orbits[0].speed:=0;
rsum:=orbits[0].radius;
//children orbits
for loop:=1 to numorbits-1 do
begin
     newr:=orbits[loop-1].radius/orbitsizeratio;
     newx:=orbits[loop-1].x+orbits[loop-1].radius+newr;
     newy:=orbits[loop-1].y;
     orbits[loop].x:=newx;
     orbits[loop].y:=newy;
     orbits[loop].radius:=newr;
     orbits[loop].angle:=orbits[loop-1].angle;
     orbits[loop].speed:=power(k,loop-1)/sqr(k*k);
end;

Then inside the main loop, you update the orbits;


//update orbits
for loop:=1 to numorbits-1 do
begin
     orbits[loop].angle:=orbits[loop].angle+orbits[loop].speed;
     rsum:=orbits[loop-1].radius+orbits[loop].radius;
     orbits[loop].x:=orbits[loop-1].x+rsum*cos(orbits[loop].angle*pi/180);
     orbits[loop].y:=orbits[loop-1].y+rsum*sin(orbits[loop].angle*pi/180);
end;

and then you use the last orbit positions to plot the line, ie


canvas.lineto(round(orbits[numorbits-1].x),round(orbits[numorbits-1].y));

Results

Once the code was working I rendered the following images and movie. They are all 4K resolution to see the details. Click the images to see them full size.

Fractal Spirograph

Fractal Spirograph

Fractal Spirograph

Fractal Spirograph

Fractal Spirograph

Here is a 4K movie showing how these curves are built up.

Fractal Spirographs are now included with the latest version of Visions of Chaos.

Finally, here is an 8K Fulldome 8192×8192 pixel resolution image. Must be seen full size to see the fine detailed plot line.

Fractal Spirograph

To Do

Experiment with more changes in the circle sizes. The original blog post links to another 4 posts here, here, here and here and even this sumo wrestler

Fractal Spirograph

Plenty of inspiration for future enhancements.

I have already experimented with 3D Spirographs in the past, but they are using spheres rotating within other spheres. Plotting the sqheres rotating around the outside of other spheres should give more new unique results.

Jason.

3D Spirographs

Ahhh, Spirograph, that simple set of plastic cogged discs and rings that created a huge amount of spirally patterned goodness (as long as you kept a steady hand and didn’t jump a cog tooth). I still remember how cool they were prior to the home computer age. Here is a 1973 commercial for them.



And here is a commercial from the 80s.



Visions Of Chaos currently supports rendering 2D spirographs, but I have wanted to explore a 3D extension of Spirographs for a long time.

It was surprisingly difficult to find the formulas required to plot the 3D result of spheres rotating within spheres within speheres etc. Finally, thanks to Henry de Valence’s code I was able to add 3D Spirographs to Visions Of Chaos.

OpenProcessing is a goldmine of ideas/formulas/algorithms. Anyone who enjoys computer graphics and programming needs to check it out.

Here are two early sample movies resulting from my initial test code.



Once they showed potential I made sure that Visions Of Chaos supported the true 1080p “real side by side 3d” output and got the following result. This looks amazing on my LG 3D TV with the polarised glasses. They really pop what seems at least a foot out of the screen as they rotate.



If you want to have a play with the new 3D Spirograph mode, download Visions Of Chaos.

Info For Coders

If you are a programmer who is looking to explore the incredible space of 3D Spirographs here is the main code that you will need to plot the curve in 3D space. This is a direct copy and paste from Henry’s processing code.


ax = 0; ay =0; az = 0;
  bx = 0; by =0; bz = 0;
  for(int i = 0; i < num_segments; ++i) {
    bx = ax + r[i]*sin(f[i]*t)*cos(g[i]*t);
    by = ay + r[i]*sin(f[i]*t)*sin(g[i]*t);
    bz = az + r[i]*cos(g[i]*t);
    line(ax, ay, az, bx, by, bz);
    ax = bx; ay = by; az = bz;
  }

num_segments is how many recursive spheres within spheres you use. For the above sample 3D movie most of them used 2 spheres, but any higher number works too and will lead to much more complex and twisted plots.

r[i] are the radius lengths of each sphere or arm segment.

f[i] and g[i] are non zero +/- period values that change the resulting plot shapes. I tested and used values between -45 and +45 for my images and movies to extend the possible resulting shapes. If the values are rational (integer numbers) then the plot will eventually come back to the start point and retrace itself.

t is time that starts at 0 and should be changed 0.01 or so per update for a smooth plot.

the ax to bx etc swapping keeps track on the sphere within sphere.

Once the segment loop is finished bx,by and bz are the next 3D point in space the Spirograph is at.

At this stage you should be plotting nice 3D spirographs. One very helpful tip is how to work out when to stop calculating and plotting new points. As stated above if you use integer values for the periods then the plot will always return to the start position and beging retracing itself again. Being able to pre-calculate how many steps the plot needs is a handy feature to have.

To calculate the ideal value that the time t variable will be when the plot finishes you find the least common multiplier (LCM) of all the period values. eg if you have a spirograph using 3 arms/segments you will need to calculcate the LCM of 6 period values. Chances are your programming language of choice has a LCM(a,b) function that takes two values. For 3 or more values you recursively call the LCM function. ie the LCM of a,b and c is LCM(a,LCM(b,c)). Thanks again to Henry for the LCM tip.

Jason.