四種分形圖形

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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章