Progressive growth of recursive lines :)

Hey everyone,

I am working on a project where I am attempting to draw a root / tree like structures and I have figured out the recursive part of it but I am struggling to work out how I can progressively draw one line at a time.

I would like to start from one root / branch and once that is fully drawn, start drawing the next two that are branching out of it and so on. I went through the forum and found some threads I thought would help but nothing specifically regarding this issue so any help would be much appreciated :slight_smile:

Here is my code to make it easier for you to understand:

//--------------------------------------------------------------//--------------------------------------------------------------//

void RootsSource::setup(){
ofBackground(255);
ofSetLineWidth(1);
ofSetFrameRate(30);
// t = ofGetElapsedTimeMillis();

angle = 35;
len = 200;
lenRatio = 0.67;

}

//--------------------------------------------------------------
void RootsSource::update(){
locY++;
}

//--------------------------------------------------------------
void RootsSource::draw(){
ofSetColor(0);
ofTranslate(ofGetWidth()/2, 150);

root(len, angle);

}
//--------------------------------------------------------------
void RootsSource::root(int len, int angle){

if (locY <= len) {
    ofDrawLine(0, 0, 0, locY);
}
else if (locY > len) {
    ofDrawLine(0, 0, 0, len);
}

ofTranslate(0, len);

if (len > 5) {
    ofPushMatrix();
    ofRotateDeg(angle);
    root(len*lenRatio, angle);
    ofPopMatrix();
    
    ofPushMatrix();
    ofRotateDeg(-angle);
    root(len*lenRatio, angle);
    ofPopMatrix();
}

}

here is some simple source example of a recursive tree from a class i taught on Generative Systems in case it helps to look thru…

Hey again Dan,

thanks for this example. I have actually managed to work out the recursive system and have the tree (actually, they are supposed to be roots) being generated as a one frame drawing. Yet I am on a bit of journey to find out how I could draw the roots one by one as an animation. Any ideas? :slight_smile:

post all the code here if you like - very happy to have a look and see if i can suggest something?

I can also heartily recommend the amazing work by @edapx on L-systems etc - you can find addons and examples here in the addons library
https://ofxaddons.com/contributors/edap

1 Like

I have provided the code above :slight_smile:

It has been making quite a nice pattern with the possibility to create variable angles and lengths. As I am planning to make the roots grow on the Y axis (with the ofRotate taking care of the direction translation) I made a locY variable which I am trying to implement but unsure how to make it work the way I desire.

My line of thought goes like this: Start drawing the root on fixed X axis and moving along Y axis. Once you are finished drawing - reaching len (and then len x lenRatio in the second iteration, len x lenRatio x lenRatio in the third etc.) - start drawing the next root. So what I need is to always store and be able to recall the len(gth) of the latest root and draw the new one from that position onwards and so on until it reaches the len > 5.

I am not able to use ad-ons at the moment as this is a uni project with some restrictions but I am happy about that since I am learning loads about doing things - somewhat - more hands on.

you can explicitly slow down the drawing by setting the framerate - use the command

    ofSetFrameRate(5);  // this will be 5 fps

and you will see the short roots being drawn more slowly, to get them to draw one at a time (if i understand you correctly) might mean you need to alter how/in what order you are calculating them. Currently - if i understand - the extremeties are calculated, then the next branch layer up (for all roots), then the next up and so on, as opposed to one specific path from tip to trunk (as it were)

this is kind of a logic problem of how/what you want to do as it starts into thinking of what the structure is - eg that several end points share the same base - how do you categories them and how do you want them to draw in your animation?

alternatively you could generate points and make a series of line objects representing roots

have a look at ofPolyLine https://openframeworks.cc/documentation/graphics/ofPolyline/

or ofPath https://openframeworks.cc/documentation/graphics/ofPath/

in case either of these might be helpful - there are also good examples in the oF/examples/graphics folder of your oF download.

1 Like

Hey Dan, thank you for keeping the conversation flowing here. Currently, the structure is so that all the roots at all levels are starting to be drawn at the same time, resulting in the smallest ones finishing the first etc. So yes, you are right. Would you perhaps suggest creating another class which would be the whole root structure and where I could adjust when each of the levels is drawn?

Here is the code again, now updated with some noise for movement and randomness.

ofPushMatrix();

if (locY <= len) {
    ofSetLineWidth(len * 0.086);
    ofDrawLine(0, 0, 0, locY);
}
else if (locY > len) {
    ofSetLineWidth(len * 0.086);
    ofDrawLine(0, 0, 0, len);
}

ofPopMatrix();

ofTranslate(0, len);

int newLen = len * lenRatio;

if (len > 5) {

    ofPushMatrix();

    float newAngleR = angle + ofNoise(len * ofGetFrameNum() * 0.0003);
    ofRotateDeg(newAngleR);
    ofSetLineWidth(len * 0.074);
    ofSetColor(colors[ofRandom(colors.size())]);
    root(newLen, angle);
    
    float newAngleL = angle - ofNoise(len * ofGetFrameNum() * 0.0003);
    ofRotateDeg(-newAngleL);
    ofSetLineWidth(len * 0.056);
    ofSetColor(colors[ofRandom(colors.size())]);
    root(newLen, -angle);

    ofPopMatrix();

}
    if (len <= 200 && len > 180) {
        float lenA = len * 0.3;
        float angleA = - angle * 1.2 + ofNoise(len * ofGetElapsedTimef() * 0.0004) * 0.1;
        root(lenA, angleA);
            }

    if (len <= 180 && len > 102) {
        float lenB = len * 0.1;
        float angleB = angle * 1.9 - ofNoise(len * ofGetElapsedTimef() * 0.0002) * 0.2;
        root(lenB, angleB);
            }

    if (len <= 102 && len > 55) {
        float lenC = len * 0.1;
        float angleC = - angle * 2.9 + ofNoise(len * ofGetElapsedTimef() * 0.0016) * 0.15;
        root(lenC, angleC);
            }

    if (len <= 55 && len > 0) {
        float lenD = len * 0.3;
        float angleD = angle * 1.9 - ofNoise(len * ofGetElapsedTimef() * 0.0003) * 0.25;
        root(lenD, angleD);
    }