在https://blog.csdn.net/derbi123123/article/details/105397176中详细说明了kock曲线的原理并以直线段实现迭代次数在6次以内的kock曲线并用键盘交互控制迭代次数
代码:
功能:按a增加迭代次数,按d减少迭代次数。
迭代六次(按六次a)效果:
#include <GL/freeglut.h>
#include <math.h>
#include <vector>
#define max_iteration_num 6//最多迭代六次
using namespace std;
struct Vertex{
GLfloat x,y;
};
vector<Vertex> V[3][max_iteration_num+1];//分别记录3条边各自6次迭代的数据(0、1、2、3、4、5、6)
int iteration_num=0;//记录迭代次数
GLfloat width=800.0,height=800.0;
//用户初始化函数
void myinit(void)
{
//设置清除屏幕的颜色
glClearColor(0.0f,0.0f,0.0f,0.0f);
Vertex Start[3],End[3];//初始元(三角形)的三个端点(每条边两个,有重合的)
Start[0].x=400.0;
Start[0].y=800.0;
End[0].x=(800.0-400.0*sqrt(3.0))/2;
End[0].y=200.0;
Start[1].x=End[0].x;
Start[1].y=End[0].y;
End[1].x=400+200*sqrt(3.0);
End[1].y=200;
Start[2].x=End[1].x;
Start[2].y=End[1].y;
End[2].x=Start[0].x;
End[2].y=Start[0].y;
//第零次迭代(没迭代)
for(int i=0;i<3;i++){
V[i][0].push_back(Start[i]);
V[i][0].push_back(End[i]);
}
}
//窗口大小变化时的回调函数
void myReshape(GLsizei w, GLsizei h)
{
//设定视区
glViewport(0, 0, w, h);
//设定透视方式
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,800.0,0.0,800.0);
}
//计算当前迭代次数下的各顶点坐标
void compute()
{
static int tmp=0;//记录上次绘制时迭代次数
int flag=0;//记录迭代次数是否被更新过
if(tmp<iteration_num){
int len=V[0][iteration_num-1].size();
for(int j=0;j<3;j++){
for(int i=0;i<len-1;i++){
V[j][iteration_num].push_back(V[j][iteration_num-1][i]);
Vertex tmp;
tmp.x=V[j][iteration_num-1][i].x+(V[j][iteration_num-1][i+1].x-V[j][iteration_num-1][i].x)/3;
tmp.y=V[j][iteration_num-1][i].y+(V[j][iteration_num-1][i+1].y-V[j][iteration_num-1][i].y)/3;
V[j][iteration_num].push_back(tmp);
tmp.x=(V[j][iteration_num-1][i].x+V[j][iteration_num-1][i+1].x)/2-(V[j][iteration_num-1][i].y-V[j][iteration_num-1][i+1].y)*sqrt(3.0)/6;
tmp.y=(V[j][iteration_num-1][i].y+V[j][iteration_num-1][i+1].y)/2-(V[j][iteration_num-1][i+1].x-V[j][iteration_num-1][i].x)*sqrt(3.0)/6;
V[j][iteration_num].push_back(tmp);
tmp.x=V[j][iteration_num-1][i].x+2*(V[j][iteration_num-1][i+1].x-V[j][iteration_num-1][i].x)/3;
tmp.y=V[j][iteration_num-1][i].y+2*(V[j][iteration_num-1][i+1].y-V[j][iteration_num-1][i].y)/3;
V[j][iteration_num].push_back(tmp);
}
V[j][iteration_num].push_back(V[j][iteration_num-1][len-1]);
}
tmp=iteration_num;
}
}
//每桢OpenGL都会调用这个函数,用户应该把显示代码放在这个函数中
void display(void)
{
//清除屏幕缓冲
glClear(GL_COLOR_BUFFER_BIT);
compute();
//开始绘制
glColor3f(1.0,1.0,1.0);
for(int j=0;j<3;j++){
glBegin(GL_LINE_STRIP);
for(int i=0;i<V[j][iteration_num].size();i++){
glVertex2f(V[j][iteration_num][i].x,V[j][iteration_num][i].y);
}
glEnd();
}
//交换前后缓冲区
glutSwapBuffers();
}
void processNormalKeys(unsigned char key,int x,int y)
{
switch(key) {
case 97: //按a增加迭代次数
if(iteration_num<max_iteration_num){
iteration_num++;
}
break;
case 100: //按d减少迭代次数
if(iteration_num>0){
iteration_num--;
}
break;
case 27: //"esc"
exit(0);
}
glutPostRedisplay();
}
//主函数
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
//初始化OPENGL显示方式
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
//设定OPENGL窗口位置和大小
glutInitWindowSize (800, 800);
glutInitWindowPosition (100, 100);
//打开窗口
glutCreateWindow ("kock曲线");
//调用初始化函数
myinit();
//设定窗口大小变化的回调函数
glutReshapeFunc(myReshape);
//设定键盘控制的回调函数
glutKeyboardFunc(processNormalKeys);
//开始OPENGL的循环
glutDisplayFunc(display);
glutMainLoop();
return 0;
}