Tuesday night, I was a bit stressed and tired from my day, and I looked for a way to relax. So, doing some code in G’MIC ![]()
My tortuous mind wondered what it would be like to rotate a polygon and at the same time have it move along a random spline-like trajectory. Yes, it sounds like a silly idea, but I had a feeling it might turn out something cool.
I have to say that the first results obtained were a little beyond my expectations, so I decided to dig a little deeper and it’s with great pleasure that I can present to you today a new filter in G’MIC-Qt, named Rendering / Spline Spirograph, which allows you to do just that:
The filter looks like this when called from the plug-in:
As always when I’m doing this kind of experiment, I was amazed by the fact that the code didn’t take that long to write (prototyping with G’MIC is so cool
). And that’s going to benefit potentially a lot of people right away. Time well spent ![]()
Here is the full source code for this new filter (56 lines of code, don’t tell me it’s too long! ).
Code for "Spline Spirograph" filter
#@gui Spline Spirograph : fx_spline_spirograph, fx_spline_spirograph
#@gui : Seed = int(0,0,65535)
#@gui : Randomize Seed = button()
#@gui : sep = separator()
#@gui : Complexity (%) = float(50,0,100)
#@gui : Sampling (%) = float(100,0,100)
#@gui : Radius (%) = float(20,0,100)
#@gui : Vertices = int(3,2,16)
#@gui : Twist = float(20,0,150)
#@gui : Offset (deg.) = float(0,-180,180)
#@gui : sep = separator()
#@gui : Colors = choice(3,"Default","HSV","Lines","Hot","Cool","Jet","Flag","Cube","Rainbow","Parula","Spring",\
# "Summer","Autumn","Winter","Bone","Copper","Pink","VGA","Algae","Amp","Balance","Curl","Deep","Delta","Dense","Diff",\
# "Gray","Haline","Ice","Matter","Oxy","Phase","Rain","Solar","Speed","Tarn","Tempo","Thermal","Topo","Turbid",\
# "Aurora","Hocuspocus","SRB2","Uzebox","Amiga7800","Amiga7800mess","Fornaxvoid1")
#@gui : Alpha Channel = bool(0)
#@gui : sep = separator()
#@gui : Normalization Strength (%) = float(50,0,100)
#@gui : Normalization Radius (%) = float(50,0,100)
#@gui : sep = separator()
#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2024/04/10</i>.</small>")
fx_spline_spirograph :
seed,randomize_seed,complexity,sampling,radius,vertices,twist,\
offset,colors,is_alpha,normalization_strength,normalization_radius=${1-12}
if $randomize_seed seed:=v(65535) fi
foreach {
nm={n}
if $is_alpha to_a else remove_opacity fi
f 0 => canvas
palette $colors r. 360,1,1,3,3 to_colormode. {0,s} => palette
# Parameterization of a random spline curve.
rs[canvas] 100,100,-1,2 ${}
srand $seed noise_poissondisk. {max(5,lerp(100,0,$complexity%^0.3))}
0 eval.. "i?da_push([u,x*w#$canvas%,y*h#$canvas%])" da_freeze. rm..
sort. +,y channels. 1,2
r. 1,{max(1,h*max(w#0,h#0)*($sampling%)^2)},1,2,5 => coords
# Draw spirograph along spline.
eval[coords] ":
const R = $radius%*max(w#$canvas,h#$canvas);
const N = $vertices;
C = round(I);
pP = [ 0,0 ];
repeat (N + (N>2),k,
ang = ($offset + lerp(0,360,k/N) + y*360*$twist/h)%360;
P = round(C + R*cexp([0,ang°]));
k>0?polygon(#$canvas,2,pP,P,-1,I(#$palette,ang,0,0,1));
pP = P;
)"
k[canvas]
n 0,255 normalize_local {10*$normalization_strength%},{max(1,($normalization_radius%)^3*10*max(w,h)%)}
}
u \{$seed\}\{0\}\{$density\}\{$radius\}\{$vertices\}\{$twist\}\{$offset\}\{$colors\}\
\{$normalization_strength\}\{$normalization_radius\}
That’s all I had to say.
Feel free to play with it and post your own exciting results!
Cheers.




















