МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
Кафедра ЗІ
Звіт до лабораторної роботи № 3
Побудова графіка функцій за допомогою засобів мови програмування С#
З дисципліни
“Програмування комп’ютерної графіки”
Львів – 2011
Мета роботи - набути практичних навиків в складанні програм для побудови графіків функцій за допомогою засобів мов програмування С#.
ЗАВДАННЯ
Домашня пiдготовка до роботи
Ознайомитися з методами побудови графіків функцій на екрані монітора комп’ютера.
Вивчити основні процедури мови Турбо-Паскаль для виведення тексту в графічному режимі.
Написати програму, яка будує в середині екрану систему координат XY і на ній графік функції Y=F(X), використовуючи графічні оператори мови Турбо Паскаль, якщо аргумент або параметр змінюється на проміжку [a;b] з кроком h. Варіанти завдань беруть з таблиці 1 за вказівкою викладача.
Таблиця 1.
N% п/п
Функція
Інтервал
Крок
15
t=[-100;100]
h=0.5
Список ідентифікаторів констант, змінних, процедур і функцій, використаних в програмі, та їх пояснення.
Glut.Init - ініціалізація бібліотеки Glut
Glut.glutInitDisplayMode() - функція встановлення режиму відображення :
GLUT_RGB - режим бітової маски вікна
GLUT_DOUBLE - подвійна буферизація вікна, з метою усунення мерехтіння, яке виникає в результаті швидкого перемальовування кадрів декілька раз підряд
GLUT_DEPTH - вказується при ініціалізації вікна, якщо в додатку буде використовуватись буфер глибини
Gl.glClearColor() - встановлення кольору очистки вікна
Gl.glViewport(0,0,OnGl.Width,OnGl.Height) - встановлення порту виводу (в нашому випадку охоплює всю область елемента OnGl)
Gl.glMatrixMode(Gl.GL_PROJECTION) - задає матричний режим, в якому будемо виконувати операції, GL_PROJECTION - матриця проекцій
Gl.glLoadIdentity() - очищення матриці, функція заміняє поточну матрицю на одиничну
Glu.gluPerspective(кут візуального охоплення, відношення сторін порту перегляду, ближня, дальня площина перегляду) - будує піраміру охоплення видимості
GL_MODELVIEW - об'єктно-видова матриця
Gl.glEnable() - включення необхідних опцій для коректної візуалізації сцени
ScreenW, ScreenH – змінні, що задають розмір вікна.
elements_count – кількість елементів в масисі.
GrapValuesArray – масив, який буде зберігати значення точок х,у графіка.
devX, devY - змінні, що відповідають за вдношення сторін вікна візуалізації.
pointPosition - номер комірки масиву, з якої будуть взяті координати для червоної точки, для візуалізації поточного кадру.
lineX, lineY - допоміжні змінні для побудови ліній від курсору миші до координатних осей.
functionCalculation() - функція, яка виробляє обчислення координат графіка і яка заносить їх у масив GrapValuesArray.
PrintText2D() – функція візуалізації тексту.
AnT_MouseMove() – обробка руху миші над елементом AnT.
PointInGrap_Tick() - функція, обробник події таймера.
DrawDiagram() – візуалізація графіка.
Draw() - функція, керування візуалізацією сцени.
Повний текст програми
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 WindowsFormsApplication8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AnT.InitializeContexts();
}
// размеры окна
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;
private void PointInGrap_Tick(object sender, EventArgs e)
{
// если мы дошли до последнего элемента массива
if (pointPosition == elements_count - 1)
pointPosition = 0; // переходим к начальному элементу
// функция визуализации
Draw();
// переход к следующему элементу массива
pointPosition++;
}
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 = 200.0;
ScreenH = 30.0 * (float)AnT.Height / (float)AnT.Width;
Glu.gluOrtho2D(0.0, ScreenW, 0.0, ScreenH);
}
else
{
ScreenW = 200.0 * (float)AnT.Width / (float)AnT.Height;
ScreenH = 30.0;
Glu.gluOrtho2D(0.0, 200.0 * (float)AnT.Width / (float)AnT.Height, 0.0, 30.0);
}
// сохранение коэфицентов, которые нам необходимы для перевода координат указателя в оконной системе, в координаты
// принятые в нашей OpenGL сцене
devX = (float)ScreenW / (float)AnT.Width;
devY = (float)ScreenH / (float)AnT.Height;
// установка объектно-видовой матрицы
Gl.glMatrixMode(Gl.GL_MODELVIEW);
// старт щетчика, отвечающего за выхов функции визуализации сцены
PointInGrap.Start();
}
private void AnT_MouseMove(object sender, MouseEventArgs e)
{
// созраняем координаты мыши
Mcoord_X = e.X;
Mcoord_Y = e.Y;
// вычисляем параметры для будующей дорисовке линий от указателя мыши к координатным осям.
lineX = devX * e.X;
lineY = (float)(ScreenH - devY * e.Y);
}
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);
}
}
private void functionCalculation()
{
// определение локальных переменных X и Y
float x = 0, y = 0;
// инициализация массива, который будет хранить значение 300 точек
// из которых будет состоять график
GrapValuesArray = new float[600, 2];
// щетчик элементов массива
elements_count = 0;
// вычисления всех значений y, для x пренадлежащего промежутку от -15 до 15, с шагом в 0.01f
for (x = 5; x < 180; x += 0.5f)
{
// вычисление y для текущего x
// по формуле y = (float)Math.Sin(x)*3 + 1;
// эта строка задает формулу, описывающую график функции для нашего уравнения y = f(x).
y = (float)10*(Math.Sin(x / 8) + Math.Log(3 * x) * Math.Cos(x / 8));
// запись координаты x
GrapValuesArray[elements_count, 0] = x;
// запись координаты y
GrapValuesArray[elements_count, 1] = y;
// подсчет элементов
elements_count++;
}
// изменяем флаг, сигнализировавший о том, что координаты графика не вычисленны
not_calculate = false;
}
private void DrawDiagram()
{
// проверка флага, сигнализирующего о том, что координаты графика вычеслены
if (not_calculate)
{
// если нет - то вызываем функцию вычисления координат графика
functionCalculation();
}
// стартуем отрисовку в режиме визуализации точек
// объединяемых в линии (GL_LINE_STRIP)
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();
// устанавливаем размер точек, равный 5 пикселям
Gl.glPointSize(5);
// устанавливаем текущим цветом - красный цвет
Gl.glColor3f(255, 0, 0);
// активируем режим вывода точек (GL_POINTS)
Gl.glBegin(Gl.GL_POINTS);
// выводим красную точку, используя ту ячеку массива, до которой мы дошли (вычисляется в функии обработчике событий таймера)
Gl.glVertex2d(GrapValuesArray[pointPosition, 0], GrapValuesArray[pointPosition, 1]);
// завершаем режим рисования
Gl.glEnd();
// устанавливаем размер точек равный еденице
Gl.glPointSize(1);
}
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 = -15; ax < 1000; ax++)
{
for (int bx = -15; bx < 1000; bx++)
{
// вывод точки
Gl.glVertex2d(ax, bx);
}
}
// завершение редима рисования примитивов
Gl.glEnd();
// активируем режим рисования, каждые 2 последовательно вызванные комманды glVertex
// объединяются в линии
Gl.glBegin(Gl.GL_LINES);
// далее мы рисуем координатные оси и стрекли на их концах
Gl.glVertex2d(0, -15);
Gl.glVertex2d(0, 15);
Gl.glVertex2d(-15, 0);
Gl.glVertex2d(15, 0);
// вертикальная стрелка
Gl.glVertex2d(0, 15);
Gl.glVertex2d(0.1, 14.5);
Gl.glVertex2d(0, 15);
Gl.glVertex2d(-0.1, 14.5);
// горизонтальная трелка
Gl.glVertex2d(15, 0);
Gl.glVertex2d(180.5, 0.1);
Gl.glVertex2d(15, 0);
Gl.glVertex2d(15.5, -0.1);
// завершаем режим рисования
Gl.glEnd();
// выводим подписи осей "x" и "y"
PrintText2D(180.5f, 0, "x");
PrintText2D(0.5f, 14.5f, "y");
// вызываем функцию рисования графика
DrawDiagram();
// возвращаем матрицу из стека
Gl.glPopMatrix();
// выводим текст со значением координат возле курсора
PrintText2D(devX * Mcoord_X + 0.2f, (float)ScreenH - devY * Mcoord_Y + 0.4f, "[ x: " + (devX * Mcoord_X - 15).ToString() + " ; y: " + ((float)ScreenH - devY * Mcoord_Y - 15).ToString() + "]");
// устанавливаем красный цвет
Gl.glColor3f(255, 0, 0);
// включаем режим рисования линий, для того чтобы нарисовать
// линии от курсора мыши к координатным осям
Gl.glBegin(Gl.GL_LINES);
Gl.glVertex2d(lineX, 15);
Gl.glVertex2d(lineX, lineY);
Gl.glVertex2d(15, lineY);
Gl.glVertex2d(lineX, lineY);
Gl.glEnd();
// дожидаемся завершения визуализации кадра
Gl.glFlush();
// сигнал для обновление элемента реализующего визуализацию.
AnT.Invalidate();
}
}
}
Результат виконання програми
Висновок
В даній лабораторній роботі я набув практичних навиків в складанні програм для побудови графіків функцій за допомогою засобів мови програмування С#.