Introduction
Happy New Year!
This is not a practical program, it's only a simple program to have some fun with mathematics. It uses Sin()
and Cos()
functions with recursion to make some fractal shapes and Trees. It has a very simple algorithm.
Background
I initially wrote this code in August 2006 (VB6 format) to show recursive functions in action to a friend. Unfortunately his email had some problems and didn't accept my zip file, so I put it on PSC for him. It was amazing when I found that it was useful for some other guys, and now it's here in C# and VB.NET.
Using the Code
The zip files contain source code that was compiled for Visual Studio .NET 2003 and Visual Studio .NET 2005 in both C# and VB.NET. Just open the solution file and compile it. The executable created is called RealTree.exe.
How It Works
1. You need a loop to make branches:
When each branch divides to 2 new branches, you have 2 ^ Step branches in each step from base (step 0) to top, and when divisions are more, the formula is numberOfDivision ^ Step.
For this part, I used a recursive procedure, each time it runs itself with new position of branch and angle:
In VB.NET:
Sub nextBranch(startX As Single, startY As Single, startAngle As Single)
...
For j As Integer = 1 To Int(numberOfDivision)
nextBranch(endX, endY, newAngle)
Next
...
End Sub
And in C#:
Void nextBranch(float startX, float startY, float startAngle)
{
...
for(int j= 1;j=(int) numberOfDivision;j++)
{
nextBranch(endX, endY, newAngle);
}
...
}
As you see, the ending position of each branch is the starting position of next branches.
2. You have to calculate the position of new branches:
In standard coordinates, you can calculate the starting position of new branches (ending position of the current branch) with the following formulas:
endX = startX + Cos(angle) * sizeOfBranch
endY = startY + Sin(angle) * sizeOfBranch
How did we find these formulas; see the following figures. Our starting point is P and we want to draw some lines with same lengths; when we draw more lines, it becomes more similar to a math shape, what is it like?
It's like a circle, our first point is the center of the circle and our lines are its radii, so for a sample PS line, we have to find S position on the surface of the circle. We draw a circle in the center of coordinates with one unit radius size to find position of S(X,Y).
If we draw a vertical line from S to X axis, it crosses it at H point, PH is X's dimension of S point. Now if we draw a horizontal line from S to Y axis, it crosses it at K point, PK is Y's dimension of S. When we look carefully at our points, we can find that KS and PH have the same size, and also PK and HS sizes are the same, So our S(X,Y) point can be as S(PH,HS) .
We have a right triangle as PHS, as you know about triangles, Sin(P-angle)=HS / PS and so HS=Sin(angle) * PS, Also Cos(P-angle)=PH / PS and so PH = Cos(angle) * PS
We know PS size because it is the radius of the circle, so our S point position would be as follows:
S (Cos(angle) * Radius, Sin(angle) * Radius)
S (Cos(60) * 1, Sin(60) * 1) == > S (0.5, 0.86)
Now we return to our project, we draw a tree and try to find the position of its branches.
We are in position P (0, 0) and know that all branches have 10 unit sizes, for PQ line we need position of Q point. It has 90 degrees angle with X axis, its X position is Cos(90) * 10 and its Y position is Sin(90) * 10, so it is as Q(0,10).
What about R and S? They have 60 degrees angle with each other, but this is not their angles with X axis, see the next figure for a better view:
When we continue the PQ line, our QR and QS lines make 30 degrees angles with it, and we know that it has 90 degrees angle with X axis, so angles of our lines are 90 + 30 = 120 for QR and 90 – 30 = 60 for QS. Now we calculate the position of R, its X position is Cos(120) * 10= -5 and its Y position is Sin(120) * 10 = 8.6 , right ?!
Wrong! Our (-5, 8.6) position is a point like Z in our shape not R, because when we moved from P to Q, our first position changed and when we want to calculate R position, we are in Q position not in P, so we have to enter these changes in our formula, it means we must add our new calculations to starting positions, so our X value must be -5 + Qx= -5 + 0= -5 and our Y value must be 8.6 + Qy = 8.6 +10 = 18.6 , so the true position is R(-5, 18.6) , and we found our main formulas:
X = startX + Cos(angle) * sizeOfBranch
Y = startY + Sin(angle) * sizeOfBranch
Now we calculate positions of other points:
Sx= 0 + Cos(60) * 10 = 5 , and Sy= 10 + Sin(60) * 10 = 18.6, so it is as S(5, 18.6).
T and U make a 60 degrees angle with each other, it means each of them has 30 degrees difference with their starting angle and we know their starting angle is 120, so RT makes a 120 + 30 = 150 degrees angle and RU makes a 120 -30 = 90 degrees angle, so their positions are as follows:
Tx= -5 + Cos(150) * 10 = -13.6, and Ty= 18.6 + Sin(150) * 10 = 23.6 , so we can show it as T(-13.6, 23.6).
Ux=-5 + Cos(90) * 10= -5, and Uy= 18.6 + Sin(90) * 10= 28.6, it means U(-5, 28.6).
What about V and W? Now you know that each of them has a 30 degrees difference from starting point angle, so SV has 60+30 = 90 degrees and SW has 60-30 = 30 degrees angles, position of these points are as follows:
Vx=5 + Cos(90) * 10 = 5 , and Vy=18.6 + Sin(90) * 10 = 28.6 , so it is as V(5, 28.6).
Wx=5 + Cos(30) * 10 = 13.6 , and Wy= 18.6 + Sin(30) * 10= 23.6 , so W(13.6,23.6).
Note: There is a simple difference between Standard and Computer coordinates, in Computer Coordinates, Positive values of Y axis growth to the bottom of screen.
These are Standard Coordinates:
And these are Computer Coordinates:
So we have to change the formula of Y value as follows:
endY = startY - Sin(angle) * sizeOfBranch
3. How about some effects like Wind, Leaf Level…:
These effects make some changes in size, position or number of branches with mathematical formulas.
Interface
It has a simple GUI; you can choose some predefined types from menu or make new types:
Total Steps (3 - 100): Maximum number of steps you want to draw.
Division per Step (1- 100): Each branch is divided to this number of branches for the next step.
Starting Branch (1- Total Steps): If you use numbers higher than 1, then program shows only branches in higher steps than selected.
Fixed Size (Checked or Not & Percentage): When checked, all branches in each step have same size, percentage part determine total size of Tree.
Fixed Angle (Checked or Not & Percentage): When checked, there are the same angles between all branches in each step, percentage part determines total angle between branches of each step.
Broken Branches (Checked or Not & Percentage): When checked, there are broken branches in Tree, percentage part determines amount of it.
B.B Scale (50 ± 50): (Broken Branches Scale) means broken effect acts more on lower branches or higher branches.
D.P.S Scale (50 ± 50): (Division per Step Scale) When you lead to right, you have more DPS in higher branches than base DPS, and when you lead to left, you have less DPS in higher branches than base DPS.
Leaf Level (50 ± 50): It determines that leaves should be on the higher branches or lower.
Trunk Height (50 ± 50): Change in height of Tree's trunk from default size.
Width (50 ± 50): Change in width of branches.
Width Scale (50 ± 50): Amount of changes in width of branches from base to leaves.
Wind (50 ± 50): Amount and direction of wind effect.
Widening (500 ± 500): This is a special effect; you must see it in action, I have to make some changes in its values and results.
Note
When you use high values for "Total Steps" or "Division per Step", maybe it takes a long time for rendering, so using of "Broken Branches" and "Division per Step Scale" make it better.
If you use values over 2 for "Division per Step", you have to use higher values for "Broken Branches", it makes a wild Tree. [e.g. with "Total Steps"=30 use following values:( DPS=3, BB=52), (DPS=4, BB=65), (DPS=5, BB=72), (DPS=6, BB=77), (DPS=7, BB=81), (DPS=8, BB=83)...] If you want to deactivate "Broken Branches", you must use lower values for "Total Steps" (~ 15, depends on speed of your computer).
Points of Interest
You can make different funny fractals by changing or adding new variables.
History
- Jan 2007: Uploaded on The Code Project
- Apr 2007: Version 1.5: Added widening effect and some new samples
- Mar 2009: Version 1.6: Added Timer, some new samples and updated to Visual Studio 2005