常见分形图案的演示
2022-2-9 ~ 2022-2-25
(0)
程序简介
这个程序包含了一些常见分形图案的动画演示,并提供了一些按钮来改变有意义的可变变量,创造不一样的分形图案。按动画演示按钮即可开启动画。
这个程序的分形大致分为三类:
第一类:线型,特点是每条线按一定的规律变成几条线。
第二类:几何型,特点是每个几何图案按一定的规律生成多个新的几何图案。
第三类:点型,特点是每个点的值按一定的规律重新迭代计算,根据点的数值大小确定图案。
分形图案演示列表:
- 科赫雪花
- 拆分三角形
- 列维曲线
- 龙形曲线
- 正方形折线
- 分形树
- 分形二叉树
- 谢尔宾斯基三角形
- 谢尔宾斯基正方形
- 海岸线
- 闵可夫斯基曲线
- Mandelbrot 集
- Julia 集
- 多边形分形
第一次更新:
1.参照参考资料,模仿出列表框功能。并抽象出列表框结构体,方便以后其他程序的使用。
2.将可调变量制成按钮,方便调整。
3.对正方形折线添加正多边形变量功能,现在可以画正三到正六边形。
4.对分形二叉树添加剪枝概率变量功能,现在可以调整剪枝概率。
5.对 Julia 集与 Mandelbrot 集添加上色功能,现在可以切换是否上色。
第二次更新:
1.对窗口名称,文章名称的更改。
2.程序执行效果的多张动图整成一张动图。
3.添加了多边形分形:这种分形我没有证明,感兴趣可以证明。只要是多边形,找一个点,与任意一边相连得三角形,找重心为新点,即三个顶点坐标平均,循环即可。原视频正六边形挺好看,我学习了一下,但我找不到原视频了。找了一个类似的视频,它的原理是找一个点,与任意顶点相连取中点为新点,循环即可。类似的原理也可以创造不一样的分形图案。这类分形应当也属于点型。
第三次更新:
- 图片更新,减小边框
- 代码更新,现在兼容 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;
}
添加评论
取消回复