Pythagoras Tree

I started out looking into a variety of different tree fractals, but one of the earliest classes of tree fractal I found has kept me pretty busy. So today I’m going to go over the Pythagoras tree and some interesting 3d extensions that you can make to the basic fractal.

The traditional Pythagoras tree uses a sequence of squares to build up a simple fractal. The first square is placed at the base, and the next two are placed on either side of a symmetrical right angled triangle. The basic wooscript for this is pretty simple so here comes iteration 1 of a Pythagoras tree.

rule main {
adjust(y, +1)
adjust(scale, *0.707106781186, *0.707106781186, *0.707106781186)
push()
adjust(rz, -45)
adjust(y, +0.5)
call(box)
pop()
adjust(rz, +45)
adjust(y, +0.5)
call(box)
}
// Wooscript 2.1 (current syntax)
box
pos.y += 1
scale *= vec(0.707106781186,0.707106781186,0.707106781186)
{ rz -= 45 pos.y += 0.5 box }
{ rz += 45 pos.y += 0.5 box }
single instance of the pythagoras fractal

Single instance of the pythagoras fractal

What makes this a fractal, is that you can continue to apply this pattern to each of the sub-squares that have been added. The script needs to be changed a bit so it calls itself recursively. To do this the main pattern is moved into a rule called “r1″ and this is called instead of the box primitive. To control the iterations of the fractal you just adjust the number of recursions you want the system to allow using adjust(recursions, =10).

So here goes with the fractal going on one more iteration, and then two more iterations.

rule main {
adjust(recursions, =2)
call (r1)
}

rule r1 {
call(box)
adjust(y, +1)
adjust(scale, *0.707106781186, *0.707106781186, *0.707106781186)
push()
adjust(rz, -45)
adjust(y, +0.5)
call(r1)
pop()
adjust(rz, +45)
adjust(y, +0.5)
call(r1)
}
// Wooscript 2.1 (current syntax)
rule main {
recursions = 2
r1
}

rule r1 {
box
pos.y += 1
scale *= vec(0.707106781186,0.707106781186,0.707106781186)
{ rz -= 45 pos.y += 0.5 r1 }
{ rz += 45 pos.y += 0.5 r1 }
}
Pythagoras tree fractal iteration 2

2nd iteration of the Pythagoras tree

3rd iteration of the Pythagoras tree

Pythagoras tree iteration 3

And finally lets just whack the iterations right up and have a look at a whole row of Pythagoras trees at increasing iteration counts.

many fractal trees

12 Pythagoras trees

This is all a lot of fun so far, but these trees do all look a bit too regular for me. A standard extension to the Pythagoras tree is to swap the 45 degree angles on the corners so that we’re building trees using a different right angled triangle. It seems fitting to use the famous 3, 4, 5 sided triangle to build a tree instead of the current symmetrical building block.

Let’s take a look at iteration 1 of the 3,4,5 fractal.

rule r1 {
call(box)
adjust(y, +1)
adjust(diff, *1, *0.88, *0.88)
push()
adjust(scale, *0.6, *0.6, *0.6)
adjust(rz, -53.13)
adjust(y, +0.625)
call(r1)
pop()
adjust(scale, *0.8, *0.8, *0.8)
adjust(rz, +36.87)
adjust(y, +0.375)
call(r1)
}
// Wooscript 2.1 (current syntax)
rule r1 {
box
pos.y += 1
{ scale *= vec(0.6,0.6,0.6) rz -= 53.13 pos.y += 0.625 r1 }
{ scale *= vec(0.8,0.8,0.8) rz += 36.87 pos.y += 0.375 r1 }
}
first iteration of asymmetric Pythagoras tree

3,4,5 Pythagoras tree, iteration 1

And once we iterate that a few times we get quite a pretty little fractal.

Full asymmetric pythagoras tree

Asymmetric Pythagoras tree (3,4,5)

This is definitely a bit cuter than the bog standard fractal, but it’s still not making much use of the 3d side of things. With a number of fractal trees I’ve added a 30 degree twist on each iteration, but with this fractal it’d break that simple pythagoras triangle which the fractal is named after, so instead of rotating the fractal step, I’m going to split the cube into two, and rotate halfway along the cube.

That gives you an interesting fractal which makes much better use of the 3d nature of the renderer.

The code does get a little bit more complex though…

rule r1 {
adjust(scaley, *0.5)
call(box)
adjust(scaley, *2)
adjust(y, +0.5)
adjust(ry, +30)
adjust(scaley, *0.5)
call(box)
adjust(scaley, *2)
adjust(y, +0.5)
adjust(diff, *1, *0.88, *0.88)
push()
adjust(scale, *0.6, *0.6, *0.6)
adjust(rz, -53.13)
adjust(y, +0.625)
call(r1)
pop()
adjust(scale, *0.8, *0.8, *0.8)
adjust(rz, +36.87)
adjust(y, +0.375)
call(r1)
}
// Wooscript 2.1 (current syntax)
rule r1 {
{ scale.y *= 0.5 box }
pos.y += 0.5 ry += 30
{ scale.y *= 0.5 box }
pos.y += 0.5
{ scale *= vec(0.6,0.6,0.6) rz -= 53.13 pos.y += 0.625 r1 }
{ scale *= vec(0.8,0.8,0.8) rz += 36.87 pos.y += 0.375 r1 }
}
First iteration of a 3d pythagoras tree

Pythagoras tree with a 3d twist, iteration 1

Pythagoras tree, 3d, iteration 10

Pythagoras tree with a 3d twist, iteration 10

So that just leaves me to do a few feature renders to show off the fractal.

First up another angle with ambient occlusion turned on, this shows a bit more colour gradient in the shadows.

twisted pythag

Pythagoras tree with a twist

And finally a darker render with full path tracing enabled.

sphere light, pathtracer, pythagoras tree

Pythagoras tree in the dark

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam Protection *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>