四种分形图形

1.基于打点的分形三角形

/* A1  Sierpinski  Gasket  Program   谢尔平斯基镂垫          */

/* gasket.c */

/* Two-Dimensional Sierpinski Gasket 谢尔平斯基镂垫     */
/* Generated Using Randomly Selected Vertices */
/* And Bisection                              */

///

//#include "stdafx.h"
#include <windows.h>
#include <gl\glut.h>
#include <gl\gl.h>						
#include <gl\glu.h>	
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")




#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL\glut.h>
#endif

void myinit()
{

	/* attributes */

	glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */
	glColor3f(1.0, 0.0, 0.0); /* draw in red */

/* set up viewing */
/* 500 x 500 window with origin lower left */

	glMatrixMode(GL_PROJECTION);   // 与流水线对话,启动投影矩阵,指定投影矩阵的参数
	glLoadIdentity();
	gluOrtho2D(0.0, 50.0, 0.0, 50.0);  // 50*50的2D投影平面空间
									   // 函数原型   0.0,(GLdouble)w,0.0,(GLdouble)h);
									   // gluOrtho2D(left,right,bottom,up)
									   // gluOrtho2D(x_mix, x_max, y_mix, y_max)
									   //(左下角x坐标,右上角x坐标,左下角y坐标,右上角y坐标)
									   // (0.0, 0.0) - (50.0, 50.0)
									   // (0.0, 0.0) - (150.0, 150.0) 投影平面空间越大,对象显示越小

	glMatrixMode(GL_MODELVIEW);
}



void display(void)
{


	GLfloat vertices[3][2] = { {0.0,0.0},{25.0,50.0},{50.0,0.0} };
	// 二维点 
   //  3行2列 
   //  行下标   0         1           2

/* A triangle, 2D是3D的特例,内部表示都一样 */

	int j, k;
	int rand();       /* standard random number generator */
	GLfloat p[2] = { 1,7.5 };  /* An arbitrary initial point inside traingle */
							  // 看看改变初始值,是否改变图形? 初始化第一个点不影响最终的分形结果
							  // 甚至初始化的点在三角形外面
							  // 该点不断第被更新,按照中点计算

	glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */  // 用初始化中指定的颜色进行 白色 清屏
														// 没有明确调用时候 情况下,用缺省 黑色 清屏  
														// 注释看看 没有明确调用 情况


/* compute and plots 5000 new points */

	glBegin(GL_POINTS);//说明下面要画的图形是点

	//基本思路就是:确定三角形的三个顶点,以及开始任意确定一个点,随机选取一个三角形的顶点,连接它与那个随机点,取中点
	for (k = 0; k < 500000; k++)  // 点数 请输入  50000 还行
							  // 50000000 有点费劲
	{
		j = rand() % 3; /* pick a vertex at random */
					//  在 0 1 2 之间随机生成  
					// rand()是伪随机数生成函数,%是模运算,%3对3取余


	/* Compute point halfway between selected vertex and old point */

		p[0] = (p[0] + vertices[j][0]) / 2.0; 
										  // p[0] 下标 0,对应x坐标
										  // j行0列 列下标 0,对应x坐标

		p[1] = (p[1] + vertices[j][1]) / 2.0;
										  // p[1] 下标 0,对应y坐标
										  // j行1列 列下标 1,对应y坐标

	/* plot new point */

		glVertex2fv(p); //理解为向流水线发送数据

	}
	glEnd();

	glFlush(); /* clear buffers */  //立即模式
}

void main(int argc, char** argv)
{

	/* Standard GLUT initialization */

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); /* default, not needed */
	glutInitWindowSize(500, 500); /* 500 x 500 pixel window */
	glutInitWindowPosition(0, 0); /* place window top left on display */
	glutCreateWindow("Sierpinski Gasket 2013-2019 WHU"); /* window title */
	glutDisplayFunc(display); /* display callback invoked when window opened */

	myinit(); /* set attributes */

	glutMainLoop(); /* enter event loop */

}

2.基于递归的分形三角形

```cpp
/* A2 recursive generation of Sierpinski gasket */
/* recursive subdivision of triangle to form Sierpinski gasket */
/* number of recursive steps given on command line */

/* gasket2.c */

///
#include <stdio.h>
#include <stdlib.h>

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#pragma comment(lib,"glut32.lib")

// #include <gl\gl.h>						
// #include <gl\glu.h>	
// 
// #pragma comment(lib,"opengl32.lib")
// #pragma comment(lib,"glu32.lib")



/* initial triangle */

GLfloat v[3][2] = { {-1.0, -0.58}, {1.0, -0.58}, {0.0, 1.15} };  // 全局二维数组存储空间,按照次序,存放浮点数
															 // 二维数组本质上是以数组作为数组元素的数组,即“数组的数组”
															// [3][2] 表示3行2列的二维数组,连续存放的三个2列数组

int n;   // 全局变量  递归层次

void triangle(GLfloat *a, GLfloat *b, GLfloat *c) 

/* specify one triangle */
{
	glVertex2fv(a);   
	glVertex2fv(b);
	glVertex2fv(c);
}


//分形函数(递归调用)
void divide_triangle(GLfloat *a, GLfloat *b, GLfloat *c, int m)  
{
	/* triangle subdivision using vertex numbers */
	//临时的点用来储存中点
	GLfloat v0[2], v1[2], v2[2];  // 局部,三个独立的一维数组,2列一维数组,分别对应x,y坐标

	int j;
	if (m > 0)                                // n 演示输入 0 ,1,2,3 看看效果如何
	{
		//每一个循环计算的是点的横纵坐标
		for (j = 0; j < 2; j++) v0[j] = (a[j] + b[j]) / 2;  //计算当前边的中点的x,y坐标,for 循环

		for (j = 0; j < 2; j++) v1[j] = (a[j] + c[j]) / 2;  //计算当前边的中点的x,y坐标,for 循环
		for (j = 0; j < 2; j++) v2[j] = (b[j] + c[j]) / 2;  //计算当前边的中点的x,y坐标,for 循环

		divide_triangle(a, v0, v1, m - 1);  // 递归调用 recursion 原来一个顶点加上新生成的二个顶点
										  // 数组名是常量指针类型,并且是数组的首地址

		divide_triangle(c, v1, v2, m - 1);  //递归调用 recursion 递归层次减一
										  // 数组名是常量指针类型,并且是数组的首地址

		divide_triangle(b, v2, v0, m - 1);  //递归调用 recursion
										  // 数组名是常量指针类型,并且是数组的首地址

	}
	else triangle(a, b, c); /* draw triangle at end of recursion */  //最终递归分解的结果
}


void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	//Efficiency Note程序效率  the glBegin and glEnd in the display callback rather than in the function triangle 
	//Efficiency Note程序效率  GL_TRIANGLES rather than GL_POLYGON

	glColor3f(1.0, 0.0, 0.0);  //设置流水线颜色状态

	glBegin(GL_TRIANGLES);  // 指定渲染三角形,


	divide_triangle(v[0], v[1], v[2], n);   // n 递归次数    前三个参数指代的是最外面的三角形的三个顶点
											// 数组名是常量指针类型
											// 全局二维数组 GLfloat v[3][2], 表示的二维数组是3行2列的
											// 表示 三个 连续存放的 一维数组(每个数组都2列)
											// 每个一维数组首地址,就是 该一维数组名字
	glEnd();
	glFlush();//立即渲染
}

void myinit()//目的是指定可视窗口的大小,以及默认的背景色和渲染颜色
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-2.0, 2.0, -2.0, 2.0);
	glMatrixMode(GL_MODELVIEW);
	glClearColor(1.0, 1.0, 1.0, 1.0); //背景白色,屏幕
	glColor3f(0.0, 0.0, 0.0);  //前景黑色,三角形

}

int main(int argc, char **argv)
{
	//argc即argument count,指代传入main函数的参数个数,由于第一个参数一定是argv[0](程序的路径名称)
	//所以,真正输入的参数个数为argc-1个

	if (argc < 2)//这里的分支语句就是在输入之前判断有没有提前传入参数
	{
		printf("Please input number of subdivision steps(less than 16) \"n\" \n Or Re-run again and Type number \"n\" following after Program name:\n");
		scanf_s("%d", &n);//scanf这里在vs2017报错,需要改成scanf_s                                          全局变量  递归层次
		// read number of subdivision steps from keyboard typing
	}
	else {
		n = atoi(argv[1]); // 把字符串转换成整型数
	}

	if (n > 16)//控制递归层次
	{
		printf("The number of dividing \"n\" less than 16 is preferred for illustrating! \n");
		exit(-1);
	}


	// n=7;  //

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutCreateWindow("Sierpinski Gasket");
	glutDisplayFunc(display);
	myinit();
	glutMainLoop();
}
3.由四个分形三角形拼接而成的四面体

```cpp
/*  A3 ??  tetra.c  */

/* Recursive subdivision of tetrahedron to form  3D Sierpinski gasket */
/* divide_triangle */

// #include <gl\gl.h>						
// #include <gl\glu.h>	
// #pragma comment(lib,"opengl32.lib")
// #pragma comment(lib,"glu32.lib")




#include <stdlib.h>

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#pragma comment(lib,"glut32.lib")


typedef float point[3];  // 自定义点类型 一维数组3列 3个元素  对应三个坐标点x,y,z

/* initial tetrahedron */

point v[] = { {0.0, 0.0, 1.0}, {0.0, 0.942809, -0.33333},
		  {-0.816497, -0.471405, -0.333333}, {0.816497, -0.471405, -0.333333} };
// point的数组,“数组的数组”
// 4行3列


static GLfloat theta[] = { 0.0,0.0,0.0 };  // 
int n;



//三角形绘制函数
void triangle(point a, point b, point c)

/* display one triangle using a line loop for wire frame, a single
normal for constant shading, or three normals for interpolative shading */
{
	glBegin(GL_POLYGON);
	glNormal3fv(a);     // 面需要方向,指定一个方向,这里相当于是设置法向量

	glVertex3fv(a);
	glVertex3fv(b);
	glVertex3fv(c);

	glEnd();
}

//对于每一个大三角形的递归分型,这个函数可以完成一个面的分型,m为递归深度
void divide_triangle(point a, point b, point c, int m)  // 形参  自定义的数组变量 point
{
	/* triangle subdivision using vertex numbers
	righthand rule applied to create outward pointing faces */

	point v1, v2, v3;   // 局部 变量  自定义的数组变量 point
	int j;
	if (m > 0)
	{
		for (j = 0; j < 3; j++) v1[j] = (a[j] + b[j]) / 2;  // 每个点 for循环 三个坐标x,y,z   计算出中点
		for (j = 0; j < 3; j++) v2[j] = (a[j] + c[j]) / 2;  // 每个点 for循环 三个坐标x,y,z   计算出中点
		for (j = 0; j < 3; j++) v3[j] = (b[j] + c[j]) / 2;  // 每个点 for循环 三个坐标x,y,z   计算出中点

		divide_triangle(a, v1, v2, m - 1);    // 原来的一个顶点+二个中点,构成一个新三角形  递归分解
		divide_triangle(c, v2, v3, m - 1);    // 原来的一个顶点+二个中点,构成一个新三角形  递归分解
		divide_triangle(b, v3, v1, m - 1);    // 原来的一个顶点+二个中点,构成一个新三角形  递归分解
	}
	else(triangle(a, b, c)); /* draw triangle at end of recursion */
}

void tetrahedron(int m)//构建四面体
{

	/* Apply triangle subdivision to faces of tetrahedron */


	glColor3f(1.0, 0.0, 0.0);    // 红
	divide_triangle(v[0], v[1], v[2], m);   // 全局变量  v    4行3列    4个点 构成 4面体  一共4个面,其中3个点构成一个面

	glColor3f(0.0, 1.0, 0.0);    // 绿
	divide_triangle(v[3], v[2], v[1], m);   // 全局变量  v   4行3列    4个点 构成 4面体   一共4个面,其中3个点构成一个面

	glColor3f(0.0, 0.0, 1.0);    // 蓝
	divide_triangle(v[0], v[3], v[1], m);   // 全局变量  v   4行3列    4个点 构成 4面体   一共4个面,其中3个点构成一个面

	glColor3f(0.0, 0.0, 0.0);     // 黑
	divide_triangle(v[0], v[2], v[3], m);   // 全局变量  v   4行3列    4个点 构成 4面体   一共4个面,其中3个点构成一个面
}

void display(void)
{
	glMatrixMode(GL_MODELVIEW);


	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //配合 3 深度测试去掉 效果 与 glEnable(GL_DEPTH_TEST); 
	//glClear(GL_COLOR_BUFFER_BIT); // 配合 3 去掉GL_DEPTH_BUFFER_BIT看看效果    与 glEnable(GL_DEPTH_TEST);  
									// 尽管main函数初始化深度测试功能,但是深度buffer没有正确初始化,
									// 当然就不能正确测试遮挡关系,也就不能争取显示


	glLoadIdentity();
	tetrahedron(n);
	glFlush();
	glMatrixMode(GL_MODELVIEW);
	glutPostRedisplay();//重新绘制

}


void myReshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,
			2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
	else
		glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,
			2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);

	glMatrixMode(GL_MODELVIEW);  //---〉mydisplay 避免显示排序问题
	glutPostRedisplay();//重新绘制
}


void main(int argc, char **argv)
{
	n = 3;  //递归的次数--演示1,修改n,  0  -   5
	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);  // 配合 1 与 glEnable(GL_DEPTH_TEST); 配合
	//glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  // 配合1  去掉GLUT_DEPTH看看效果, 与 glEnable(GL_DEPTH_TEST); 配合

	glutInitWindowSize(500, 500);
	glutCreateWindow("3D Gasket");
	//glutReshapeFunc(myReshape);   ///形状回调 注释看看不同效果 2017,为了设置窗口相应的参数
	glutDisplayFunc(display);//绘制

	glEnable(GL_DEPTH_TEST); //配合2 深度测试去掉 效果 与 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);配合
	

	glClearColor(1.0, 1.0, 1.0, 1.0); //背景色,白色

	glutMainLoop();
}

4.分形四面体

/* A3    gasket3.c    */

/* recursive subdivision of a tetrahedron to form 3D Sierpinski gasket */
/* number of recursive steps given on command line */

#include <stdlib.h>
#include <stdio.h>

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* initial tetrahedron */

GLfloat v[4][3] = { {0.0, 0.0, 1.0}, {0.0, 0.942809, -0.33333},
	  {-0.816497, -0.471405, -0.333333}, {0.816497, -0.471405, -0.333333} };

GLfloat colors[4][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0},
						{0.0, 0.0, 1.0}, {0.0, 0.0, 0.0} };

int n;

void init()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}

//以下为三层调用:三角形=>四面体=>分形四面体
void triangle(GLfloat *va, GLfloat *vb, GLfloat *vc)
{
	glVertex3fv(va);
	glVertex3fv(vb);
	glVertex3fv(vc);
}

void tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d)//单个四面体的绘制
{
	glColor3fv(colors[0]);  //R 色绘制
	triangle(a, b, c);
	glColor3fv(colors[1]);  //G 色绘制
	triangle(a, c, d);
	glColor3fv(colors[2]);  //B 色绘制
	triangle(a, d, b);
	glColor3fv(colors[3]);  //0 黑色绘制   背面为黑色 看不到  消隐效果
	triangle(b, d, c);
}

void divide_tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d, int m)
{

	GLfloat mid[6][3];   //6行3列,6个三维点,每个三维点3个坐标值x,y,z
	int j;
	if (m > 0)
	{
		/* compute six midpoints */  //   4面体 6个边  6个中点 

		for (j = 0; j < 3; j++) mid[0][j] = (a[j] + b[j]) / 2;  // for 循环,0 1 2 对应  x y z
		for (j = 0; j < 3; j++) mid[1][j] = (a[j] + c[j]) / 2;
		for (j = 0; j < 3; j++) mid[2][j] = (a[j] + d[j]) / 2;
		for (j = 0; j < 3; j++) mid[3][j] = (b[j] + c[j]) / 2;
		for (j = 0; j < 3; j++) mid[4][j] = (c[j] + d[j]) / 2;
		for (j = 0; j < 3; j++) mid[5][j] = (b[j] + d[j]) / 2;

		/* create 4 tetrahedrons by subdivision */   //   一个4面体 子分为 4个四面体

		divide_tetra(a, mid[0], mid[1], mid[2], m - 1);  //一个顶点+三个中点连接的
		divide_tetra(mid[0], b, mid[3], mid[5], m - 1);  //一个顶点+三个中点连接的
		divide_tetra(mid[1], mid[3], c, mid[4], m - 1);  //一个顶点+三个中点连接的
		divide_tetra(mid[2], mid[4], d, mid[5], m - 1);  //一个顶点+三个中点连接的

	}
	else(tetra(a, b, c, d)); /* draw tetrahedron at end of recursion */ //最终不能分解为止,基本单元为4面体
}


void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//glClear(GL_COLOR_BUFFER_BIT);    //注释去掉 | GL_DEPTH_BUFFER_BIT);  看看效果


	glBegin(GL_TRIANGLES);//绘制三角形
	divide_tetra(v[0], v[1], v[2], v[3], n);
	glEnd();


	glFlush();
}


void myReshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)//适应窗口比例
		glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,
			2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
	else
		glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,
			2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);
	glMatrixMode(GL_MODELVIEW);
	glutPostRedisplay();//标记当前的窗口需要重新绘制
}


int main(int argc, char **argv)
{

	if (argc < 2)
	{
		printf("Please input number of subdivision steps(less than 16) \"n\" \n Or Re-run again and Type number \"n\" following after Program name:\n");
		scanf_s("%d", &n); // read number of subdivision steps from keyboard typing  
	}
	else {
		n = atoi(argv[1]); // or set number of subdivision steps here  
	}


	if (n > 16)
	{
		printf("The number of dividing \"n\" less than 16 is preferred for illustrating! \n");
		exit(-1);
	}


	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 注释去掉 GLUT_DEPTH 看看 不同效果
	//glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB ); //注释去掉 GLUT_DEPTH 看看 不同效果

	glutInitWindowSize(500, 500);
	glutCreateWindow("3D Gasket");
	glutDisplayFunc(display);
	glutReshapeFunc(myReshape);   ///形状回调 注释看看不同效果

	init();
	glEnable(GL_DEPTH_TEST);  ///看看注释 不同效果
	//深度测试去掉 效果 与 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);配合



	glClearColor(1.0, 1.0, 1.0, 1.0);
	glutMainLoop();
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值