65.9K
CodeProject 正在变化。 阅读更多。
Home

分形雪

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (38投票s)

2003 年 12 月 14 日

Ms-PL

4分钟阅读

viewsIcon

212594

downloadIcon

5508

介绍了如何使用分形绘制雪花,并包含一个漂亮的雪屏保。

Snow generatedd using fractals

引言

本文介绍了一些分形的基本特征,并演示了如何使用分形绘制雪花。源代码包含一个绘制单个雪花的类和一个用于显示下落雪花的Windows窗体控件。此控件可用于创建屏保应用程序。在屏保应用程序中,雪花是通过随机设置生成的,因此几乎有无限的雪花变化。

分形

分形是几何形状,其中某个模式根据缩放重复出现。也就是说,当你放大对象的某个部分时,它看起来与缩放前的原始对象相同或非常相似。

在程序中,分形是通过递归创建的。相同的(或非常相似的)绘图操作会一直重复,直到递归深度超过指定的次数。在我的应用程序中,绘图操作在连接雪花中心与其边缘的线上执行,然后在第一步创建的新线上执行。

雪花

应用程序使用两种略有不同的算法来制作更多样化的雪花。这两种方法具有相同的输入参数和相同的含义,因此使用这两种方法绘制雪花非常简单。

如果您想了解更多关于雪花是如何生成的以及每个输入参数的作用,请安装屏保并进入设置 - 雪花预览

第一种类型 (LineType)

First type of snow flakes

绘制雪花

  1. 从雪花中心向边缘绘制六个分形分支。
  2. 线段按指定比例分成两部分。
  3. 在找到的点处,以指定角度绘制两条新线。
  4. 操作(从第2步到第4步)在两条新创建的线上重复执行。

第二种类型 (PointType)

Second type of snow flakes

绘制雪花

  1. 从雪花中心向边缘创建六个分形分支(此时不进行绘制!)。
  2. 线段按指定比例分成两部分。
  3. 在找到的点处,创建两条新线(不绘制),角度与指定角度相同。
  4. 操作(从第2步到第4步)在两条新创建的线以及从找到的点到边缘点的第三条线上重复执行。
  5. 超过重复次数后,绘制所有剩余的线。

源代码

UML类图

Uml class diagram

雪花绘制

以下函数是用于绘制第一种雪花类型的简化递归函数

此代码使用 Rotate 函数。此函数绕指定中心旋转点,并在 SnowFlake.cs 中实现。

// Ratio used for calculating dividing point
private const float fBranching=0.3f;
// Ratio used for decreasing length of lines
private const float fShrinking=0.6f;
// Maximal depth of recursion
private const int   iMaxDepth=5;
// Angle between parent and child line (in degrees)
private const int   iBranchAngle=35;

// Draw snowflake branch
// output - Graphics to draw on
// start  - Starting point of line
// end    - Ending point of line
// depth  - Depth of recursion
private void DrawBranch(Graphics output,
         PointF start,PointF end,int depth)
{
  if (depth==iMaxDepth) return;
  DrawLine(output,pn,start,end);

  // calculate dividing point
  PointF cnt=new PointF(start.X+(end.X-start.X)*fBranching,
                 start.Y+(end.Y-start.Y)*fBranching);
  // calculate point used as end (after rotation) of two new lines
  PointF nend=new PointF(cnt.X+(end.X-start.X)*fShrinking,
                 cnt.Y+(end.Y-start.Y)*fShrinking);

  // recursion - draw two new lines
  DrawBranch(output,cnt,Rotate(nend,cnt,iBranchAngle),depth+1);
  DrawBranch(output,cnt,Rotate(nend,cnt,-iBranchAngle),depth+1);
}

使用此代码

使用 SnowFlake

SnowFlake 对象可用于绘制雪花。它有两种绘制方法。第一种方法 Draw(Graphics, PointF) 可用于正常绘制,第二种方法 Draw(Graphics, PointF, int) 允许您为绘制的像素指定 alpha 值。第二种方法用于屏保中的雪花融化。RandomSnowFlake 是派生自 SnowFlake 的类。唯一的区别是,雪花的所有属性都在构造函数中通过随机数生成,因此如果您想创建雪花,则不必设置所有属性。

// Draw snowflakes in Paint event handler
private void Form_Paint(object sender, PaintEventArgs pe)
{
  Random rndGen=new Random();
  pe.Graphics.Clear(Color.Black);
  SnowFlake flake=new SnowFlake(),
     random=new RandomSnowFlake(rndGen.Next(Int32.MaxValue));
            
  // draw snowflake
  flake.Draw(pe.Graphics,new PointF(70.0f,70.0f));
  
  // draw melting snowflake
  flake.Draw(pe.Graphics,new PointF(70.0f,140.0f,128));
  
  // draw random snowflake
  random.Draw(pe.Graphics,new PointF(105.0f,105.0f));
}

使用 SnowControl

SnowControl 是用于创建下落雪花的控件。这与填充屏保整个屏幕的控件完全相同。可以使用设计器将此控件添加到 Form 中,或通过类似以下代码的手动添加:

此控件有很多属性,在屏保设置部分有详细说明。

SnowControl snowCtrl;

public Form()
{
  // Create control
  snowCtrl=new SnowControl();
  Controls.Add(snowCtrl);
  snowCtrl.Dock=DockStyle.Fill;
}

private void Form_Load(object sender,EventArgs e)
{
  // Start animation
  snowCtrl.Start();
}

Screen saver

SnowControl 和屏保设置

环境

名为 StopFalling 的属性是从屏幕底部算起的像素长度,下落的雪花将在该位置停止。如果此属性小于零,雪花将落到屏幕外。下落的雪花会受到风的影响。WindForce 指定了风对雪花的影响程度,WindChanging 决定了风向改变的速度。

雪花

您可以更改屏幕上显示的雪花数量 (MaxFlakes) 和雪花的颜色 (FlakeColor)。大小和速度属性会在指定的最小值和最大值之间随机生成(MinSpeed, MaxSpeedMinSize, MaxSize)。

当雪花落到屏幕底部时,它会在该位置停留指定的帧数 (MeltingStart),之后雪花开始融化,融化过程持续的帧数由 MeltingFluency 属性指定。

背景

屏保的背景可以是任何兼容 .NET 的图像、纯色或两种颜色之间的渐变(顶部和底部颜色)。请注意,如果您将背景设置为图像并且雪花数量较多,则屏保可能会非常慢!

感谢...

感谢 Xenik (Adam Abonyi) 提供此想法、有益的建议以及在撰写此英文文章过程中提供的巨大帮助。额外感谢以下文章的作者。

相关文章

Marc 的分形树为本文提供了很大的启发,另外两篇文章包含有关创建屏保的有用信息,包括多显示器支持以及如何在 .NET 中绘制屏保预览。

  1. 创建分形圣诞树,作者 Marc Clifton。
  2. Christian 和 James 的 Code Project 屏保,作者 Christian Graus 和 James T. Johnson。
  3. 如何在 C# 中开发屏保,作者 Rakesh Rajan。
© . All rights reserved.