Skip to content

Fractals

A fractal is a complex geometric shape that can be split into parts, each of which is a reduced-scale copy of the whole. This property is known as self-similarity.

dragon.gle

dragon.gledragon.gle

dragon.gle
! Example with the dragon curve.
! Author: Francois Tonneau

size 11 8

set color cadetblue lwidth 0.03

dist = 0.1
angle = 0

sub expansion letter$
    if letter$ = "X" then
        return "X+YF+"
    else &
    if letter$ = "Y" then
        return "-FX-Y"
    else
        return letter$
    end if
end sub

sub goforward
    rline dist*cos(angle) dist*sin(angle)
end sub

sub turnleft
    angle = angle + pi/2
end sub

sub turnright
    angle = angle - pi/2
end sub

sub takeaction letter$
    if letter$ = "F" then
        goforward
    else &
    if letter$ = "+" then
        turnleft
    else &
    if letter$ = "-" then
        turnright
    end if
end sub

sub growdragon times
    local stage
    for stage = 1 to times
        local adult$ = ""
        local pos, code$
        for pos = 1 to len(dragon$)
            code$ = seg$(dragon$, pos, pos)
            adult$ = adult$ + expansion(code$)
        next pos
        dragon$ = adult$
    next stage
end sub

sub drawdragon
    local pos, code$
    for pos = 1 to len(dragon$)
        code$ = seg$(dragon$, pos, pos)
        takeaction(code$)
    next pos
end sub

dragon$ = "FX"
growdragon times 12

amove 8 3
drawdragon

koch.gle

koch.glekoch.gle

koch.gle
size 10 10

sub koch x1 y1 x2 y2 d
  if d = 0 then
    amove x1 y1
    aline x2 y2
  else
    local x13 = x1+(x2-x1)/3
    local y13 = y1+(y2-y1)/3
    local x23 = x1+(x2-x1)*2/3
    local y23 = y1+(y2-y1)*2/3
    local x_c = x1+0.5*(x2-x1)+(y2-y1)/sqrt(12)
    local y_c = y1+0.5*(y2-y1)-(x2-x1)/sqrt(12)
    koch x1  y1  x13 y13 d-1
    koch x13 y13 x_c y_c d-1
    koch x_c y_c x23 y23 d-1
    koch x23 y23 x2  y2  d-1
  end if
end sub

sub kochflake wd depth
  local x0 = pagewidth()/2-wd
  local y0 = pageheight()/2-wd*tan(torad(30))
  local x1 = x0+wd
  local y1 = y0+2*wd*sin(torad(60))
  local x2 = x0+wd*2
  koch x0 y0 x2 y0 depth
  koch x1 y1 x0 y0 depth
  koch x2 y0 x1 y1 depth
end sub

for i = 1 to 4
  set color rgb(0,0,i/5)
  kochflake 0.4*(1.8^i) i
next i

lindenmayer.gle

lindenmayer.glelindenmayer.gle

lindenmayer.gle
! Example of Lindenmayer system.
! Author: Francois Tonneau

size 18 15

set color #afbb63 cap round

dist = 0.1

angle = torad(50)

turn = torad(25)

mark = 0

sub expansion letter$
    if letter$ = "F" then
        return "FF"
    else &
    if letter$ = "X" then
        return "F[+X][X]F[+X]-FX"
    else
        return letter$
    end if
end sub

sub goforward
    rline dist*cos(angle) dist*sin(angle)
end sub

sub turnleft
    angle = angle + turn
end sub

sub turnright
    angle = angle - turn
end sub

! We abuse named points to simulate push() and pop() functions on a stack; the
! 'mark' variable is increased or decreased as the depth of the stack varies.

sub takenote
    mark = mark + 1
    local placetag$ = eval("place_" + mark)
    save placetag$
    gsave
    local angletag$ = eval("angle_" + mark)
    amove angle 0
    save angletag$
    grestore
end sub

sub comeback
    local placetag$ = eval("place_" + mark)
    amove ptx(placetag$.cc) pty(placetag$.cc)
    local angletag$ = eval("angle_" + mark)
    angle = ptx(angletag$.cc)
    mark = mark - 1
end sub

sub takeaction letter$
    if letter$ = "F" then
        goforward
    else &
    if letter$ = "+" then
        turnleft
    else &
    if letter$ = "-" then
        turnright
    else &
    if letter$ = "[" then
        takenote
    else &
    if letter$ = "]" then
        comeback
    end if
end sub

sub growplant times
    local stage
    for stage = 1 to times
        local adult$ = ""
        local pos, code$
        for pos = 1 to len(plant$)
            code$ = seg$(plant$, pos, pos)
            adult$ = adult$ + expansion(code$)
        next pos
        plant$ = adult$
    next stage
end sub

sub drawplant
    local pos, code$
    for pos = 1 to len(plant$)
        code$ = seg$(plant$, pos, pos)
        takeaction(code$)
    next pos
end sub

plant$ = "X"
growplant times 6

amove 1 1
drawplant

mandelbrot.gle

mandelbrot.glemandelbrot.gle mandelbrot.zip zip file contains all files for this figure.

mandelbrot.gle
! Example of Mandelbrot set.
! Author: Francois Tonneau

size 18 16

! ------------------------------
! Set plot resolution.
! ------------------------------

resolution = 1250           ! Use a value < 1000 if plotting takes too long!

itermax = 30
worth = 4

! ------------------------------
! Cover background with default hue.
! ------------------------------

! We overflow borders by 2 cm to cover possible white margins.
amove -1 -1
box pagewidth()+2 pageheight()+2 fill rgb255(38, 44, 64)

! ------------------------------
! Define plot parameters.
! ------------------------------

xmax = pagewidth()
ymax = pageheight()

dx = xmax/resolution
dy = ymax/resolution

ulow  = -2.20
uhigh =  0.80

vlow  = -1.45
vhigh =  1.45

uspan = uhigh - ulow
vspan = vhigh - vlow

declare sub spot u0 v0
declare sub color iter
declare sub paint hue$

! ------------------------------
! Cover the plot surface.
! ------------------------------

print "This may take a while..."

for x = 0 to xmax step dx
    for y = 0 to ymax step dy
        amove x y
        u0 = (x/xmax * uspan) + ulow
        v0 = (y/ymax * vspan) + vlow
        spot(u0, v0)
    next y
next x

print "Preparing output..."

! ------------------------------
! Implement coloring utilities.
! ------------------------------

sub spot u0 v0
    local u = 0.0
    local v = 0.0
    local iter = 0
    local utemp
    while ((u*u + v*v <= 4) and (iter < itermax))
        utemp = u*u - v*v + u0
        v = 2*u*v + v0
        u = utemp
        iter = iter + 1
    next
    if iter = itermax then
        paint black
    else
        ! To speed up the code, do nothing when iter < worth, leaving the
        ! default background show through.
        if iter >= worth then paint color(iter)
    end if
end sub

sub color iter
    local t = (iter - worth)/(itermax - worth)
    !
    local r0 = 45
    local g0 = 52
    local b0 = 72
    !
    local r1 = 190
    local g1 = 65
    local b1 = 50
    !
    local r2 = 220
    local g2 = 220
    local b2 = 180
    !
    local r, g, b
    if t <= 0.50 then
        r = (1 - t) * r0 + t * r1
        g = (1 - t) * g0 + t * g1
        b = (1 - t) * b0 + t * b1
    else
        r = r2
        g = g2
        b = b2
    end if
    return rgb255(r, g, b)
end sub

sub paint hue$
    set color hue$
    box dx dy fill hue$
end sub

pythagoras.gle

pythagoras.glepythagoras.gle

pythagoras.gle
! Example of Pythagoras tree.
! Author: Francois Tonneau

! This is a slight modification of the Pythagoras tree example available on GLE
! 4.2.5. The idea for edge coloring comes from Timo Bingmann:

! https://panthema.net/2013/0627-TikZ-Pythagoras-Tree/

size 32 22

small = 3
medium = 4
large = sqrt(small^2 + medium^2)

set lwidth 0.1

sub growtree times
    local rchan = rnd(0.5)
    local gchan = rnd(0.8)
    local bchan = rnd(0.6)
    set color rgb(rchan, gchan, bchan)
    box large large
    if times > 0 then
        begin translate 0 large
            begin rotate todeg(acos(medium/large))
                begin scale medium/large medium/large
                    growtree times-1
                end scale
            end rotate
        end translate
        begin translate large large
            begin rotate todeg(-acos(small/large))
                begin scale small/large small/large
                    begin translate -large 0
                        growtree times-1
                    end translate
                end scale
            end rotate
        end translate
    end if
end sub

begin translate 16 0
    growtree times 11
end translate

pythagorean.gle

pythagorean.glepythagorean.gle

pythagorean.gle
size 32 22

a = 3; b = 4; c = sqrt(a^2+b^2)

sub pythagorean n
   local red   = (34+n*92)/(n+1)
   local green = (139+n*64)/(n+1)
   local blue  = (34+n*51)/(n+1)
   box c c fill rgb255(red,green,blue)
   if n = 0 then return
   begin translate c c
      begin rotate todeg(-acos(a/c))
         begin scale a/c a/c
            begin translate -c 0
               pythagorean n-1
            end translate
         end scale
      end rotate
   end translate
   begin translate 0 c
      begin rotate todeg(acos(b/c))
         begin scale b/c b/c
            pythagorean n-1
         end scale
      end rotate
   end translate
end sub

begin translate 16 0
   pythagorean 10
end translate

recursiontree.gle

recursiontree.glerecursiontree.gle

recursiontree.gle
size 8 8

! Based on "C" code by Lode Vandevenne
! http://www.student.kuleuven.ac.be/~m0216922/CG/

set cap round

maxRecursions = 8  ! never make this too big or it'll take forever
angle = 0.2 * pi   ! angle in radians
shrink = 1.8       ! relative size of new branches

! Now follows the recursion function, a function that only draws a single line and calls
! itself a few times, but results in a huge tree!

sub recursion posX posY dirX dirY bsize n

! Here's the part that draws the line. The line is drawn from (posX, posY) to (posX+dirX, 
! posY+dirY). So the position and direction of the line is given as a vector, instead of 
! a begin point, an angle and a size, because direction vectors are much easier to work 
! with. The size parameter itself isn't used to draw the line directly, it's only needed 
! later to calculate the direction vector of the next branches. If the maximum number of 
! recursions is reached, the function returns immediately after drawing the line, without 
! calling itself again.

    local posX2 = posX + bsize * dirX
    local posY2 = posY + bsize * dirY

    if n > 5 then
        set color forestgreen
    else
        set color rgb255(128, 96, 64)
    end if
    set lwidth 0.2/(n+1)+0.005
    amove posX pageheight()-posY
    aline posX2 pageheight()-posY2

    if n < maxRecursions then

! And in the second part of the function, the new position of the new branches is
! calculated as the endpoint of the previous branch, and the new direction vector for
! the new branches is calculated out of the size and current direction of the current
! branch. The new branches are rotated with the angle, the sine and cosine formulas are
! actually the calculation of the rotation matrix. Then the recursion function is called
! again with the new branch as its parameters. This is done twice: once for a branch
! rotated to the right, and then for a branch rotated to the left.

       dirX2 = cos(angle) * dirX + sin(angle) * dirY
       dirY2 = -sin(angle) * dirX + cos(angle) * dirY
       recursion posX2 posY2 dirX2 dirY2 bsize/shrink n+1

       dirX2 = cos(-angle) * dirX + sin(-angle) * dirY
       dirY2 = -sin(-angle) * dirX + cos(-angle) * dirY
       recursion posX2 posY2 dirX2 dirY2 bsize/shrink n+1
   end if
end sub

! The main program doesn't do much more than calling the recursive function.
! The value "h/2.3" in the parameters of the recursion function is the initial 
! length of the first branch (the stem). The coordinates are the begin
! point and direction vector of the first branch.

w = pagewidth()
h = pageheight()

recursion w/2 h-0.1 0 -1 h/2.3 0

sierpinski.gle

sierpinski.glesierpinski.gle

sierpinski.gle
size 10 8.75

wd = 4.75; ad = 0.2
set lwidth 0.01 cap round

sub a_line x0 y0 x1 y1
  amove x0 y0
  aline x1 y1
end sub

sub sierpinski x_left x_right y_bot y_top d
  if d > 0 then
    set color rgb(1/(d+ad),0,0)
    local y_c = (y_bot+y_top)/2     ! middle y coordinate
    local x_c = (x_left+x_right)/2  ! middle x coordinate
    local x_1 = (x_left+x_c)/2      ! 1/3 x coordinate
    local x_2 = (x_c+x_right)/2     ! 2/3 x coordinate
    a_line x_c y_bot x_1 y_c
    a_line x_1 y_c   x_2 y_c
    a_line x_2 y_c   x_c y_bot
    sierpinski x_left x_c     y_bot y_c   d-1 ! lower left triangle
    sierpinski x_c    x_right y_bot y_c   d-1 ! lower right triangle
    sierpinski x_1    x_2     y_c   y_top d-1 ! top triangle
  end if
end sub

x_left  = pagewidth()/2 - wd
y_bot   = pageheight()/2 - wd*sin(torad(60))
y_top   = y_bot + 2*wd*sin(torad(60))
x_right = x_left + wd*2
x_c     = x_left + wd

a_line x_left  y_bot x_c     y_top
a_line x_c     y_top x_right y_bot
a_line x_right y_bot x_left  y_bot

sierpinski x_left x_right y_bot y_top 7

tree.gle

tree.gletree.gle

tree.gle
! Example of tree-like fractal.
! Author: Francois Tonneau

! This is a slight modification of the recursion-tree example available on GLE
! 4.2.5. We use the GLE rotation command instead of computing coordinates
! manually.

size 8 8

set lwidth 0.03 cap round

root = 3

maxiters = 10
maxwhite = maxiters + 3

turn = 20
shrinkage = 0.56

sub fork trunk iteration
    if iteration <= maxiters then
        set color iteration/maxwhite
        rline 0 trunk
        local branch = trunk * shrinkage
        begin rotate turn
            fork branch iteration+1
        end rotate
        begin rotate -turn
            fork branch iteration+1
        end rotate
    else
        rmove 0 0.1+rnd(0.3)
        circle 0.03 fill rosybrown
    end if
end sub

amove pagewidth()/2 0

fork root iteration 1