# 3D tree curve (Fractal again)

At the end of 3D turtle graphics, I leave an exercise for you to create your Customizable tree curve.

# 2D tree curve

Before you can implement a 3D tree curve, you should have the ability to create a 2D tree curve. Before you can do a 2D tree curve, you should be able to draw a “Y”.

``````// omitted...require 3D turtle graphics

leng = 50;
leng_scale = 0.7;
angle = 20;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale, angle, width, fn) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

t3 = moveX(turnZ(t2, angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t3)], width, ``````fn);

t4 = moveX(turnZ(t2, -angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t4)], width, ``````fn);
}

tree(t, leng, leng_scale, angle, width, fn);
``````

If you want to grow more “Y” from the branches of the original “Y”, you can invoke the `tree` module recursively. The recursion needs a stop condition, and we use the length of branches here.

``````// omitted...require 3D turtle graphics

leng = 50;
leng_limit = 5;
leng_scale = 0.7;
angle = 20;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale, leng_limit, angle, width, fn) {
if(leng > leng_limit) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

t3 = moveX(turnZ(t2, angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t3)], width, ``````fn);

t4 = moveX(turnZ(t2, -angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t4)], width, ``````fn);

tree(
turnZ(t2, angle),
leng * leng_scale,
leng_scale,
leng_limit,
angle, width, fn);

tree(
turnZ(t2, -angle),
leng * leng_scale,
leng_scale,
leng_limit,
angle, width, fn);

}
}

tree(t, leng, leng_scale, leng_limit, angle, width, fn);
``````

We have a 2D version of the recursive tree.

However, we draw some branches repeatedly except the endings. That is, the following code repeats branches.

``````t3 = moveX(turnZ(t2, angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t3)], width, ``````fn);

t4 = moveX(turnZ(t2, -angle), leng * leng_scale);
polyline3D([getPt(t2), getPt(t4)], width, ``````fn);
``````

Deleting the code will lose some ending branches; however, we have clean code.

``````// omitted...require 3D turtle graphics

leng = 50;
leng_limit = 5;
leng_scale = 0.7;
angle = 20;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale, leng_limit, angle, width, fn) {
if(leng > leng_limit) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

tree(
turnZ(t2, angle),
leng * leng_scale,
leng_scale,
leng_limit,
angle, width, fn);

tree(
turnZ(t2, -angle),
leng * leng_scale,
leng_scale,
leng_limit,
angle, width, fn);

}
}

tree(t, leng, leng_scale, leng_limit, angle, width, fn);
``````

# 3D tree curve

Evolving the above 2D tree into a 3D tree is easy. If we turn around the z-axis before invoking the `tree` module and one of the angles is 0 degree, what will happen?

``````// omitted...require 3D turtle graphics

leng = 50;
leng_limit = 5;
leng_scale = 0.7;
angle1 = 20;
angle2 = 0;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale, leng_limit, angle1, angle2, width, fn) {
if(leng > leng_limit) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

tree(
turnZ(t2, angle1),
leng * leng_scale, leng_scale, leng_limit,
angle1, angle2,
width, fn);

tree(
turnZ(t2, angle2),
leng * leng_scale, leng_scale, leng_limit,
angle1, angle2,
width, fn);
}
}

tree(t, leng, leng_scale, leng_limit, angle1, angle2, width, fn);
``````

The tree looks weird. It grows toward the upper and the left.

How about changing the second `turnZ` to `turnX` and the `angle2` value to 127?

``````// omitted...require 3D turtle graphics

leng = 50;
leng_limit = 5;
leng_scale = 0.7;
angle1 = 20;
angle2 = 127;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale, leng_limit, angle1, angle2, width, fn) {
if(leng > leng_limit) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

tree(
turnZ(t2, angle1),
leng * leng_scale, leng_scale, leng_limit,
angle1, angle2,
width, fn);

tree(
turnX(t2, angle2),
leng * leng_scale, leng_scale, leng_limit,
angle1, angle2,
width, fn);
}
}

tree(t, leng, leng_scale, leng_limit, angle1, angle2, width, fn);
``````

Wow, we have a cute 3D tree.

127 is a prime number. That's why I choose it. You can choose any angle which doesn't divide 360 so that the branches doesn't appear at the same angle. We can change `leng_scale` to `leng_scale1` and `leng_scale2`; choose suitable values for them; set appropriate angles for `angle1` and `angle2`. After that, we'll have a pretty 3D tree. For clearness, we rename `angle1` and `angle2` to `angleZ` and `angleX` respectively.

``````// omitted...require 3D turtle graphics

leng = 100;
leng_limit = 1;
leng_scale1 = 0.4;
leng_scale2 = 0.9;
angleZ = 60;
angleX = 135;
width = 2;
fn = 4;

t = turtle3D(
pt3D(0, 0, 0),
[pt3D(1, 0, 0), pt3D(0, 1, 0), pt3D(0, 0, 1)]
);

module tree(t, leng, leng_scale1, leng_scale2, leng_limit,
angleZ, angleX, width, fn) {
if(leng > leng_limit) {
t2 = moveX(t, leng);
polyline3D([getPt(t), getPt(t2)], width, ``````fn);

tree(
turnZ(t2, angleZ),
leng * leng_scale1, leng_scale1, leng_scale2, leng_limit,
angleZ, angleX,
width, fn);

tree(
turnX(t2, angleX),
leng * leng_scale2, leng_scale1, leng_scale2, leng_limit,
angleZ, angleX,
width, fn);
}
}

tree(t, leng, leng_scale1, leng_scale2, leng_limit,
angleZ, angleX, width, fn);
``````

To make branches intensive, I also choose appropriate values for `leng` and `leng_limit`. The tree is below.

If you want, you can give efforts in the width of branch lines, such as a thickest main trunk and thinner branches while growing. You can add more recursions, such as I did in Customizable tree curve. I even make a little random to the branches. It makes the tree curve more like a real tree. Try to realize all the above by yourself.