Welcome to the 16th Task… Wow, 4 months have flow by…

We did a month of 1D, and then switched to 2D patterns for a while. Based on requests, next week, we’ll switch back to 1D for a bit, but some of the tasks will involve ways to use 1d strips in new ways.

For this last of the 2D tasks (for now), @zranger1 's code for his flower pattern used one of my favorite math bits: the golden ratio. I knew we needed to go there.

If you aren’t familiar with the golden ratio, or phi, there are plenty of good videos about it. I’ll link some below.

What you need to know:

Phi aka the Golden Ratio, is considered to be the “Divine Proportion” because so much of nature uses it. It’s a ratio that is pleasing to the eye, and also happens to be very math based. It’s 1.618xxxx… but you can use 1.618 and it’s close enough… And the inverse of 1.618xxx is… 0.618xxxx. The small is to the large as the large is to the whole.

Fibonacci numbers? The ratio of any two numbers approaches Phi as you go along.
(Actually any sequence where you add two numbers together and then add the last two number to get the next in the series, that’s a phi ratio)

If you turn phi degrees each time, you end up with a beautiful spiral design that @JasonCoon and others have turned into an led panel. That makes it super easy to make spiral designs, but you can make them on a normal matrix too.

It could be a spiral, it could be a set of rectangles, it could be something organic looking (if you make phi ratioed designs, they often will)

Videos to come.

The usual rules: avoid spoilers, golfing is encouraged, this is about learning to code better, and sharing. We’ve had so many good patterns so far, and I’m sure this will continue.

2 Likes

Videos (so many… I avoided design, architecture, color theory, and more… It’s a rabbit hole for sure)

Why flowers use Phi:

phi in music (cause it’s interesting to hear it)

Led panels [stay on target, Scruffy!]

(Last in the series, but the earlier ones show building it)

One of Jason’s many videos

And wokwi has made a similar panel

Not that you need a special panel…

Fibonacci boxes:

Pentagons also use phi:

4 Likes

This task gave me an opportunity to try an experiment I’ve been wondering about for a while. Today’s effort attempts to map a Fibonacci spiral onto a 2D display, and runs a 1D pattern (Block Reflections in this case) on it to give an idea what it would look like on one of those nifty spiral LED display panels.

Obviously the pixel positions are going to be a pretty rough match. But it looks cool enough, and the idea of remapping pixel indices is interesting enough that I consider this one almost a success. And it definitely uses the golden ratio! Code below the video.

``````/*
Fibonacci spiral remap demo. Builds a Fibonacci spiral display on
your 2D matrix display. Works by building a reordered pixel index -- essentially
a new map.

The mathematical match of spiral to matrix is um... some distance from perfect, so
this doesn't  look nearly as good as an actual spiral LED build, but you can kinda
get the idea...

The pattern code being run here  is lifted directly from "Block Reflections". You can
plug any 1D pattern  in to see how it will look by just copying its working code to
this pattern  and substituting "spiralPixels" for "pixelCount" and  "spiral[index]" for "index".

ZRanger1

*/

// display size - enter the dimensions of your matrix here
var width = 16;
var height = 16;

// Global variables for rendering
var spiral = array(pixelCount)
export var density = 1/(width+height);

export function sliderDensity(v) {
density = 1/(width + (v * height));
drawSpiral();
}

function drawSpiral() {

// pixels with negative indices are never rendered
for (var i = 0; i < pixelCount; i++) {
spiral[i] = -1;
}

i = 0;

// build fibonacci spiral, stopping when the radius reaches
// the edge of the display.
while (1) {
var r = (density * sqrt(i));
var theta = i *  2.39982;   // golden angle in radians!
if (r > 0.5) break;

var x1 = ((r * cos(theta))) + 0.5;
var y1 = (-1 * r * sin(theta)) + 0.5;
x1 = floor(width * x1);
y1 = floor(height * y1);
spiral[x1+(y1 * width)] = i;

i++;
}
spiralPixels = i;
}

drawSpiral();

// most of the beforeRender and render code is taken directly from
// the Block Reflections pattern, with the minor changes mentioned
// in the comment block at the top of this pattern.
var t1,t2,t3,t4;
export function beforeRender(delta) {
t2 = time(0.1) * PI2
t1 = time(.1)
t3 = time(.5)
t4 = time(0.2) * PI2
}

function render(index) {
if (spiral[index] < 0) { rgb(0,0,0); return; }

h = sin(t2)
m = .3 + triangle(t1) * .2
h = h + (((spiral[index] - spiralPixels / 2) / spiralPixels * ( triangle(t3) * 10 + 4 * sin(t4)) % m))
s = 1;
v = ((abs(h) + abs(m) + t1) % 1);
v = v * v
hsv(h, s, v)
}

export function render2D(index, x, y) {
render(index);
}
``````
2 Likes