妙妙小豆子

胆子大一点,想开一点。长风破浪会有时,直挂云帆济沧海

常见分形图案的演示 银牌收录

程序简介

这个程序包含了一些常见分形图案的动画演示,并提供了一些按钮来改变有意义的可变变量,创造不一样的分形图案。按动画演示按钮即可开启动画。

这个程序的分形大致分为三类:
第一类:线型,特点是每条线按一定的规律变成几条线。
第二类:几何型,特点是每个几何图案按一定的规律生成多个新的几何图案。
第三类:点型,特点是每个点的值按一定的规律重新迭代计算,根据点的数值大小确定图案。

分形图案演示列表:
1. 科赫雪花
2. 拆分三角形
3. 列维曲线
4. 龙形曲线
5. 正方形折线
6. 分形树
7. 分形二叉树
8. 谢尔宾斯基三角形
9. 谢尔宾斯基正方形
10. 海岸线
11. 闵可夫斯基曲线
12. Mandelbrot 集
13. Julia 集
14. 多边形分形

第一次更新:
1.参照参考资料,模仿出列表框功能。并抽象出列表框结构体,方便以后其他程序的使用。
2.将可调变量制成按钮,方便调整。
3.对正方形折线添加正多边形变量功能,现在可以画正三到正六边形。
4.对分形二叉树添加剪枝概率变量功能,现在可以调整剪枝概率。
5.对 Julia 集与 Mandelbrot 集添加上色功能,现在可以切换是否上色。

第二次更新:
1.对窗口名称,文章名称的更改。
2.程序执行效果的多张动图整成一张动图。
3.添加了多边形分形:这种分形我没有证明,感兴趣可以证明。只要是多边形,找一个点,与任意一边相连得三角形,找重心为新点,即三个顶点坐标平均,循环即可。原视频正六边形挺好看,我学习了一下,但我找不到原视频了。找了一个类似的视频,它的原理是找一个点,与任意顶点相连取中点为新点,循环即可。类似的原理也可以创造不一样的分形图案。这类分形应当也属于点型。

第三次更新:
1. 图片更新,减小边框
2. 代码更新,现在兼容 vc2010,不兼容 vc6.0
vc2010:_stscanf_s,vc6.0:_stscanf
vc2010:_stprintf_s,vc6.0:_stprintf

程序执行效果

完整源代码

////////////////////////////////////////
// 程序:常见分形图案的演示
// 作者:Gary
// 编译环境:Visual C++ 2010,EasyX_20211109
// 编写日期:2020-11-10

# include <math.h>
# include <graphics.h>
# include <string>
# include <stdlib.h>
# include <time.h>

static double pi = acos (-1.0);			// 圆周率 π
static HWND hOut;						// 画布

// 定义一个结构体,按钮
struct Node1
{
	int posx1, posy1, posx2, posy2;		// 坐标
	int type;							// 按钮激活状态
	double r;							// 圆按钮半径
	COLORREF color;						// 颜色
	LPTSTR text;						// 文字
	int time_of_fractal;				// 可分形次数
};

// 定义一个结构体,列表框
struct Node2
{
	int posx1, posy1, posx2, posy2;		// 坐标
	double every_text_num;				// 列表框每次展示文本数量
	double all_text_num;				// 列表框所有文本数量
	int flag_text_num;					// 列表框当前选定文本编号
	Node1 box_button[20];				// 按钮,预制

};

// 定义一个结构体,分形
struct Node3
{
	double posx1, posy1;				// 坐标
	double posx2, posy2;				// 坐标
	double posx3, posy3;				// 坐标
	double R;							// 长度
};

// 定义一个结构体,临时储存
struct Node4
{
	double posx1, posy1;				// 坐标
	double posx2, posy2;				// 坐标
	double posx3, posy3;				// 坐标
	double R;							// 长度
};

// 定义一个结构体,另一个分形
struct Node5
{
	double x, y;						// 点值
	double x0, y0;						// 点值
	int lifenum;						// 颜色
};

// 定义一个类
class Gary
{
public:
	void carry ();						// 主进程
	void initialization ();				// 初始化
	void initialization_fractal ();		// 分形初始化
	void move ();						// 窗口主视角
	void draw_scene ();					// 绘制界面函数
	void draw_fractal (int num);		// 分形绘制函数
	void refresh_fractal ();			// 分形参数更新函数
	Node1 box_button[6];				// 按钮,预制
	Node2 box_list[1];					// 列表框,预制
	int exit_carry;						// 主循函数控制参数
	int exit_move;						// 开始界面控制参数
	int num_button;						// 按钮数量参数
	int num_list;						// 数量参数
	double R, r1, r2;					// 长度变量参数
	double w, w0, w1, w2;				// 角度变量参数
	double flag, flag1, flag2;			// 数量变量参数	
	double Cx, Cy, Zx, Zy;				// Julia 集与 Mandelbrot 集所需的四个变量参数
	int color_or_not;					// Julia 集与 Mandelbrot 集绘制是否上色参数
	int pruning_probability;			// 剪枝概率参数
};

// 如果放类内,堆栈分配不够,每次都要重调,就放外面了
Node3 box[30000];
Node4 eat[30000];
Node5 box_set[500][500];

// 分形参数初始化函数
void Gary::initialization_fractal ()
{
	int i, j, k;

	// 参数初始化
	switch (box_list[0].flag_text_num)
	{
		// 科赫雪花
	case 3:
	{
		// 分形参数初始化
		flag = 3; R = 400;
		// 线参数初始化
		box[0].posx1 = 250; box[0].posy1 = 10; box[0].posx2 = 50; box[0].posy2 = 10 + R / 2 * sqrt (3.0);
		box[1].posx1 = 50; box[1].posy1 = 10 + R / 2 * sqrt (3.0); box[1].posx2 = 450; box[1].posy2 = 10 + R / 2 * sqrt (3.0);
		box[2].posx1 = 450; box[2].posy1 = 10 + R / 2 * sqrt (3.0); box[2].posx2 = 250; box[2].posy2 = 10;
		break;
	}
	// 拆分三角形
	case 4:
	{
		// 分形参数初始化
		flag1 = 2; flag2 = 1; R = 240.0; r1 = R; r2 = R;
		// 线参数初始化
		box[0].posx1 = 250; box[0].posy1 = 10; box[0].posx2 = 250 - cos (w / 180.0 * pi) * R; box[0].posy2 = 10 + sin (w / 180.0 * pi) * R;
		eat[0].posx1 = box[0].posx2; eat[0].posy1 = box[0].posy2; eat[0].posx2 = 250 + cos (w / 180.0 * pi) * R; eat[0].posy2 = box[0].posy2;
		box[1].posx1 = eat[0].posx2; box[1].posy1 = box[0].posy2; box[1].posx2 = box[0].posx1; box[1].posy2 = box[0].posy1;
		break;
	}
	// Levy 曲线
	case 5:
	{
		// 分形参数初始化
		flag = 1; R = 200;
		// 线参数初始化
		box[0].posx1 = 400; box[0].posy1 = 150; box[0].posx2 = 400; box[0].posy2 = 350;
		break;
	}
	// 龙形曲线
	case 6:
	{
		// 分形参数初始化
		flag = 1; R = 200;
		// 线参数初始化
		box[0].posx1 = 250; box[0].posy1 = 150; box[0].posx2 = 250; box[0].posy2 = 350;
		break;
	}
	// 正方形折线
	case 7:
	{
		// 分形参数初始化
		flag = 1; R = 300; w0 = 360.0 / w;
		// 线参数初始化	
		box[0].posx1 = 100; box[0].posy1 = 250; box[0].posx2 = 400; box[0].posy2 = 250;
		break;
	}
	// 分形树
	case 8:
	{
		// 分形参数初始化
		flag1 = 0; flag2 = 1; R = 100;
		// 线参数初始化
		box[0].posx1 = 250; box[0].posy1 = 490; box[0].posx2 = 250; box[0].posy2 = 490 - R; box[0].R = R;
		break;
	}
	// 分形二叉树
	case 9:
	{
		// 分形参数初始化
		flag1 = 0; flag2 = 1; R = 100;
		// 线参数初始化	
		box[0].R = R; box[0].posx1 = 250; box[0].posy1 = 490; box[0].posx2 = 250; box[0].posy2 = 490 - R;
		break;
	}
	// 谢尔宾斯基三角形
	case 10:
	{
		// 分形参数初始化
		flag = 1; R = 400;
		// 线参数初始化			
		box[0].posx1 = 250; box[0].posy1 = 10;
		box[0].posx2 = 50; box[0].posy2 = 10 + 200 * sqrt (3.0);
		box[0].posx3 = 450; box[0].posy3 = 10 + 200 * sqrt (3.0);
		break;
	}
	// 谢尔宾斯基正方形
	case 11:
	{
		// 分形参数初始化
		flag = 1; R = 75;
		// 线参数初始化
		box[0].posx1 = 250; box[0].posy1 = 250; box[0].R = 75;
		break;
	}
	// 海岸线
	case 12:
	{
		// 分形参数初始化
		flag = 1; R = 300;
		// 线参数初始化
		box[0].posx1 = 100; box[0].posy1 = 250; box[0].posx2 = 400; box[0].posy2 = 250;
		break;
	}
	// 闵可夫斯基曲线
	case 13:
	{
		// 分形参数初始化
		flag = 1; R = 300;
		// 线参数初始化
		box[0].posx1 = 100; box[0].posy1 = 250; box[0].posx2 = 400; box[0].posy2 = 250;
		break;
	}
	// Mandelbrot 集
	case 14:
	{
		// 点参数初始化
		for (i = 0; i < 500; i++)
		{
			for (j = 0; j < 500; j++)
			{
				// M 集,固定 z,z 是设定值
				box_set[i][j].x = Zx;
				box_set[i][j].y = Zy;

				box_set[i][j].x0 = (-250.0 + i) / 100.0;
				box_set[i][j].y0 = (-250.0 + j) / 100.0;
				box_set[i][j].lifenum = 0;
			}
		}
		break;
	}
	// Julia 集
	case 15:
	{
		// 点参数初始化
		for (i = 0; i < 500; i++)
		{
			for (j = 0; j < 500; j++)
			{
				// J 集,固定 c,c 是设定值
				box_set[i][j].x = (-250.0 + i) / 100.0;
				box_set[i][j].y = (-250.0 + j) / 100.0;

				box_set[i][j].lifenum = 0;
			}
		}
		break;
	}
	// 多边形分形
	case 16:
	{
		// 分形参数初始化
		flag = w; R = 300;
		// 线参数初始化
		for (i = 0; i < flag; i++)
		{
			box[i].posx1 = 250 + 200 * cos (360.0 / double (flag) * double (i) / 180.0 * pi);
			box[i].posy1 = 250 + 200 * sin (360.0 / double (flag) * double (i) / 180.0 * pi);
			box[i].posx2 = 250 + 200 * cos (360.0 / double (flag) * double (i + 1) / 180.0 * pi);
			box[i].posy2 = 250 + 200 * sin (360.0 / double (flag) * double (i + 1) / 180.0 * pi);
		}
		box[int (flag)].posx1 = 250;
		box[int (flag)].posy1 = 250;
		break;
	}
	default:break;
	}

	// 按钮初始化
	k = box_list[0].flag_text_num;

	// 矩形按钮
	for (i = 0; i < 6; i++)
	{
		box_button[i].type = 0;
	}
	box_button[2].text = _T ("动画演示");	box_button[2].type = 1;

	// 分情况绘制
	// 类似雪花
	if (k == 3 || k == 4 || k == 5 || k == 6)
	{
		box_button[0].text = _T ("角度");	box_button[0].type = 1;
	}
	else if (k == 7 || k == 16)
	{
		box_button[0].text = _T ("正多边形");	box_button[0].type = 1;
		if (k == 16)
		{
			box_button[3].text = _T ("迭代次数");	box_button[3].type = 1;
		}
	}
	// 类似分形树
	else if (k == 8 || k == 9)
	{
		box_button[0].text = _T ("长度一");	box_button[0].type = 1;
		box_button[1].text = _T ("长度二");	box_button[1].type = 1;
		box_button[3].text = _T ("角度一");	box_button[3].type = 1;
		box_button[4].text = _T ("角度二");	box_button[4].type = 1;
		if (k == 9)
		{
			box_button[5].text = _T ("剪枝概率");	box_button[5].type = 1;
		}
	}
	// M 集和 J 集
	else if (k == 14 || k == 15)
	{
		box_button[0].text = _T ("X 值");		box_button[0].type = 1;
		box_button[1].text = _T ("Y 值");		box_button[1].type = 1;
		box_button[3].text = _T ("迭代次数");	box_button[3].type = 1;
		box_button[4].text = _T ("是否上色");	box_button[4].type = 1;
	}
}

// 分形参数更新函数
void Gary::refresh_fractal ()
{
	int i, j, n, l;
	double k;
	double x, y;

	switch (box_list[0].flag_text_num)
	{
		// 科赫雪花
	case 3:
	{
		// 长度迭代
		R = R / 2.0 / (cos (w / 180.0 * pi) + 1.0);
		// 上一次线段总数
		// 每次迭代都要对上次所有线段进行分段
		j = int (flag);
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条,剪短
			box[i].posx2 = box[i].posx1 + cos (double (k) / 180.0 * pi) * R;
			box[i].posy2 = box[i].posy1 + sin (double (k) / 180.0 * pi) * R;

			// 第二条
			k += w;
			box[j].posx1 = box[i].posx2;
			box[j].posy1 = box[i].posy2;
			box[j].posx2 = box[j].posx1 + cos (double (k) / 180.0 * pi) * R;
			box[j].posy2 = box[j].posy1 + sin (double (k) / 180.0 * pi) * R;

			// 第三条
			k -= 2 * w;
			box[j + 1].posx1 = box[j].posx2;
			box[j + 1].posy1 = box[j].posy2;
			box[j + 1].posx2 = box[j + 1].posx1 + cos (double (k) / 180.0 * pi) * R;
			box[j + 1].posy2 = box[j + 1].posy1 + sin (double (k) / 180.0 * pi) * R;

			// 第四条
			k += w;
			box[j + 2].posx1 = box[j + 1].posx2;
			box[j + 2].posy1 = box[j + 1].posy2;
			box[j + 2].posx2 = box[j + 2].posx1 + cos (double (k) / 180.0 * pi) * R;
			box[j + 2].posy2 = box[j + 2].posy1 + sin (double (k) / 180.0 * pi) * R;

			// 一变三
			j += 3;
		}
		flag = j;
		break;
	}
	// 拆分三角形
	case 4:
	{
		// 长度迭代
		r1 = r2 * cos (w / 180.0 * pi) / (cos (2.0 * w / 180.0 * pi) + 1.0);
		r2 = r2 / 2.0 / (cos (2 * w / 180.0 * pi) + 1.0);
		// 每次迭代都要对上次所有线段进行分段
		// 奇次迭代
		j = int (flag2);
		for (i = 0; i < flag2; i++)
		{
			// 读取线段方向
			k = atan ((eat[i].posy2 - eat[i].posy1) / (eat[i].posx2 - eat[i].posx1)) * 180.0 / pi;
			if ((eat[i].posx2 - eat[i].posx1) < 0)k += 180;

			// 第一条,剪短
			eat[i].posx2 = eat[i].posx1 + cos (double (k) / 180.0 * pi) * r1;
			eat[i].posy2 = eat[i].posy1 + sin (double (k) / 180.0 * pi) * r1;

			// 第二条
			k -= 2 * w;
			eat[j].posx1 = eat[i].posx2;
			eat[j].posy1 = eat[i].posy2;
			eat[j].posx2 = eat[j].posx1 + cos (double (k) / 180.0 * pi) * r1;
			eat[j].posy2 = eat[j].posy1 + sin (double (k) / 180.0 * pi) * r1;

			// 第三条
			k += 4 * w;
			eat[j + 1].posx1 = eat[j].posx2;
			eat[j + 1].posy1 = eat[j].posy2;
			eat[j + 1].posx2 = eat[j + 1].posx1 + cos (double (k) / 180.0 * pi) * r1;
			eat[j + 1].posy2 = eat[j + 1].posy1 + sin (double (k) / 180.0 * pi) * r1;

			// 第四条
			k -= 2 * w;
			eat[j + 2].posx1 = eat[j + 1].posx2;
			eat[j + 2].posy1 = eat[j + 1].posy2;
			eat[j + 2].posx2 = eat[j + 2].posx1 + cos (double (k) / 180.0 * pi) * r1;
			eat[j + 2].posy2 = eat[j + 2].posy1 + sin (double (k) / 180.0 * pi) * r1;

			// 一变三
			j += 3;
		}
		flag2 = j;

		// 偶次迭代
		j = int (flag1);
		for (i = 0; i < flag1; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条,剪短
			box[i].posx2 = box[i].posx1 + cos (double (k) / 180.0 * pi) * r2;
			box[i].posy2 = box[i].posy1 + sin (double (k) / 180.0 * pi) * r2;

			// 第二条
			k -= 2 * w;
			box[j].posx1 = box[i].posx2;
			box[j].posy1 = box[i].posy2;
			box[j].posx2 = box[j].posx1 + cos (double (k) / 180.0 * pi) * r2;
			box[j].posy2 = box[j].posy1 + sin (double (k) / 180.0 * pi) * r2;

			// 第三条
			k += 4 * w;
			box[j + 1].posx1 = box[j].posx2;
			box[j + 1].posy1 = box[j].posy2;
			box[j + 1].posx2 = box[j + 1].posx1 + cos (double (k) / 180.0 * pi) * r2;
			box[j + 1].posy2 = box[j + 1].posy1 + sin (double (k) / 180.0 * pi) * r2;

			// 第四条
			k -= 2 * w;
			box[j + 2].posx1 = box[j + 1].posx2;
			box[j + 2].posy1 = box[j + 1].posy2;
			box[j + 2].posx2 = box[j + 2].posx1 + cos (double (k) / 180.0 * pi) * r2;
			box[j + 2].posy2 = box[j + 2].posy1 + sin (double (k) / 180.0 * pi) * r2;

			// 一变三
			j += 3;
		}
		flag1 = j;
		break;
	}
	// 列维曲线
	case 5:
	{
		n = 0;
		// 长度迭代
		R = R / 2.0 / cos (w / 180 * pi);
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条
			k += w;
			eat[n].posx1 = box[i].posx1;
			eat[n].posy1 = box[i].posy1;
			eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
			eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

			// 第二条
			k -= 2 * w;
			eat[n + 1].posx1 = eat[n].posx2;
			eat[n + 1].posy1 = eat[n].posy2;
			eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
			eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);

			// 一变二
			n += 2;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2;
			box[i].posy2 = eat[i].posy2;
		}
		flag = n;
		break;
	}
	// 龙形曲线
	case 6:
	{
		// 长度迭代
		R = R / 2.0 / cos (w / 180.0 * pi);
		n = 0;
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 奇
			if (i % 2 == 0)
			{
				// 第一条
				k += w;
				eat[n].posx1 = box[i].posx1;
				eat[n].posy1 = box[i].posy1;
				eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
				eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

				// 第二条
				k -= 2 * w;
				eat[n + 1].posx1 = eat[n].posx2;
				eat[n + 1].posy1 = eat[n].posy2;
				eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
				eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);
			}
			// 偶
			else
			{
				// 第一条
				k -= w;
				eat[n].posx1 = box[i].posx1;
				eat[n].posy1 = box[i].posy1;
				eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
				eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

				// 第二条
				k += 2 * w;
				eat[n + 1].posx1 = eat[n].posx2;
				eat[n + 1].posy1 = eat[n].posy2;
				eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
				eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);
			}

			// 一变二
			n += 2;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2;
			box[i].posy2 = eat[i].posy2;
		}
		flag = n;
		break;
	}
	// 正方形折线
	case 7:
	{
		n = 0;
		// 三分之一和三方之二处画正多边形
		// 长度迭代
		R = R / 3.0;
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条
			eat[n].posx1 = box[i].posx1;
			eat[n].posy1 = box[i].posy1;
			eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
			eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

			// 第二条
			k -= (180 - w0);
			eat[n + 1].posx1 = eat[n].posx2;
			eat[n + 1].posy1 = eat[n].posy2;
			eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
			eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);

			// 第三条到倒数第二条
			for (j = n + 2; j < n + w; j++)
			{
				k += w0;
				eat[j].posx1 = eat[j - 1].posx2;
				eat[j].posy1 = eat[j - 1].posy2;
				eat[j].posx2 = eat[j].posx1 + R * cos (k / 180 * pi);
				eat[j].posy2 = eat[j].posy1 + R * sin (k / 180 * pi);
			}

			// 最后一条
			k -= (180 - w0);
			eat[j].posx1 = eat[j - 1].posx2;
			eat[j].posy1 = eat[j - 1].posy2;
			eat[j].posx2 = eat[j].posx1 + R * cos (k / 180 * pi);
			eat[j].posy2 = eat[j].posy1 + R * sin (k / 180 * pi);

			// 一变(w + 1)
			n = int (n + (w + 1));
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2;
			box[i].posy2 = eat[i].posy2;
		}

		flag = n;
		break;
	}
	// 分形树
	case 8:
	{
		j = 0;
		n = int (flag1 + flag2);
		// 树枝长新枝
		for (i = int (flag1); i < flag1 + flag2; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条
			k -= w2;
			box[n].R = box[i].R / r2;
			box[n].posx1 = (box[i].posx1 + box[i].posx2) / 2.0;
			box[n].posy1 = (box[i].posy1 + box[i].posy2) / 2.0;
			box[n].posx2 = box[n].posx1 + box[n].R * cos (k / 180 * pi);
			box[n].posy2 = box[n].posy1 + box[n].R * sin (k / 180 * pi);

			// 第二条
			box[n + 3].R = box[i].R / (r2 + 0.5);
			box[n + 3].posx1 = box[i].posx2;
			box[n + 3].posy1 = box[i].posy2;
			box[n + 3].posx2 = box[n + 3].posx1 + box[n + 3].R * cos (k / 180 * pi);
			box[n + 3].posy2 = box[n + 3].posy1 + box[n + 3].R * sin (k / 180 * pi);

			// 第三条
			k += 2 * w2;
			box[n + 2].R = box[i].R / (r2 + 0.5);
			box[n + 2].posx1 = box[i].posx2;
			box[n + 2].posy1 = box[i].posy2;
			box[n + 2].posx2 = box[n + 2].posx1 + box[n + 2].R * cos (k / 180 * pi);
			box[n + 2].posy2 = box[n + 2].posy1 + box[n + 2].R * sin (k / 180 * pi);

			// 第四条
			box[n + 1].R = box[i].R / r2;
			box[n + 1].posx1 = (box[i].posx1 + box[i].posx2) / 2.0;
			box[n + 1].posy1 = (box[i].posy1 + box[i].posy2) / 2.0;
			box[n + 1].posx2 = box[n + 1].posx1 + box[n + 1].R * cos (k / 180 * pi);
			box[n + 1].posy2 = box[n + 1].posy1 + box[n + 1].R * sin (k / 180 * pi);

			// 第五条
			k = k + w1 - w2;
			box[n + 4].R = box[i].R / r1;
			box[n + 4].posx1 = box[i].posx2;
			box[n + 4].posy1 = box[i].posy2;
			box[n + 4].posx2 = box[n + 4].posx1 + box[n + 4].R * cos (k / 180 * pi);
			box[n + 4].posy2 = box[n + 4].posy1 + box[n + 4].R * sin (k / 180 * pi);

			// 一变五
			j += 5;
			n += 5;
		}
		// 树枝变树干
		flag1 += flag2;
		// 新生成的是树枝
		flag2 = j;

		break;
	}
	// 分形二叉树
	case 9:
	{
		j = 0;
		n = int (flag1 + flag2);
		for (i = int (flag1); i < flag1 + flag2; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 随机剪枝概率
			l = rand () % pruning_probability;

			// 正常
			if (l == 0)
			{
				// 第一条
				k -= w1;
				box[n].R = box[i].R / r1;
				box[n].posx1 = box[i].posx2;
				box[n].posy1 = box[i].posy2;
				box[n].posx2 = box[n].posx1 + box[n].R * cos (k / 180 * pi);
				box[n].posy2 = box[n].posy1 + box[n].R * sin (k / 180 * pi);
				j += 1;
				n += 1;

				// 第二条
				k = k + w1 + w2;
				box[n].R = box[i].R / r2;
				box[n].posx1 = box[i].posx2;
				box[n].posy1 = box[i].posy2;
				box[n].posx2 = box[n].posx1 + box[n].R * cos (k / 180 * pi);
				box[n].posy2 = box[n].posy1 + box[n].R * sin (k / 180 * pi);
				j += 1;
				n += 1;

			}
			// 剪枝
			else if (l == 1)
			{
				// 第一条
				k += w1;
				box[n].R = box[i].R / r2;
				box[n].posx1 = box[i].posx2;
				box[n].posy1 = box[i].posy2;
				box[n].posx2 = box[n].posx1 + box[n].R * cos (k / 180 * pi);
				box[n].posy2 = box[n].posy1 + box[n].R * sin (k / 180 * pi);
				j += 1;
				n += 1;
			}
			else
			{
				// 第一条
				k -= w2;
				box[n].R = box[i].R / r1;
				box[n].posx1 = box[i].posx2;
				box[n].posy1 = box[i].posy2;
				box[n].posx2 = box[n].posx1 + box[n].R * cos (k / 180 * pi);
				box[n].posy2 = box[n].posy1 + box[n].R * sin (k / 180 * pi);
				j += 1;
				n += 1;
			}

		}

		flag1 += flag2;
		flag2 = j;
		break;
	}
	// 谢尔宾斯基三角形
	case 10:
	{
		// 长度迭代
		R = R / 2.0;
		n = 0;
		// 对所存三角形构造新三角形,一个大的对应三个小的
		for (i = 0; i < flag; i++)
		{

			// 第一个
			eat[n].posx1 = box[i].posx1;
			eat[n].posy1 = box[i].posy1;
			eat[n].posx2 = eat[n].posx1 + R / 2;
			eat[n].posy2 = eat[n].posy1 + R / 2 * sqrt (3.0);
			eat[n].posx3 = eat[n].posx1 - R / 2;
			eat[n].posy3 = eat[n].posy1 + R / 2 * sqrt (3.0);

			// 第二个
			eat[n + 1].posx1 = eat[n].posx2;
			eat[n + 1].posy1 = eat[n].posy2;
			eat[n + 1].posx2 = eat[n + 1].posx1 + R / 2;
			eat[n + 1].posy2 = eat[n + 1].posy1 + R / 2 * sqrt (3.0);
			eat[n + 1].posx3 = eat[n + 1].posx1 - R / 2;
			eat[n + 1].posy3 = eat[n + 1].posy1 + R / 2 * sqrt (3.0);

			// 第三个
			eat[n + 2].posx1 = eat[n].posx3;
			eat[n + 2].posy1 = eat[n].posy3;
			eat[n + 2].posx2 = eat[n + 2].posx1 + R / 2;
			eat[n + 2].posy2 = eat[n + 2].posy1 + R / 2 * sqrt (3.0);
			eat[n + 2].posx3 = eat[n + 2].posx1 - R / 2;
			eat[n + 2].posy3 = eat[n + 2].posy1 + R / 2 * sqrt (3.0);

			// 一变三
			n += 3;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1; box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2; box[i].posy2 = eat[i].posy2;
			box[i].posx3 = eat[i].posx3; box[i].posy3 = eat[i].posy3;
		}
		flag = n;
		break;
	}
	// 谢尔宾斯基正方形
	case 11:
	{
		// 长度迭代
		R = R / 3.0;
		n = 0;
		// 一个大的对应八个小的
		for (i = 0; i < flag; i++)
		{
			// 第一个
			eat[n].posx1 = box[i].posx1 - 2 * box[i].R;
			eat[n].posy1 = box[i].posy1 - 2 * box[i].R;
			eat[n].R = R;

			// 第二个
			eat[n + 1].posx1 = box[i].posx1;
			eat[n + 1].posy1 = box[i].posy1 - 2 * box[i].R;
			eat[n + 1].R = R;

			// 第三个
			eat[n + 2].posx1 = box[i].posx1 + 2 * box[i].R;
			eat[n + 2].posy1 = box[i].posy1 - 2 * box[i].R;
			eat[n + 2].R = R;

			// 第四个
			eat[n + 3].posx1 = box[i].posx1 - 2 * box[i].R;
			eat[n + 3].posy1 = box[i].posy1;
			eat[n + 3].R = R;

			// 第五个
			eat[n + 4].posx1 = box[i].posx1 + 2 * box[i].R;
			eat[n + 4].posy1 = box[i].posy1;
			eat[n + 4].R = R;

			// 第六个
			eat[n + 5].posx1 = box[i].posx1 - 2 * box[i].R;
			eat[n + 5].posy1 = box[i].posy1 + 2 * box[i].R;
			eat[n + 5].R = R;

			// 第七个
			eat[n + 6].posx1 = box[i].posx1;
			eat[n + 6].posy1 = box[i].posy1 + 2 * box[i].R;
			eat[n + 6].R = R;

			// 第八个
			eat[n + 7].posx1 = box[i].posx1 + 2 * box[i].R;
			eat[n + 7].posy1 = box[i].posy1 + 2 * box[i].R;
			eat[n + 7].R = R;

			// 一变八
			n += 8;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].R = eat[i].R;
		}
		flag = n;
		break;
	}
	// 海岸线
	case 12:
	{
		n = 0;
		// 长度迭代
		R = R / 4.0;
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条
			eat[n].posx1 = box[i].posx1;
			eat[n].posy1 = box[i].posy1;
			eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
			eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

			// 第二条
			k -= 60;
			eat[n + 1].posx1 = eat[n].posx2;
			eat[n + 1].posy1 = eat[n].posy2;
			eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
			eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);

			// 第三条
			k += 120;
			eat[n + 2].posx1 = eat[n + 1].posx2;
			eat[n + 2].posy1 = eat[n + 1].posy2;
			eat[n + 2].posx2 = eat[n + 2].posx1 + R * cos (k / 180 * pi);
			eat[n + 2].posy2 = eat[n + 2].posy1 + R * sin (k / 180 * pi);

			// 第四条
			eat[n + 3].posx1 = eat[n + 2].posx2;
			eat[n + 3].posy1 = eat[n + 2].posy2;
			eat[n + 3].posx2 = eat[n + 3].posx1 + R * cos (k / 180 * pi);
			eat[n + 3].posy2 = eat[n + 3].posy1 + R * sin (k / 180 * pi);

			// 第五条
			k -= 120;
			eat[n + 4].posx1 = eat[n + 3].posx2;
			eat[n + 4].posy1 = eat[n + 3].posy2;
			eat[n + 4].posx2 = eat[n + 4].posx1 + R * cos (k / 180 * pi);
			eat[n + 4].posy2 = eat[n + 4].posy1 + R * sin (k / 180 * pi);

			// 第六条
			k += 60;
			eat[n + 5].posx1 = eat[n + 4].posx2;
			eat[n + 5].posy1 = eat[n + 4].posy2;
			eat[n + 5].posx2 = eat[n + 5].posx1 + R * cos (k / 180 * pi);
			eat[n + 5].posy2 = eat[n + 5].posy1 + R * sin (k / 180 * pi);

			// 一变六
			n += 6;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2;
			box[i].posy2 = eat[i].posy2;
		}

		flag = n;
		break;
	}
	// 闵可夫斯基曲线
	case 13:
	{
		n = 0;
		// 长度迭代
		R = R / 4.0;
		for (i = 0; i < flag; i++)
		{
			// 读取线段方向
			k = atan ((box[i].posy2 - box[i].posy1) / (box[i].posx2 - box[i].posx1)) * 180.0 / pi;
			if ((box[i].posx2 - box[i].posx1) < 0)k += 180;

			// 第一条
			eat[n].posx1 = box[i].posx1;
			eat[n].posy1 = box[i].posy1;
			eat[n].posx2 = eat[n].posx1 + R * cos (k / 180 * pi);
			eat[n].posy2 = eat[n].posy1 + R * sin (k / 180 * pi);

			// 第二条
			k -= 90;
			eat[n + 1].posx1 = eat[n].posx2;
			eat[n + 1].posy1 = eat[n].posy2;
			eat[n + 1].posx2 = eat[n + 1].posx1 + R * cos (k / 180 * pi);
			eat[n + 1].posy2 = eat[n + 1].posy1 + R * sin (k / 180 * pi);

			// 第三条
			k += 90;
			eat[n + 2].posx1 = eat[n + 1].posx2;
			eat[n + 2].posy1 = eat[n + 1].posy2;
			eat[n + 2].posx2 = eat[n + 2].posx1 + R * cos (k / 180 * pi);
			eat[n + 2].posy2 = eat[n + 2].posy1 + R * sin (k / 180 * pi);

			// 第四条
			k += 90;
			eat[n + 3].posx1 = eat[n + 2].posx2;
			eat[n + 3].posy1 = eat[n + 2].posy2;
			eat[n + 3].posx2 = eat[n + 3].posx1 + R * cos (k / 180 * pi);
			eat[n + 3].posy2 = eat[n + 3].posy1 + R * sin (k / 180 * pi);

			// 第五条
			eat[n + 4].posx1 = eat[n + 3].posx2;
			eat[n + 4].posy1 = eat[n + 3].posy2;
			eat[n + 4].posx2 = eat[n + 4].posx1 + R * cos (k / 180 * pi);
			eat[n + 4].posy2 = eat[n + 4].posy1 + R * sin (k / 180 * pi);

			// 第六条
			k -= 90;
			eat[n + 5].posx1 = eat[n + 4].posx2;
			eat[n + 5].posy1 = eat[n + 4].posy2;
			eat[n + 5].posx2 = eat[n + 5].posx1 + R * cos (k / 180 * pi);
			eat[n + 5].posy2 = eat[n + 5].posy1 + R * sin (k / 180 * pi);

			// 第七条
			k -= 90;
			eat[n + 6].posx1 = eat[n + 5].posx2;
			eat[n + 6].posy1 = eat[n + 5].posy2;
			eat[n + 6].posx2 = eat[n + 6].posx1 + R * cos (k / 180 * pi);
			eat[n + 6].posy2 = eat[n + 6].posy1 + R * sin (k / 180 * pi);

			// 第八条
			k += 90;
			eat[n + 7].posx1 = eat[n + 6].posx2;
			eat[n + 7].posy1 = eat[n + 6].posy2;
			eat[n + 7].posx2 = eat[n + 7].posx1 + R * cos (k / 180 * pi);
			eat[n + 7].posy2 = eat[n + 7].posy1 + R * sin (k / 180 * pi);

			// 一变八
			n += 8;
		}

		// 反读
		for (i = 0; i < n; i++)
		{
			box[i].posx1 = eat[i].posx1;
			box[i].posy1 = eat[i].posy1;
			box[i].posx2 = eat[i].posx2;
			box[i].posy2 = eat[i].posy2;
		}

		flag = n;
		break;
	}
	// Mandelbrot 集
	case 14:
	{
		n = 0;
		// 对所有点进行 z' = z ^ 2 + c 的复平面计算
		for (i = 0; i < 500; i++)
		{
			for (j = 0; j < 500; j++)
			{
				if (box_set[i][j].lifenum == 0)
				{
					// M 集,固定 z
					x = box_set[i][j].x * box_set[i][j].x - box_set[i][j].y * box_set[i][j].y + box_set[i][j].x0;
					y = box_set[i][j].x * box_set[i][j].y * 2.0 + box_set[i][j].y0;
					// 根据结果染色
					if (x * x + y * y <= 4.0)
					{
						box_set[i][j].lifenum = 1;
					}
					else
					{
						box_set[i][j].lifenum = 2;
					}
					// 读值
					box_set[i][j].x = x;
					box_set[i][j].y = y;
				}
			}
		}
		break;
	}
	// Julia 集
	case 15:
	{
		n = 0;
		// 对所有点进行 z' = z ^ 2 + c 的复平面计算
		for (i = 0; i < 500; i++)
		{
			for (j = 0; j < 500; j++)
			{
				if (box_set[i][j].lifenum == 0)
				{
					// J 集,固定 c
					x = box_set[i][j].x * box_set[i][j].x - box_set[i][j].y * box_set[i][j].y + Cx;
					y = box_set[i][j].x * box_set[i][j].y * 2.0 + Cy;
					// 根据结果染色
					if (x * x + y * y <= 4.0)
					{
						box_set[i][j].lifenum = 1;
					}
					else
					{
						box_set[i][j].lifenum = 2;
					}
					// 读值
					box_set[i][j].x = x;
					box_set[i][j].y = y;
				}
			}
		}
		break;
	}
	// 多边形分形
	case 16:
	{
		j = int (flag);
		// 取随机一条边组成三角形,取三角形重心为新顶点
		k = rand () % j;
		box[int (flag)].posx1 = double (box[int (flag)].posx1 + box[int (k)].posx1 + box[int (k)].posx2) / 3.0;
		box[int (flag)].posy1 = double (box[int (flag)].posy1 + box[int (k)].posy1 + box[int (k)].posy2) / 3.0;
		break;
	}
	default:break;
	}
}

// 分形绘制函数
void Gary::draw_fractal (int num)
{

	int i, j, k;
	// 框框范围绘制
	setfillcolor (WHITE);
	setlinecolor (BLACK);
	setlinestyle (PS_SOLID, 2);

	k = box_list[0].flag_text_num;

	// 分情况绘制
	if (k == 3 || k == 5 || k == 6 || k == 7 || k == 12 || k == 13)
	{
		// 清屏
		fillrectangle (0, 0, 500, 500);
		// 单线绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag; i++)
		{
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx2), int (box[i].posy2));
		}
	}
	else if (k == 4)
	{
		// 清屏
		fillrectangle (0, 0, 500, 500);
		// 奇偶绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag1; i++)
		{
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx2), int (box[i].posy2));
		}
		for (i = 0; i < flag2; i++)
		{
			line (int (eat[i].posx1), int (eat[i].posy1), int (eat[i].posx2), int (eat[i].posy2));
		}
	}
	else if (k == 8 || k == 9)
	{
		// 清屏
		fillrectangle (0, 0, 500, 500);
		// 单线绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag1 + flag2; i++)
		{
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx2), int (box[i].posy2));
		}
	}
	else if (k == 10)
	{
		// 三角形绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag; i++)
		{
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx2), int (box[i].posy2));
			line (int (box[i].posx2), int (box[i].posy2), int (box[i].posx3), int (box[i].posy3));
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx3), int (box[i].posy3));
		}
	}
	else if (k == 11)
	{
		// 矩形绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag; i++)
		{
			fillrectangle (int (box[i].posx1 - box[i].R), int (box[i].posy1 - box[i].R), int (box[i].posx1 + box[i].R), int (box[i].posy1 + box[i].R));
		}
	}
	else if (k == 14 || k == 15)
	{
		// 不上色
		if (color_or_not == 0)
		{
			// 清屏
			fillrectangle (0, 0, 500, 500);
			// 颜色
			num = 0;
		}
		// 上色
		else if (color_or_not == 1)
		{
			// 颜色
			num = 255 * num / (box_list[0].box_button[k].time_of_fractal - 1);
		}
		// 点绘制
		for (i = 0; i < 500; i++)
		{
			for (j = 0; j < 500; j++)
			{
				if (box_set[i][j].lifenum == 1)
				{
					putpixel (i, j, RGB (num, num, num));
					box_set[i][j].lifenum = 0;
				}
			}
		}
	}
	else if (k == 16)
	{
		// 单线绘制
		setlinestyle (PS_SOLID, 1);
		setlinecolor (BLACK);
		for (i = 0; i < flag; i++)
		{
			line (int (box[i].posx1), int (box[i].posy1), int (box[i].posx2), int (box[i].posy2));
		}
		// 点绘制
		fillrectangle (int (box[int (flag)].posx1), int (box[int (flag)].posy1), int (box[int (flag)].posx1 + 1), int (box[int (flag)].posy1 + 1));
	}

	FlushBatchDraw ();
}

// 界面绘制函数
void Gary::draw_scene ()
{
	POINT pts[3];
	TCHAR s[20];
	int i, j, k;
	// 背景绘制
	setbkcolor (WHITE);
	cleardevice ();

	// 框框范围绘制
	setfillcolor (WHITE);
	setlinecolor (BLACK);
	setlinestyle (PS_SOLID, 2);
	fillrectangle (0, 0, 803, 500);
	fillrectangle (0, 0, 500, 500);

	// 列表框绘制
	for (k = 0; k < num_list; k++)
	{
		// 清理区域
		setfillcolor (RGB (128, 128, 128));
		setlinecolor (RGB (128, 254, 0));
		setlinestyle (PS_SOLID, 2);
		fillrectangle (box_list[k].posx1, box_list[k].posy1, box_list[k].posx2, box_list[k].posy2);
		line (box_list[k].posx2 - 40, box_list[k].posy1, box_list[k].posx2 - 40, box_list[k].posy2);


		// 三角箭头的绘制
		setfillcolor (RGB (128, 254, 0));
		setlinecolor (RGB (35, 33, 168));

		i = 0;
		pts[0].x = box_list[k].box_button[i].posx1;			pts[0].y = box_list[k].box_button[i].posy2;
		pts[1].x = box_list[k].box_button[i].posx2;			pts[1].y = box_list[k].box_button[i].posy2;
		pts[2].x = box_list[k].box_button[i].posx1 + 19;	pts[2].y = box_list[k].box_button[i].posy1;
		fillpolygon (pts, 3);

		i = 1;
		pts[0].x = box_list[k].box_button[i].posx1;			pts[0].y = box_list[k].box_button[i].posy1;
		pts[1].x = box_list[k].box_button[i].posx2;			pts[1].y = box_list[k].box_button[i].posy1;
		pts[2].x = box_list[k].box_button[i].posx1 + 19;	pts[2].y = box_list[k].box_button[i].posy2;
		fillpolygon (pts, 3);

		// 滑条的绘制
		setfillcolor (RGB (128, 254, 0));
		i = 2;
		fillrectangle (box_list[k].box_button[i].posx1,
			box_list[k].box_button[i].posy1,
			box_list[k].box_button[i].posx2,
			box_list[k].box_button[i].posy2);

		double size = 38;
		// 文本绘制
		// 参数设置,填充透明
		setbkmode (TRANSPARENT);
		settextstyle (int (size), int (size / 5 * 2), _T ("Consolas"));
		settextcolor (RGB (35, 33, 168));

		j = int (
			(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
			((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
				(box_list[k].all_text_num - box_list[k].every_text_num + 1))
			);
		for (i = 0; i < box_list[k].every_text_num; i++)
		{
			if (i + 3 + j == box_list[k].flag_text_num)
			{
				fillrectangle (box_list[k].box_button[i + 3].posx1,
					box_list[k].box_button[i + 3].posy1,
					box_list[k].box_button[i + 3].posx2,
					box_list[k].box_button[i + 3].posy2);
			}
			outtextxy (box_list[k].box_button[i + 3].posx1,
				box_list[k].box_button[i + 3].posy1,
				box_list[k].box_button[i + 3 + j].text);
		}
		// 恢复填充
		setbkmode (OPAQUE);
	}

	// 设置参数
	setlinecolor (RGB (125, 125, 125));
	setbkcolor (WHITE);
	settextcolor (BLACK);
	settextstyle (25, 9, _T ("Consolas"));
	setlinestyle (PS_SOLID, 2);

	// 根据按钮数量,按钮类型参数绘制
	for (i = 0; i < num_button; i++)
	{
		setfillcolor (WHITE);
		// 边框
		fillrectangle (box_button[i].posx1, box_button[i].posy1, box_button[i].posx2, box_button[i].posy2);
		// 矩形激活按钮
		if (box_button[i].type == 1)
		{
			// 文字
			outtextxy (box_button[i].posx1 + (box_button[i].posx2 - box_button[i].posx1) / 2 - textwidth (box_button[i].text) / 2, box_button[i].posy1 + 6, box_button[i].text);
		}
	}

	// 参数绘制
	i = 24; j = 30;

	// 读取当前分形图案编号
	k = box_list[0].flag_text_num;

	// 分情况绘制
	// 类似雪花
	if (k == 3 || k == 4 || k == 5 || k == 6 || k == 7)
	{
		_stprintf_s (s, _T ("%0.1f"), w);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
	}
	// 类似分形树
	else if (k == 8 || k == 9)
	{
		_stprintf_s (s, _T ("%0.1f"), r1);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1f"), r2);	outtextxy (box_button[1].posx1 + i, box_button[1].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1f"), w1);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
		_stprintf_s (s, _T ("%0.1f"), w2);	outtextxy (box_button[4].posx1 + i, box_button[4].posy1 + j, s);
		if (k == 9)
		{
			_stprintf_s (s, _T ("%0.0d"), pruning_probability);	outtextxy (box_button[5].posx1 + i, box_button[5].posy1 + j, s);
		}
	}
	// M 集和 J 集
	else if (k == 14 || k == 15 || k == 16)
	{
		// 迭代次数
		_stprintf_s (s, _T ("%0.0d"), box_list[0].box_button[k].time_of_fractal);	outtextxy (box_button[3].posx1 + i, box_button[3].posy1 + j, s);
		if (k == 14 || k == 15)
		{
			// 上色与否
			if (color_or_not == 0) { outtextxy (box_button[4].posx1 + i, box_button[4].posy1 + j, _T ("否")); }
			else if (color_or_not == 1) { outtextxy (box_button[4].posx1 + i, box_button[4].posy1 + j, _T ("是")); }
			// 分形变量参数
			if (k == 14)
			{
				// Z
				_stprintf_s (s, _T ("%0.3f"), Zx);	outtextxy (box_button[0].posx1 + i - 10, box_button[0].posy1 + j, s);
				_stprintf_s (s, _T ("%0.3f"), Zy);	outtextxy (box_button[1].posx1 + i - 10, box_button[1].posy1 + j, s);
			}
			else if (k == 15)
			{
				// C
				_stprintf_s (s, _T ("%0.3f"), Cx);	outtextxy (box_button[0].posx1 + i - 10, box_button[0].posy1 + j, s);
				_stprintf_s (s, _T ("%0.3f"), Cy);	outtextxy (box_button[1].posx1 + i - 10, box_button[1].posy1 + j, s);
			}
		}
		else if (k == 16)
		{
			// 多边形边数
			_stprintf_s (s, _T ("%0.1f"), w);	outtextxy (box_button[0].posx1 + i, box_button[0].posy1 + j, s);
		}
	}

	FlushBatchDraw ();
}

// 初始化函数
void Gary::initialization ()
{
	int i, j;

	// 列表框数量
	num_list = 1;

	// 列表框初始化

	// 每个列表框的不同之处
	j = 0;
	// 列表框范围坐标
	box_list[j].posx1 = 502;
	box_list[j].posy1 = 2;
	box_list[j].posx2 = 802;
	box_list[j].posy2 = 302;
	// 每次展示数量
	box_list[j].every_text_num = 7;
	// 之后的文本按钮
	// 数量
	box_list[j].all_text_num = 14;
	// 内容
	box_list[j].box_button[3].text = _T ("科赫雪花");				box_list[j].box_button[3].time_of_fractal = 6;
	box_list[j].box_button[4].text = _T ("拆分三角形");				box_list[j].box_button[4].time_of_fractal = 6;
	box_list[j].box_button[5].text = _T ("列维曲线");				box_list[j].box_button[5].time_of_fractal = 14;
	box_list[j].box_button[6].text = _T ("龙形曲线");				box_list[j].box_button[6].time_of_fractal = 14;
	box_list[j].box_button[7].text = _T ("正方形折线");				box_list[j].box_button[7].time_of_fractal = 5;
	box_list[j].box_button[8].text = _T ("分形树");					box_list[j].box_button[8].time_of_fractal = 6;
	box_list[j].box_button[9].text = _T ("分形二叉树");				box_list[j].box_button[9].time_of_fractal = 13;
	box_list[j].box_button[10].text = _T ("谢尔宾斯基三角形");		box_list[j].box_button[10].time_of_fractal = 9;
	box_list[j].box_button[11].text = _T ("谢尔宾斯基正方形");		box_list[j].box_button[11].time_of_fractal = 4;
	box_list[j].box_button[12].text = _T ("海岸线");				box_list[j].box_button[12].time_of_fractal = 5;
	box_list[j].box_button[13].text = _T ("闵可夫斯基曲线");		box_list[j].box_button[13].time_of_fractal = 4;
	box_list[j].box_button[14].text = _T ("曼德布洛特集");			box_list[j].box_button[14].time_of_fractal = 15;
	box_list[j].box_button[15].text = _T ("茱莉亚集");				box_list[j].box_button[15].time_of_fractal = 15;
	box_list[j].box_button[16].text = _T ("多边形分形");			box_list[j].box_button[16].time_of_fractal = 3000;

	// 每个列表框的共同之处
	for (j = 0; j < num_list; j++)
	{
		// 前三个按钮是固定的
		box_list[j].box_button[0].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[0].posy1 = box_list[j].posy1 + 2;
		box_list[j].box_button[0].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[0].posy2 = box_list[j].posy1 + 50 - 2;

		box_list[j].box_button[1].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[1].posy1 = box_list[j].posy2 - 50 + 2;
		box_list[j].box_button[1].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[1].posy2 = box_list[j].posy2 - 2;

		box_list[j].box_button[2].posx1 = box_list[j].posx2 - 40 + 2;
		box_list[j].box_button[2].posy1 = box_list[j].box_button[0].posy2 + 2;
		box_list[j].box_button[2].posx2 = box_list[j].posx2 - 2;
		box_list[j].box_button[2].posy2 = box_list[j].box_button[0].posy2 + 60 - 2;

		// 文本按钮参数设置
		for (i = 0; i < box_list[j].every_text_num; i++)
		{
			box_list[j].box_button[i + 3].posx1 = int (box_list[j].posx1 + 2);
			box_list[j].box_button[i + 3].posy1 = int (box_list[j].posy1 + i * (box_list[j].posy2 - box_list[j].posy1) / box_list[j].every_text_num + 2);
			box_list[j].box_button[i + 3].posx2 = int (box_list[j].posx2 - 40 - 2);
			box_list[j].box_button[i + 3].posy2 = int (box_list[j].box_button[i + 3].posy1 + (box_list[j].posy2 - box_list[j].posy1) / box_list[j].every_text_num - 5);
		}

		// 初始选定文本编号初始化
		box_list[j].flag_text_num = 3;
	}

	// 分形参数初始化
	w = 60;
	initialization_fractal ();

	// 按钮的初始化
	num_button = 6;

	// 矩形按钮
	for (i = 0; i < 6; i++)
	{
		box_button[i].posx1 = 510 + i % 3 * 100;
		box_button[i].posy1 = 340 + i / 3 * 70;
		box_button[i].posx2 = 590 + i % 3 * 100;
		box_button[i].posy2 = 400 + i / 3 * 70;
		box_button[i].type = 0;
	}

	box_button[0].text = _T ("角度");		box_button[0].type = 1;
	box_button[1].text = _T ("");
	box_button[2].text = _T ("动画演示");	box_button[2].type = 1;
	box_button[3].text = _T ("");
	box_button[4].text = _T ("");
	box_button[5].text = _T ("");

	// 绘制
	draw_scene ();
	draw_fractal (0);
}

// 窗口主视角函数,获取用户操作
void Gary::move ()
{
	// 鼠标定义
	ExMessage m;
	TCHAR ss[20];
	int i, k;
	float j;
	// 控制参数置零
	exit_move = 0;

	while (exit_move == 0)
	{

		if (peekmessage (&m, EM_MOUSE | EM_KEY))
		{
			// 左键单击判断
			if (m.message == WM_LBUTTONDOWN)
			{
				// 判断是否点击了列表框
				for (k = 0; k < num_list; k++)
				{
					// 列表框范围
					if (m.x > box_list[k].posx1 && m.y > box_list[k].posy1 && m.x < box_list[k].posx2 && m.y < box_list[k].posy2)
					{
						break;
					}
				}
				// 点击了列表框
				if (k < num_list)
				{
					// 滑条点击
					if (m.x > box_list[k].box_button[2].posx1 && m.x<box_list[k].box_button[2].posx2 && m.y>box_list[k].box_button[2].posy1 && m.y < box_list[k].box_button[2].posy2)
					{
						while (m.message != WM_LBUTTONUP)
						{
							if (peekmessage (&m, EM_MOUSE | EM_KEY))
							{
								j = float (m.y > box_list[k].posy1 + 50 + 30 - 4 ? m.y : box_list[k].posy1 + 50 + 30 - 4);
								j = float (m.y < box_list[k].posy2 - 50 - 30 + 4 ? j : box_list[k].posy2 - 50 - 30 + 4);
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
								draw_scene ();
							}
						}
						// 第一次绘制
						draw_scene ();
					}
					// 箭头点击
					else if (m.x > box_list[k].box_button[0].posx1 && m.x<box_list[k].box_button[0].posx2 && m.y>box_list[k].box_button[0].posy1 && m.y < box_list[k].box_button[0].posy2)
					{
						if (box_list[k].flag_text_num > 3)
						{
							box_list[k].flag_text_num--;
							// 滑条相对位置编号
							i = int (
								(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
								((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
									(box_list[k].all_text_num - box_list[k].every_text_num + 1))
								);
							// 到顶了,向上需要自动移动滑块
							if (i + 2 >= box_list[k].flag_text_num)
							{
								// 滑条相对位置编号
								j = float (
									(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
									((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1))
									);
								// 滑条相对位置编号变更
								j--;
								// 滑条相对位置变更
								j = float(
									box_list[k].posy1 + 50 + 30 + j * (
										(box_list[k].posy2 - 100 - box_list[k].posy1 - 50) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1)
										));
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
							}
							goto A;
						}
					}
					else if (m.x > box_list[k].box_button[1].posx1 && m.x<box_list[k].box_button[1].posx2 && m.y>box_list[k].box_button[1].posy1 && m.y < box_list[k].box_button[1].posy2)
					{
						if (box_list[k].flag_text_num < box_list[k].all_text_num + 2)
						{
							box_list[k].flag_text_num++;
							// 滑条相对位置编号
							i = int (
								(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
								((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
									(box_list[k].all_text_num - box_list[k].every_text_num + 1))
								);
							// 到底了,向下需要自动移动滑块
							if (i + 10 <= box_list[k].flag_text_num)
							{
								// 滑条相对位置编号
								j = float (
									(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
									((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1))
									);
								// 滑条相对位置编号变更
								j++;
								// 滑条相对位置变更
								j = float (
									box_list[k].posy1 + 50 + 30 + j * (
										(box_list[k].posy2 - 100 - box_list[k].posy1 - 50) /
										(box_list[k].all_text_num - box_list[k].every_text_num + 1)
										));
								box_list[k].box_button[2].posy1 = int (j - 30 + 2);
								box_list[k].box_button[2].posy2 = int (j + 30 - 2);
							}
							goto A;
						}
					}
					// 按钮点击
					else if (m.x > box_list[k].posx1 && m.x<box_list[k].posx2 - 40 && m.y>box_list[k].posy1 && m.y < box_list[k].posy2)
					{
						// 滑条相对位置编号
						j = float (
							(box_list[k].box_button[2].posy1 - 50 - box_list[k].posy1) /
							((box_list[k].box_button[1].posy1 - box_list[k].box_button[0].posy2 - 60 + 8) /
								(box_list[k].all_text_num - box_list[k].every_text_num + 1))
							);
						// 按钮相对位置编号
						i = int (
							(m.y - box_list[k].posy1) /
							((box_list[k].posy2 - box_list[k].posy1) /
								(box_list[k].every_text_num))
							);
						box_list[k].flag_text_num = int (i + 3 + j);
						goto A;

					A:
						// 分形参数初始化,都是可调参数,与可调按钮一一对应
						switch (box_list[0].flag_text_num)
						{
						case 3: {w = 60;														break; }// 科赫雪花
						case 4: {w = 40;														break; }// 拆分三角形
						case 5: {w = 45;														break; }// Levy 曲线
						case 6: {w = 45;														break; }// 龙形曲线
						case 7: {w = 4;															break; }// 正方形折线
						case 8: {r1 = 1.5; r2 = 3.0; w1 = 0; w2 = 40;							break; }// 分形树
						case 9: {r1 = 1.5; r2 = 1.5; w1 = 30; w2 = 30; pruning_probability = 3;	break; }// 分形二叉树
						case 10: {																break; }// 谢尔宾斯基三角形
						case 11: {																break; }// 谢尔宾斯基正方形
						case 12: {																break; }// 海岸线
						case 13: {																break; }// 闵可夫斯基曲线
						case 14: {Zx = 0; Zy = 0; color_or_not = 0;								break; }// Mandelbrot 集
						case 15: {Cx = -0.75; Cy = 0; color_or_not = 0;							break; }// Julia 集
						case 16: {w = 4;															break; }// 多边形分形
						default:break;
						}

						// 分形点线初始化,按钮初始化
						initialization_fractal ();

						// 第一次绘制
						draw_scene ();
						draw_fractal (0);
					}
				}

				// 判断是否点击了自制按钮
				for (i = 0; i < num_button; i++)
				{
					// 矩形按钮
					if (m.x > box_button[i].posx1 && m.y > box_button[i].posy1 && m.x < box_button[i].posx2 && m.y < box_button[i].posy2)
					{
						break;
					}
				}
				// 按钮为激活状态
				if (box_button[i].type == 1)
				{
					// 动画演示按钮
					if (i == 2)
					{
						// 分形点线初始化
						initialization_fractal ();

						// 第一次绘制
						draw_scene ();
						draw_fractal (0);
						// 该程序特殊之处是只有一个列表框
						// 若出现多个列表框,应改变临时变量
						// 第一次动画演示
						for (k = 0; k < box_list[0].box_button[box_list[0].flag_text_num].time_of_fractal; k++)
						{
							refresh_fractal ();
							if (box_list[0].flag_text_num != 16) { Sleep (500); }
							draw_fractal (k);
						}
					}
					// 与分形参数有关的其他按钮
					else
					{
						// 读取当前选定分形编号
						k = box_list[0].flag_text_num;
						// 按钮一
						if (i == 0)
						{
							// 分情况绘制
							// w
							// 类似雪花
							if (k == 3 || k == 4 || k == 5 || k == 6)
							{
								InputBox (ss, 10, _T ("输入角度(-90 ~ 90)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= -90 && i <= 90) { w = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							else if (k == 7 || k == 16)
							{
								InputBox (ss, 10, _T ("输入正多边形边数(3 ~ 6)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 3 && i <= 6) { w = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// r1
							// 类似分形树
							else if (k == 8 || k == 9)
							{
								InputBox (ss, 10, _T ("输入长度缩短倍数(1.2 ~ 3.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= 1.2 && j <= 3.0) { r1 = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// Zx 和 Cx
							// M 集和 J 集
							else if (k == 14)
							{
								InputBox (ss, 10, _T ("输入 Zx(-1.0 ~ 1.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= -1.0 && j <= 1.0) { Zx = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							else if (k == 15)
							{
								InputBox (ss, 10, _T ("输入 Cx(-1.0 ~ 1.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= -1.0 && j <= 1.0) { Cx = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
						}
						// 按钮二
						else if (i == 1)
						{
							// 分情况绘制
							// r2
							// 类似分形树
							if (k == 8 || k == 9)
							{
								InputBox (ss, 10, _T ("输入长度缩短倍数(1.2 ~ 3.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= 1.2 && j <= 3.0) { r2 = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// Zy 和 Cy
							// M 集和 J 集
							else if (k == 14)
							{
								InputBox (ss, 10, _T ("输入 Zy(-1.0 ~ 1.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= -1.0 && j <= 1.0) { Zy = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							else if (k == 15)
							{
								InputBox (ss, 10, _T ("输入 Cy(-1.0 ~ 1.0)"));
								_stscanf_s (ss, _T ("%f"), &j);
								if (j >= -1.0 && j <= 1.0) { Cy = j; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
						}
						// 按钮三
						else if (i == 3)
						{
							// 分情况绘制
							// w1
							// 类似分形树
							if (k == 8 || k == 9)
							{
								InputBox (ss, 10, _T ("输入角度(-180 ~ 180)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= -180 && i <= 180) { w1 = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// box_list[0].box_button[k].time_of_fractal
							// M 集和 J 集
							else if (k == 14 || k == 15)
							{
								InputBox (ss, 10, _T ("输入迭代次数(1 ~ 30)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 1 && i <= 30) { box_list[0].box_button[k].time_of_fractal = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// 多边形分形
							else if (k == 16)
							{
								InputBox (ss, 10, _T ("输入迭代次数(3000 ~ 90000)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 3000 && i <= 90000) { box_list[0].box_button[k].time_of_fractal = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
						}
						// 按钮四
						else if (i == 4)
						{
							// 分情况绘制
							// w2
							// 类似分形树
							if (k == 8 || k == 9)
							{
								InputBox (ss, 10, _T ("输入角度(-180 ~ 180)"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= -180 && i <= 180) { w2 = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
							// color_or_not
							// M 集和 J 集
							else if (k == 14 || k == 15)
							{
								color_or_not = (color_or_not == 1 ? 0 : 1);
							}
						}
						// 按钮五
						else if (i == 5)
						{
							// 分情况绘制
							// pruning_probability
							// 类似分形树
							if (k == 9)
							{
								InputBox (ss, 10, _T ("输入剪枝概率(1 ~ 10),1 是无剪枝;数字越大,剪枝越剧烈"));
								_stscanf_s (ss, _T ("%d"), &i);
								if (i >= 1 && i <= 10) { pruning_probability = i; }
								else { MessageBox (hOut, _T ("输入错误,不在范围内"), _T ("来自小豆子的提醒"), MB_OK); }
							}
						}
						// 分形点线初始化
						initialization_fractal ();
						// 第一次绘制
						draw_scene ();
						draw_fractal (0);
					}
				}
			}
		}
	}
}

// 主进程
void Gary::carry ()
{
	// 窗口定义
	hOut = initgraph (804, 501);
	SetWindowText (hOut, _T ("常见分形图案的演示"));
	// 进程控制参数
	exit_carry = 0;
	// 随机种子初始化
	srand ((unsigned)time (NULL));
	BeginBatchDraw ();
	while (exit_carry == 0)
	{
		initialization ();
		move ();
		// 刷新,重置,返回按钮,进程控制参数置零
		// 退出按钮,进程控制参数置一
	}
	EndBatchDraw ();
	closegraph ();
}

// 主函数
int main (void)
{
	// 创建类对象
	Gary G;
	// 进入类对象主循函数
	G.carry ();
	return 0;
}

参考资料

添加评论