DotNet Real Tree






4.74/5 (57投票s)
一个绘制复杂分形树的简单程序
- 下载演示项目 (VS 2003) - 65 KB
- 下载源代码 (VS 2003) - 143.85 KB
- 下载演示项目 (VS 2005) - 191.13 KB
- 下载源代码 (VS 2005) - 393 KB
![]() |
![]() |

引言
新年快乐!
这不是一个实用的程序,它只是一个用数学来玩乐的简单程序。它使用Sin()
和Cos()
函数通过递归来制作一些分形形状和树。它有一个非常简单的算法。
背景
我最初在 2006 年 8 月(VB6 格式)编写了这段代码,以向朋友展示递归函数的功能。不幸的是,他的电子邮件出现了一些问题,没有收到我的 zip 文件,所以我把它放在 PSC 上给他。当我发现它对其他人也有用时,我感到非常惊喜,现在它以 C# 和 VB.NET 的形式在这里。
Using the Code
zip 文件包含为 Visual Studio .NET 2003 和 Visual Studio .NET 2005 编译的 C# 和 VB.NET 源代码。只需打开解决方案文件并编译。创建的可执行文件名为RealTree.exe。
工作原理
1. 您需要一个循环来制作分支
当每个分支在每一步从基部(第 0 步)到顶部分裂成 2 个新分支时,您将拥有2 ^ 步 个分支,当分裂次数更多时,公式为分裂次数 ^ 步。
对于这部分,我使用了递归过程,每次它都使用新的分支位置和角度来调用自身。
在 VB.NET 中
Sub nextBranch(startX As Single, startY As Single, startAngle As Single)
...
'And it runs itself from inside as following:
For j As Integer = 1 To Int(numberOfDivision)
nextBranch(endX, endY, newAngle)
Next
...
End Sub
在 C# 中
Void nextBranch(float startX, float startY, float startAngle)
{
...
//And also it runs itself as:
for(int j= 1;j=(int) numberOfDivision;j++)
{
nextBranch(endX, endY, newAngle);
}
...
}
如您所见,每个分支的结束位置是下一个分支的起始位置。
2. 您必须计算新分支的位置
在标准坐标系中,您可以使用以下公式计算新分支的起始位置(当前分支的结束位置)。
endX = startX + Cos(angle) * sizeOfBranch
endY = startY + Sin(angle) * sizeOfBranch
我们是如何找到这些公式的?请看下面的图。我们的起点是 P,我们想画一些相同长度的线;当我们画更多的线时,它变得越来越像一个数学形状,它像什么?

它像一个圆,我们的第一个点是圆心,我们的线是它的半径,所以对于一条样本 PS 线,我们需要找到 S 的位置。我们在坐标中心画一个半径为 1 个单位的圆来找到 S(X,Y) 的位置。

如果我们从 S 画一条垂直线到 X 轴,它在 H 点与 X 轴相交,PH 是 S 点的 X 坐标。现在,如果我们从 S 画一条水平线到 Y 轴,它在 K 点与 Y 轴相交,PK 是 S 的 Y 坐标。当我们仔细观察我们的点时,我们可以发现 KS 和 PH 的大小相同,PK 和 HS 的大小也相同。所以我们的 S(X,Y) 点可以表示为 S(PH,HS)。
我们有一个直角三角形 PHS,正如您所知,Sin(P-角度)=HS / PS,所以 HS=Sin(角度) * PS;同样,Cos(P-角度)=PH / PS,所以 PH = Cos(角度) * PS。
我们知道 PS 的大小,因为它是圆的半径,所以我们的 S 点位置如下。
S (Cos(angle) * Radius, Sin(angle) * Radius)
S (Cos(60) * 1, Sin(60) * 1) == > S (0.5, 0.86)
现在我们回到我们的项目,我们画一棵树并尝试找到它的分支位置。

我们在位置 P (0, 0),并且知道所有分支的大小都是 10 个单位,对于 PQ 线,我们需要 Q 点的位置。它与 X 轴成 90 度角,它的 X 位置是 Cos(90) * 10,它的 Y 位置是 Sin(90) * 10,所以它是 Q(0,10)。
R 和 S 怎么样?它们之间有 60 度的夹角,但这并不是它们与 X 轴的角度,请看下图以获得更好的视图。

当我们继续 PQ 线时,我们的 QR 和 QS 线与 PQ 线成 30 度角,并且我们知道 PQ 线与 X 轴成 90 度角,所以我们的线的角度是 90 + 30 = 120 度,用于 QR;90 – 30 = 60 度,用于 QS。现在我们计算 R 的位置,它的 X 位置是 Cos(120) * 10 = -5,它的 Y 位置是 Sin(120) * 10 = 8.6,对吧?!
错误!我们的 (-5, 8.6) 位置是形状中像 Z 这样的点,而不是 R,因为当我们从 P 移动到 Q 时,我们的初始位置发生了变化,当我们想计算 R 的位置时,我们是在 Q 位置而不是 P 位置,所以我们必须将这些变化计入我们的公式,这意味着我们将新的计算添加到起始位置,所以我们的 X 值必须是 -5 + Qx = -5 + 0 = -5,我们的 Y 值必须是 8.6 + Qy = 8.6 + 10 = 18.6,所以真实位置是 R(-5, 18.6),我们找到了我们的主要公式。
X = startX + Cos(angle) * sizeOfBranch
Y = startY + Sin(angle) * sizeOfBranch
现在我们计算其他点的位置。
Sx = 0 + Cos(60) * 10 = 5,Sy = 10 + Sin(60) * 10 = 18.6,所以它是 S(5, 18.6)。
T 和 U 之间有一个 60 度的夹角,这意味着它们每个都与它们的起始角度有 30 度的差异,并且我们知道它们的起始角度是 120 度,所以 RT 线与 X 轴成 120 + 30 = 150 度角,RU 线与 X 轴成 120 - 30 = 90 度角,所以这些点的位置如下。
Tx = -5 + Cos(150) * 10 = -13.6,Ty = 18.6 + Sin(150) * 10 = 23.6,所以我们可以将其显示为 T(-13.6, 23.6)。
Ux = -5 + Cos(90) * 10 = -5,Uy = 18.6 + Sin(90) * 10 = 28.6,这意味着 U(-5, 28.6)。
V 和 W 怎么样?现在您知道它们每个都与起始点角度有 30 度的差异,所以 SV 线与 X 轴成 60 + 30 = 90 度角,SW 线与 X 轴成 60 - 30 = 30 度角,这些点的位置如下。
Vx = 5 + Cos(90) * 10 = 5,Vy = 18.6 + Sin(90) * 10 = 28.6,所以它是 V(5, 28.6)。
Wx = 5 + Cos(30) * 10 = 13.6,Wy = 18.6 + Sin(30) * 10 = 23.6,所以 W(13.6, 23.6)。
注意:标准坐标和计算机坐标之间存在一个简单的区别,在计算机坐标中,Y 轴的正值朝屏幕底部增长。
这是标准坐标。

这是计算机坐标。

所以我们必须像这样修改 Y 值的公式。
endY = startY - Sin(angle) * sizeOfBranch
3. 关于风、叶片级别等效果呢?
这些效果会通过数学公式改变分支的大小、位置或数量。
接口
它有一个简单的 GUI;您可以从菜单中选择一些预定义的类型或创建新类型。

总步数(3 - 100):您想要绘制的最大步数。
每步分裂数(1-100):每个分支在下一步分裂成此数量的分支。
起始分支(1-总步数):如果您使用大于 1 的数字,程序将只显示所选步数之外的分支。
固定大小(选中或未选中 & 百分比):选中时,每一步的所有分支大小相同,百分比部分决定了树的总大小。
固定角度(选中或未选中 & 百分比):选中时,每一步的所有分支之间的角度都相同,百分比部分决定了每一步分支之间的总角度。
断裂分支(选中或未选中 & 百分比):选中时,树中会有断裂的分支,百分比部分决定了其数量。
BB 比例(50 ± 50):(断裂分支比例)表示断裂效果对较低分支或较高分支的影响更大。
DPS 比例(50 ± 50):(每步分裂比例)当您向右拖动时,较高分支的 DPS 比基础 DPS 更大;当您向左拖动时,较高分支的 DPS 比基础 DPS 更小。
叶片级别(50 ± 50):它决定叶片应该出现在较高分支还是较低分支。
树干高度(50 ± 50):树干高度相对于默认大小的变化。
宽度(50 ± 50):分支宽度的变化。
宽度比例(50 ± 50):分支宽度从基部到叶片的改变量。
风(50 ± 50):风力大小和方向。
宽度增加(500 ± 500):这是一个特殊效果;您必须实际看到它才能理解,我需要对其值和结果做一些修改。
注意
当您对“总步数”或“每步分裂数”使用较高值时,渲染可能需要很长时间,因此使用“断裂分支”和“每步分裂比例”可以使其更好。
如果您对“每步分裂数”使用大于 2 的值,您必须对“断裂分支”使用更高的值,这会创建一个狂野的树。[例如,当“总步数”=30 时,使用以下值:(DPS=3, BB=52), (DPS=4, BB=65), (DPS=5, BB=72), (DPS=6, BB=77), (DPS=7, BB=81), (DPS=8, BB=83)...] 如果您想禁用“断裂分支”,您必须对“总步数”使用较低的值(约 15,取决于您计算机的速度)。
关注点
您可以通过更改或添加新变量来创建各种有趣的 the fractals。
历史
- 2007 年 1 月:上传到 The Code Project
- 2007 年 4 月:版本 1.5:添加了宽度增加效果和一些新示例
- 2009 年 3 月:版本 1.6:添加了计时器、一些新示例,并更新到 Visual Studio 2005