Міністерство освіти і науки, молоді та спорту України
Національний університет „Львівська політехніка”
Кафедра БІТ
Розрахункова робота №1
З курсу:
“Копм’ютерна графіка”
Мета роботи : Набути практичних навиків в складанні програм для побудови зображень на екрані комп’ютера.
Завдання:
Побудувати графік функції (таблиця 1), заданої таблично. Графік повинен відображати результати розрахунків, які записані у файлі на диску. Масштаб розмітки осей координат графіка повинен відповідати реальним результатам розрахунків. Параметри для побудови графіка визначені в таблиці 2. Варіант завдання визначає викладач.
Необхідно передбачити “плаваючий” центр координат – основну частину екрану мають займати ті чверті, в яких знаходиться графік функції.
Варіант: 2
№ варіанту
Функція f(x)
Діапазон зміни аргументу
y=lg(x–19)
[19,0001;19,001]
№ варіанту
Тип лінії для побудови кривої графіка
Товщина лінії (пікселів)
Колір лінії
Шрифт розмітки осей графіка
2
2
Green
Gothic
Короткі теоретичні відомості.
Для адекватного відображення числових результатів на екрані необхідно для кожної прикладної задачі розробити чіткий алгоритм приведення реальних координат об’єкту дослідження до машинних координат. Це передбачає відображення центру реальних координат на екрані в машинних координатах та одержання функціональних залежностей для розрахунку машинних координат.
При побудові графіків для приведення реальних координат до машинних в загальному випадку використовують такі вирази:
; (1)
, (2)
де Xмаш , Yмаш - поточні машинні координати точки в пікселях ;
, - відображення центру реальних координат на екрані в машинних координатах ;
Xреальн ,Yреальн - поточні реальні координати точки ;
kX, kY - коефіцієнти перетворення .
Коефіцієнти перетворення в загальному випадку розраховують за наступними співвідношеннями :
; (3)
. (4)
Таким чином, для побудови графіка довільної функції можна скористатися алгоритмом:
Протабулювати задану функцію на проміжку зміни аргументу з метою визначення максимального та мінімального значень функції.
Визначити значення коефіцієнтів перетворення для стискання (у випадку, якщо максимальні значення функції або аргументу перевищують допустиму роздільну здатність монітора) або розширення діапазонів значень функції і аргументу для нормального візуального сприйняття заданої функції на екрані монітора.
Побудувати графік функції за попередньо обрахованими значеннями координат точок функції.
Здійснити розмітку осей через певні проміжки табулювання для X та Y.
Код програми:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// для работи з бібліотекою OpenGL
using Tao.OpenGl;
// для работи з бібліотекою FreeGLUT
using Tao.FreeGlut;
// для работи з елементом управління SimpleOpenGLControl
using Tao.Platform.Windows;
namespace rozrah1
{
public partial class Form1 : Form
{
// размеры окна
double ScreenW, ScreenH;
// отношения сторон окна визуализации
// для корректного перевода координат мыши в координаты,
// принятые в программе
private float devX;
private float devY;
// массив, который будет хранить значения x,y точек графика
private float[,] GrapValuesArray;
// количество элементов в массиве
private int elements_count = 0;
// флаг, означающий, что массив с значениями координат графика пока еще не заполнен
private bool not_calculate = true;
// номер ячейки массива, из которой будут взяты координаты для красной точки,
// для визуализации текущего кадра
private int pointPosition = 0;
// вспомогательные переменные для построения линий от курсора мыши к координатным осям
float lineX, lineY;
// текущение координаты курсора мыши
float Mcoord_X = 0, Mcoord_Y = 0;
public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}
private void AnT_Load(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
// инициализация бибилиотеки glut
Glut.glutInit();
// инициализация режима экрана
Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE);
// установка цвета очистки экрана (RGBA)
Gl.glClearColor(255, 255, 255, 1);
// установка порта вывода
Gl.glViewport(0, 0, AnT.Width, AnT.Height);
// активация проекционной матрицы
Gl.glMatrixMode(Gl.GL_PROJECTION);
// очистка матрицы
Gl.glLoadIdentity();
// определение параметров настройки проекции, в зависимости от размеров сторон элемента AnT.
if ((float)AnT.Width <= (float)AnT.Height)
{
ScreenW = 30.0;
ScreenH = 60.0 * (float)AnT.Height / (float)AnT.Width;
Glu.gluOrtho2D(0.0, ScreenW, 0.0, ScreenH);
}
else
{
ScreenW = 30.0 * (float)AnT.Width / (float)AnT.Height;
ScreenH = 60.0;
Glu.gluOrtho2D(0.0, 30.0 * (float)AnT.Width / (float)AnT.Height, 0.0, 60.0);
}
// сохранение коэфицентов, которые нам необходимы для перевода координат указателя в оконной системе, в координаты
// принятые в нашей OpenGL сцене
devX = (float)ScreenW / (float)AnT.Width;
devY = (float)ScreenH / (float)AnT.Height;
// установка объектно-видовой матрицы
Gl.glMatrixMode(Gl.GL_MODELVIEW);
// старт щетчика, отвечающего за выхов функции визуализации сцены
PointInGrap.Start();
}
// функция, управляющая визуализацией сцены
private void Draw()
{
// очистка буфера цвета и буфера глубины
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
// очищение текущей матрицы
Gl.glLoadIdentity();
// утснаовка черного цвета
Gl.glColor3f(0, 0, 0);
// помещаем состояние матрицы в стек матриц
Gl.glPushMatrix();
// выполняем перемещение в прострастве по осям X и Y
Gl.glTranslated(15, 15, 0);
// активируем рижим рисования (Указанные далее точки будут выводиться как точки GL_POINTS)
Gl.glBegin(Gl.GL_POINTS);
// с помощью прохода вдумя циклами, создаем сетку из точек
for (int ax = -20; ax < 20; ax++)
{
for (int bx = -48; bx < 48; bx++)
{
// вывод точки
Gl.glVertex2d(ax, bx);
}
}
// завершение редима рисования примитивов
Gl.glEnd();
// активируем режим рисования, каждые 2 последовательно вызванные комманды glVertex
// объединяются в линии
Gl.glBegin(Gl.GL_LINES);
// далее мы рисуем координатные оси и стрекли на их концах
Gl.glVertex2d(0, -20);
Gl.glVertex2d(0, 43);
Gl.glVertex2d(-15, 19);
Gl.glVertex2d(43, 19);
// вертикальная стрелка
Gl.glVertex2d(0, 43);
Gl.glVertex2d(0.1, 42.5);
Gl.glVertex2d(0, 43);
Gl.glVertex2d(-0.1, 42.5);
// горизонтальная трелка
Gl.glVertex2d(15, 19);
Gl.glVertex2d(14.5, 19.1);
Gl.glVertex2d(15, 19);
Gl.glVertex2d(14.5, 18.9);
// завершаем режим рисования
Gl.glEnd();
// выводим подписи осей "x" и "y"
PrintText2D(15.5f, 19.5f, "x");
PrintText2D(0.5f, 40.5f, "y");
// вызываем функцию рисования графика
DrawDiagram();
// возвращаем матрицу из стека
Gl.glPopMatrix();
// сигнал для обновление элемента реализующего визуализацию.
AnT.Invalidate();
}
// визуализация графика
private void DrawDiagram()
{
// проверка флага, сигнализирующего о том, что координаты графика вычеслены
if (not_calculate)
{
// если нет - то вызываем функцию вычисления координат графика
functionCalculation();
}
Gl.glColor3f(0, 1, 0);
// стартуем отрисовку в режиме визуализации точек
// объединяемых в линии (GL_LINE_STRIP)
Gl.glPointSize(2);
Gl.glLineStipple(1, 0x00FF);
Gl.glEnable(Gl.GL_LINE_STIPPLE);
Gl.glBegin(Gl.GL_LINE_STRIP);
// рисуем начальную точку
Gl.glVertex2d(GrapValuesArray[0, 0], GrapValuesArray[0, 1]);
// проходим по массиву с координатами вычисленных точек
for (int ax = 1; ax < elements_count; ax += 2)
{
// передаем в OpenGL информацию о вершине, участвующей в построении линий
Gl.glVertex2d(GrapValuesArray[ax, 0], GrapValuesArray[ax, 1]);
}
// завершаем режим рисования
Gl.glEnd();
Gl.glPointSize(1);
}
private void PrintText2D(float x, float y, string text)
{
// устанавливаем позицию вывода растровых символов
// в переданных координатах x и y.
Gl.glRasterPos2f(x, y);
// в цикле foreach перебираем значения из массива text,
// который содержит значение строки для визуализации
foreach (char char_for_draw in text)
{
// визуализируем символ c, с помощью функции glutBitmapCharacter, используя шрифт GLUT_BITMAP_9_BY_15.
Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_9_BY_15, char_for_draw);
}
}
// функция, производящая вычисления координат графика
// и заносящая их в массив GrapValuesArray
private void functionCalculation()
{
// определение локальных переменных X и Y
float x = 0, y = 0;
// инициализация массива, который будет хранить значение 300 точек
// из которых будет состоять график
GrapValuesArray = new float[300, 2];
// щетчик элементов массива
elements_count = 0;
// вычисления всех значений y, для x пренадлежащего промежутку от -15 до 15, с шагом в 0.01f
for (x = -15; x < 15; x += 0.1f)
{
// вычисление y для текущего x
// по формуле y = (float)Math.Sin(x)*3 + 1;
// эта строка задает формулу, описывающую график функции для нашего уравнения y = f(x).
y = (float)Math.Log(x);
// запись координаты x
GrapValuesArray[elements_count, 0] = x;
// запись координаты y
GrapValuesArray[elements_count, 1] = y;
// подсчет элементов
elements_count++;
}
// изменяем флаг, сигнализировавший о том, что координаты графика не вычисленны
not_calculate = false;
}
private void PointInGrap_Tick_1(object sender, EventArgs e)
{
// если мы дошли до последнего элемента массива
if (pointPosition == elements_count - 1)
pointPosition = 0; // переходим к начальному элементу
// функция визуализации
Draw();
// переход к следующему элементу массива
pointPosition++;
}
}
}
Виконання програми:
Висновок: Виконуючи розрахункову роботу я набув практичних навиків в складанні програм для побудови зображень на екрані комп’ютера.