图形学里分形树模拟现实中的树和叶达到不错的视觉效果。本篇简单介绍分形树的实现。
经典分形树
一条线段,取其黄金分割点,向线段左右分出夹角为π/3、长度为黄金分割率与原线段长度的积的两条线段,分出的线段再做相同的处理。迭代过程如下:
下图为迭代层次为10的分形树。
代码为:
const double G = 0.618;
const double PI = Math.PI;
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
leaf(new Point(500, 500), 400, PI / 2);
}
void leaf(Point pStart, double length, double angle)
{
Point pEnd;
Point pTemp = new Point();
double len;
double sin = Math.Sin(angle);
double cos = Math.Cos(angle);
pEnd = new Point(pStart.X + length * cos, pStart.Y - length * sin);//终点
Line l = new Line();
l.Stroke = new SolidColorBrush(Colors.Red);
l.X1 = pStart.X;
l.Y1 = pStart.Y;
l.X2 = pEnd.X;
l.Y2 = pEnd.Y;
LayoutRoot.Children.Add(l);//划线
if (length < 10)
{
return;
}
len = length;
pTemp.X = pStart.X;
pTemp.Y = pStart.Y;
for (int count = 0; count < 10; count++)
{
pTemp = new Point(pTemp.X + len * (1 - G) * cos, pTemp.Y - len * (1 - G) * sin);
leaf(new Point(pTemp.X, pTemp.Y), len * (1 - G), angle + PI / 3);
leaf(new Point(pTemp.X, pTemp.Y), len * (1 - G), angle - PI / 3);
len *= G;
}
}
左右分出的角度用随机量代替可得以下随机分形树。
二叉分形树
一条线段,以线段的终点为起点向两边分出一定的角度、长度为黄金分割率与原线段长度的积的两条线段,分出的线段的终点再做相同处理。
代码为:
运行效果:
结束语
还有一些其他类型的分形树(如交错分形树),原理基本相同。做分形做好的程序设计方法是递归。
这些图形都比较简单,要做到真实感图形还要做很多工作。
经典分形树
一条线段,取其黄金分割点,向线段左右分出夹角为π/3、长度为黄金分割率与原线段长度的积的两条线段,分出的线段再做相同的处理。迭代过程如下:
下图为迭代层次为10的分形树。
代码为:
const double G = 0.618;
const double PI = Math.PI;
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
leaf(new Point(500, 500), 400, PI / 2);
}
void leaf(Point pStart, double length, double angle)
{
Point pEnd;
Point pTemp = new Point();
double len;
double sin = Math.Sin(angle);
double cos = Math.Cos(angle);
pEnd = new Point(pStart.X + length * cos, pStart.Y - length * sin);//终点
Line l = new Line();
l.Stroke = new SolidColorBrush(Colors.Red);
l.X1 = pStart.X;
l.Y1 = pStart.Y;
l.X2 = pEnd.X;
l.Y2 = pEnd.Y;
LayoutRoot.Children.Add(l);//划线
if (length < 10)
{
return;
}
len = length;
pTemp.X = pStart.X;
pTemp.Y = pStart.Y;
for (int count = 0; count < 10; count++)
{
pTemp = new Point(pTemp.X + len * (1 - G) * cos, pTemp.Y - len * (1 - G) * sin);
leaf(new Point(pTemp.X, pTemp.Y), len * (1 - G), angle + PI / 3);
leaf(new Point(pTemp.X, pTemp.Y), len * (1 - G), angle - PI / 3);
len *= G;
}
}
左右分出的角度用随机量代替可得以下随机分形树。
二叉分形树
一条线段,以线段的终点为起点向两边分出一定的角度、长度为黄金分割率与原线段长度的积的两条线段,分出的线段的终点再做相同处理。
代码为:
const double G = 0.618;
const double PI = Math.PI;
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
binTree(new Point(500, 600), 200, PI / 2);
}
private void binTree(Point pStart, double length, double angle)
{
Point pEnd;
double sin = Math.Sin(angle);
double cos = Math.Cos(angle);
pEnd = new Point(pStart.X + length * cos, pStart.Y - length * sin);
Line l = new Line();
l.Stroke = new SolidColorBrush(Colors.Red);
l.X1 = pStart.X;
l.Y1 = pStart.Y;
l.X2 = pEnd.X;
l.Y2 = pEnd.Y;
LayoutRoot.Children.Add(l);//划线
if (length < 10)
{
return;
}
binTree(pEnd, length * G, angle + new Random().NextDouble());
binTree(pEnd, length * G, angle - new Random().NextDouble());
}
const double PI = Math.PI;
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
binTree(new Point(500, 600), 200, PI / 2);
}
private void binTree(Point pStart, double length, double angle)
{
Point pEnd;
double sin = Math.Sin(angle);
double cos = Math.Cos(angle);
pEnd = new Point(pStart.X + length * cos, pStart.Y - length * sin);
Line l = new Line();
l.Stroke = new SolidColorBrush(Colors.Red);
l.X1 = pStart.X;
l.Y1 = pStart.Y;
l.X2 = pEnd.X;
l.Y2 = pEnd.Y;
LayoutRoot.Children.Add(l);//划线
if (length < 10)
{
return;
}
binTree(pEnd, length * G, angle + new Random().NextDouble());
binTree(pEnd, length * G, angle - new Random().NextDouble());
}
运行效果:
结束语
还有一些其他类型的分形树(如交错分形树),原理基本相同。做分形做好的程序设计方法是递归。
这些图形都比较简单,要做到真实感图形还要做很多工作。