
- •6.080200 – «Інформатика»
- •Під час виконання роботи студенти набувають досвіду у використанні спеціальних функцій графічного пакета OpenGl і методів програмування.
- •1 Рекомендації щодо написання та оформлення ргр
- •2 Короткі теоретичні відомості щодо виконання ргр
- •3 Приклади програм
- •4 Завдання до ргр
- •Список літератури
- •Розрахунково-графічна робота
- •39600, М. Кременчук, вул. Першотравнева, 20
3 Приклади програм
Приклади програм OPENGL слугують ілюстрацією застосування примітивів. У кожній програмі використовується одна або кілька функцій з тих, які наведені в табл. 1. Вікно зображення в кожній програмі задається за допомогою стандартних процедур GLUT.
Перша програма слугує ілюстрацією використання ламаної лінії, набору полімаркерів і підписів, що складаються з растрових символів, для побудови лінійного графіка за даними для кожного місяця протягом року. Тут використовується пропорційний шрифт, хоча по точках на графіку легше вирівнюється шрифт з постійною шириною символів. Оскільки растрове розташування визначається по лівому нижньому куту за допомогою функції визначення растрового розташування, необхідно змістити точку відліку, щоб вирівняти центр текстового рядка за розташуванням точок на графіці.
#include <GL/glut.h>
GLsizei winWidth = 600, winHeight = 500;
/* Вихідний розмір вікна зображення. */
GLint xRaster = 25, yRaster = 150;
/* Ініціалізація растрового розташування. */
GLubyte label [36] = {'J','a','n', 'F','e','b', 'M','a', 'r','A','p','r', 'M','a','y', 'J','u', 'n', 'J','u','l', 'A','u','g', 'S','e', 'p', 'O','c','t', 'N','o','v', 'D','e', 'c'};
GLint dataValue [12] = {420, 342, 324, 310, 262, 185,190, 196, 217, 240, 312, 438};
void init (void) {
glClearColor (1.0, 1.0, 1.0, 1.0); // Біле вікно.
glMatrixMode (GL_PROJECTION);
gluOrtho2D (0.0, 600.0, 0.0, 500.0);
}
void lineGraph (void) {
GLint month, k;
GLint x = 30; // Ініціалізація координати х.
glClear (GL_COLOR_BUFFER_BIT);
/*Чисте вікно зображення.*/
glColor3f (0.0, 0.0, 1.0); //Синій колір лінії.
glBegin (GL_LINE_STRIP);
/*Відображення графіку у вигляді ламаної лінії. */
for (k =0; k < 12; k++)
glVertex2i (x + k*50, dataValue [k]); glEnd ( );
glColor3f (1.0, 0.0, 0.0); //Червоний колір маркера.
for (k =0; k < 12; k++) {
/* Відображення даних полімаркером (зірочками). */ glRasterPos2i (xRaster + k*50, dataValue [k] - 4); glutBitmapCharacter (GLUT_BITMAP_9_BY_15, '*');
}
glColor3f (0.0, 0.0, 0.0); // Чорний колір тексту.
xRaster = 20;
/* Відображення підписів на діаграмі. */
for (month = 0; month < 12; month++) {
glRasterPos2i (xRaster, yRaster);
for (k = 3*month; k < 3*month + 3; k++){ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, label [k]);
xRaster += 50;}
glFlush ( );
}
void winReshapeFcn (GLint newWidth, GLint newHeight){
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( ) ;
gluOrtho2D (0.0, GLdouble (newWidth),
0.0, GLdouble (newHeight));
glClear (GL_COLOR_BUFFER_BIT);
}
void main (int argc, char** argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Лінійний графік даних");
init ( );
glutDisplayFunc (lineGraph); glutReshapeFunc (winReshapeFcn); glutMainLoop ( );
}
У другій програмі використовується той же набір даних і будується гістограма. Ця програма проілюструє застосування зафарбованих прямокутників, а також підписів, що складаються з растрових символів.
void barChart (void) {
GLint month, k, h;
glClear(GL_COLOR_BUFFER_BIT); // Чисте вікно зображення.
glColor3f (1.0, 0.0, 0.0);
/* Червоний колір прямокутників. */
for (k = 0; k < 12; k++)
glRecti (20 + k*50, 165, 40 + k*50, dataValue [k]); glColor3f (0.0, 0.0, 0.0); // Чорний колір тексту.
xRaster = 20;
/* Відображення підписів на діаграмі. */
for (month = 0; month < 12; month++) {
glRasterPos2i (xRaster, yRaster);
for (h = 3*month; h < 3*month + 3; h++){
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_12,label[h]);
xRaster += 50;
}
glFlush ( );
}
Щоб показати процентне співвідношення окремих частин цілого, використовують секторні діаграми. Наступна програма відображує секторну діаграму, яка будується за допомогою методу середньої точки для побудови кола. Для кількості та відносної величини секторів використовуються значення з попереднього прикладу.
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
const GLdouble twoPi = 6.283185;
GLsizei winWidth = 400, winHeight = 300;
/* Вихідний розмір вікна зображення. */
class scrPt { public: GLint x, y;
}
void init (void){
glClearColor (1.0, 1.0, 1.0, 1.0);
glMatrixMode (GL_PROJECTION);
gluOrtho2D (0.0, 200.0, 0.0, 150.0);
}
… // Процедури
… // відображення
… // кола.
void pieChart (void){
scrPt circCtr, piePt;
GLint radius = winWidth /4; // Радіус кола.
GLdouble sliceAngle, previousSliceAngle = 0.0;
GLint k, nSlices = 12; // Кількість секторіов.
GLfloat dataValues[12] = {10.0, 7.0, 13.0, 5.0, 13.0,
14.0,3.0, 16.0, 5.0, 3.0, 17.0, 8.0};
GLfloat dataSum = 0.0;
circCtr.x = winWidth / 2; // Координати центра кола.
circCtr.y = winHeight /2;
circleMidpoint (circCtr.x, circCtr.y, radius);
//Виклик процедури побудови кола методом середньої точки.
for (k = 0; k < nSlices; k++)
dataSum += dataValues[k];
for (k = 0; k < nSlices; k++) {
sliceAngle = twoPi * dataValues[k] / dataSum + previousSliceAngle;
piePt.x = circCtr.x + radius * cos (sliceAngle);
piePt.y = circCtr.y + radius * sin (sliceAngle);
glBegin (GL_LINES);
glVertex2i (circCtr.x, circCtr.y); glVertex2i (piePt.x, piePt.y);
glEnd ( );
previousSliceAngle = sliceAngle;
}
}
void displayFcn (void){
glClear (GL_COLOR_BUFFER_BIT);
/* Чисте вікно відображення. */
glColor3f (0.0, 0.0, 1.0); // Синій колір кола.
pieChart ( );
glFlush ( );
}
void winReshapeFcn (GLint newWidth, GLint newHeight) {
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
gluOrtho2D (0.0, GLdouble (newWidth), 0.0,GLdouble (newHeight));
glClear (GL_COLOR_BUFFER_BIT) ;
/* Зміна параметрів розміру вікна відображення.*/
winWidth = newWidth;
winHeight = newHeight;
}
void main (int argc, char** argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Секторна діаграма");
init ( );
glutDisplayFunc (displayFcn);
glutReshapeFunc (winReshapeFcn);
glutMainLoop ( );
}
Зображення різних фігур можна отримати за допомогою невеликих змін рівняння кола в останній програмі-прикладі, де для обчислення координат точок, що належать до кривої, використовуються параметричні полярні рівняння. Потім набутих значень використовують як координати кінців прямолінійних відрізків, за допомогою яких криві апроксимуються ламаними лініями. Криві, зображені на рис. 1, були отримані шляхом зміни радіусу r кола. Залежно від того, як змінюється радіус r, можна отримати равлика, кардіоїду, спіраль або інші подібні фігури.
а) б) в) г) д)
Рис. 1 – Фігури, зображення яких можна отримати за допомогою процедури drawCurve: а) равлик, б) кардіоїда, в) трилисник, г) чотирилисник, д) спіраль
#include <GL/glut.h> #include <stdlib.h> #include <math.h>
#include <iostream.h> struct screenPt {
GLint x;
GLint y;
}
typedef enum limacon = 1, cardioid, threeLeaf, fourLeaf,
spiral curveName;
GLsizei winWidth = 600, winHeight = 500;
/* Вихідний розмір вікна зображення. */
void init (void) {
glClearColor (1.0, 1.0, 1.0, 1.0); glMatrixMode (GL_PROJECTION);
gluOrtho2D (0.0, 200.0, 0.0, 150.0);
}
void lineSegment (screenPt ptl, screenPt pt2) { glBegin (GL_LINES);
glVertex2i (pt1.x, pt1.y);
glVertex2i (pt2.x, pt2.y);
glEnd ( );
}
void drawCurve (GLint curveNum) {
/* Равлик Паскаля є однією з модифікацій рівняння кола, при * якому радіус змінюється як r = а * cos(theta) + b з
* незмінними а і b. Кардіоїдою називається равлик, коли а = * b. Трилисник і чотирилисник створюються, коли r = а *
* cos(n * theta), де n = 3 або n = 2 відповідно. Зображення * спіралі виходить, коли r кратне theta.*/
const GLdouble twoPi = 6.283185;
const GLint a = 175, b = 60;
GLfloat r, theta, dtheta = 1.0 / float (a);
GLint x0 = 200, y0 = 250;// Вихідне положення на екрані.
screenPt curvePt[2];
glColor3f (0.0, 0.0,.0); // Чорний колір кривої.
// Ініціалізація розташування кривої.
curvePt[0].x = x0;
curvePt[0].y = y0;
switch (curveNum) {
case limacon: curvePt[0] .x += a + b; break;
case cardioid: curvePt[0] .x += a + a; break;
case threeLeaf: curvePt[0] x += a; break;
case fourLeaf: curvePt[0] x += a; break;
case spiral: break;
default: break;
}
theta = dtheta;
while (theta < two_Pi){
switch (curveNum){
case limacon:r = a * cos (theta) + b; break;
case cardioid:r = a * (1 + cos (theta)); break;
case threeLeaf:r = a * cos (3 * theta); break;
case fourLeaf:r = a * cos (2 * theta); break;
case spiral:r = (a / 4.0) * theta; break; default:break;
}
curvePt [].].x = x0 + r * cos (theta); curvePt[l].y = y0 + r * sin (theta); lineSegment (curvePt[0], curvePt[1]);
curvePt[0].x = curvePt[J].x;
curvePt[0].у = curvePt[1].y;
theta += dtheta;
}
}
void displayFcn (void){
GLint curveNum;
glClear (GL_COLOR_BUFFER_BIT); // Чисте вікно відображення.
cout « "\n Введіть ціле число, відповідне одній \n";
cout « " з перерахованих нижче назв кривих. Для виходу\n";
cout « " з програми натисніть будь-яку іншу клавішу.\n";
cout « "\n 1 - равлик, 2 - кардіоїда, 3 - трилисник,
4 - чотирилисник, 5 - спіраль: ";
cin » curveNum;
if (curveNum == 1 || curveNum == 2 || curveNum == 3 ||
curveNum == 4 | | curveNum == 5)
drawCurve (curveNum);
else
exit (0);
glFlush ( );
void winReshapeFcn (GLint newWidth, GLint newHeight) {
glMatrixMode (GL_PROJECTION);
glLoadldentity ( );
glu0rtho2D (0.0,(GLdouble) newWidth, 0.0, (GLdouble)
newHeight);
glClear (GL_COLOR_BUFFER_BIT);
}
void main (int argc, char** argv) {
glutlnit (Sargc, argv);
glutlnitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutlnitWindowPosition (100, 100);
glutlnitWindowSize (winWidth, winHeight);
glutCreateWindow ("Побудова кривих");
init ( );
glutDisplayFunc (displayFcn);
glutReshapeFunc (winReshapeFcn);
glutMainLoop ( );
}