Рекурсивная функция JavaScript не вернет данные родительского вызова?

Я работаю над проектом HTML5/JS, чтобы нарисовать двоичное фрактальное дерево на холсте.

HTML5::

<!DOCTYPE html>
<html>
  <body>
    <canvas id="canvas1" width="500" height="500"></canvas>
    <br />
    <script src="tree.js"></script>
    <button id="button1" type="button" onclick="main()">Start</button>
  </body>
</html>

Javascript::

var scale = 0.5;
var min_len = 1;
//setup canvas
var c = document.getElementById("canvas1");
var ctx = c.getContext("2d");
ctx.moveTo(250, 500);

//returns length of branch
function len(branch) {

    return Math.sqrt( Math.pow(branch.len_x, 2) + Math.pow(branch.len_y, 2) );
}

//draws from start to length of branch
function drawBranch(start, branch) {

    ctx.moveTo(start.x, start.y);
    ctx.lineTo(start.x + branch.len_x, start.y - branch.len_y);
    ctx.stroke();
}

//recursively builds binary fractal tree
function makeChildren(start, theta, parent) {

    if(len(parent) >= min_len) {
        drawBranch(start, parent);

        //linear transformation applied to parent branch which rotates and scales to produce child branch
        child = {len_x: ( parent.len_x * Math.cos(theta) - parent.len_y * Math.sin(theta) ) * scale,
                 len_y: ( parent.len_x * Math.sin(theta) + parent.len_y * Math.cos(theta) ) * scale};

        //recursively build left and right branches of tree
        makeChildren( {x: start.x + parent.len_x, y: start.y - parent.len_y}, theta, child);
        makeChildren( {x: start.x + parent.len_x, y: start.y - parent.len_y}, theta * (-1), child);
    }
}

function main() {

    //initialize tree
    makeChildren( {x: 250, y: 500}, Math.PI / 4, {len_x: 0, len_y: 100} );
}

Когда я запускаю свой код, он создает спиральную структуру, обращенную к левой стороне (извините, пока нельзя публиковать изображения).

Проблема заключается в проверке длины в функции makeChildren, когда оператор if уже не является истинным, т.е. когда ветвь слишком мала, программа попадает в рекурсивный цикл, где размер остается слишком маленьким. Вот консольный журнал длин веток:

[Log] 100 (tree.js, строка 24)

[Журнал] 49.99999999999999 (tree.js, строка 24)

[Журнал] 25 (tree.js, строка 24)

[Журнал] 12,5 (tree.js, строка 24)

[Журнал] 6.25 (tree.js, строка 24)

[Log] 3.125 (tree.js, строка 24)

[Журнал] 1.5624999999999998 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

[Log] 0.7812499999999999 (tree.js, строка 24)

Он должен достичь базового варианта для рекурсивного цикла (длина ветви слишком мала) и вернуться к предыдущему рекурсивному циклу, но, похоже, он просто продолжает проверять одну и ту же длину, 0,78125, снова и снова. Я не могу понять, почему, пожалуйста, помогите!

2 ответа

Решение

проверка одинаковой длины, 0,78125, снова и снова

Каждый уровень рекурсии удваивает количество вызовов. Он достигнет этого базового случая, как... 128 (?) Раз.

это создает левостороннюю спиральную структуру

Как есть, есть единый глобальный child переменная. Когда первый субmakeChild работает, он переназначает этот глобальный child переменная, а второйmakeChild начинается с этого модифицированного.

Вы, вероятно, хотели

var child = {len_x: ...

http://jsfiddle.net/hLxe4fx1/

Я пришел к такому же выводу, но гость был быстрее меня:) Чтобы знать, почему это происходит, помните, что объекты передаются по ссылке и как child был неопределен, это было в глобальном масштабе.

Другой jsfiddle http://jsfiddle.net/6pjduncg/

Другие вопросы по тегам