In this post, I will show you how to draw a Fractal tree in WPF. The purpose of this tutorial is to show how to create a fractal using WPF. Despite the fact that the example has little practical usefulness, it is a good example of recursive programming. A binary tree can be defined recursively as a trunk connected to branches. The branches connect to smaller branches, which connect to even smaller branches, and so on.
Algorithm
To draw a fractal tree is simple:
- Draw the trunk
- At the end of the trunk, split by some angle and draw two branches
- Repeat at the end of each branch until a sufficient level of branching is reached
Step1
Create a new WPF application and add the following code
<Window x:Class="HelloWorld.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Viewbox Stretch="Uniform">
<StackPanel>
<StackPanel Orientation="Horizontal"
Margin="5,5,5,0">
<Button Name="btnStart" Click="btnStart_Click"
Width="50" Content="Start"/>
<TextBlock Name="tbLabel" Margin="20,5,0,0"/>
</StackPanel>
<Canvas Name="canvas1" Width="300" Height="300"
Margin="5"/>
</StackPanel>
</Viewbox>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
namespace HelloWorld
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private int depth = 0;
private int i = 0;
private double lengthScale = 0.75;
private double deltaTheta = Math.PI / 5;
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//Application.Current.Dispatcher.BeginInvoke(
// DispatcherPriority.Background,
// new Action(() => DrawSine()));
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
canvas1.Children.Clear();
tbLabel.Text = "";
i = 0;
depth = 1;
CompositionTarget.Rendering += StartAnimation;
}
private void StartAnimation(object sender, EventArgs e)
{
i += 1;
if (i % 60 == 0)
{
DrawBinaryTree(canvas1, depth, new Point(canvas1.Width / 2, 0.83 * canvas1.Height), 0.2 * canvas1.Width, -Math.PI / 2);
string str = "Binary Tree - Depth = " + depth.ToString();
tbLabel.Text = str;
depth += 1;
if (depth > 10)
{
tbLabel.Text = "Binary Tree - Depth =10. Finished";
CompositionTarget.Rendering -= StartAnimation;
}
}
}
private void DrawBinaryTree(Canvas canvas, int depth, Point pt, double length, double theta)
{
double x1 = pt.X + length * Math.Cos(theta);
double y1 = pt.Y + length * Math.Sin(theta);
Line line = new Line();
line.Stroke = Brushes.Blue;
line.X1 = pt.X;
line.Y1 = pt.Y;
line.X2 = x1;
line.Y2 = y1;
canvas.Children.Add(line);
if (depth > 1)
{
DrawBinaryTree(canvas, depth - 1, new Point(x1, y1), length * lengthScale, theta + deltaTheta);
DrawBinaryTree(canvas, depth - 1, new Point(x1, y1), length * lengthScale, theta - deltaTheta);
}
else
return;
}
}
}