The Math of The Flower of Life (+ implementing it in JavaScript)

Beginners: I promise if you can follow instructions you’ll make it through this and be able to extend it on your own. I try to explain most concepts but if something doesn’t make sense don’t hesitate to just copy and paste :) The most important part of creative coding is making something work. I learned everything I know through copy/pasting and seeing what happens

Developers: This starts slow but ramps up at Drawing The Rest Of The Circles. You can just jump there and copy the code right above if you already know p5 and geometry basics

So what are we •actually• doing here? Believe it or not it’s pretty much just what did above but with some math that fifteen year-olds know and I, as a grownup, totally had to google. The following is done in p5.js but the general principles apply everywhere.

Setting It Up

To build our Flower of Life we’re going to use p5.js, an art library that makes ‘coding accessible for artists, designers, educators, and beginners’.

Strictly for convenience we’re going to do this in CodePen to prevent you from having to do setup work. Go ahead and click this link, adjust the screen so it looks like the screenshot below, and you can immediately start coding. Now, let’s get to communing with everything !

Core Functions

The first thing we need to do is set up p5’s essential functions, setup() and draw() . Pretty much anything you do in p5 requires these two so let's talk a little bit about what they do.

setup() is called first and defines some of the initial properties of our program. In our case this will be the size of the canvas and the frame rate, the number of times per second our image refreshes. Go ahead and type the following block in.

Quick note for beginners: Lines that begin with a `/` are not code but rather instructions or further explanation called comments. You can include them or not — they’re there to educate :)

Next let’s take a look at draw() . As the name implies this is where we put all of our instructions about what to draw. Right now let's just set a background color so we know everything is working.

Your First Circle

Okay cool. We’ve got ourselves a grey background but out of the void must come something… so let’s draw our first circle.

P5 has a bunch of functions that help you draw shapes as long as you know some basic information about them. To draw an ellipse we just use a function called, wait for it, ellipse() !

Ellipse() takes three parameters , or pieces of information, inside its parentheses: the x coordinate of the shape's center, the y coordinate of the shape's center, and the diameter of the circle.

Let’s add the following line to our draw() function

Looking good but maybe not the most exciting thing in the world. Let’s get our second identical circle on the screen and turn everything into every thing !

The Second Circle

We know the second circle starts one radius away from the center of the first but we need to give our ellipse() function coordinates. So how do we find them?

There are several ways to do this but as we're working in Sacred Geometry might as well use the Pythagorean Theorem and really commit to the aesthetic and our cybermonk forebears.

The Pythagorean Theorem , a² + b² = c², is a way to find the length of the sides of any right triangle. This may not seem like it will help us find coordinates on a circle but imagine a triangle that starts at the center of our circle with a hypotenuse, the c in the theorem, with a length of 100, the radius we used in ellipse()

I said nice things about the protractor earlier but you can see it got less effective the more I used it

Let's arbitrarily decide we want to draw our second circle at a 60º angle from the center of the first. If we can find the length of the other two sides of this triangle all we have to do is tell p5 to draw a circle at them.

First let’s find the length of the opposite side of the triangle which will represent our x coordinate. To get that we'll use the sin equation [you may remember it as the SOH part of SOHCAHTOA)

sin(angle) = opposite/hypotenuse

So in our case we can solve it like this

// We know the angle, 60, and the length of the hypotenuse, 100, so we fill those in

sin(60) = Y / 100

// then we multiple both sides by 100 so we get the Y alone

100 * sin(60) = Y

// which leaves us with our answer ~ 86.6

86.6 = Y

We do the same to find the value of X using the the cosine equation, the CAH part

//We know the angle, 60, and the length of the hypotenuse, 100, so we fill those in

cos(60) = X / 100

// then we multiply both sides by 100 so we get the Xalone

100 * cos(60) = X

// which leaves us with our answer of ~ 50

50 = X

Now that we know the length of both the X and Y sides of the triangle we can find the point of our first circle by adding these values to the center point of our first circle.

// We're adding the values we found to 400 as that's where our first circle is centered

circle2.x = 400 + 50

circle2.y = 400 + 86.6

We don’t even need to do the math in our code as p5 has convenient sin() and cos() functions

and there we go! We’ve got ourselves two circles. If you want to play more with basic trig this site was super helpful and taught me a ton.

Your pen should look like this

The First Round Of Circles

We know the first part of the Flower of Life has six, equally spaced circles around the edge of another and we’ve just learned the formula for finding the coordinates of different parts of a circle’s edge. As a circle has 360º all we need to do is place a circle every 60º (360/6) and we’re good-to-go!

To do that we’re going to use a for loop which just runs a bit of code as many times as we tell it to — check out out:

You’ll notice we deleted the code for our second circle — that’s because it was just a circle at 60º and we’re drawing that here

Things don’t look right, do they? That’s because by default p5 assumes any angle value you’re giving is in radians. We could convert the above formula to radians through a fairly simple formula but, honestly, it’s easier to just tell p5 that we’re working in degrees using the convenient angleMode() function. Go ahead and write

in your setup() function and pow! You've got yourself the right shape!

Or you do assuming it looks like this 😁

Adding some style

So now we’ve got some circles but, honestly, they don’t look great. The Flower of Life is so visually compelling because you see where the circles overlap… and we’ve got here is a mess of white circles. As the guy at my deli says ‘What up, Kahlo’

The HSB spectrum via p5’s color article

The first thing we want to do is to tell p5 we want to work in the Hue Saturation Brightness mode of color, or HSB . P5's site has a great article on color but all you really need to know that hue , what you might think of as the 'color' part of the color, is a visualized as a circle with values between 0 and 360 while brightness and saturation are given values between 0 and 100.

I know that’s a little confusing so if the graph above doesn’t help check out this great color picker by Hunor Marton Borbely I found. It should make it really clear.

HSB is a little unusual and you don't have to use it but I personally find it to be the best color system for animation and generative art. We'll see this in practice later. For now just go ahead and just add colorMode(HSB) to your setup() function.

Annnnnnd…. you’ll notice no change at all :/

That’s because to do that we need to tell p5 how we want to color our ellipses. We’ll do that using the fill() draw() like this:

If HSB or for loops are new to you go ahead and play around with the fill value… maybe even try putting the `fill()` function in the for loop and seeing if you can get a different color each time!

Before we move onto drawing the next round of circles we should take a minute to clean things up and make sure my code is in sync with yours. I’ve done some light refactoring for readability.

Drawing The Rest Of The Circles

So now all that’s left is repeating the above formula with with different radius values, right? That’s what I thought and spent, uh, several days trying to figure out a formula that allowed me to easily do that. Feel free to try on your own but I’m almost certain no such formula exists :/

Our first set of circles can be easily drawn because they’re all one radius away from the center of the initial circle. After our first round, however, the intersections are at totally different distances so a simple formula is out of the question.

So how do we do this? It requires going back to the initial description of this shape: for each circle we draw a new circle at its first clockwise point of intersection. And lucky for us some smart people have already figured out a way for us to find those points.

To do this we’re going to be using Intersection of Two Circles by Paul Bourke (scroll down a bit on the linked page to see it.)

I spent so many hours with this graph that it‘s now my own personal sacred geometry

In conversational terms we’re able to find the intersections point, p3 , as long as we know the radii, r0 and r1 , and centers, p0 and p1 , of the intersecting circles. We do it like this:

Use the Distance Formula to find the straight line distance between p0 and p1

to find the straight line distance between and Use this equation to find the lengths of a and b

and Find the length of h using the the Pythagorean Theorem

using the the Use h to determine the x/y coordinates of the intersection

Let’s try it with our circles:

We know that our first circle is at x = 400, y = 400; we derived that our second is at x = 500, y = 400; and both have a radius of 100.

Because we already know they intersect we can skip the first of Bourke’s steps and immediately find the length of the chord that connects the two centers, d . To do that we'll use the distance formula:

// Distance formula

d = √((x2-x1)^2 + (y2-y1)^2)

// For our example

d = √((500-400)^2 + (400 - 400)^2)

d = √(100^2 + 0^2)

d = √(10000)

d = 100

So d , the line connecting our two circles, is 100px long.

Next we’ll need to figure out how long just segment a is. We can do that using our new d value with the following equation:

// General Formula

a = (r^2 - r^2 + d^2 ) / (2*d) // For our example

a = (100^2 - 100^2 + 100^2) / 2 * 100

a = 100^2 / 2 * 100

a = 10000/200

a = 50

Okay! Now we know the length of a and the length of r so finding h is just the Pythagorean Theorem

//General Formula

h^2 = r^2 - d^2 // For our example

h^2 = 100^2 - 50^2

h = 100 - 50

h = 50

Now that we know this all we need to do is add our a length to our p0 ’s x value and our h length to our p0 ’s y value and we’ve got the coordinates p3 which are x = 450, y = 450.

These images got progressively harder to read, I know

Okay but that’s a lot to do every time and, honestly, it’s kind of confusing. Luckily the formula was converted into js so we can just use it without having to understand too much. Remember — creative coding is about getting it done :D

I’ve updated that function slightly so it’s better suited for us but this is largely just an adaptation of 01AutoMonkey’s work. Go ahead and take the following and just paste it into the bottom of your CodePen

Now when we want a circles intersection we can just call our new getIntersection() function, pass it the circles and radii we’re curious about, and get the values without doing any work :)

Creating Classes

We’ve made some real progress but our current approach in draw() is going to get us into trouble. Right now we’re calculating our ellipses in the for loop and not saving any information about them. See the problem? Our getIntersection() formula requires a reference to ur circles to tell us the intersection point. We can solve this by saving our circles in an array . While we’re at let’s stop calling our shapes circles and move to a more project-appropriate name and call them petals . Go ahead and update the top of your js file to include an allPetals array like this

For more information on arrays check out Daniel Shiffman’s wonderful video

We need something to put in that array, though. So why not make a class for each new petal!

A class is really just a way to create multiple versions of a thing that share certain properties. If you really want to learn more Eloquent JavaScript has a great section on the topic… but for our purposes you can just know it's an easy way to make a bunch of similar things.

Let's make a class for our petals like this and toss it just below those global variables:

Now let’s take advantage of all these cool new features and update our loop so instead of drawings petals with the ellipse() function we're storing information about them and saving them to the allPetals array.

But uhhh… now nothing is drawing? This seems like a lot of typing to have just gotten rid of everything?

That’s because we’re now saving our petals in the allPetals array but we’re not actually doing anything with them :/

Let’s fix that and see what classes can do all at once.

Doing Stuff With Classes

So we’ve got to tell something to use our ellipse() function so the shape is actually drawn… why not do it on that Petal class we just built!

Classes aren’t just data like x , y , or index . They can also contain functions that do stuff with that data. Lets prove it by giving our Petal class the ability to draw itself by calling a function called drawPetal()

So now we can draw our petals but we’re still not actually telling our program to draw them anywhere. Let’s head to our draw() function and do just that:

But how are we going to draw those ellipses? We can do it easily by just iterating through our allPetals array and calling our new drawPetal() method on each thing inside of it. It looks like this

Simply this new code just tells our program to go through each petal in the order they’re in our array and call the drawPetal() function on each of them. With that in our draw() function and we're... back to where we started... That’s just coding sometimes 😓

We’ve just made a bunch of changes so before we move on why not do another quick checkin to make sure we’re in sync:

You with me? Great. Now that we’re through that detour let’s make the most of all this new stuff.

Improving Performance

I’ll admit I’ve been misleading you a bit — maybe you’ve ever noticed. I said this shape is just a pattern of

draw a circle find the first thing that circle intersects draw another circle there repeat

But instead I’ve got us doing a for loop with a bunch of math. and we’re doing a bunch of math that just isn’t necessary. Let’s refactor a bit and use that getIntersection() function.

First thing we should do is move our flower creation process out of the draw() function. That function runs 30 times per second which is great for things that change a lot, like animation, but terrible for things that never do, like math.

Let’s make a function called getPetalPositions() and move all our our current creation stuff into it. It’ll look like this:

This is really the same code we’ve been using — it’s just in a different spot

now go ahead and call getPetalPositions() in setup() so this function only runs once when the program is first started.

That’s better! You may have even noticed a slight speed increase in your browser. Coding is dangerous business 🤕

Using getIntersection()

Now let’s finally use that getIntersection() function we worked so hard on. It’ll look like there’s a lot of new stuff here but really we’re just restating the work we’ve already done

You’ll notice we have an if statement that draws our 0th and 1st petals differently. This is because those are the two that set up all the rules every later petal follows. It makes the code a little bit less graceful than it otherwise might be but it’s really just repurposing work we did earlier and this is just one of those annoying realities of adapting things from the real world into code :)

Drawing More Rounds

So I wish I could tell you we just increase the number in circleCount and call ourselves in harmony with all things but it’s not that easy. They tell me enlightenment never is. 😓

You’ll notice we’ve currently just hardcoded our getIntersection() to always give the intersection between the previous petal and the origin circle. This is true for the first six circle but, if you think back to our animations, petal 6 intersects with petal 1 , not 0 , and it’s at that intersection that we need to draw the new circle.

So, uhhhh, how do we figure that out then? Well it ain’t easy and I spent about a week drawing increasingly wacko graphs on a legal pad and writing serial killer-lite notes like ‘something about 7 is wrong’ and, for reasons I literally could not tell you, the word ‘angle’ in an octagon?