Fractal tree

From Rosetta Code
Revision as of 09:13, 5 May 2010 by rosettacode>Dkf (→‎Tcl: Added implementation)
Task
Fractal tree
You are encouraged to solve this task according to the task description, using any language you may know.

Generate and draw a fractal tree.

To draw a fractal tree is simple:

  1. Draw the trunk
  2. At the end of the trunk, split by some angle and draw two branches
  3. Repeat at the end of each branch until a sufficient level of branching is reached

C

Library: SDL
Library: SGE

<lang c>#include <SDL/SDL.h>

  1. include <SDL/sge.h>
  2. include <stdlib.h>
  3. include <time.h>
  4. include <math.h>
  1. define SIZE 800 // determines size of window
  2. define SCALE 5 // determines how quickly branches shrink (higher value means faster shrinking)
  3. define BRANCHES 14 // number of branches
  4. define ROTATION_SCALE 0.75 // determines how slowly the angle between branches shrinks (higher value means slower shrinking)
  5. define INITIAL_LENGTH 50 // length of first branch

double rand_fl(){

 return (double)rand() / (double)RAND_MAX;

}

void draw_tree(SDL_Surface * surface, double offsetx, double offsety, double directionx, double directiony, double size, double rotation, int depth){

 sge_AALine(surface,
     (int)offsetx, (int)offsety,
     (int)(offsetx + directionx * size), (int)(offsety + directiony * size),
     SDL_MapRGB(surface->format, 0, 0, 0));
 if (depth > 0){
   // draw left branch
   draw_tree(surface,
       offsetx + directionx * size,
       offsety + directiony * size,
       directionx * cos(rotation) + directiony * sin(rotation),
       directionx * -sin(rotation) + directiony * cos(rotation),
       size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE,
       rotation * ROTATION_SCALE,
       depth - 1);
   
   // draw right branch
   draw_tree(surface,
       offsetx + directionx * size,
       offsety + directiony * size,
       directionx * cos(-rotation) + directiony * sin(-rotation),
       directionx * -sin(-rotation) + directiony * cos(-rotation),
       size * rand_fl() / SCALE + size * (SCALE - 1) / SCALE,
       rotation * ROTATION_SCALE,
       depth - 1);
 }

}

void render(SDL_Surface * surface){

 SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255));
 draw_tree(surface,
     surface->w / 2.0,
     surface->h - 10.0,
     0.0, -1.0,
     INITIAL_LENGTH,
     PI / 8,
     BRANCHES);
 SDL_UpdateRect(surface, 0, 0, 0, 0);

}

int main(){

 SDL_Surface * screen;
 SDL_Event evt;
 SDL_Init(SDL_INIT_VIDEO);
 srand((unsigned)time(NULL));
 screen = SDL_SetVideoMode(SIZE, SIZE, 32, SDL_HWSURFACE);
 render(screen);
 while(1){
   if (SDL_PollEvent(&evt)){
     if(evt.type == SDL_QUIT) break;
   }
   SDL_Delay(1);
 }
 SDL_Quit();
 return 0;

}</lang>

Tcl

Library: Tk

<lang tcl>package require Tk

set SIZE 800 set SCALE 4.0 set BRANCHES 14 set ROTATION_SCALE 0.85 set INITIAL_LENGTH 50.0

proc draw_tree {w x y dx dy size theta depth} {

   global SCALE ROTATION_SCALE
   $w create line $x $y [expr {$x + $dx*$size}] [expr {$y + $dy*$size}]
   if {[incr depth -1] >= 0} {

set x [expr {$x + $dx*$size}] set y [expr {$y + $dy*$size}] set ntheta [expr {$theta * $ROTATION_SCALE}]

# Draw left branch draw_tree $w $x $y \ [expr {$dx*cos($theta) + $dy*sin($theta)}] \ [expr {$dy*cos($theta) - $dx*sin($theta)}] \ [expr {$size * (rand() + $SCALE - 1) / $SCALE}] $ntheta $depth # Draw right branch draw_tree $w $x $y \ [expr {$dx*cos(-$theta) + $dy*sin(-$theta)}] \ [expr {$dy*cos(-$theta) - $dx*sin(-$theta)}] \ [expr {$size * (rand() + $SCALE - 1) / $SCALE}] $ntheta $depth

   }

}

pack [canvas .c -width $SIZE -height $SIZE] draw_tree .c [expr {$SIZE/2}] [expr {$SIZE-10}] 0.0 -1.0 $INITIAL_LENGTH \

   [expr {3.1415927 / 8}] $BRANCHES</lang>