Search code examples
javascriptalgorithml-systems

"Maximum call stack size exceeded" error while implementing Fractal plant in processing JS


I am trying to implement a fractal plant (up-till level - 6) in processing javascript. I get "Maximum call stack size exceeded" error even though the base conditions are being met.

Here is the code: First function custom draw line draws line on basis of length, angle and point of origin. Increment function increases the angle by 25 degree. Decrement function decreases angle by 25 degree.

var customDrawLine = function(x, y, length, angle)
{
    var f={x2:'', y2:''};
    f.x2 = x+(sqrt(sq(length)/(1+sq(tan (angle)))));
    f.y2 = y + ((f.x2-x) * tan (angle));
    line(x, y, f.x2, f.y2);
    return f;
};
var incrementAngle = function(angle)
{
    return (angle+25);
};
var decrementAngle = function(angle)
{
    return (angle-25);
};

var fProductionRule = function(x, y, z, degrees, flag)
{
    var l = {x1:'', y1:''};
    if(flag === 1)
    {
        for (var a=0; a<2;a++)
        {
           l = customDrawLine(l.x1, l.y1, z, degrees);
        }
    }
    else
    {
        l = customDrawLine(l.x1, l.y1, z, degrees);
    }
    return l;
};
var xProductionRule = function(x, y, degrees, nLevel, flag)
{
    var k = {x1:'', y1:''};
    var m;
    k.x1 = x;
    k.y1 = y;
    m = degrees;
    for(var z=0; z<7; z++)
    {
        var f = fProductionRule(k.x1, k.y1, (10-z), m, flag);
        m = incrementAngle(m);
        flag = 1;
        {
            {
                xProductionRule(f.x2,f.y2, m, z);
            }
            m = decrementAngle(m);
            xProductionRule(f.x2,f.y2, m, z);
        }
        m = decrementAngle(m);
        f = fProductionRule(k.x1, k.y1, (10-z), m, flag);
        {
            m = decrementAngle(m);
            f = fProductionRule(k.x1, k.y1, (10-z), m, flag);
            xProductionRule(f.x2,f.y2, m, z);
        }
        m = incrementAngle(m);
        xProductionRule(f.x2,f.y2, m, z);
       }
   };
var drawShape = function(x, y, degrees) 
{
   xProductionRule(x, y, degrees, 0, 0);
};
drawShape(10, 380, 25);

Solution

  • Yor code contains an inifinite recursion, as xProductionRule calls itself unconditionally.

    To draw fractals, you must either constrain the depth of the recursion, or prevent the rendering of parts under a specific size (like 1 pixel).

    I see that xProductionRule has 5 arguments, one of them is called nLevel, but that argument is not used anywhere, in fact you call the function with only 4 parameters. I think you were to use that argument to constrain the depth of the recursion. Add some check (nLevel < 7) to the function, and make every recursive calls to include nLevel+1 as parameter.

    In my opinion, based on the wikipedia article you mentioned, the skeleton of your code should be structured something like this:

    function drawA(depth, ... /* placement information */) {
        // here, draw the current branch
        // and then continue with it's children
        if (depth > 0) {
            drawA(depth - 1, ... /* derived placement information  */)
            drawB(depth - 1, ... /* another derived placement information  */)
        }
    }
    
    function drawB(depth, ... /* placement information */) {
        // here, draw the current branch
        // and then continue with it's children
        if (depth > 0) {
            drawA(depth - 1, ... /* derived placement information  */)
        }
    }
    
    drawA(7, ... /* placement of the root branch */)
    

    I don't see a place where you would need a 7-loop.