Программный продукт "Графический редактор учебно-методических материалов"
Наиболее распространенные графические редакторы. Использование специфических возможностей для создания графических иллюстративных компонентов по высшей математике с помощью специализированного формата хранения векторной информации. Достоинства приложения.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 08.06.2011 |
Размер файла | 904,4 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
setCoordPoint() - вызывается методом onMouseDown() и производит работу по присвоению координат начальной и конечной точки линии. Выделение такого метода обусловлено необходимостью создания более наглядного кода, для дальнейшего сопровождения программы.
Для моделирования динамических аспектов работы класса в рамках языка UML применяются диаграммы последовательностей. Данные диаграммы позволяют более подробно увидеть процессы взаимодействия методов описанного класса. В Приложении Б «Диаграмма последовательностей вызовов методов класса «Линия»» составлена схема взаимодействия различных методов, начиная с отправки сообщений от программы к классу, и заканчивая взаимодействием отдельных методов и свойств, оказывающих влияние друг на друга.
3.3.1.3 Класс «Ломаная линия»
Класс позволяет нарисовать несколько отрезков. Причем для рисования первого отрезка необходимо задания двух точек, а для всех последующих - только одной. Основная функциональная возможность данного класса, в отличие от класса «Линия», заключается в том, что при работе с данным примитивом возможно рисование различных фигур состоящих из множества отрезков, например, рисования прямоугольников, ромбов и т.д. Также класс позволяет реализовать возможность рисования замкнутых фигур, состоящих из прямых отрезков, и в последующем применять к ним заливки различных цветов.
Наличие класса «Линия» и класса «Ломаная линия», столь похожих друг на друга, определяется, прежде всего, потребностью пользователя. Так как создание примитива «Линия» по сравнению с заданием примитива «Ломаная линия» требует меньшее количество операций мыши, задействует меньшее количество её кнопок, что несколько упрощает работу с примитивом «Линия».
Класс является наследником класса «Примитив», а, следовательно, кроме своих свойств и методов в нем доступны открытые свойства и методы класса «Примитив». Рассмотрим основные методы и свойства, кроме тех, что реализуют одинаковый функционал.
Открытые свойства.
PLPoints [1000] - массив элементов типа «Точка». Позволяет хранить информацию о точках, задающих ломаную линию. Максимальное количество точек в примитиве «Ломаная линия» ограничено 1000. Такое количество точек позволяет пользователю нарисовать окружность, переломы на которой будут не отличимыми для глаза.
Numpoints - свойство характеризует количество заданных точек. Задание примитива считается законченным, когда пользователь нажимает правую кнопку мыши или замыкает примитив. При этом в родительском классе «Примитив» устанавливается значение _closed и/или _finished.
Открытые методы.
Draw() - метод рисования ломаной линии на экране, как в момент задания линии пользователем, так и в процессе работы с другими примитивами при изменении содержания OpenGL сцены. В качестве параметров принимает контекст устройства воспроизведения и контекст окна Open GL. Данный метод также реализует подсветку линии, если в текущий момент времени пользователем выделен данный объект. Подсветка реализуется как задание прямоугольника, координаты которого определяются закрытыми методами FindMax() и FindMin(). При рисовании незаконченной фигуры производится отрисовка той части примитива, которая закончена, а после, добавляется сегмент, который пользователь в текущий момент перемещает для выбора точки. Данный метод вызывает и заливку заданной фигуры.
onMouseOver() - особенностью данного метода является тот факт, что массив точек задающих примитив по сравнению с классом линия расширен и может иметь большее количество точек, чем член класса linePoints. Метод класса «Ломаная линия» в качестве параметров принимает значения координат указателя мыши.
isPointInPoligon() - является наследуемым от класса «Примитив» и позволяет узнать принадлежит ли точка, указываемая пользователем, примитиву. При этом если точка принадлежит примитиву, производится переприсвоение значения цвета заливки примитива. В противном случае изменение цвета заливки не будет применено и цвет останется прежним.
Закрытые методы.
setCoordPoint() - особенностью данного метода от метода, определенного в классе «Линия», является необходимость проверки номера точки, так как для задания первого отрезка ломаной линии необходимо задавать две точки, а каждый следующий отрезок требует ввода только одной точки. При этом храниться только необходимое количество точек для ломаной линии, т.е. N+1 точек, где N- число отрезков ломаной линии. Выделение такого метода обусловлено необходимостью создания более наглядного кода, для
дальнейшего сопровождения программы.
Для более подробного описания процессов взаимодействия членов данного класса в Приложении В приводится «Диаграмма последовательностей вызовов методов класса «Ломаная линия».
3.3.1.4 Класс «Вектор»
Класс «Вектор» - позволяет построить на основе ломаной линии совокупность векторов. Основными членами данного класса являются ломаная линия, и массив точек для рисования стрелки вектора. Данный класс является наследником класса «Примитив», а также в качестве своих членов использует классы «Ломаная линия» и «Точка». В целом для данного класса характерны большинство методов описанных ранее, однако некоторые из них имеют характерные для данного класса отличия. Рассмотрим более подробно свойства и метода данного класса.
Открытые свойства.
vector: Polyline - член класса является экземпляром класса «Ломаная линия». И позволяет не останавливаться подробно на создании и рисовании ломаной линии, лежащей в основе вектора. Отличие вектора от ломаной линии в том, что необходимо рисовать стрелки для указания направления вектора.
Arrow[4]: Point - временное хранилище точек для каждой стрелки вектора. Далее будет описана процедура заполнения точками данного массива, а также процедура отрисовки стрелки.
typeArrow: byte - хранит значение типа стрелки. В рамках проекта было реализовано два вида: в качестве двух линий и в качестве треугольника (см. рис. 3.2.).
Размещено на http://www.allbest.ru/
Рисунок 3.2. Допустимые типы стрелок вектора.
Открытые методы
Draw() - позволяет нарисовать вектор на экране. В ходе рисования выполняется рад действий: установка параметров рисования (цвета и толщины); передача параметров выделения через член класса vector в класс «Ломаная линия»; отрисовка ломаной линии через член класса vector; цикл для рисования стрелки в конце каждого отрезка. В данном цикле выполняется пересчет значений массива Arrow, т.к. в зависимости от начальной и конечной точки изменяется позиция точек стрелки, приводя при этом к изменению наклона стрелки. Без этой процедуры корректная отрисовка точек стрелки не будет производиться. После вычисления значений точек стрелки производится её рисование в соответствии с установленным типом стрелки.
onMouseOver(), onMouseMove(), onMouseDown(), onRemove(), isPointInPoligon() - выполняют тот же набор действий что и одноименные методы других классов. Однако отличие данных методов состоит в более простом обработке, т.к. большинство методов вызывается членом vector класса «Вектор». Так, например, для перемещения вектора на экране необходимо изменить позицию заданной ломаной линии путем вызова функции onRemove() к открытому свойству vector;
recalcPoints() - позволяет изменить положение точек вектора на экране
при изменении размеров сцены. Особенностью данного метода также является необходимость вызова функции recalcPoints() класса «Ломаная линия» для члена класса vector;
changeTypeArrow() - метод принимает в качестве параметра целочисленное значение. Если целое значение равно 1, то свойству typeArrow присваивается значение константы GL_LINES, позволяющее рисовать стрелку в виде двух линий. В противном случае устанавливается значение константы GL_TRIANGLES из библиотеки OpenGL, позволяющее нарисовать стрелку вектора в виде треугольника;
getTypeArrow() - возвращает целочисленное значение 1 или 2, характеризующее установленный тип стрелки вектора. Данная информация в дальнейшем используется для сохранения параметров вектора в файл.
Закрытые методы.
calcArrow() - позволяет просчитать наклон стрелки и установить значения её точек в массив Arrow. Вычисление значений точек производится исходя из формул поворота и начального состояния стрелки. Данная функция учитывает и пограничные случаи, например, рисование стрелки в вертикальной (сверху вниз, снизу вверх) или горизонтальной позиции (слева направо, справа налево).
Формула поворота, используемая для вычисления значений точки, в случаях отличных от описанного выше, имеет вид:
, (3)
где X,Y - новые координаты точки, Xc, Yc -центр вращения точки, X1, Y1 - старые координаты точки, - угол поворота точки, который рассчитывается предварительно, используя координаты начала и конца отрезка вектора по формуле:
, (4)
где i- номер точки конца вектора. Формула применяется для всех точек кроме первой.
Для более полного понимания процессов, происходящих при обращении основной программы к данному классу, построим диаграмму последовательностей вызовов функций характерных для данного класса (Приложение Г).
3.3.1.5 Класс «Безье»
Класс «Кривая Безье» - позволяет рисовать совокупность сплайнов третьего порядка. Задание первой кривой производится посредством ввода четырех точек: двух опорных и двух управляющих. Каждый последующий сплайн задается только тремя точками. Для задания возможности редактирования кривой Безье, опорные и управляющие точки заданы массивом, для подсчета количества заданных точек используется специальный член класса. Рассмотрим основные функции и свойства, определенные в данном классе.
Открытые свойства.
BPoints [1000]:Point - массив экземпляров класса «Точка» позволяет хранить информацию о точках кривой третьего порядка. Отличительной особенностью данного массива от других классов состоит в том, что каждая вторая и четвертая точка является управляющей и позволяет изменять изгиб данного примитива;
numPoint: int - позволяет сохранить количество точек линии третьего порядка. В общем случае количество точек кратно четырем.
Открытые методы.
Draw() - отличается от одноименного метода, описанного выше, тем, что для рисования каждой отдельной кривой Безье выделяются четыре точки. По данным точкам, используя стандартные функции создания сложных объектов, так называемых итераторов, производится вычисление промежуточных точек линии Безье. Полученные в результате вычисления точки сохраняются в специальном объекте «карта точек», являющимся массивом, определенным в библиотеке OpenGL. Используя стандартные процедуры графической библиотеки, можно произвести рисование сегментов кривой Безье, по полученным точкам используя функцию glEvalCoord1f. В качестве значений функция принимает значение элемента массива, в котором хранятся промежуточные точки.
Таким образом, последовательное обращение к четверкам точек можно произвести рисование всех линий Безье, из которых состоит кривая третьего порядка.
onMouseOver(), onMouseMove(), onMouseDown(), onRemove(), isPointInPoligon(), isSelected(), recalcPoints(), getNumPoint(), isClosedPrim(), GetX(int i), GetY(int i), UndoPoint() - выполняют тот же набор действий, что и одноименные методы других классов (кроме класса «Ломаная линия»). Особенностью метода isPointInPoligon является необходимость проверки попадания точки в полигон. Сложность данной процедуры состоит в том, что объект является достаточно сложным и невозможно узнать положение промежуточных точек, так как библиотека OpenGL не предоставляет средств доступа к данному массиву. По этой причине для реализации в дальнейшем заливки принято решение о том, что если пользователь нажимает кнопку мыши в области, характеризующей выделение, то заливка будет применяться, в противном случае заливка области не будет осуществляться. Как и для остальных примитивов, заливка области применима только для замкнутых фигур.
Закрытые методы.
В целом основная масса закрытых методов данного класса носит тот же функционал, что и закрытые методы, описанных выше классов, однако их выделение в данном классе позволяет акцентировать внимание на особенностях задания точек кривой третьего порядка и проверку тех или иных свойств в
соответствии с объявленными членами класса.
Особенностью закрытого метода setCoordPoint() состоит в том, что для задания первой части кривой третьего порядка необходимо задание четырех точек, а каждой последующей только трех. Кроме того метод позволяет переносить значения еще не заданных точек в соответствии с последней заданной. Так, например, если пользователь задал одну контрольную и одну управляющую точку и ищет позицию для задания второй контрольной точки, то значения курсора при перемещении изменяется, и данные значения устанавливаются в те точки, которые ещё не заданы. Такой подход позволяет рисовать линию третьего порядка достаточно наглядно, так как пользователь, перемещая указатель мыши, видит, к каким изменениям кривой приводят данные перемещения.
В целом данная характеристика характерна для создания любых объектов на основе точек и позволяет достигать большей производительности при использовании программного продукта в целом.
3.3.1.6 Класс «Окружность»
Класс предназначен для рисования окружностей различных радиусов. Пользователь при выборе инструмента «Окружность» должен задать пару точек: центр окружности и радиус. Центр окружности и её радиус вводится при помощи нажатия левой кнопки мыши. Данный инструмент позволяет создавать выколотые точки с различной заливкой, а также является общим классом, для описанных далее классов «Два множества» и «Три множества». Данный класс наследуется от класса «Примитив», что позволяет определить абстрактные методы и хранить экземпляры класса в одном массиве, наряду с другими классами описанными выше.
Рассмотрим основные свойства и методы данного класса.
Открытые свойства.
arrpoint: POINT - является постоянным и не может быть изменено только программно. Так как в библиотеке OpenGL не существует возможностей создания окружностей, то для её реализации необходимо просчитать точки расположенные на окружности, и соединить их используя ломаную линию. Данное свойство позволяет сохранить информацию о точках данной ломаной линии.
centerP: Point - хранит информацию о центре окружности, задается пользователем путем нажатия мыши в начале создания данного графического примитива.
pointR: Point - хранит информацию о точке которую пользователь
выбрал при указании радиуса. Так как после задания центральной точки пользователь может перемещать мышь и видеть, какую окружность он получает, то необходимо при таких манипуляциях рассчитывать истинный радиус окружности по формуле:
, (5)
где Xc, Yc - координаты центра окружности, Xm, Ym - текущие координаты мыши.
Информации о данной точке, пользователю в дальнейшем позволяет изменить радиус окружности, при этом используются методы определенные в классе точка.
radius: real - хранит информацию о текущем радиусе окружности, необходим для сокращения вычислений при рисовании и вычисляется при изменении координат предыдущего члена.
numPoint: byte - позволяет узнать какое количество точек было задано. При помощи использования данного члена при задании окружности, можно узнать, задана она полностью, т.е. введены и центр окружности и точка, характеризующая радиус или задана только центральная точки и при следующем нажатии левой клавиши мыши будет задана точка для вычисления радиуса окружности.
rgnCircle: HRGN - позволяет в дальнейшем определить попадание точки в окружность и залить окружность требуемым цветом.
Закрытые свойства.
numLines: int {frozen} - свойство позволяет установить значение количества точек располагаемых на окружности для её построения ломаными линиями. Данный член класса не изменяется и является постоянным числом, определяемым при создании экземпляра класса.
Открытые свойства.
onResize() - позволяет отработать событие изменения размера сцены, так как при её изменении изменяется как позиция центральной точки окружности, так и точки используемой для вычисления радиуса.
Draw() - позволяет нарисовать окружность, используя ряд след. шагов: проверка выделения объекта и при условии выделения рисование прямоугольника подсветки; установка цвета и толщины линии рисовании окружности; вычисление точек окружности и их рисование соединяя точки ломаной замкнутой линией с использованием константы OpenGL GL_LINE_LOOP. Вычисление точек окружности производится по формуле:
, (6)
где Xc, Yc - центр окружности, numLines - значение одноименного свойства класса, i - номер точки для расчета.
getRegion() - позволяет создавать регион из точек окружности. Строится по промежуточным точкам, и позволяет при использовании в наследуемых классах производить заливку сложных регионов, путем выполнения пересечения данных регионов.
Закрытые методы.
setCoordPoint() - позволяет задать координаты центра или точки, характеризующей радиус окружности. Для определения характеристики: какая из точек задается в текущие момент - используется член класса numPoint.
3.3.1.7 Два множества
Класс «Два множества » предназначен для реализации функциональной возможности рисования диаграмм Эйлера-Венна. Суть данного класса состоит в том, что, используя базовый класс «Примитив», позволяющий хранить экземпляры данного класса, как и остальные примитивы, создать совокупность двух окружностей, изображающих два пресекающихся множества. Такое изображение двух окружностей позволит применять заливку к трем отдельным областям, и тем самым реализовывать различные логические операции над множествами: пересечение, объединение, разность и другие.
Рисунок 3.3. Изображение двух пересекающихся множеств при помощи окружностей.
Для реализации данного класса потребовалось задание новых свойств и некоторых методов, описанных далее.
Открытые свойства.
FCircle: Circle, SCircle: Circle - члены класса «Два множества» обеспечивают храние информации об окружностях, изображающих множества и являются экземплярами класса «Окружность».
SPoint: Point - предназначен для хранения информации о том, где располагается центр первой (левой) окружности. Данное свойство позволит в дальнейшем изменять местоположение примитива на экране, используя описанные выше процедуры.
Закрытые свойства.
oldMPX: real, oldMPY: real - назначение данных двух свойств аналогично назначению одноименных свойств других классов, описанных выше.
fill1: bool, fill2: bool,fill3: bool - при пересечении двух окружностей можно получить три отдельных сектора заливки: левый, центральный и правый. Свойства позволяют определить: была ли присвоена заливка каждой из заданных областей. В дальнейшем они применяются как для снятия, так и наложения цветовой однотонной заливки.
A_B: HRGN - свойство описывает регион, позволяющий производить заливку крайней левой области, обозначенной на Рис. 3.3. цифрой 1, и реализующей логическую функцию
B_A: HRGN - свойство описывает регион, позволяющий производить заливку крайней правой области, обозначенной на Рис.3.3. цифрой 3, и реализующей логическую функцию .
A_AND_B: HRNG - свойство описывает регион, позволяющий производить заливку центральной области, обозначенной на Рис.3.3. цифрой 2, и реализующей логическую функцию .
Открытые методы.
В целом основные свойства, наследуемые от базового класса, используются для тех же целей, что и в других примитивах с некоторыми отличиями.
Draw() - метод позволяет рисовать множества и реализовать заливку, используя следующие этапы: вычисление регионов окружностей, составляющих экземпляр класса «Два множества»; рисование прямоугольника выделения для подсветки выделенного объекта; выбор цвета заливки каждой из областей; рисование областей с заливкой; рисование окружностей, составляющих множества.
isPointInPoligon() - позволяет производить создание областей для заливки. При вычислении области заливки используются значения, получаемые в результате применения функции getRegion класса «Окружность» применяя данный метод к свойствам FCircle и SCircle класса «Два множества». Вычисление заливаемой области производится стандартной функцией WinAPI CombineRegion. Для вычисления логической функции используются различные параметры: порядок задания исходных регионов, результирующий регион и выполняемая логическая операция. Для выполнения операции вычитания одного множества из другого используется константа RGN_DIFF, а для вычисления пересечения - RGN_AND. После проверки попадания курсора в область, принадлежащую одному из вычисленных регионов и нажатии левой кнопки мыши производится установка свойств Fill1, fill2, fill3. В качестве результата функция возвращает основной программе логическое значение показывающее была или нет применена заливка.
onRemove() - отличие метода от объявленных ранее объясняется тем, что перемещение возможно только для объекта в целом, изменение радиуса окружностей в данном случае заблокировано, так как оно может привести к некорректному пересечению окружностей или отсутствию пересечения.
3.3.1.8 Три множества
Класс «Три множества » предназначен для реализации функциональной возможности рисования диаграмм Эйлера-Венна на случай пересечения трех множеств. Используя базовый класс «Примитив», позволяющий хранить экземпляры данного класса, как и остальные примитивы, описываемый класса позволяет создать совокупность трех окружностей. Такое изображение окружностей позволит применять заливку к семи отдельным областям, показанных на рисунке 3.4.
Рисунок 3.4. Изображение трех пересекающихся множеств
Для реализации класса потребовалось задние новых свойств и некоторых методов, описанных ниже.
Открытые свойства.
FCircle: Circle, SCircle: Circle, TCircle - члены класса «Два множества» обеспечивают хранение информации об окружностях, изображающих множества и являются экземплярами класса «Окружность».
SPoint: Point - предназначен для хранения информации о том где располагается центр первой (левой) окружности, данное свойство позволит в дальнейшем изменять местоположение данного примитива на экране, используя описанные выше процедуры.
Закрытые свойства.
oldMPX: real, oldMPY: real - назначение данных двух свойств аналогично назначению одноименных свойств других классов, описанных выше.
fill1: bool, fill2: bool,fill3: bool, fill4: bool, fill5: bool, fill6: bool, fill7: bool - при пересечении трех окружностей можно получить семь отдельных секторов заливки, обозначенных на рис. 3.4. цифрами. Данные свойства позволяют, определить: была ли присвоена заливка каждой из заданных областей. В дальнейшем свойства применяются как для снятия, так и наложения цветовой однотонной заливки.
Таблица 5. Сектора заливки
Свойство |
Формула региона заливки |
№ области на рисунке 3.4. |
|
AB_C: HRGN |
4 |
||
AC_B: HRGN |
6 |
||
BC_A: HRGN |
5 |
||
B_AvC: HRGN |
2 |
||
A_BvC: HRGN |
1 |
||
C_AvB: HRGN |
3 |
||
ABC: HRGN |
7 |
Открытые методы.
В целом основные свойства, наследуемые от базового класса, используются для тех же целей, что и в других примитивах с некоторыми отличиями. Например, метод Draw() позволяет рисовать множества и реализовать заливку аналогично одноименному методу, описанному в классе «два множества», только уже для трех множеств; а метод onRemove() - при перемещении целой фигуры перемещает вместо двух окружностей - три.
Данный класс завершается описанием основных используемых классов в создаваемом проекте примитивов. Совокупность данных классов позволяет пользователям создавать и в дальнейшем редактировать созданные примитивы, в рамках одного запуска программы. В дальнейшем рассмотрим основные функции по сохранению и импортированию созданных с помощью программы изображений, а также рассмотрим методы автоматизации заполнения шаблонов связанных с построением графиков функций, промежутков знакопостоянства функции и диаграмм Эйлера-Венна, а также другие возможности построения изображений.
3.3.2 Описание основных модулей программы
Раздел посвящен основным модулям, реализованным в программе. Созданная структура классов позволяет пользователю только создавать примитивы и осуществлять механизмы работы с ними, описывает основные методы, используемые для хранения информации о параметрах примитива: цвете, толщине линии, цвете заливки, типе линии и другие. Рассмотрим другие возможности программы, которые сопровождают процесс создания и редактирования иллюстраций по высшей математике.
3.3.2.1 Сохранение
В рамках реализации программного продукта предполагается возможность сохранения и последующую загрузку полученной иллюстрации для дальнейшего редактирования. Большинство форматов используемых в графических редакторах является закрытыми форматами, изменение информации в данных файлах не предназначено сторонними продуктами, так как структура каждого из форматов различается, а зачастую информации хранится в бинарном виде. Однако, присутствуют и открытые форматы среди них, такие как SVG, AI и другие.
При сохранении в файлы присутствуют следующие возможности:
- сохранение в собственный формат файла для последующего редактирования,
- сохранение созданного изображения в растровый файл для последующей печати,
- сохранение файла в векторные открытые форматы для последующего импорта в сторонние графические растровые редакторы.
Таким образом, программный продукт для сохранения используется следующие модули: сохранение в собственный формат vff (vector file format); сохранение в растровый формат; импорт в открытые векторные форматы. Рассмотрим данные функции подробнее.
Сохранение в формат *.vff.
Для задания программному продукту возможностей по сохранению, загрузке и дальнейшему редактированию иллюстраций был разработан следующий формат файла, несколько схожий с нотацией XML, при этом структура файла напоминает векторный формат SVG. Отличительной особенность разработанного формата является возможность ручного редактирования информации о примитивах, посредством обыкновенного текстового редактора.
Разработанный векторный формат предполагает задание для каждого из примитивов своего обозначения или тега, его свойств и наименование свойств характерных для данного тега. Таким образом, для сохранения информации о примитивах опишем XML подмножество. В таблице 6 приведен список возможных тегов.
Таблица 6. Список возможных тегов
Тег |
Примитив/элемент изображения |
|
<line></line> |
линия |
|
<polyline></polyline> |
ломаная линия |
|
<bezier></bezier> |
кривая третьего порядка |
|
<vector></vector> |
вектор |
|
<graphic></graphic> |
график функции |
|
<rpoint/> |
стертая точка графика |
|
<point/> |
точка примитива |
|
<circle/> |
окружность |
|
<twosets/> |
два множества |
|
<treesets/> |
три множества |
|
<text/> |
надпись |
Служебное слово point обозначает название тега, после которого следуют свойства, указывающие на позицию точки на экране («X» и «Y»). Значения свойств следуют после знака равно и взяты в одинарные кавычки. Для позиционирования точки на экране используются целочисленные значения пикселей, причем центр координат экрана располагается в его нижнем левом углу. Сохранение точки в данном формате рассмотрено в Приложении Д.
Сохранение линии предполагает использование пары тегов line. В открывающем теге указываются основные свойства сохраняемой линии, а закрывающий тег указывает на тот факт, что определение точек примитива было завершено. Необходимость использования закрывающего тега необходимо, так как заранее программа не знает информации о количестве заданных точек, а прямое указание количества точек в рамках открывающего тега нецелесообразно с той точки зрения, что обработка данного атрибута потребует создания дополнительных процедур для выявления и распознавания параметра указывающего на их количество. Основными свойствами данного тега являются: Name - уникальное имя линии; Size - толщина линии; Color - цвет линии; typeLine - тип начертания линии. Целочисленное значение от 1 до 3. При этом значение 1 указывает на рисование сплошной линии, значение 2 - на штриховую линию, а значение 3 - на создание штрих пунктирной линии.
Для сохранения информации о начальной и конечной точках линии используется тег point. Пример сохранения представлен в Приложении Д.
Для сохранения ломаной линии используется специализированный тег
polyline. Основные атрибуты данного тега соответствуют атрибутам тега line. Однако для сохранения информации о замкнутости линии и цвете заливки примитива используются следующие имена атрибутов:
fcolor - для обозначения цвета заливки. В качестве параметров принимает целочисленное значение от 0 до 4261543935. Для определения и задания собственного цвета при использовании текстового редактора можно воспользоваться следующей формулой:
,(7)
где R, G, B - цветовые составляющие модели RGB и характеризуют значения красного, зеленого и синего тонов в результирующем цвете.
closed - для указания признака замкнутости фигуры. Значения характерные для данного атрибута представляют собой целочисленные значение ноль или единица. Значение единица указывает на то, что фигура является замкнутой.
Для сохранения информации о количестве и координатах заданных точек между открывающим и закрывающим тегом используется тег point. Код для создания ломаной линии представлен в Приложении Д.
Для сохранения векторов используется пара тегов vector. Закрывающий тег позволяет определиться с окончанием задания точек примитива, а к свойствам используемым для сохранения кроме описанных для ломаной линии добавлено свойство, указывающее на тип используемой для отображения стрелки. Данный атрибут носит название typearrow. Так как для отображения стрелок вектора в программном продукте присутствует два их возможных типа, то параметры, принимаемые данным тегом, являются целочисленными значениями 1 и 2. Для указания стрелки состоящей двух линий используется значение 2. Пример сохранения вектора представлен в Приложении Д.
Сохранение в векторный файл информации о кривой третьего порядка используется пара тегов <bezier>. Открывающий тег также содержит рад атрибутов характерных для всех примитивов и указывает на имя примитива, толщину линии, цвет линии, цвет заливки, замкнутость фигуры, тип линии. Как и в случае основных примитивов для сохранения информации о точках используется тег point.
Примером сохранения кривой третьего порядка может служить код, показывающий использование данного тега для сохранения информации о кривой третьего порядка, состоящей из 10 точек (рисунок 3.5.).
<bezier name='Безье 0' size='2' color='32896' fcolor='65280' closed='1'
typeline='1' >
<point X='104' Y='435'>
<point X='204' Y='535'>
<point X='344' Y='415'>
…
<point X='204' Y='175'>
<point X='104' Y='435'>
<point X='24' Y='355'>
<\bezier>
Рисунок 3.5. Пример созданной кривой третьего порядка
Для сохранения информации о подписях добавленных на иллюстрацию используется одинарный тег text. Перечислим основные атрибуты данного тега.
Атрибуты тега текст: name - уникальное имя текста для дальнейшего обращения к его свойствам при использовании программы; size - размер текста в пикселях; color - цвет отображаемой надписи; caption - выводимый текст; X, Y - позиция в пикселях расположения текста на экране.
Пример сохранения надписи представлен в Приложении Д. Инструмент и класс, позволяющий производить работу с текстом, будет описан далее.
Следующим элементом необходимым для сохранения является элементы позволяющие редактировать информацию о графике функции. С целью сокращения размера файлов для сохранения информации о построенном графике будем использовать только информацию о формуле, участках, которые были стерты пользователем, а также информацию о цвете отображения графика функции. В общем случае для сохранения информации о построенном графике будем использовать пару тегов graphic. Синтаксис сохранения представлен в Приложении Д.
Для сохранения и редактирования информации о созданных при редактировании диаграммах Эйлера-Венна служат следующие теги:
- Twosets - для сохранения информации о двух множествах,
- Treesets - для сохранения информации о трех множествах.
Основанные атрибуты данных тегов характеризуют информацию о залитых областях с помощью имен атрибутов одноименных со свойствами данных классов, для сохранения информации о цвете заливки используется атрибут color.
3.3.2.2 Преобразование форматов файлов
Создание возможностей по реализации сохранения в растровые форматы и возможностей сохранения и загрузки в векторные форматы файлов сторонних программ требует определения новых классов и процедур для выполнения для загрузки.
Так как большинство растровых форматов используют различные методы сжатия, то программная реализация требует дополнительных усилий на разбор синтаксиса и методов сжатия используемых для сохранения. Для ускорения процесса разработки в качестве методов сохранения в форматы файлов можно воспользоваться как стандартными средствами, предоставляемыми средой разработки, так и библиотеками сторонних разработчиков.
Однако так как OpenGL не позволяет производить непосредственного снятия копии созданного изображения, для дальнейшего сохранения, потребуется написание одного из классов позволяющих производить сохранение в файл типа *.bmp. Данный растровый формат был рассмотрен нами ранее. Информация хранится в файле данного типа в бинарном виде, при этом присутствуют служебные поля, характеризующие тип файла, размер изображения по вертикали и горизонтали, и другие, а также информация о каждом пикселе изображения. С точки зрения реализации наиболее простым растровым форматом данного файла является bmp изображение с использованием 24-битного значения для сохранения информации о каждом пикселе.
Для реализации возможностей работы с растровыми изображениями и сохранения информации в файл *.bmp были разработаны следующие классы.
Класс RGBpixel.
Данный класс позволяет хранить информацию о каждой составляющей цвета: красной, зеленой и синей. В дальнейшем будет использован для указания параметров каждого сохраняемого пикселя изображения.
Рассмотрим основные свойства и методы данного класса.
Открытые свойства.
R,G,B - позволяют указать и хранить значения каждого из оттенков исходного цвета пикселя.
Открытые методы.
void setColor(int Color) - позволяет установить цвет пикселя, в качестве параметра принимает целочисленное значение цвета.
void setColor(uint R, uint G, uint B) - является перегруженным по параметрам методом и позволяет устанавливать цвет пикселя на основании составляющих компонент цвета.
int getColor() - возвращает значение текущего цвета пикселя.
uint getR(), uint getG(), uint getB() - позволят узнать красную, зеленую и синюю составляющие основного цвета соответственно.
Класс clBitMap.
Класс предоставляет методы и свойства для реализации возможностей по сохранению и загрузке растровых изображений формата *.bmp для дальнейшего использования в качестве подложки рисования. Также данный метод позволяет производить выделение загруженных изображений и перемещать их по экрану редактирования. Рассмотрим свойства класса.
Открытые свойства
int nRow, nCol - размеры пиксельной карты, т.е количество элементов массива для хранения пикселей.
RGBpixel *pixels - массив. Используется для хранения пикселей и представляет собой элемент класса RGBpixel.
int x,y,z - позиция загруженного изображения на экране.
bool mOver - признак выделения пиксельной карты.
Закрытые свойтва:
int oldMPX,oldMPY - хранят информацию о позиции курсора на экране при условии выделения пиксельной карты.
К основным методам данного класса относятся как закрытые методы,
позволяющие получать из целочисленных значений байты информации для записи, так и открытые методы для работы с пиксельной картой. Рассмотрим их более подробно.
Открытые методы.
clBitMap и clBitMap(int cols, int rows) - конструкторы класса,
позволяющие создавать экземпляр данного класса. Первый конструктор подразумевает создание экземпляра класса с параметрами по умолчанию, а второй - позволяет сразу задать размер пиксельной карты, за счет передачи параметров cols и rows.
setPixel(int X, int Y, int Color) - позволяет задать точку на экране в определенной позиции и с определенным цветом.
getPixel(int X, int Y) - метод позволяет получить значении цвета пикселя находящегося в позиции указываемой передаваемыми параметрами X и Y.
DrawBitMapAtPos(HDC hdc, HGLRC hglrc) - предназначен для рисования пиксельной карты в позиции экрана определяемой свойствами x,y,z.
ReadBitMapInMem(HDC hdc, HGLRC hglrc,int X, int Y, int Width, int Height) -позволяет считать область экрана прямоугольную в пиксельную карту.
LoadBitMap(AnsiString fname) - производит загрузку *.bmp файла в пиксельную карту.
SaveBitMap(AnsiString fname) - производит сохранение пиксельной карты в bmp файл.
MouseOver(int X, int Y) - метод позволяет производить выделение пиксельной карты, для её дальнейшего перемещения.
Drag(int X, int Y) - отображает пиксельную карту в поле редактирования.
Закрытые методы.
getShort(),getLong() - используются для загрузки информации о значениях служебных полей из файла bmp. Методы позволяют получить из файла набор байт и представить его в виде целочисленного 16-битного и 32-битного значения соответственно.
writeShort(ushort val), writeLong(ulong val) - методы позволяют сохранить 16-битное и 32-битное соответственно беззнаковое целое число в виде последовательности байт от старшего к младшему. Используется для сохранения служебной информации bmp файла.
Таким образом, данный класс позволяет производить «снимок» экрана OpenGL и сохранять его в файл соответствующий формату bmp. Для реализации сохранения полученного рисунка в другие растровые форматы можно воспользоваться следующей последовательностью шагов:
а) осуществление сохранения в файл bmp,
б) загрузка файла в специализированные структуры или классы открытых библиотек предназначенных для конвертирования файлов,
в) Сохранение рисунка в требуемый формат,
г) Удаление созданного временного файла bmp.
3.3.2.3 Реализация механизма отмена/возврат
Реализация механизма отмена/возврат предполагает возможности гибкого редактирования графических иллюстраций. Такой механизм достаточно широко используется в различных приложениях, начиная с операций над файлами в операционных системах, и заканчивая сложными программными комплексами. Необходимость использования данного механизма объясняется тем, что он прилагает пользователям гибкий инструмент редактирования, заключающийся в отмене нежелательных действий или возможностей удаления последних изменений и возврата их в случае необходимости.
В данном проекте реализована полная поддержка механизма отмена/возврат для созданных примитивов, при использовании операции «отмена» примитив удаляется с экрана и не рисуется, а при выполнении операции «возврат» последний удаленный примитив должен снова быть отображен на редактируемой иллюстрации. Дополнительно возможностью реализован механизм отмены последней созданной точки незавершенного примитива. Рассмотрим эти возможности более подробно.
Так как для хранения информации о примитивах используется массив экземпляров класса «Примитив», то наиболее приемлемым способом реализации механизма отмена/возврат будет являться способ временного перенесения созданных примитивов во временный массив. Таким массивом является массив, предназначенный для хранения информации о созданных примитивах. При отмене выполняется следующая последовательность действий: перемещение последнего созданного примитива из массива хранения используемого для рисования в массив для хранения истории отмененных примитивов; уменьшение значения количества созданных примитивов; увеличение значения количества отмененных примитивов; рисование сцены по массиву созданных примитивов.
В случае, когда пользователь отменил первый созданный примитив или примитивы еще не были заданы, кнопка «отмена» блокируется во избежание ошибок обращения к адресам массива, которые не определены.
Для реализации действия «Возврат» необходимо произвести аналогичные действия с некоторыми изменениями: перемещение последнего отмененного примитива из массива хранения истории отмененных примитивов в массив, используемый для рисования; уменьшение значения количества отмененных примитивов; увеличение значения количества созданных примитивов; рисование сцены по массиву созданных примитивов.
Для избегания ситуаций выполнения действия «Возврат» в случаях, когда массив отмененных примитивов пуст кнопка, предназначенная для выполнения данного действия, блокируется.
Для реализации механизма отмены последней созданной точки используются функции UndoPoint, определенные в каждом классе. Данный метод позволяет определить различные ситуации отмены точки и при этом продолжить рисование примитива. Сложность выполнения механизма отмены в данном случае заключается в необходимости учета количества уже созданных точек, так как при удалении первой созданной точки необходимо производить удалении и самого примитива из массива предназначенного для рисования. С данной целью метод UndoPoint при условии удаления первой созданной точки примитива возвращает истинное значение, в противном случае - ложное. Еще одной особенностью является необходимость переноса для некоторых примитивов значения последней точки на те, которые не созданы, так как в противном случае рисование примитива при установке точек будет невозможно.
Для реализации полного механизма «отмена/возврат» при удалении точек необходимо сохранять отмененные точки в некоторый массив. Однако организация такого массива нецелесообразна с той точки зрения, что вызывает дополнительное использование оперативной памяти. При этом эффективность метода возврата точки вызывает сомнения с точки зрения его использования, так как пользователю гораздо проще выполнить указание новой точки для примитива, используя только мышь, чем нажать комбинацию клавиш на клавиатуре.
3.3.2.4 Реализация сетки/привязка к сетке
Реализация привязки к сетке является дополнительной возможностью для облегчения редактирования объектов создаваемого изображения. Суть использования состоит в том, что пользователь может задать точку только в узлах рисуемой сетки. Такой подход позволяет рисовать, например, правильные фигуры: равнобедренный треугольник, квадрат, прямоугольник и другие.
Реализация привязки к сетке осуществляется за счет использования специализированного класса clGrid. Рассмотрим основные свойства и методы данного класса.
Открытые свойства.
bool visible - позволяет применить функцию отображения скрытия сетки. При скрытой сетке привязка к узлам при рисовании не осуществляется.
Закрытые свойства.
short int R,G,B - цветовые составляющие используемого для отображения сетки цвета.
int step - шаг сетки. Задается в пикселях каждый узел сетки расположен от другого на количество пикселей которое характеризуется данным свойством.
int color - используется для определения цветовых составляющих.
int height, int width - свойство позволяет внутри класса определить значение высоты и ширины сцены OpenGL соответственно.
int CAxesX, int CAxesY - позволяет хранить центр экрана по горизонтали и вертикали соответственно. В данном случае под центром экрана подразумевается цент заданной декартовой системы координат.
Открытые методы.
void setStep(int st) - позволяет установить шаг сетки за счет использования передаваемого в процедуру параметра st.
int getStep() - возвращает целочисленное значение шага сетки.
void setColor(int clr) - реализует алгоритм присвоения цвета используемого при рисовании сетки на экране.
int getColor() - получаем используемый для отображения цвет сетки.
void Resize(int W, int H, int CX, int CY) - метод позволяет произвести пересчет шага сетки и её линий при изменении размера OpenGL окна.
void Draw(float zoom, HDC hdc, HGLRC hglrc) - осуществляет рисование
сетки на экране выполняя ряд действий: проверка на видимость; установка параметров рисования: цвет, толщина; рисование от цента к левому краю вертикальны линий; рисование от центра системы координат к правому краю вертикальных линий; рисование от центра системы координат к верхнему краю сцены горизонтальных линий; рисование горизонтальных линий от центра системы координат к нижнем краю сцены.
Закрытые методы.
short int GetR(), GetG(), GetB() - методы предназначены для вычисления цветовых составляющих из общего цвета, хранящегося в члене класса color.
Данный класс позволяет задать и хранить информацию о шаге сетке и производить её рисование в соответствии с заданными параметрами. Однако он не позволяет передавать параметры в экземпляры классов используемых для создания и рисования примитивов. Данные действия могут осуществляться окном, в котором производится рисование с использованием некоторых свойств и методов данного класса.
Таким образом, для осуществления привязки к сетке используется процедура позиционирования координат курсора за счет использования следующих формул преобразования:
(8)
где Xn,Yn - новые координаты точки соответствующие узлу сетки; CAxesX, CAxesY - центр заданной декартовой системы координат; zoom - коэффициент увеличения/уменьшения масштаба; GridStep - шаг сетки; mod -выполнение целочисленного деления (деления без остатка).
Новые координаты, полученные путем такого преобразования, подаются в экземпляр примитива в качестве параметров функции onMouseDown, onMouseMove и onRemove.
3.3.2.5 Вывод и построение графика
Автоматизации построения графика функции позволяет пользователю, используя функции, операции, переменные и константы осуществлять ввод функций одной переменной . Для задания функциональной зависимости могут быть использованы переменные и операции, приведенные в таблице 7.
Таблица 7.Список функций и операций
Операция/ функция |
Назначение |
|
+ |
Бинарная операция «сложение» |
|
- |
Бинарная операция «вычитание» |
|
* |
Бинарная операция «умножение» |
|
/ |
Бинарная операция «деление» |
|
^ |
Бинарная операция «возведение в степень» |
|
sin |
Тригонометрическая функция «синус» |
|
cos |
Тригонометрическая функция «косинус» |
|
tg |
Тригонометрическая функция «тангенс» |
|
asin |
Обратная тригонометрическая функция «синус» |
|
acos |
Обратная тригонометрическая функция «косинус» |
|
atan |
Обратная тригонометрическая функция «тангенс» |
|
ln |
Логарифмическая функция «натуральный логарифм» |
Кроме ввода функции одной переменной пользователю предоставляется возможность установки интервала рассмотрения функции и диапазона значений, а также возможность, установки цвета рисования графика функции. Интервал рассмотрения и диапазон значений функции позволяют нарисовать график на декартовой системе координат с выводом осей и подписями значений оси абсцисс и ординат.
При вычислении значений точек графика по вводимому выражению функции одной переменной строится бинарное дерево, позволяющее используя процедуру рекурсивного обхода вычислить значение функции при заданном аргументе. Бинарное дерево представляет собой совокупность вершин и связей между ними. При этом вершины дерева хранят информацию об операциях, функция, переменной «x» и различных констант. Для построения такого бинарного дерева можно использовать сторонние открытые библиотеки CxImage, ImageStone. При этом на вход функций данных модулей подается значение строки содержащей формулу, а на выходе получаем бинарное дерево, полученное в ходе лексико-грамматического анализа и процедур построения бинарных деревьев.
Вычисление значения в каждой точке графика производится исходя из значения аргумента функции, следовательно, для получения всех значений функции на заданном пользователем интервале необходимо произвести последовательное вычисление в циклической структуре значений введенной функции, от постепенно наращиваемого аргумента. В качестве начального значения аргумента принимается значение минимума аргумента функции заданного пользователем. Однако при рисовании функций необходимо учитывать, что их точки, принимающие небольшие значения будут невидны на иллюстрации. По этой причине необходимо осуществлять преобразование, как подаваемого аргумента, так и вычисленного значения функции к значениям пикселей экрана. А, следовательно, задача сводится к построению графика функции одной переменной по пикселям экрана. Решение данной проблемы состоит в использовании следующих функций преобразования значений функции из одной системы координат в другую:
, (9)
где X, Y - координаты точки графика функции в системе экранной системе координат, CX, CY - координаты центра экранной системы координат, X1, Y1 - координаты точки графика в исходной системе координат заданной пользователем, deltaX, deltaY - коэффициенты сжатия/растяжения исходной системы координат.
Коэффициенты сжатия/растяжения вычисляются по следующим формулам:
, (10)
где Xmax, Xmin - максимальное и минимальное значения интервала рассмотрения функции; Ymax, Ymin - максимальное и минимальное значение интервала отрисовки по оси ординат; W, H - ширина и высота экрана соответственно.
Для хранения полученных точек используется специализированный динамический массив длинной равной значению количества пикселей OpenGL сцены, в который помещаются, по мере вычисления, значения преобразованных координат. Если в ходе вычисления значения функции происходит переполнение, например при делении на ноль, то в качестве значения функции и её аргумента ставиться точка со значениями (-100000, -100000). Такая точка при рисовании не будет учитываться.
Процедура рисования состоит из цикла, позволяющего пройти по всем значениям вычисленных ранее точек. Рисование только точки не позволяет добиться непрерывной функции, что связано с неточностью округления значений, поэтому для рисования используется константа OpenGL с именем GL_LINES, при этом на каждом этапе строится прямая соединяющая две соседние точки массива. Такой подход позволяет создавать видимость непрерывного графика функции.
Таким образом, работа модуля по построению графика функции сводится к выполнению двух процедур: определения значений графика функции и рисования полученных значений функции на экране. Блок-схема алгоритма вычисления, в соответствии с описанным выше, представлена на рисунке 3.6.
На данной блок схеме в начале вычисления производится инициализация переменных используемых в дальнейшем при вычислении, так устанавливается начальное значение curX, хранящее значение текущего для вычисления аргумента, а также вычисляются ранее описанные переменные CX, CY, deltaX, deltaY. Следующим этапом является организация цикла по всем элементами массива, количество значений в котором характеризуется ранее описанной переменной W. В цикле для вычисления значения функции fvalue используется специальная процедура, в которую подается вершина бинарного дерева, текущее значение аргумента curX и флаг, указывающий на возможные ошибки вычисления. Далее если значение флага после вычисление истина, значит, в ходе вычисления произошла ошибка переполнения, в противном случае процедура возвращает значение введенной функции от заданного аргумента. В случае отсутствия ошибки вычисления полученное значение функции и аргумента преобразовывается в экранные координаты и заносится в массив, в противном случае устанавливаются значения, указывающие на точку разрыва первого или второго рода. Следующий блок позволяет изменить значение текущего аргумента на шаг, и если не достигнуто вычисление массива, то процедура продолжает вычислять значения функции на интервале. В конце вычислительной процедуры получаем массив, заполненный значениями функции, при этом каждому значению функции соответствует некоторое значение аргумента. Данный массив подается в функцию рисования, где, проходя последовательно каждый его элемент, производится рисование полученных точек, соединенных линиями на экране.
Подобные документы
Растровые и векторные графические редакторы. Форматы файлов, используемые для хранения графических изображений. Графические редакторы, используемые для создания изображений. Редакторы для создания трехмерных изображений. Создание графического редактора.
курсовая работа [306,5 K], добавлен 23.08.2013Графический редактор — программа, позволяющая создавать и редактировать двумерные изображения с помощью компьютера. Adobe Illustrator - широко используемая программа создания изображений. Adobe Photoshop и GIMP - основные растровые графические редакторы.
реферат [28,1 K], добавлен 25.11.2009Виды графических редакторов. Форматы файлов для хранения растровых графических изображений. Среда графического редактора. Панели инструментов и режимы работы графических редакторов. Инструменты редактирования рисунка. Изменение шрифта текста на рисунке.
контрольная работа [246,6 K], добавлен 16.12.2010Растровая графика, составление графических изображений из отдельных точек (пикселей). Растровые графические редакторы. Векторная графика - построение изображения из простых объектов. Достоинства, недостатки и применение растровой и векторной графики.
презентация [7,8 K], добавлен 06.01.2014Понятие, сущность и основные функции графических редакторов. Свойства основных графических редакторов, таких программ как PCAD и CirCad (для создания радиосхем и разводки печатных плат), AutoCAD (чертежи), ProtoCAD (стереометрия), Photoshop и Corel DRAW.
курсовая работа [6,1 M], добавлен 03.11.2010Преобразование графической информации из аналоговой формы в цифровую. Количество цветов, отображаемых на экране монитора. Расчет объема видеопамяти для одного из графических режимов. Способы хранения информации в файле. Формирование векторной графики.
презентация [2,1 M], добавлен 22.05.2012Сущность и содержание формата компьютерных графических данных. Анализ структурной схемы цветов и цветовых моделей CIE Lab, RGB, HSBCMYK. Основные приемы работы с программ для векторной графики Аdobe Photoshop, Corel Draw, Adobe Illustrator, Corel Xara.
реферат [28,1 K], добавлен 07.05.2016Характеристика графических возможностей среды программирования Lazarus. Анализ свойств Canvas, Pen, Brush. Сущность методов рисования эллипса и прямоугольника. Возможности компонентов Image и PaintBox. Реализации программы "Графический редактор".
курсовая работа [2,8 M], добавлен 30.03.2015Растровые и векторные графические редакторы. Формирование изображений, форматы графических файлов. Особенности векторной графики, ее достоинства. Построение треугольника и гиперболы по алгоритму Бразенхема. Математические модели поверхностей и объектов.
курсовая работа [769,5 K], добавлен 21.12.2013Представление графической информации в компьютере. Графические форматы и их преобразование. Информационные технологии обработки графической информации. Формирование и вывод изображений. Файлы векторного формата и растровый графический редактор.
курсовая работа [1,0 M], добавлен 25.04.2013