В представленных программах с помощью программного интерфейса OpenGL пользователю предоставляется возможность 1 ) В первой программе кривая вычерчивается по интерполяционной формуле. 2 ) Во второй программе кривая вычерчивается средствами OpenGL. ВНИМАНИЕ! Для запуска программы необходимо установить библиотеку GLUT. Библиотека GLUT присутствует в архиве. Инструкция (с картинками) по использованию OpenGL и GLUT в Visual Studio (Windows 7/XP) в архиве. Используемая среда разработки: Microsoft Visual Studio 2010. Кривая вычерчивается по интерполяционной формуле #include <gl\glut.h> struct point { float x, y; } P[350]; int n = 0, i, j; bool tP = false; void Draw( ); void Mouse(int button, int state, int x, int y); void MenuChek(int v); void CurveBezier( ); void Line( ); void main( ) { //Инициализируем режим отображения окна OpenGL //GLUT_DOUBLE - окно с двойной буферизацией //GLUT_RGB - режим RGBA glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(350,350); //устанавливаем размер окна glutCreateWindow("Кривая Безье"); //создаем окно с заголовком glutDisplayFunc(Draw); //устанавливаем функцию отрисовки glutMouseFunc(Mouse); //устанавливаем функцию обработки нажатий мыши //Установить цвет и значение альфа, используемые при очистке буферов цвета glClearColor(1,1,1,1); //цвет фона (RGBA) glMatrixMode(GL_PROJECTION); //Определяем стек матриц (матрица проекций) glLoadIdentity(); //установить текущую матрицу равной еденичной glOrtho(0,350,0,350,0,1); //Установить границы объема отсечения glColor3f(0,0,0); //Установить текущий цвет (R,G,B) glutCreateMenu(MenuChek); //Меню вызываемое нажатием ПКМ glutAddMenuEntry("Удалить последнюю точку", 0); //Пункт меню glutAddMenuEntry("Очистить", 1); //Пункт меню glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); //Запуск основного цикла обработки GLUT } void Draw( ) { glClear(GL_COLOR_BUFFER_BIT); //Очистка буфера цвета Line( ); if (n > 3) CurveBezier(); glutSwapBuffers(); //Переключить буферы в режиме двойной буферизации } void Mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON) { if (tP && (x > 0 && x < 350)&& (350 > y && y < 700) ) { P[j].x = x; P[j].y = 350-y; } else if (state == GLUT_DOWN && n != 0 && !tP) for (i = 0; i <= n; i++) if ((x<P[i].x+30 && x>P[i].x-30) && (320-y<P[i].y && 380-y>P[i].y)) { tP = true; j = i; break; } if (state == GLUT_UP) { if (!tP) { P[n].x = x; P[n].y = 350-y; n++; } tP = false; } } glutPostRedisplay(); //Обновить текущее окно } void MenuChek(int v) { if (v == 0 && n > 0) n--; else if (v == 1) n = 0; glutPostRedisplay(); //Обновить текущее окно } void Line ( ) { glPointSize(5); glColor3f(0,0,0); //Контрольные точки glBegin(GL_POINTS); for (i = n-1; i >= 0; i--) glVertex2f(P[i].x, P[i].y); glEnd(); //Пунктирные линии glLineStipple(2,58360); glEnable(GL_LINE_STIPPLE); glBegin(GL_LINES); for (i = 0; i < n-1; i++) { glVertex2f(P[i].x, P[i].y); glVertex2f(P[i+1].x, P[i+1].y); } glEnd(); glDisable(GL_LINE_STIPPLE); glPointSize(1); } void CurveBezier( ) { float px0,px1,px2,px3, py0,py1,py2,py3, xt, yt; for(i = 1; i < n-2; i++) { px0 = (P[i-1].x + 4*P[i].x + P[i+1].x) / 6.0; px1 = (-P[i-1].x + P[i+1].x) / 2.0; px2 = (P[i-1].x - 2*P[i].x + P[i+1].x) / 2.0; px3 = (-P[i-1].x + 3*P[i].x - 3*P[i+1].x + P[i+2].x) / 6.0; py0 = (P[i-1].y + 4*P[i].y + P[i+1].y) / 6.0; py1 = (-P[i-1].y + P[i+1].y) / 2.0; py2 = (P[i-1].y - 2*P[i].y + P[i+1].y) / 2.0; py3 = (-P[i-1].y + 3*P[i].y - 3*P[i+1].y + P[i+2].y) / 6.0; glColor3f(1,0,0); glPointSize(2); glBegin(GL_POINTS); for(float t = 0.0; t <= 1.0; t += 0.001) { xt = ((px3*t + px2)*t + px1)*t + px0; yt = ((py3*t + py2)*t + py1)*t + py0; glVertex3f(xt, yt, 0); } glEnd(); } } Кривая вычерчивается средствами OpenGL. #include <gl\glut.h> float point[350][3]; int n = 0, i, j; bool tP = false; void Draw( ); void Mouse(int button, int state, int x, int y); void MenuChek(int v); void CurveBezier( ); void Line( ); void main( ) { //Инициализируем режим отображения окна OpenGL //GLUT_DOUBLE - окно с двойной буферизацией //GLUT_RGB - режим RGBA glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(350,350); //устанавливаем размер окна glutCreateWindow("Кривая Безье"); //создаем окно с заголовком glutDisplayFunc(Draw); //устанавливаем функцию отрисовки glutMouseFunc(Mouse); //устанавливаем функцию обработки нажатий мыши //Установить цвет и значение альфа, используемые при очистке буферов цвета glClearColor(1,1,1,1); //цвет фона (RGBA) glMatrixMode(GL_PROJECTION); //Определяем стек матриц (матрица проекций) glLoadIdentity(); //установить текущую матрицу равной еденичной //Установить границы объема отсечения glOrtho(0,350,0,350,0,1); glColor3f(0,0,0); //Установить текущий цвет (R,G,B) glutCreateMenu(MenuChek); //Меню вызываемое нажатием ПКМ glutAddMenuEntry("Удалить последнюю точку", 0); //Пункт меню glutAddMenuEntry("Очистить", 1); //Пункт меню glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); //Запуск основного цикла обработки GLUT } void Draw( ) { glClear(GL_COLOR_BUFFER_BIT); //Очистка буфера цвета Line( ); if (n > 1) CurveBezier(); glutSwapBuffers(); //Переключить буферы в режиме двойной буферизации } void Mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON) { if (tP && (x > 0 && x < 350)&& (350 > y && y < 700) ) { point[j][0] = x; point[j][1] = 350-y; } else if (state == GLUT_DOWN && n != 0 && !tP) for (i = 0; i <= n; i++) if ((x<point[i][0]+30 && x>point[i][0]-30) && (320-y<point[i][1] && 380-y>point[i][1])) { tP = true; j = i; break; } if (state == GLUT_UP) { if (!tP) { point[n][0] = x; point[n][1] = 350-y; n++; } tP = false; } } glutPostRedisplay(); //Обновить текущее окно } void MenuChek(int v) { if (v == 0 && n > 0) n--; else if (v == 1) n = 0; glutPostRedisplay(); } void Line ( ) { glPointSize(5); glColor3f(0,0,0); //Контрольные точки glBegin(GL_POINTS); for (i = n-1; i >= 0; i--) glVertex2fv(point[i]); glEnd(); //Пунктирные линии glLineStipple(2,58360); glEnable(GL_LINE_STIPPLE); glBegin(GL_LINES); for (i = 0; i < n-1; i++) { glVertex2fv(point[i]); glVertex2fv(point[i+1]); } glEnd(); glDisable(GL_LINE_STIPPLE); glPointSize(1); } void CurveBezier( ) { //glMap1f - Функция оценки, генерирующая координаты. //Параметры: // GL_MAP1_VERTEX_3 - тип генерируемых данных, // 0.0f - нижняя граница параметра u (первая точка), // 100.0f - верхняя граница(последняя точка), // 3 - расстояние между точками данных, // n - число точек, // &P[0][0] - массив контрольных точек glMap1f(GL_MAP1_VERTEX_3, 0.0f, 100.0f, 3, n, &point[0][0]); glEnable(GL_MAP1_VERTEX_3); glLineWidth(2); glColor3f(1.0f,0.0f,0.0f); glBegin(GL_LINE_STRIP); //точки соединяются ломанной линией for (i = 0; i <= 100; i++) //Оценка кривой в точке. Функция принимает параметрическое значение, и вычисляет точку glEvalCoord1f(float(i)); glEnd(); glLineWidth(1); }
Ключевые слова:
кривая, безье, opengl, сплайн, интерполяция, curve, bezier
|
|||||||