Создание графических компонент

Разработка компоненты для математических вычислений (операций над матрицами) с использованием технологии OpenGL (сложение, вычитание, умножение, транспонирование, определитель, обратная матрица). Базовые навыки по работе с технологией в среде .Net.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 17.02.2015
Размер файла 365,6 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Введение

Язык С# как средство обучения программированию обладает рядом несомненных достоинств. Он хорошо организован, строг, большинство его конструкций логичны и удобны. Развитые средства диагностики и редактирования кода делают процесс программирования приятным и эффективным. Мощная библиотека классов платформы .NET берет на себя массу рутинных операций, что дает возможность решать более сложные задачи, используя готовые "строительные блоки". Все это позволяет расценивать С# как перспективную замену языков Паскаль, BASIC и С++ при обучении программированию. Немаловажно, что С# является не учебным, а профессиональным языком, предназначенным для решения широкого спектра задач, и в первую очередь -- в быстро развивающейся области создания распределенных приложений. Поэтому базовый курс программирования, построенный на основе языка С#, позволит студентам быстрее стать востребованными специалистами-профессионалами. Мощь языка С# имеет и оборотную сторону: во-первых, он достаточно требователен к ресурсам компьютера, во-вторых, для осмысленного написания простейшей программы, вычисляющей, "сколько будет дважды два", требуется изучить достаточно много материала, но многочисленные достоинства языка и платформы .NET перевешивают все недостатки.

Целью данной курсовой работы является закрепление навыков работы в среде .NET при создании графических компонент с использованием пользовательских элементов управления.

К задачам курсовой работы можно отнести:

1. Разработка компоненты для математических вычислений (операций над матрицами) с использованием технологии OpenGL.

2. Приобрести базовые навыки и знания по работе с технологией OpenGL в среде .Net.

Задание на курсовую работу.

Использование передовых 3-D технологий OpenGL для перспективных разработок.

Разработка компоненты для автоматизации математических расчетов: операции с матрицами (сложение, вычитание, умножение, транспонирование, определитель, обратная матрица).

1. Аналитическая часть

1.1 Анализ предметной области

Матрицей называется прямоугольная таблица из чисел aij, где i=1,2,..,m , j=1,2,..,n

cостоящая из m строк и n столбцов.

Операции с матрицами.

Сложение и вычитание.

Складывать можно только матрицы одинакового размера. Сложение матриц A+B есть операция нахождения матрицы C, все элементы которой равны попарной сумме всех соответствующих элементов матриц A и B, то есть каждый элемент матрицы C равен

Разность двух матриц одинакового размера можно определить через операцию сложения матриц и через умножение матрицы на число:

(3)

Свойства сложения матриц:

1. Коммутативность: A+B = B+A;

2. Ассоциативность: (A+B)+C =A+(B+C);

3. Сложение с нулевой матрицей: A + И = A;

4. Существование противоположной матрицы: A + (-A) = И.

Умножение.

Умножение матриц (обозначение AB, реже со знаком умножения AxB) -- есть операция вычисления матрицы C, каждый элемент которой равен сумме произведений элементов в соответствующей строке первого множителя и столбце второго.

Количество столбцов в матрице A должно совпадать с количеством строк в матрице B, иными словами, матрица A обязана быть согласованной с матрицей B. Если матрица A имеет размерность mxn, B -- nxk, то размерность их произведения AB=C есть mxk.

Свойства умножения матриц:

1. Ассоциативность (AB)C = A(BC);

2. Некоммутативность (в общем случае): AB BA;

3. Произведение коммутативно в случае умножения с единичной матрицей: AI = IA;

4. Дистрибутивность: (A+B)C = AC + BC, A(B+C) = AB + AC;

5. Ассоциативность и коммутативность относительно умножения на число:

(лA)B = л(AB) = A(лB);

Транспонирование.

Транспонированная матрица -- матрица AT, полученная из исходной матрицы A заменой строк на столбцы. Формально, транспонированная матрица для матрицы A размеров mxn -- матрица AT размеров nxm, определённая как AT[i, j] = A[j, i].

Свойства транспонированных матриц:

1. Дважды транспонированная матрица А равна исходной матрице А:

(AT)T =A

2. Транспонированная сумма матриц равна сумме транспонированных матриц:

(A+B)T =AT +BT

3. Транспонированное произведение матриц равно произведению транспонированных матриц, взятых в обратном порядке:

(AB)T = BT AT

4. При транспонировании можно выносить скаляр:

(лA)T = л AT

5. Определитель транспонированной матрицы равен определителю исходной матрицы:

det AT = det AT

Определитель.

Определитель (или детерминант) -- одно из основных понятий линейной алгебры. Определитель матрицы является многочленом от элементов квадратной матрицы (то есть такой, у которой количество строк и столбцов равно).

Для матрицы первого порядка детерминантом является сам единственный элемент этой матрицы:

Для матрицы 2x2 детерминант определяется как

Для матрицы nxn определитель задаётся рекурсивно:

где -- дополнительный минор к элементу .

Эта формула называется разложением по строке.

Минор матрицы A Ї определитель такой квадратной матрицы B порядка k (который называется также порядком этого минора), элементы которой стоят в матрице A на пересечении строк с номерами и столбцов с номерами .

В частности, формула вычисления определителя матрицы 3x3 такова:

Обратная матрица.

Обрамтная мамтрица -- такая матрица A?1, при умножении на которую, исходная матрица A даёт в результате единичную матрицу E:

AA-1 =AA-1=E (9)

Квадратная матрица обратима тогда и только тогда, когда она невырожденная, то есть её определитель не равен нулю. Для неквадратных матриц и вырожденных матриц обратных матриц не существует.

-- транспонированная матрица алгебраических дополнений;

Алгебраическим дополнением элемента aij матрицы A называется число

,

где -- дополнительный минор, определитель матрицы, получающейся из исходной матрицы A путем вычёркивания i -й строки и j -го столбца.

Полученная матрица A?1 и будет обратной. Сложность алгоритма зависит от сложности алгоритма расчета определителя Odet и равна O(nІ)·Odet. Иначе говоря, обратная матрица равна единице, делённой на определитель исходной матрицы и умноженной на транспонированную матрицу алгебраических дополнений элементов исходной матрицы.

Анализ

Матрица представляет собой систему взаимосвязанных элементов. Для этих элементов характерны сходства и различия, которые необходимо выявить на этапе разработки компоненты. Кроме того, важно определить взаимодействие элементов системы как части целого.

Исходя из рассмотрения составных частей матрицы, можно выделить следующие наиболее общие для любой матрицы типы элементов:

1. Ячейка

2. Ячейки с данными

3. Сетка

Представить матрицу можно разными способами, целесообразным будет сделать её в виде таблицы со значениями в каждой ячейке. Ячейка имеет свою ширину и высоту, как и сетка, состоящая из ячеек. Кроме того, таблицу нужно заполнить данными, для этого необходимо создать отдельный элемент, который будет представлять ячейки с данными. Также нужно принимать во внимание, что каждая сетка и таблица с данными имеет фиксированное количество строк и столбцов. Все перечисленные элементы являются основными для любых матриц.

К дополнительным элементам будут относиться:

1. Надписи с нумерацией строк и столбцов (текст ячейки)

2. Надпись перед матрицей (текст матрицы)

Чтобы организовать нумерацию по столбцам и строкам (начиная с нуля), необходимо напротив каждого элемента нулевого столбца и нулевой строки отобразить числовое значение, соответствующее столбцу или строке в которой находится элемент. Основой для нумерации будет ячейка. Текст, расположенный слева вертикально относительно положения ячейки будет обозначать номер строки, а текст расположенный сверху над ячейкой будет являться номером столбца.

Надпись перед матрицей используется для обозначения введенных матриц (к примеру - А, B), а также для результата выполненной операции. Основой для данного элемента будут ячейки со значениями.

Исходя из системного анализа матрицы можно составить следующую структурную схему системы:

1.2 Информация об openGL

OpenGL -- это мощный программный интерфейс, применяемый для получения высококачественных, программно генерируемых изображений и интерактивных приложений, использующих двух- и трехмерные объекты, а также растровые изображения.OpenGL - это графический стандарт в области компьютерной графики. На данный момент он является одним из самых популярных графических стандартов во всём мире. Ещё в 1982 г. в Стенфордском университете была разработана концепция графической машины, на основе которой фирма Silicon Graphics в своей рабочей станции Silicon IRIS реализовала конвейер рендеринга. Таким образом была разработана графическая библиотека IRIS GL. На основе библиотеки IRIS GL, в 1992 году был разработан и утверждён графический стандарт OpenGL. Разработчики OpenGL - это крупнейшие фирмы разработчики как оборудования так и программного обеспечения: Silicon Graphics, Inc., Microsoft, IBM Corporation, Sun Microsystems, Inc., Digital Equipment Corporation (DEC), Evans & Sutherland, Hewlett-Packard Corporation, Intel Corporation и Intergraph Corporation.OpenGL переводится как Открытая Графическая Библиотека (Open Graphics Library), это означает, что OpenGL - это открытый и мобильный стандарт. Программы, написанные с помощью OpenGL можно переносить практически на любые платформы, получая при этом одинаковый результат, будь это графическая станция или суперкомпьютер. OpenGL освобождает программиста от написания программ для конкретного оборудования. Если устройство поддерживает какую-то функцию, то эта функция выполняется аппаратно, если нет, то библиотека выполняет её программно.Что же представляет из себя OpenGL? С точки зрения программиста OpenGL - это программный интерфейс для графических устройств, таких как графические ускорители. Он включает в себя около 150 различных команд, с помощью которых программист может определять различные объекты и производить рендеринг.

Для интеграции openGL в среду разработки Visual Studio была выбрана свободно распространяемая библиотека OpenTK. Также для отображения текста была использована библиотека TexLib, основанная на OpenTK и также являющаяся свободно распространяемой.

Основные функции OpenTK, использованные в курсовой работе:

1. GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferit)

Установка режима отображения буфера цветов и глубины.

2. GL.Viewport(0, 0, glControl1.Width, glControl1.Height)

Установка порта вывода.

3. GL.ClearColor(Color.SkyBlue)

Очистка экрана выбранным цветом

4. GL.MatrixMode(MatrixMode.Modelview)

Установка матрицы проекций

5. GL.LoadIdentity()

Замена текущей матрицы единичной.

6. GL.Ortho(0, resolution.X, resolution.Y, 0, -1, 1)

Настройка ортогональной проекции.

Фукнции библиотеки TexLib:

1. TexUtil.CreateTextureFromFile("F:\\font1.png")

Создание текстуры из файла.

2. texFont.WriteStringAt("A=", 20, 8, resolution.Y -10, 0, resolution)

Рисование текста по указанным координатам

1.3 Формирование требований к компоненте

Основные функции, которыми должна обладать компонента:

1. Ввод данных

2. Расчет операций

3. Сохранение и воспроизведение данных.

Поскольку одной из целей данной курсовой работы является создание пользовательского элемента управления, то архитектура приложения будет строиться на основе компонентного подхода разработки приложений, что позволяет упростить его в целом, а также обеспечить повторное использование программного кода, разрабатываемой компоненты.

Следовательно, за реализацию всех вышеназванных функций должна будет отвечать разрабатываемая компонента, скрывая от остального приложения подробности работы с матрицами. Вся работа с графикой должна быть выполнена с использованием технологии OpenGL и отображение данных будет производиться с помощью шрифтов, считываемых из bmp файла. Для некоторого дополнительного удобства интерфейс приложения будет реализован с использованием многодокументного интерфейса (MDI). Это позволит пользователю одновременно работать с несколькими операциями для матриц.

2. Специальная часть

2.1 Структура приложения

Разрабатываемое приложение будет выполнено с использованием многодокументного интерфейса(MDI). Следовательно, оно будет иметь:

1. родительскую форму , которая предоставляет возможность создания нескольких окон.

2. множество дочерних форм, содержащих компоненту для расчёта матриц.

Поверхностью для расчета матриц является разрабатываемая в данной курсовой работе графическая пользовательская компонента (matrixCalc).

Родительская и дочерняя форма.

Родительская форма содержит пункты меню:

Добавить форму

Добавляет дочернюю форму с пользовательской компонентой

Расположение: вертикально, горизонтально.

Упорядочивает дочерние окна.

Файл

Открыть (открывает .txt или. mtx)

Сохранить как подразделяется на .txt (сохраняет матрицы в txt файл) и .mtx (сохраняет в двоичный файл)

2.2 Пользовательская компонента для расчета матриц

Общее описание компоненты (matrixCalc)

Компонента разделяется на три взаимосвязанных части:

1.Меню menustip

2.Компонента glControl

3.Формы для ввода данных

Meню

С помощью него задается операция и отображается нужная форма.

Пункт:

Операции:

Две матрицы(умножение, сложение, вычитание)

Одна матрица(обратная, транспонирование, определитель)

Компонента glControl

Представляет из себя область для отображения данных.

Формы для ввода данных

Состоит из 3 форм, одна из которых является родительской, остальные 2 формы являются потомками.

Родительская форма(Form1) состоит из 2 числовых полей(myTextBox) и таблицы для ввода данных(myDataGridView), а также кнопки button.

Элемент формы myTextbox является пользовательской компонентой, унаследованной от элемента textbox и является числовым полем, в которое можно вводить только целочисленные значения.

Элемент формы myDataGridView также является пользовательской компонентой, унаследованной от элемента DataGridView и является таблицей, в которую пользователь может вводить только целые числа или числа с плавающей запятой.

Ввод данных осуществлен таким образом: пользователь выбирает операцию, открывается форма, вводит количество строк и столбцов, вводит данные в таблицу, если режим умножение, сложение или вычитание, то после ввода данных и нажатии на клавишу Enter открывается вторая форма и вводятся данные в таблицу для матрицы 2, после нажатии на кнопку OK второй формы происходит расчет операции для введенных матриц и результат отображается на компоненте glControl. Если же выбрана операция для одной матрицы (определитель, обратная, транспонирование) открытие второй формы не происходит, пользователь вводит количество строк и столбцов и нажимает на кнопку OK, после этого производится расчет и отображение. Также производится обработка некорректных значений, о чем пользователь извещается с помощью сообщений.

Основные элементы поля компоненты:

public static List<matrix> matrixList

Список матриц

public static Mode operationMode

Текущая операция

public static Point resolution

Максимальное значение осей x и у

TextureFont texFont

Объект, содержащий в себе шрифты для отображения текста

Дополнительные поля для хранения данных, используемых алгоритмами (loaded, check, det)

Программная реализация элементов matrixCalc.

В результате анализа предметной области была получена структурная схема системы. На данном этапе разработки пользовательской компоненты необходимо создать программную реализацию этой системы.

Общая особенность всех элементов, это то, что каждый должен иметь свой фиксированный размер и иметь метод для графического отображения, поэтому это будет является основой для матрицы.

Для сетки и ячеек со значениями (т.е. матрицы) общим элементом являются количество строк и столбцов.

Ячейка представляет из себя прямоугольник, состоящий из 4 линий, а линия состоит из 2 точек, поэтому для отображения прямоугольника необходим метод для создания линии по 2 точкам, чтобы впоследствии с его использованием построить ячейку с выбранными размерами.

Классом наследником ячейки будет являться текст ячейки. Текст ячейки включает в себя расположение посередине над ячейкой (для обозначения номера столбца) и слева от ячейки (для обозначения номера строки). Сетка состоит из определенного количества строк и столбцов, поэтому в методе для графического отображения нужно создать количество ячеек, соответствующих данным значениям. Отображение чисел для нумерации строк и столбцов будет производится с помощью класса текста ячейки. Отличие сетки от матрицы - это наличие данных в ячейках, данные необходимо хранить в массиве. Кроме того, нужно как-то обозначить введенные матрицы, для этого выделим отдельный класс надписи матрицы, являющийся наследником класса ячеек с данными. Также понадобится метод определяющий попадает ли точка в объект матрицы. Исходя из вышесказанного, вытекает следующее дерево наследования элементов матрицы:

Расчет операций.

Расчет операций производиться с использованием статического класса, который содержит в себе необходимые функции, реализация которых была осуществлена на основе теоритического материала, представленного в разделе 2.1.1.

Ввод данных

Основой для ввода данных является форма Form1 имеющая потомков Form2 и Form3.

Form2 необходима для ввода данных, если был выбран режим для двух матриц, а Form3 если для одной.

При отображении Form1 кнопка button скрыта, потому что переход на следующую форму осуществлен по нажатию на Enter, причем пользователь оповещается об этом появлением всплывающей подсказки toolTip, после того, как все элементы введены в таблицу dataGridView. Переход производится на Form2, где осуществляется ввод второй матрицы.

Особенностью Form3 является отображение только одного числового поля для ввода размерности матрицы (при режимах обратной матрицы и нахождения определителя), а также не реагирование на клавишу Enter, потому что в данном случае нет необходимости вводить вторую матрицу.

Класс Matrix

Базовым классом для всех элементов матриц является класс Matrix. Он имеет следующий метод:

abstract public void Draw(int x, int y, Point resolution) - рисование элемента

Поля:

public int rowCount - количество строк

public int columnCount - количество столбцов

public Point size - размер элемента

Класс Cell

Представляет собой ячейку с указанными размерами.

Дополнительный метод: DrawLine(Point A, Point B) - рисование линии

Класс matrixTable

Используется для создания таблицы. Таблица состоит из объектов класса Cell.

Дополнительный метод:

public void drawText(TextureFont texFont, Point resolution) - рисует нумерацию строк и столбцов

Класс matrix

Является матрицей.

Дополнительное поле:

public double[,] mtx - массив значений матрицы

Дополнительные методы:

public void setMatrix(DataGridView dataGridView1) - записывает значения из dataGridView в массив

public bool Contains(Point point, int x0, int y0) - проверяет попадает ли точка в область матрицы

Класс matrixText.

Является наследником класса matrix. Представляет из себя обозначение матрицы (A, B, A*B, A+B и т.д.)

Метод:

public void draw(int x, int y, TextureFont texFont, Point resolution) - рисует текст

Поле:

public string text - текст операции

Класс cellText

Является наследником класса Cell. Служит для отображения нумерации строк и столбцов.

Поле:

public string text - номер строки или столбца

public void drawVertical(int x, int y, TextureFont texFont, Point resolution) - рисует текста слева от ячейки по вертикали(для обозначения строк)

public void drawHorizontal(int x, int y, TextureFont texFont, Point resolution) -

рисует текст над ячейкой(для обозначения столбцов)

Класс matrixOperations Содержит статические методы для расчета операций:

public static multiplication(double[,] matrix1, double[,] matrix2)-умножение

public static addition(double[,] matrix1, double[,] matrix2)-сложение

public static subtraction(double[,] matrix1, double[,] matrix2)-вычитание

public static Transpose(double[,] mtx)-транспонирование

public static double Determinent(double[,] matrix)-определитель

public static double[,] Inverse(double[,] matrix)-обратная матрица

Основные функции Form1:

public void setMatrixToData(int k,DataGridView dataGridView) - для заполнения значениями из списка матриц таблицы dataGridView, используется при загрузке формы когда происходит редактирование матриц.

public void clearData(DataGridView dataGridView) - очищает dataGridView от введенных значений

public bool checkValues(DataGridView dataGridView) - проверяет все ли ячейки таблицы dataGridView были заполнены

События Form1, обрабатываемые при вводе данных и их основные функции:

private void myTextBox1_TextChanged(object sender, EventArgs e) - устанавливает количество строк в dataGridView

private void myTextBox2_TextChanged(object sender, EventArgs e) -

устанавливает количество столбцов в dataGridView

public void myDataGridView1_CurrentCellChanged(object sender, EventArgs e)-

заносит матрицу в список если было изменены значения dataGridView

public void myDataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e) - заносит введенную матрицу в список при нажатии на Enter

private void myDataGridView1_SizeChanged(object sender, EventArgs e) - изменяет размер формы в зависимости от размера dataGridView

События Form2:

private void button1_Click(object sender, EventArgs e)- для занесения матрицы 2 в список и расчета выбранной операции и последующего отображения на компоненте glControl

private void Form2_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) - обновляет данные текстбоксов при их изменении на Form1

События Form3:

private void button1_Click(object sender, EventArgs e)- для занесения матрицы в список и расчета выбранной операции и последующего отображения на компоненте glControl

Событие MouseDown.

Данное события обрабатывается для осуществления редактирования матриц при клике правой кнопкой мыши в область матрицы.

Сохранение и воспроизведение матриц

Сохранение и воспроизведение производится в двоичный файл(.mtx) и текстовый файл(.txt).

Структура двоичного файла:

1.Выбранная операция

2.Количество матриц

3.Размерность введенных матриц

4.Массив элементов матрицы

Структура текстового файла:

1. Количество матриц

2. Выбранная операция

3.Размерность введенных матриц

4.Массивы элементов матриц

Заключение

В процессе выполнения данной курсовой работы была разработана пользовательская компонента для вычисления операций с матрицами, предоставляющая следующие функции:

1. Вычисления различных операций (умножение, сложение, вычитание, поиск обратной матрицы, транспонирование, поиск определителя).

2. Сохранение в двоичный и текстовый файл.

3. Редактирование матриц.

4. Масштабирования матриц.

Исходя из анализа предметной области и определения требований к системе, была разработана архитектура системы, основывающаяся на компонентном подходе разработки приложений. Т. е. было произведено разбиение системы на компоненты и последующая организация их взаимодействия.

Для моделирования элементов матриц была разработана система классов, отражающая наиболее общие и абстрактные свойства, характерные для всех элементов. Кроме того, были введены промежуточные классы в дереве наследования, реализующие и поддерживающие дополнительные функции, необходимые их наследникам.

Для осуществления операций был разработан класс матрицы, на основе которого строились таблицы со значениями.

Реализация рисования текста была организована с помощью библиотеки TexLib, которая инкапсулирует в себе все нюансы инициализации, настройки и применения функций технологии OpenGL.

В результате разбиения системы на модули был разработан пользовательский элемент управления matrixCalc, а именно:

1. Разработан интерфейс компоненты для предоставления своего функционала пользователю.

2. Определен алгоритм на реакцию события MouseDown.

3. Разработаны структуры данных, а именно иерархия классов элементов матриц.

Из всего вышесказанного следует, что в процессе выполнения данной курсовой работы были выполнены все поставленные первоначально задачи.

Список использованных источников

1. Карли Ватсон, С# / М.: Лори, 2005 - 862 с.

2. Фролов А. В, Язык С#. Самоучитель. / Фролов А. В., Фролов Г. В. М.: ДИАЛОГ-МИФИ, 2003. - 560 с.

3. Estate.ru. Уроки С#. OpenGL http://www.esate.ru/page/uroki-OpenGL-c-sharp/

4. http://svn.opentk.net/ - Библиотека openTK

5. Агуров П.В. C#. Разработка компонентов в MS Visual Studio 2005/2008

6. Агуров П.В. C#. Сборник рецептов.2007, 429 стр.

7. http://e-science.ru/math/theory/?t=379 - Информация о матрицах

Приложения

математический opengl матрица net

Графический интерфейс приложения.

Рис.1. Созданные пользовательские компоненты

Рис.2. Конструктор компоненты.

Рис.3. Компонента на форме.

Рис.4. Ввод значений.

Рис.5. Результат работы программы.

Рис.6. Содержание текстового файла.

Исходный текст программы.

Компонента.

namespace MatrixCalc

{

public partial class matrixCalc : UserControl

{

bool loaded = false;

TextureFont texFont;

bool сheck = false;

public static List<matrix> matrixList;//Список матриц

public static Mode operationMode = Mode.Default;//текущая операция

public static Point resolution = new Point(200, 200);//размерность x и y

static double det;

public matrixCalc()

{

InitializeComponent();

}

private void matrixCalc_Load(object sender, EventArgs e)

{

texFont = null;

matrixList = null;

operationMode = Mode.Default;

loaded = true;

}

private void glControl1_Load(object sender, EventArgs e)

{

loaded = true;

}

private void glControl1_Resize(object sender, EventArgs e)

{

if (!loaded)

return;

}

private void обратнаяToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Invert;

}

private void транспонированиеToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Transpose;

}

private void определительToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Determinant;

}

private void умножениеToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Multiplication;

}

private void сложениеToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Addition;

}

private void вычитаниеToolStripMenuItem_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixList = new List<matrix>();

сheck = false;

operationMode = Mode.Substraction;

}

private void однаМатрицаToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)

{

glControlSetting();

matrixCalc mtxCalc = this;

Form3 f = new Form3(mtxCalc);

f.ShowDialog();

}

private void двеМатрицыToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)

{

glControlSetting();

matrixCalc mtxCalc = this;

Form1 f = new Form1(mtxCalc);

f.ShowDialog();

}

private void glControlSetting()

{

loaded = true;

fontSetting(glControl1);//настраиваем шрифты и opengl

texFont = fontSetting(glControl1);

GL.ClearColor(Color.SkyBlue);//Заливка по умолчанию

}

private void matrixCalc_SizeChanged(object sender, EventArgs e)

{

glControl1.Width = this.Width;

glControl1.Height = this.Height - 24;

if (matrixList!=null)

{

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

drawAllMatrix(texFont, matrixList[0].mtx);

if (operationMode != Mode.Determinant)

{

drawAllMatrix(texFont, matrixList[0].mtx, matrixList[1].mtx);

}

glControl1.SwapBuffers();

}

}

public void saveAsTxt()

{

dataOperations data = new dataOperations();

SaveFileDialog sfd = new SaveFileDialog();

sfd.DefaultExt = "txt";

sfd.Filter = "Matrix textfile|*.txt";

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

if (matrixList == null)

{

MessageBox.Show("Матрицы не были введены");

return;

}

if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)

{

data.saveAllMatrixTxt(sfd.FileName);

drawAllMatrix(texFont, matrixList[0].mtx);

if (operationMode != Mode.Determinant)

{

drawAllMatrix(texFont, matrixList[0].mtx, matrixList[1].mtx);

}

glControl1.SwapBuffers();

}

}

public void saveAsMtx()

{

dataOperations data = new dataOperations();

SaveFileDialog sfd = new SaveFileDialog();

sfd.DefaultExt = "mtx";

sfd.Filter = "Matrix file|*.mtx";

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

if (matrixList == null)

{

MessageBox.Show("Матрицы не были введены");

return;

}

if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)

{

data.saveAllMatrixMtx(sfd.FileName);

drawAllMatrix(texFont, matrixList[0].mtx);

if (operationMode != Mode.Determinant)

{

drawAllMatrix(texFont, matrixList[0].mtx, matrixList[1].mtx);

}

glControl1.SwapBuffers();

}

}

public void openFile()

{

dataOperations data = new dataOperations();

glControlSetting();

OpenFileDialog od = new OpenFileDialog();

od.Filter = "Matrix file|*.mtx|Matrix textfile|*.txt";

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

if (od.ShowDialog() == System.Windows.Forms.DialogResult.OK)

{

string p = od.FileName;

string type = Path.GetExtension(p);

if (type == ".mtx")

{

data.readAllMatrixMtx(od.FileName);

}

if (type == ".txt")

{

data.readAllMatrixTxt(od.FileName);

}

drawAllMatrix(texFont, matrixList[0].mtx);

if (operationMode != Mode.Determinant)

{

drawAllMatrix(texFont, matrixList[0].mtx, matrixList[1].mtx);

}

glControl1.SwapBuffers();

}

}

private void glControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

matrixCalc mtxCalc = this;

сheck = false;

Point worldCoords = convertScreenToWorldCoords(e.X, e.Y);

worldCoords.Y = (resolution.Y - worldCoords.Y);

if (e.Button == MouseButtons.Right && matrixList!=null)

{

if (matrixList.Count > 0 && matrixList[0].Contains(worldCoords,30,13)==true)

{

switch (operationMode)//Операции

{

case Mode.Invert:

case Mode.Transpose:

case Mode.Determinant:

Form3 f3 = new Form3(mtxCalc);

f3.ShowDialog();

break;

case Mode.Addition:

case Mode.Substraction:

case Mode.Multiplication:

Form1 f1 = new Form1(mtxCalc);

f1.ShowDialog();

break;

}

}

}

}

private void glControl1_Paint(object sender, PaintEventArgs e)

{

if (matrixList != null)

{

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);//очищаем поверхность

drawAllMatrix(texFont, matrixList[0].mtx);

if (operationMode != Mode.Determinant)

{

drawAllMatrix(texFont, matrixList[0].mtx, matrixList[1].mtx);

}

glControl1.SwapBuffers();

}

}

public TextureFont fontSetting(GLControl glControl1)//Для настройки поверхности опегл и шрифтов

{

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);//очищаем поверхность

GL.MatrixMode(MatrixMode.Modelview);

GL.LoadIdentity();

// Настраиваем опенгл для текстуры

TexUtil.InitTexturing();

//Загружаем текстуру со шрифтами

int tex = TexUtil.CreateTextureFromFile(Application.StartupPath + @"\" + "font1.png");

// Создаем объект TextureFont из загруженной текстуры

TextureFont texFont = new TextureFont(tex);

return texFont;

}

public static Point convertScreenToWorldCoords(int x, int y)

{

int[] viewport = new int[4];

Matrix4 modelViewMatrix, projectionMatrix;

GL.GetFloat(GetPName.ModelviewMatrix, out modelViewMatrix);

GL.GetFloat(GetPName.ProjectionMatrix, out projectionMatrix);

GL.GetInteger(GetPName.Viewport, viewport);

Vector2 mouse;

mouse.X = x;

mouse.Y = y;

Vector4 vector = UnProject(ref projectionMatrix, modelViewMatrix, new Size(viewport[2], viewport[3]), mouse);

Point coords = new Point((int)vector.X, (int)vector.Y);

return coords;

}

public static Vector4 UnProject(ref Matrix4 projection, Matrix4 view, Size viewport, Vector2 mouse)

{

Vector4 vec;

vec.X = 2.0f * mouse.X / (float)viewport.Width - 1;

vec.Y = 2.0f * mouse.Y / (float)viewport.Height - 1;

vec.Z = 0;

vec.W = 1.0f;

Matrix4 viewInv = Matrix4.Invert(view);

Matrix4 projInv = Matrix4.Invert(projection);

Vector4.Transform(ref vec, ref projInv, out vec);

Vector4.Transform(ref vec, ref viewInv, out vec);

if (vec.W > float.Epsilon || vec.W < float.Epsilon)

{

vec.X /= vec.W;

vec.Y /= vec.W;

vec.Z /= vec.W;

}

return vec;

}

public void drawAllMatrix(TextureFont texFont, double[,] mtx)//для рисования матриц(обратная, определитель, транспонирование)

{

double font = 20;//размер шрифта

int m = matrixList[0].rowCount;//Кол-во строк

resolution = new Point(200, 200);

switch (operationMode)

{

case Mode.Invert:

if (m > 3)

{

resolution.X = m * 60 + 17;

resolution.Y = m * 60 + 17;

}

else

{

resolution = new Point(210, 210);

}

if (сheck == false)

{

matrix matrixI = new matrix(matrixOperations.Inverse(mtx).GetLength(0), matrixOperations.Inverse(mtx).GetLength(1));

matrixI.mtx = matrixOperations.Inverse(mtx);

matrixList.Add(matrixI);

}

GL.LoadIdentity();

GL.Ortho(0, resolution.X, resolution.Y, 0, -1, 1);

GL.Viewport(0, 0, glControl1.Width, glControl1.Height);

matrixList[0].Draw("A=",30, 13, texFont, resolution);

matrixList[1].Draw("A^(-1)=",45, matrixList[0].size.Y + 27, texFont, resolution);

break;

case Mode.Transpose:

if (сheck == false)

{

matrix matrixT = new matrix(matrixOperations.Transpose(mtx).GetLength(0), matrixOperations.Transpose(mtx).GetLength(1));

matrixT.mtx = matrixOperations.Transpose(mtx);

matrixList.Add(matrixT);

}

int n = matrixList[0].columnCount;

int m1 = matrixList[1].rowCount;

int n1 = matrixList[1].columnCount;

if (m > 2 || n > 2)

{

if (n > n1)

{

resolution.X = n * 55;

}

else

{

resolution.X = n1 * 55;

}

}

resolution.Y = m * 25 + m1 * 25 + 60;

GL.LoadIdentity();

GL.Ortho(0, resolution.X, resolution.Y, 0, -1, 1);

GL.Viewport(0, 0, glControl1.Width, glControl1.Height);

matrixList[0].Draw("A=",30, 13, texFont, resolution);

matrixList[1].Draw("AT=",40, matrixList[0].size.Y +27,texFont, resolution);

break;

case Mode.Determinant:

if (сheck == false)

{

det = matrixOperations.Determinent(mtx);

}

if (m > 3)

{

resolution.X = m * 60;

resolution.Y = m * 30 + 40;

}

else

{

resolution = new Point(200, 200);

}

GL.LoadIdentity();

GL.Ortho(0, resolution.X, resolution.Y, 0, -1, 1);

GL.Viewport(0, 0, glControl1.Width, glControl1.Height);

matrixList[0].Draw("A=",30, 13, texFont, resolution);

texFont.WriteStringAt("detA=", font, 18, resolution.Y - matrixList[0].size.Y -25, 0, resolution);

texFont.WriteStringAt(Convert.ToString(det), font, 60, resolution.Y - matrixList[0].size.Y - 25, 0, resolution);

break;

}

сheck = true;

}

public void drawAllMatrix(TextureFont texFont, double[,] mtx1, double[,] mtx2)//для рисования матриц(умножение, сложение, вычитание)

{

switch (operationMode)

{

case Mode.Multiplication:

drawOperation("A*B=", texFont, mtx1, mtx2);

break;

case Mode.Addition:

drawOperation("A+B=", texFont, mtx1, mtx2);

break;

case Mode.Substraction:

drawOperation("A-B=", texFont, mtx1, mtx2);

break;

}

}

private void drawOperation(string operation, TextureFont texFont, double[,] mtx1, double[,] mtx2)//для метода выше

{

double font = 20;//размер шрифта

resolution = new Point(200, 200);

if (сheck == false)

{

switch (operationMode)

{

case Mode.Multiplication:

matrix matrixM = new matrix(matrixOperations.multiplication(mtx1, mtx2).GetLength(0), matrixOperations.multiplication(mtx1, mtx2).GetLength(1));

matrixM.mtx = matrixOperations.multiplication(mtx1, mtx2);

matrixList.Add(matrixM);

break;

case Mode.Addition:

matrix matrixA = new matrix(matrixOperations.addition(mtx1, mtx2).GetLength(0), matrixOperations.addition(mtx1, mtx2).GetLength(1));

matrixA.mtx = matrixOperations.addition(mtx1, mtx2);

matrixList.Add(matrixA);

break;

case Mode.Substraction:

matrix matrixS = new matrix(matrixOperations.subtraction(mtx1, mtx2).GetLength(0), matrixOperations.subtraction(mtx1, mtx2).GetLength(1));

matrixS.mtx = matrixOperations.subtraction(mtx1, mtx2);

matrixList.Add(matrixS);

break;

}

}

int m = matrixList[0].rowCount;

int m1 = matrixList[2].rowCount;

int n1 = matrixList[0].columnCount;

int n2 = matrixList[1].columnCount;

int m3 = matrixList[2].rowCount;

resolution.X = n1 * 55 + n2 * 55 + 30;

resolution.Y = 25 * (m1 + m3) + 60;

GL.LoadIdentity();

GL.Ortho(0, resolution.X, resolution.Y, 0, -1, 1);

GL.Viewport(0, 2, glControl1.Width, glControl1.Height);

matrixList[0].Draw("A=",30, 13 ,texFont,resolution);

matrixList[1].Draw("B=", matrixList[0].size.X + 60,13, texFont, resolution);

matrixList[2].Draw(operation,30, matrixList[0].size.Y +25, texFont, resolution);

сheck = true;

}

}

Классы.

public abstract class Matrix

{

public int rowCount;

public int columnCount;

public Point size;

public Matrix()

{

size = new Point(0, 0);

}

abstract public void Draw(int x, int y);

}

public class Cell : Matrix

{

public int width;

public int height;

public Cell(int w, int h)

{

this.width = w;

this.height = h;

}

private void DrawLine(Point A, Point B)

{

GL.Vertex2(A.X, A.Y);

GL.Vertex2(B.X, B.Y);

}

public override void Draw(int x0, int y0)

{

Point p1 = new Point(x0, y0);

Point p2 = new Point(x0 + width, y0);

Point p3 = new Point(x0, y0 + height);

Point p4 = new Point(x0 + width, y0 + height);

DrawLine(p1, p2);

DrawLine(p1, p3);

DrawLine(p3, p4);

DrawLine(p4, p2);

size.X = width;

size.Y = height;

}

}

public class matrixTable : Matrix

{

private Cell cell;

int x;

int y;

public matrixTable(int rowCount, int columnCount)

{

cell = new Cell(45, 25);

this.rowCount = rowCount;

this.columnCount = columnCount;

}

public override void Draw(int x0, int y0)

{

x = x0;

y = y0;

GL.Begin(BeginMode.Lines);

for (int i = 0; i < rowCount; i++)

{

for (int j = 0; j < columnCount; j++)

{

cell.Draw(x0 + cell.width * j, y0 + cell.height * i);

}

}

size.X = cell.width * columnCount;

size.Y = cell.height * rowCount;

GL.End();

}

public void drawText(TextureFont texFont, Point resolution)

{

for (int i = 0; i < rowCount; i++)

{

cellText text = new cellText(45, 25, Convert.ToString(i));

text.drawVertical(x, resolution.Y - y - cell.height * i - 25, texFont, resolution);

}

for (int j = 0; j < columnCount; j++)

{

cellText text = new cellText(45, 25, Convert.ToString(j));

text.drawHorizontal(x + cell.width * j, resolution.Y - y + 7, texFont, resolution);

}

}

}

public class matrix : Matrix

{

public double[,] mtx;

matrixTable mtxTab;

public matrix(int rowCount, int columnCount)

{

this.rowCount = rowCount;

this.columnCount = columnCount;

mtx = new double[rowCount, columnCount];

mtxTab = new matrixTable(rowCount, columnCount);

size = new Point(45 * columnCount, 25 * rowCount);

}

public void Draw(string operation, int x0, int y0, TextureFont texFont, Point resolution)

{

int y = resolution.Y - 11 - y0;

double M = Convert.ToDouble(mtx.GetLength(1));

double dx = 0;//Интервал между цифрами

int dy = 0;//Интервал между строками

for (int i = 0; i < mtx.GetLength(0); i++)

{

for (int j = 0; j < mtx.GetLength(1); j++)

{

dx = dx + 45;

texFont.WriteStringAt(Convert.ToString(mtx[i, j]), 20, x0 + dx - 20, y + dy, 0, resolution);

}

dx = dx - 45 * (M);

dy = dy - 25;

}

matrixText text = new matrixText(operation, rowCount, columnCount);

text.draw(x0, y0, texFont, resolution);

GL.Disable(EnableCap.Texture2D);

Draw(x0, y0);

GL.Enable(EnableCap.Texture2D);

mtxTab.drawText(texFont, resolution);

}

public override void Draw(int x0, int y0)

{

mtxTab.Draw(x0, y0);

}

public void setMatrix(DataGridView dataGridView1)//Записывает матрицу в список

{

for (int i = 0; i < rowCount; i++)

{

for (int j = 0; j < columnCount; j++)

{

mtx[i, j] = Convert.ToDouble(dataGridView1.Rows[i].Cells[j].Value);

}

}

}

public bool Contains(Point point, int x0, int y0)

{

bool contains = false;

GraphicsPath GraphicsPathRectangle = new GraphicsPath();

Rectangle RectangleDraw = new Rectangle(x0, y0, size.X, size.Y);

GraphicsPathRectangle.AddRectangle(RectangleDraw);

if (GraphicsPathRectangle.IsVisible(point))

{

contains = true;

}

return contains;

}

}

public class matrixText : matrix

{

public string text;

public int width;

public int height;

public matrixText(string text, int rowCount, int columnCount)

: base(rowCount, columnCount)

{

this.text = text;

size = new Point(45 * columnCount, 25 * rowCount);

}

public Point calculateLocation()

{

Point location = new Point(0, 0);

location.X = this.size.X - size.X - 20;

location.Y = this.size.Y / 2;

return location;

}

//x,y - координаты таблицы

public void draw(int x, int y, TextureFont texFont, Point resolution)

{

texFont.WriteStringAt(text, 20, x - 18, resolution.Y - y, 0, resolution);

}

}

public class cellText : Cell

{

public string text;

public cellText(int width, int height, string text)

: base(width, height)

{

this.text = text;

}

public void drawVertical(int x, int y, TextureFont texFont, Point resolution)

{

texFont.WriteStringAt(text, 10, x - 4, y + (this.height / 2), 0, resolution);

}

public void drawHorizontal(int x, int y, TextureFont texFont, Point resolution)

{

texFont.WriteStringAt(text, 10, x + (this.width / 2), y, 0, resolution);

}

}

public static class matrixOperations

{

#region//Умножение, сложение, вычитание

public static double[,] multiplication(double[,] matrix1, double[,] matrix2)//Умножение

{

if (matrix1.GetLength(1) != matrix2.GetLength(0)) throw new Exception("Матрицы нельзя перемножить");

double[,] r = new double[matrix1.GetLength(0), matrix2.GetLength(1)];

for (int i = 0; i < matrix1.GetLength(0); i++)

{

for (int j = 0; j < matrix2.GetLength(1); j++)

{

for (int k = 0; k < matrix2.GetLength(0); k++)

{

r[i, j] += matrix1[i, k] * matrix2[k, j];

}

}

}

return r;

}

public static double[,] addition(double[,] matrix1, double[,] matrix2)//Сложение

{

double[,] r = new double[matrix1.GetLength(0), matrix2.GetLength(1)];

if (matrix1.GetLength(0) != matrix2.GetLength(0) && matrix1.GetLength(1) != matrix2.GetLength(1)) throw new Exception("Матрицы нельзя сложить");

for (int i = 0; i < matrix1.GetLength(0); i++)

{

for (int j = 0; j < matrix2.GetLength(1); j++)

{

r[i, j] = matrix1[i, j] + matrix2[i, j];

}

}

return r;

}

public static double[,] subtraction(double[,] matrix1, double[,] matrix2)//Вычитание

{

double[,] r = new double[matrix1.GetLength(0), matrix2.GetLength(1)];

if (matrix1.GetLength(0) != matrix2.GetLength(0) && matrix1.GetLength(1) != matrix2.GetLength(1)) throw new Exception("Матрицы нельзя вычесть");

for (int i = 0; i < matrix1.GetLength(0); i++)

{

for (int j = 0; j < matrix2.GetLength(1); j++)

{

r[i, j] = matrix1[i, j] - matrix2[i, j];

}

}

return r;

}

#endregion

#region//Транспонирование, обратная, определитель

public static double[,] Transpose(double[,] mtx)

{

double[,] TransposeMatrix = new double[mtx.GetLength(1), mtx.GetLength(0)];

for (int i = 0; i < TransposeMatrix.GetLength(0); i++)

for (int j = 0; j < TransposeMatrix.GetLength(1); j++)

TransposeMatrix[i, j] = mtx[j, i];

return TransposeMatrix;

}

private static double[,] Minor(double[,] matrix, int iRow, int iCol)

{

double[,] minor = new double[matrix.GetLength(0) - 1, matrix.GetLength(1) - 1];

int m = 0, n = 0;

for (int i = 0; i < matrix.GetLength(0); i++)

{

if (i == iRow)

continue;

n = 0;

for (int j = 0; j < matrix.GetLength(1); j++)

{

if (j == iCol)

continue;

minor[m, n] = matrix[i, j];

n++;

}

m++;

}

return minor;

}

public static double Determinent(double[,] matrix)

{

double det = 0;

if (matrix.GetLength(0) != matrix.GetLength(1))

MessageBox.Show("Матрица не квадратная");

if (matrix.GetLength(0) == 1)

return matrix[0, 0];

for (int j = 0; j < matrix.GetLength(1); j++)

det += (matrix[0, j] * Determinent(Minor(matrix, 0, j)) * (int)System.Math.Pow(-1, 0 + j));

return det;

}

private static double[,] Adjoint(double[,] matrix)

{

if (matrix.GetLength(0) != matrix.GetLength(1))

throw new Exception("Матрица не квадратная");

double[,] AdjointMatrix = new double[matrix.GetLength(0), matrix.GetLength(1)];

for (int i = 0; i < matrix.GetLength(0); i++)

for (int j = 0; j < matrix.GetLength(1); j++)

AdjointMatrix[i, j] = Math.Pow(-1, i + j) * Determinent(Minor(matrix, i, j));

AdjointMatrix = Transpose(AdjointMatrix);

return AdjointMatrix;

}

public static double[,] Inverse(double[,] matrix)

{

double[,] temp = Adjoint(matrix);

double[,] temp1 = new double[temp.GetLength(0), temp.GetLength(1)];

if (Determinent(matrix) == 0)

MessageBox.Show("Матрица вырождена, обратной не существует");

for (int i = 0; i < temp.GetLength(0); i++)

{

for (int j = 0; j < temp.GetLength(1); j++)

{

temp1[i, j] = Math.Round(temp[i, j] / Determinent(matrix), 3);

}

}

return temp1;

}

#endregion

}

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.