draw recursive tree with lines and circles

Repeat: RECURSIVE TREE

Within the domain of image making, recursion involves drawing a group of related, self-similar shapes. Treelike forms are a clear example — each branch spawns many smaller branches, which in turn spawn more branches. As a simple example, draw the letter Y on a sheet of paper. Now draw two smaller Ys sprouting from the top of each branch. After repeating this process a few times, the number of Ys drawn at each step has increased from 1 to 2, to 4, 8, 16, 32, 64, and so on.

While this type of tree makes a predictable shape, adding a small amount of randomness to the line lengths and number of branches can yield more organic forms. These treelike forms were created by drawing one circle at a time. Starting at the base, each circle was slightly rotated and scaled relative to the one before it. At random intervals during the growth, two smaller branches sprout to form new growths. This continues until the circles reach the minimum size set by the user.

/**  * Repeat: Recursive Tree  * from Form+Code in Design, Art, and Architecture  * by Casey Reas, Chandler McWilliams, and LUST  * Princeton Architectural Press, 2010  * ISBN 9781568989372  *  * This program is based on Context Free program  * "Foggy Tree by Chris Coyne:  * http://www.contextfreeart.org/gallery/view.php?id=4  *  * This code was written for Processing 1.2+  * Get Processing at http://www.processing.org/download  */ float dotSize = 9; float angleOffsetA; float angleOffsetB; void setup () {size(900, 600);noStroke();fill(0);smooth();frameRate(1); // Redraw the tree once a second angleOffsetA =radians(1.5); // Convert 1.5 degrees to radians angleOffsetB =radians(50); // Convert 50 degrees to radians } void draw () {background(255); // White backgroundtranslate(width/2, height); // Move to the center, bottom of the screen seed1(dotSize,radians(270), 0, 0); // Start the tree } void seed1(float dotSize, float angle, float x, float y) {if (dotSize > 1.0) {// Create a random numbers between 0 and 1float r = random(0, 1.0);// 98% chance this will happenif (r > 0.02) {ellipse(x, y, dotSize, dotSize);float newx = x + cos(angle) * dotSize;float newy = y + sin(angle) * dotSize;       seed1(dotSize * 0.99, angle - angleOffsetA, newx, newy);        }// 02% chance this will happenelse {ellipse(x, y, dotSize, dotSize);float newx = x + cos(angle);float newy = y + sin(angle);       seed2(dotSize * 0.99, angle + angleOffsetA, newx, newy);       seed1(dotSize * 0.60, angle + angleOffsetB, newx, newy);       seed2(dotSize * 0.50, angle - angleOffsetB, newx, newy);     }    } } void seed2(float dotSize, float angle, float x, float y) {if (dotSize > 1.0) {// Create a random numbers between 0 and 1float r = random(0, 1.0);// 95% chance this will happenif (r > 0.05) {ellipse(x, y, dotSize, dotSize);float newx = x + cos(angle) * dotSize;float newy = y + sin(angle) * dotSize;       seed2(dotSize * 0.99, angle + angleOffsetA, newx, newy);     }// 05% chance this will happenelse {ellipse(x, y, dotSize, dotSize);float newx = x + cos(angle);float newy = y + sin(angle);       seed1(dotSize * 0.99, angle + angleOffsetA, newx, newy);         seed2(dotSize * 0.60, angle + angleOffsetB, newx, newy);       seed1(dotSize * 0.50, angle - angleOffsetB, newx, newy);     }   } }

Contributed Examples

  • Go

                                      package                  main                  import                  (                                      "github.com/ajstarks/svgo"                                                        "fmt"                                                        "rand"                                                        "math"                                                        "time"                                                        "os"                                    )                  var                  (                  width  =                  900                  height =                  600                  canvas = svg.                    New(os.Stdout) )                  var                  (                  angleOffsetA =                                                            radians(                  1.5)   angleOffsetB =                                                            radians(                  50)  )                                      func                    radians(angle float64)                    float64                                        {                      return                      (angle * math.Pi)                      /                      180                      }                                                        func                    seed1(dotSize, angle, x, y float64)                    {                      if                      dotSize >                      1.0                      {                                                       r                            :=                                                                          rand.                          Float64()                               if                        (r >                          0.02)                        {                                                                                                              dot(x, y, dotSize)                                                      newx                              :=                                                                                x + math.                            Cos(angle) * dotSize                                                      newy                              :=                                                                                y + math.                            Sin(angle) * dotSize                                                                                                              seed1(dotSize * .99, angle - angleOffsetA, newx, newy)       }                        else                        {                                                                                                              dot(x, y, dotSize)                                                      newx                              :=                                                                                x + math.                            Cos(angle)                                                      newy                              :=                                                                                y + math.                            Sin(angle)                                                                                                              seed2(dotSize * .99, angle + angleOffsetA, newx, newy)                                                                                                              seed1(dotSize * .60, angle + angleOffsetB, newx, newy)                                                                                                              seed2(dotSize * .5, angle - angleOffsetB, newx, newy)    }                        }                      }                                                        func                    seed2(dotSize, angle, x, y float64)                    {                      if                      dotSize >                      1.0                      {                                                      r                            :=                                                                          rand.                          Float64()                            if                        (r >                          0.05)                        {                                                                                                              dot(x, y, dotSize)                                                      newx                              :=                                                                                x + math.                            Cos(angle) * dotSize                                                      newy                              :=                                                                                y + math.                            Sin(angle) * dotSize                                                                                                              seed2(dotSize * .99, angle + angleOffsetA, newx, newy)    }                        else                        {                                                                                                              dot(x, y, dotSize)                                                      newx                              :=                                                                                x + math.                            Cos(angle)                                                      newy                              :=                                                                                y + math.                            Sin(angle)                                                                                                              seed1(dotSize * .99, angle + angleOffsetA, newx, newy)                                                                                                              seed2(dotSize * .60, angle + angleOffsetB, newx, newy)                                                                                                              seed1(dotSize * .50, angle - angleOffsetB, newx, newy)    }                        }                      }                                                        func                    dot(x, y, d float64)                    {   canvas.                        Circle(                      int                      (x),                                                                        int(y),                                                                        round(d/2))   }                                                        func                    round(x float64)                    int                                        {                                              i                          :=                                                                                                                                            int(x)                                              f                          :=                                                                    x -                                                                        float64(i)                      if                      f >                      0.5                      {                        return                        i +                        1                        }                      return                      i }                                                        func                    main()                    {   rand.                        Seed(time.                        Nanoseconds() %                      1e9)   canvas.                        Start(width, height)   canvas.                        Gstyle(                                              "fill:black;fill-opacity:0.5"                      )   canvas.                        Gtransform(fmt.                        Sprintf(                                              "translate(%d,%d)"                      ,width/2,height))                                                                                              seed1(                      12,                                                                        radians(                      270),                      0,                      0)   canvas.                        Gend()   canvas.                        Gend()   canvas.                        End() }                                                
  • ActionScript

                                             package                {                import                  flash.display.Sprite                  ;                                import                  flash.events.Event                  ;                                import                  flash.events.MouseEvent                  ;                                import                  flash.text.TextField                  ;                                import                  flash.text.TextFieldAutoSize                  ;                                                  [                  SWF                (width                =                '900',                height                =                '600',                backgroundColor                =                '#ffffff', framerate=                1)]                public                  class                  Repeat_RecursiveTree                  extends                  Sprite                                {                private                var                dotSize:                Number                =                9                ;                private                var                angleOffsetA:                Number                ;                private                var                angleOffsetB:                Number                ;                private                var                instructions:                TextField                ;                public                  function                  Repeat_RecursiveTree                ():                void                {                if                (stage)                init();                else                addEventListener(Event                .ADDED_TO_STAGE,                init);                }                private                  function                  init                (e:                Event                =                null):                void                {                removeEventListener(Event                .ADDED_TO_STAGE,                init);                             instructions                =                new                TextField();                instructions.                text                =                "Click to generate a Tree, Double-Click to clear the stage."                ;                instructions.                autoSize                =                TextFieldAutoSize                .LEFT                ;                addChild(instructions);                angleOffsetA                =                degToRad(1                .5);                angleOffsetB                =                degToRad(50);                stage                .                doubleClickEnabled                =                true                ;                stage                .                addEventListener(MouseEvent                .CLICK, generateThree);                stage                .                addEventListener(MouseEvent                .DOUBLE_CLICK, clearStage);                }                private                  function                  clearStage                (e:                MouseEvent):                void                {                this                .                graphics                .                clear();                }                private                  function                  generateThree                (e:                MouseEvent):                void                {                this                .                graphics                .                beginFill(0x000000);                seed1(dotSize, degToRad(270), mouseX, mouseY);                }                private                  function                  seed1                (dotSize:                Number, angle:                Number, xpos:                Number, ypos:                Number):                void                {                var                newX:                Number                ;                var                newY:                Number                ;                if                (dotSize>                1)        {                         var                r:                Number                =                Math                .                random();                                if                (r>                0                .02)          {                this                .                graphics                .                drawEllipse(xpos, ypos, dotSize, dotSize);                newX                =                xpos                +                Math                .                cos(angle)                *                dotSize;                newY                =                ypos                +                Math                .                sin(angle)                *                dotSize;                seed1(dotSize                *                0                .99, angle-                angleOffsetA, newX, newY);                }                         else                {                this                .                graphics                .                drawEllipse(xpos, ypos, dotSize, dotSize);                newX                =                xpos                +                Math                .                cos(angle);                newY                =                ypos                +                Math                .                sin(angle);                seed2(dotSize                *                0                .99, angle                +                angleOffsetA, newX, newY);                seed1(dotSize                *                0                .60, angle                +                angleOffsetB, newX, newY);                seed2(dotSize                *                0                .50, angle-angleOffsetB, newX, newY);                }       }     }                private                  function                  seed2                (dotSize:                Number, angle:                Number, xpos:                Number, ypos:                Number):                void                {                var                newX:                Number                ;                var                newY:                Number                ;                if                (dotSize>                1)        {                         var                r:                Number                =                Math                .                random();                                if                (r>                0                .05)          {                this                .                graphics                .                drawEllipse(xpos, ypos, dotSize, dotSize);                newX                =                xpos                +                Math                .                cos(angle)                *                dotSize;                newY                =                ypos                +                Math                .                sin(angle)                *                dotSize;                seed2(dotSize                *                0                .99, angle+                angleOffsetA, newX, newY);                }                         else                {                this                .                graphics                .                drawEllipse(xpos, ypos, dotSize, dotSize);                newX                =                xpos                +                Math                .                cos(angle);                newY                =                ypos                +                Math                .                sin(angle);                seed1(dotSize                *                0                .99, angle                +                angleOffsetA, newX, newY);                seed2(dotSize                *                0                .60, angle                +                angleOffsetB, newX, newY);                seed1(dotSize                *                0                .50, angle-angleOffsetB, newX, newY);                }       }     }                private                  function                  degToRad                (deg:                Number):                Number                {                return                deg                *                (Math                .PI                /                180);                }        }    }
  • OpenFrameworks

                                                #include                  "ofMain.h"                class                testApp :                public                ofBaseApp{                public:                void                setup();                void                draw();                void                seed1(float                dotSize,                float                angle,                float                x,                float                y);                void                seed2(float                dotSize,                float                angle,                float                x,                float                y);                float                dotSize, angleOffsetA, angleOffsetB; };                     #include                  "Repeat_RecursiveTree.h"                                void                testApp::setup(){   ofSetFrameRate(1);   ofBackground(255,                255,                255);   ofEnableSmoothing();      dotSize =                9.0f;   angleOffsetA = ofDegToRad(1.5);   angleOffsetB = ofDegToRad(50); }                  void                testApp::draw(){   ofBackground(255,                255,                255);   ofSetColor(0,                0,                0);   ofTranslate(ofGetWidth()/2, ofGetHeight(),                0);   seed1(dotSize, ofDegToRad(270),                0,                0);  }                  void                testApp::seed1(float                dotSize,                float                angle,                float                x,                float                y){                if(dotSize >                1.0f){                float                r = ofRandomuf();                if(r >                0.02f){       ofCircle(x, y, dotSize);                float                newx = x + cos(angle) * dotSize;                float                newy = y + sin(angle) * dotSize;       seed1(dotSize *                0.99f, angle - angleOffsetA, newx, newy);     }                else                {       ofCircle(x, y, dotSize);                float                newx = x + cos(angle);                float                newy = y + sin(angle);       seed2(dotSize *                0.99f, angle + angleOffsetA, newx, newy);       seed1(dotSize *                0.6f, angle + angleOffsetB, newx, newy);       seed2(dotSize *                0.5f, angle - angleOffsetB, newx, newy);     }   } }                  void                testApp::seed2(float                dotSize,                float                angle,                float                x,                float                y){                if(dotSize >                1.0f){                float                r = ofRandomuf();                if(r >                0.05f){       ofCircle(x, y, dotSize);                float                newx = x + cos(angle) * dotSize;                float                newy = y + sin(angle) * dotSize;       seed2(dotSize *                0.99f, angle + angleOffsetA, newx, newy);     }                else                {       ofCircle(x, y, dotSize);                float                newx = x + cos(angle);                float                newy = y + sin(angle);       seed1(dotSize *                0.99f, angle + angleOffsetA, newx, newy);       seed2(dotSize *                0.6f, angle + angleOffsetB, newx, newy);       seed1(dotSize *                0.5f, angle - angleOffsetB, newx, newy);     }   } }              
  • Cinder

                                              #include                  "cinder/app/AppBasic.h"                #include                  "cinder/CinderMath.h"                #include                  "cinder/Rand.h"                class                Repeat_RecursiveTree :                public                ci::app::AppBasic {                public:                void                prepareSettings(Settings* settings);                void                setup();                void                draw();                void                seed1(float                dotSize,                float                angle,                float                x,                float                y);                void                seed2(float                dotSize,                float                angle,                float                x,                float                y);                private:                float                dotSize;                float                angleOffsetA;                float                angleOffsetB;     ci::Rand rand; };                void                Repeat_RecursiveTree::prepareSettings(Settings* settings) {     dotSize =                9;     settings->setWindowSize(900,                600);     settings->setFrameRate(1.0f);   }                void                Repeat_RecursiveTree::setup() {     ci::gl::color(ci::Color::black());     glEnable(GL_SMOOTH);      angleOffsetA = ci::toRadians(1.5f);     angleOffsetB = ci::toRadians(50.0f);      rand.randomize(); }                void                Repeat_RecursiveTree::draw() {     ci::gl::setMatricesWindow(getWindowSize());     ci::gl::clear(ci::Color::white());      ci::gl::translate(ci::Vec2f(getWindowWidth()/2, getWindowHeight()));      seed1(dotSize, ci::toRadians(270.0f),                0,                0);  }                void                Repeat_RecursiveTree::seed1(float                dotSize,                float                angle,                float                x,                float                y) {                if                (dotSize >                1.0) {                          float                r = rand.randFloat(0,                1.0f);                            if                (r >                0.02) {             ci::gl::drawSolidCircle(ci::Vec2f(x, y), dotSize/2);                float                newx = x + ci::math<float>::cos(angle) * dotSize;                float                newy = y + ci::math<float>::sin(angle) * dotSize;             seed1(dotSize *                0.99, angle - angleOffsetA, newx, newy);            }                         else                {               ci::gl::drawSolidCircle(ci::Vec2f(x, y), dotSize/2);                float                newx = x + ci::math<float>::cos(angle);                float                newy = y + ci::math<float>::sin(angle);             seed2(dotSize *                0.99, angle + angleOffsetA, newx, newy);             seed1(dotSize *                0.60, angle + angleOffsetB, newx, newy);             seed2(dotSize *                0.50, angle - angleOffsetB, newx, newy);         }      } }                void                Repeat_RecursiveTree::seed2(float                dotSize,                float                angle,                float                x,                float                y) {                if                (dotSize >                1.0) {                          float                r = rand.randFloat(0,                1.0);                          if                (r >                0.05) {             ci::gl::drawSolidCircle(ci::Vec2f(x, y), dotSize/2);                float                newx = x + ci::math<float>::cos(angle) * dotSize;                float                newy = y + ci::math<float>::sin(angle) * dotSize;             seed2(dotSize *                0.99, angle + angleOffsetA, newx, newy);         }                          else                {             ci::gl::drawSolidCircle(ci::Vec2f(x, y), dotSize/2);                float                newx = x + ci::math<float>::cos(angle);                float                newy = y + ci::math<float>::sin(angle);             seed1(dotSize *                0.99, angle + angleOffsetA, newx, newy);               seed2(dotSize *                0.60, angle + angleOffsetB, newx, newy);             seed1(dotSize *                0.50, angle - angleOffsetB, newx, newy);         }     } }  CINDER_APP_BASIC(Repeat_RecursiveTree, ci::app::RendererGl)              

We are looking for implementations of the code examples in other programming languages to post on the site. If you would like to submit a sample, or if you find a bug, please write to

greeneponim1945.blogspot.com

Source: http://formandcode.com/code-examples/repeat-recursive-tree

0 Response to "draw recursive tree with lines and circles"

Postar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel