Updated 2018-04-29 07:20:26 by dbohdan

GS - Iterated Function Systems (IFS) is a self-similar model introduced by Michael Barnsley to generate fractal images like fern leaf or other aesthetic natural shapes. Here is a script to draw some of them like Serpienski gasket or Von Koch curve.

For more details about the theory behind IFS, see:

  • Michael F. Barnsley, Fractals everywhere, Academic Press, 1993.
  • H.-O. Peitgen, H. Juergens, D. Saupe, Chaos and Fractals: New Frontiers of Science, Springer-Verlag, 1992, Chapter 5.
 # ifs.tcl  
 
 package require Tk
 
 proc IFSMain { wd ht } {
 
  set w .ifs
  catch {destroy $w}
  toplevel $w
  wm withdraw .
  wm title $w "Iterated Function System"
  wm iconname $w "ifs"
  wm geometry $w +100+10
 
  set i 0
 
 # Parameters
 # 1st group: name of the fractal
 # 2nd group: iterations, scale_x, scale_y, translation_x, translation_y
 # 3rd group: coefficients for the affine transformation:
 #  x = a(i)x + b(i)y + e(i)
 #  y = c(i)x + d(i)y + f(i)
 
  set tab {
     {{fern}  {24000 520 470 70 420} \
              {0 0 0 .172 .496 -.091   0.076 .312 -.257 .204 .494 .133 \
              0.821 -.028 .03 .845 .088 .176   -.024 -.356 -.323 .074 .47 .26}}
     {{wind}  {32000 80 140 30 440} \
              {.3333 0 0 .3333 0 0   .1666 -.2886 .2886 .1666 3.3333 0 \
              .1666 .2886 -.2886 .1666 5 2.8867   .3333 0 0 .3333 .6666 0}}
     {{fir}   {32000 460 480 110 470} \
              {.65 -.013 .013 .65 .175 0   .65 -.026 .026 .65 .165 .325  \
              0.318 -.318 .318 .318 .2 0   -.1666 .2886 .2886 .1666 .6666 0}}
     {{tree1} {44000 1000 1000 300 480} \
              {0 0 0 .5 0 0   0.42 -.42 .42 .42 0 .2 \
              0.42 .42 -.42 .42 0 .2   0.1 0 0 .1 0 .2}}
     {{vkoch} {10000 580 580 10 300} \
              {0.3333 0 0 .3333 0 0   0.3333 0 0 .3333 .6666 0 \
              0.1666 -.2886 .2886 .1666 .3333 0   -.1666 .2886 .28867 .1666 .6666 0}}
     {{mayan} {19000 40 40 300 440} \
              {.5  0 0 .5 -2.5634 -.000003   .5 0 0 .5 2.4365 -.000003 \
              .0 -.5 .5 0 4.8730  7.5635}}
     {{carpet1} {28000 420 400 90 440} \
              {.333 0 0 .333 .333 .666   0 .333 1 0 .666 0   0 -.333 1 0 .333 0}}
     {{carpet2} {19000 40 40 300 450} \
              {0 -.5  .5 0 -1.7323 3.3661   .5 0 0 .5 -.0278 5.0148 \
              0  .5 -.5 0 1.6208 3.3104}}
     {{triangle} {22000 180 180 130 430} \
              {.5 0 0 .5 0 0   .5 0 0 .5        0 1   .5 0 0 .5 1 1}}
     {{xmas}  {22000 400 400 100 450} \
              {0 -.5 .5 0 .5 0   0 .5 -.5 0 .5 .5   .5 0 0 .5 .25 .5}}
     {{storm} {12000 400 400 90 430} \
              {0 .577 -.577 0 .0951 .5893   0 .577 -.577 0 .4413 .7893 \
              0 .577 -.577 0 .0952 .9893}}
     {{twig}  {19000 600 600 30 530} \
              {.387 .43 .43 -.387 .256 .522   .441 -.091 -.009 -.322 .4219 .5059 \
              -.468 .2 -.113 .15 .4 .4}}
     {{coral} {28000 43 43 300 450} \
              {.3076 -.5314 -.4615 -.2937 5.402 8.6551   .3076 -.077 .1538 -.4475 -1.2952 4.153 \
              0 .5454 .6923 -.1958 -4.8936 7.2697}}
     {{spiral} {44000 38 38 300 440} \
              {.7878 -.4242 .2424 .8598 1.7586 1.408   -.1212 .2575 .1515 .053 -6.7216 1.3772 \
              .1818 -.1363 .091 .1818 6.0861 1.568}}
     {{dragon} {34000 40 40 300 440} \
              {.824 .2814 -.2123  .8641 -1.8823 -.1106 \
              .0882 .521 -.4638 -.3777 .7853 8.0957}}
     {{crystal} {36000 60 44 290 470} \
              {.6969 -.481 -.394 -.6628 2.147 10.3102 \
              .091 -.4431 .5151 -.0946 4.2865 2.9257}}
     {{snow}  {32000 500 500 40 520} \
              {.255 0 0 .255 .3726 .6714   .255 0 0 .255 .1146 .2232 \
              .255 0 0 .255 .6306 .2232   .37 -.642 .642 .37 .6356 -.0061}}
     {{zigzag} {42000 40 40 310 450} \
              {-.6324 -.6148 -.5453 .6592 3.8408 1.2823 \
              -.0361 .4444 .2101 .037 2.071 8.3305}}
     {{firework} {28000 40 40 300 450} \
              {.7454 -.4591 .406 .8871 1.4602 .691 \
              -.4242 -.0651 -.1757 -.2181 3.8095 6.7414}}
     {{fish}  {22000 40 34 300 420} \
              {.3077 0 0 .2941 4.1191 1.6042   .1923 -.2058 .6538 .0882 -0.6888 5.979 \
              .1923 .2058 -.6538 .0882 .6685 5.9625   .3077 0 0 .2941 -4.1365 1.6042 \
              .3846 0 0 -.2941 -.0077 2.9411}}
     {{shield} {22000 400 400 100 460} \
              {.382 0 0 .382 .3072 .619   .382 0 0 .382 .6033 .4044 \
              .382 0 0 .382 .0139 .4044   .382 0 0 .382 .1253 0.595 \
              .382 0 0 .382 .492 .0595}} 
     {{tree2} {24000 410 410 80 430} \
              {.195 -.488 .344 .443 .4431 .2452   .462 .414 -.252 .361 .2511 .5692 \
              -.058 -.07 .453 -.111 .5976 .097   -.035 .7 -.469 -.022 .4884 0.507 \
              -.637 0 0 .501 .8562 .2513}} 
  }
 
  pack [canvas $w.c -width $wd -height $ht -bg white]
 
  set f1 [frame $w.f1 -relief sunken -borderwidth 2]
  pack $f1 -fill x
  set f2 [frame $w.f2 -relief sunken -borderwidth 2]
  pack $f2 -fill x
 
  set n [expr {[llength $tab]/2}]
  set f $f1
 
  foreach l $tab {
   set s [lindex [lindex $tab $i] 0]
   button $f.b$i -text $s -width 5 \
    -bg blue -fg white \
    -command "IFS $w $s [list [lindex [lindex $tab $i] 1]] [list [lindex [lindex $tab $i] 2]]"
   incr i
   if {$i >= $n} then {set f $f2}
  }
  eval pack [winfo children $f1] -side left
  eval pack [winfo children $f2] -side left
 
  set f3 [frame $w.f3 -relief sunken -borderwidth 2]
  pack $f3 -fill x
  button $f3.bq -text Quit -width 5 -command exit 
  label $f3.lb -text " " -font system
  eval pack [winfo children $f3] -side left
 }
 
 proc IFS { w s sparam fparam } {
 
  array set m {}
  set x0 0
  set y0 0
 
  $w.c delete all
  [lindex [winfo children $w.f3] 0] configure -state disabled
  [lindex [winfo children $w.f3] 1] configure -text "  RUNNING: $s"
  wm title $w "Iterated Function System ($s)"
 
  set pix [image create photo]
  set cmap #000000
 
  $w.c create image 0 0 -anchor nw -image $pix
 
  foreach {maxit mx my tx ty} $sparam {}
  set j 0
  foreach {m1 m2 m3 m4 m5 m6} $fparam {
         incr j
         set m($j,1) $m1
         set m($j,2) $m2
         set m($j,3) $m3
         set m($j,4) $m4
         set m($j,5) $m5
         set m($j,6) $m6
  }
 
  for {set i 1} {$i <= $maxit} {incr i} { 
 
     set k [expr {int($j*rand() - 0.0001) + 1}]
 
     set x [expr {$m($k,1)*$x0 + $m($k,2)*$y0 + $m($k,5)}]
     set y [expr {$m($k,3)*$x0 + $m($k,4)*$y0 + $m($k,6)}]
 
     set x0 $x
     set y0 $y
 
     if {$maxit > 10} then {
       set X [expr {round([expr $mx*$x + $tx])}]
       set Y [expr {round([expr -$my*$y + $ty])}]
       $pix put $cmap -to $X $Y
       update
     }
  }
 
  [lindex [winfo children $w.f3] 0] configure -state normal
  [lindex [winfo children $w.f3] 1] configure -text "  DONE: $s"
 }
 
 IFSMain 600 480 ; # Screen size (x,y)