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

使用 Visual C++ 6.0 在 Win32 控制台中实时动画显示曼德尔布罗集缩放

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.16/5 (23投票s)

2010年5月22日

CPOL

5分钟阅读

viewsIcon

71192

downloadIcon

1528

本文介绍如何使用 Visual C++ 6.0 在 Win32 控制台中创建曼德尔布罗集缩放的实时动画。

引言

这个简单的应用程序演示了如何使用 Visual C++ 6.0 在 Win32 控制台中创建一个简单的实时曼德尔布罗集缩放。但在开始之前,让我们先来了解一下复数和曼德尔布罗集的数学原理。

复数

复数是一个由实部和虚部组成的数,可以写成 Z = X + iY 的形式,其中 XY 是实数,i 是标准的虚数单位,满足 i2 = -1。复数包含普通的实数,但通过引入 i 和额外的虚数来扩展它们。

共形映射

共形映射是一个函数,在变换到特定坐标系时会保持角度不变。共形映射同时保持角度和无限小的图形形状,但不一定保持其大小。在最常见的情况下,函数是在复平面中的域之间进行的,这就引出了曼德尔布罗集。我们将使用共形映射将曼德尔布罗集映射到二维坐标系。

矩形网格函数 f(左)及其在共形映射函数 f(右)下的图像。
可以看出,函数 f 将相交于 90° 的直线对映射为仍然相交于 90° 的曲线对。

曼德尔布罗集

在数学中,曼德尔布罗集是复平面中的点集,其边界形成一个分形。当在复平面上计算和绘制时,曼德尔布罗集 具有复杂的边界,无论放大多少倍都不会简化。

曼德尔布罗集的面积可以精确地写为:

04.jpg

其中 bn 是单位圆盘外部到曼德尔布罗集外部的共形映射在无穷远处的洛朗级数系数。此外,曼德尔布罗集被定义为复数 C 的集合,对于该集合,0 在复二次多项式 zn+1 = Z2n + C 的迭代下保持有界。例如,如果复数 c 满足以下条件,则它属于曼德尔布罗集:从 Z0 = 0 开始,重复应用迭代,无论 n 有多大,Zn 的绝对值都不会超过某个特定值。

magnitude.JPG

要创建分形,我们需要找到许多属于曼德尔布罗集的数字。
为此,我们需要一个测试来确定给定的数字是位于曼德尔布罗集内部还是外部。该测试基于方程 zn+1 = Z2n + C 。这里的 C 代表一个常数,意味着它在测试过程中不会改变,我们并不真正关心 Z 的实际变化值,我们只关注它的模长或到零的距离,然后我们将根据该模长设置颜色,并使用共形映射将其绘制到二维坐标系上。

曼德尔布罗集缩放的工作原理

  • 首先,我们设置计算曼德尔布罗集的边界值。
  • 然后,我们设置初始值并进行计算,根据曼德尔布罗集计算出的模长设置颜色,并使用共形映射将其映射到二维坐标系。
  • 在此步骤之后,我们以每秒 60 帧的速度重复计算并实时动画。
  • 完成了。

类 CMandelzoom

我们像往常一样创建一个项目和一个类。我们将类命名为 CMandelzoom,然后继续用类成员来充实它。

但我们选择不在头文件CMandelzoom.h中定义和实现我们的成员函数,我们只将函数或方法的原型放在CMandelzoom.h中。成员函数的实现将在CMandelzoom.cpp中完成。

Visual C++ 6.0 项目文件包括:

CMandelzoom_main.cpp

主文件

CMandelzoom.cpp

类定义和方法体文件

CMandelzoom.h

类声明文件

CTextMode.h

控制台文本模式图形类

我们的类 CMandelzoom 从类 CTextMode 继承了函数方法,所以我们需要包含此语法。

 CMandelzoom::CMandelzoom( int i) : CTextMode()

现在,继承之后,CTextMode.h中的函数和方法就与
我们类 CMandelzoom 中的函数方法“融为一体”了。我们可以像对待 CMandelzoom 的原生方法一样对待那些方法。

我们还将要在启动时初始化的函数调用放在构造函数中,
这样,当我们的类被实例化时,这些函数方法就会被调用和执行。

initFractal() 方法

initFractal() 方法设置计算曼德尔布罗集的边界。

void CMandelzoom::initFractal(double x0,double y0,double x1,double y1)
{
xx++;
	 zoomcount =zoomcount+1;
	 xmin =x0;
	 ymin =y0;
	 xmax =x1;
	 ymax =y1;
	 zxmin =xmin-(0.0012)/1.666666;
	 zymin =ymin;
	 zxmax =xmax-(0.0012)/1.666666;
	 zymax =ymax;

	 if(zoomcount>150)
	 {
	   zoomcount=0;
	   xzoomfactor=-xzoomfactor;
	   yzoomfactor=-yzoomfactor;

	   xmin =-xmin;
	   ymin =-ymin;
	   xmax =-xmax;
	   ymax =-ymax;
	 }
} 

putpixel() 方法

putpixel() 方法在控制台窗口上绘制一个点。

 void CMandelzoom::putpixel (unsigned int x, unsigned int y, unsigned char c)
 {
   txtPlot(x,y,c);
 } 

getFractalColor() 方法

getFractalColor() 方法根据曼德尔布罗集计算出的模长返回一个颜色。

int CMandelzoom::getFractalColor(int x,int y)
{
	  double p,q,r,i,prev_r,prev_i;
	  int n;

	  p =(x*widthfactor)+xmin;
	  q =(y*heightfactor)+ymin;

	  prev_i =0;
	  prev_r =0;

	  for (n=0;n<=numcolors;n++)
	  {
		   r =(prev_r*prev_r)-(prev_i*prev_i)+p;
		   i =2*(prev_r*prev_i)+q;

		   if (((r*r) + (i*i)) < cutoff)
		   {
				prev_r =r;
				prev_i =i;
		   }
		   else  return n;
	  }

	  return n;
} 

calculateFractal() 方法

calculateFractal() 方法通过使用 putpixel() 方法,并以 getFractalColor() 计算的颜色值,将曼德尔布罗集共形映射到二维坐标系并在控制台窗口上绘制。

void  CMandelzoom::calculateFractal()
{
   int  x,y,tempcol=0;

	heightfactor =(ymax-ymin)/Height;
	widthfactor =(xmax-xmin)/Width;
	for (y=0; y<=Height;y++)
	{
		 for(x=0;x<=Width;x++)
		 {
			  putpixel(x+ (40-(Width /2)),y+(12-(Height /2)+2),
				getFractalColor(x,y));
		 }
	}
   	setcolor(15);
} 

zoom() 方法

zoom() 方法简单地增加或减少初始值并计算新的曼德尔布罗集分形。

void CMandelzoom::zoom()
{
	 zxmin =zxmin+xzoomfactor;
	 zymin =zymin+yzoomfactor;
	 zxmax =zxmax-xzoomfactor;
	 zymax =zymax-yzoomfactor;
	 initFractal(zxmin,zymin,zxmax,zymax);

	 calculateFractal();
	 delay(20);
} 

实时动画

函数 Realtime_Animate_At_60_Frames_Per_Second() 以每秒 60 帧的速度实时连续缩放并更新图像。

void CMandelzoom::Realtime_Animate_At_60_Frames_Per_Second()
{
 NewTicksPerSecond=GetTickCount();
 DeltaTicksPerSecond=NewTicksPerSecond-OldTicksPerSecond;
 frames++;
  if(DeltaTicksPerSecond>=PreferredFramesPerSecond) 
  {
    key2();
    zoom(); 

    OldTicksPerSecond=NewTicksPerSecond;
    InverseFramesPerSecond=1/((float)PreferredFramesPerSecond/1000.0f);	
    OneFramePerSecond=(float)frames*InverseFramesPerSecond;	
    fps+=OneFramePerSecond;
    fps/=2;
    setcolor(31);gotoxy(70,22);printf(" %d FPS ",DeltaTicksPerSecond );setcolor(15);
    frames=0;
    Refesh=60/fps;
   }
   Sleep(33);
}

Realtime_Animate_At_60_Frames_Per_Second() 函数调用在一个 while 循环中完成。应用程序实时动画,并等待用户按下“Escape”键,
当按下“Escape”键时,应用程序退出。

while(ch!=27)
{	 
    Realtime_Animate_At_60_Frames_Per_Second()  //only update every 60 frames per second
}

主文件

最后,在文件CMandelzoom_main.cpp中,我们创建了类的实例并运行了我们的应用程序。

#include "CMandelzoom.h"

int main()
{
  CMandelzoom *mandelZoom  = new CMandelzoom(1);
  return 0;
}

这就是在 Win32 控制台中创建曼德尔布罗集缩放实时动画的简单方法。

感谢阅读。

© . All rights reserved.