С какого элемента считаются матрицы c

С какого элемента считаются матрицы c

Введение

В этом документе, как в большинстве книг по математике, все матрицы представлены в стандартном математическом виде. К сожалению, в уроках и документах по использованию графических библиотек типа IrisGL, OpenGL используют представление, в котором изменены местами столбцы и строки.

В этом документе, к примеру, матрица переноса 4×4 записывается в таком виде:

\(M = \begin 1 & 0 & 0 & X\cr 0 & 1 & 0 & Y\cr 0 & 0 & 1 & Z\cr 0 & 0 & 0 & 1\cr \end\)

В коде это можно записать вот так:

OpenGL использует одномерный массив для хранения матриц, но, к счастью, они находятся в памяти в таком виде, что получив адрес pfMatrix и скастовав его к float* можно увидеть матрицу в том виде, в каком ее передают в glLoadMatrixf.

Во фрагментах кода в этом документе используются одномерные массивы для хранения матриц. Порядок элементов в них транспонирован как в OpenGL.

Этот документ OpenGL
\(M = \begin 0 & 1 & 2 & 3\cr 4 & 5 & 6 & 7\cr 8 & 9 & 10 & 11\cr 12 & 13 & 14 & 15\cr \end\) \(M = \begin 0 & 4 & 8 & 12\cr 1 & 5 & 9 & 13\cr 2 & 6 & 10 & 14\cr 3 & 7 & 11 & 15\cr \end\)

Что такое матрица?

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

Матрицы можно складывать, вычитать, умножать и делить.

Размер матрицы определяется количеством рядов и колонок.

Матрица с M рядов и N колонок описывается как матрица MxN.

Описать отдельный элемент матрицы можно в виде двух индексов.

Используя математическую нотацию индексы обозначают переменными i и j. Сначала пишут строку, затем колонку.

К примеру, если есть матрица M с порядком 4×4, то элементы этой матрицы описываются парами индексов строк и колонок:

\(M = \begin 00 & 10 & 20 & 30\cr 01 & 11 & 21 & 31\cr 02 & 12 & 22 & 32\cr 03 & 13 & 23 & 33\cr \end\)

У верхнего правого элемента матрицы i=0 и j=3, что можно описать так:
\(M_=M_<03>\)

В компьютерной анимации обычно используют матрицы 2×2, 3×3 и 4×4.

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

Матрицы 3×3 достаточны для хранения информации о повороте (вращении) и масшатбировании. Такие матрицы могут быть использованы для скелетной анимации.

Матрицы 4×3 достаточно, чтобы хранить поворот, масштабирование и перемещение.

Матрицы 4×4 используются для всего набора трансформаций в трёхмерном пространстве, включая перспективное проецирование.

Что такое порядок матрицы?

Порядок матрицы — это её размерность. Матрица из M строк и N столбцов имеет порядок MxN.

Как я могу сделать матрицу в C/C++?

Проще всего использовать ключевое слово typedef.

Матрицы 3×3 и 4×4 могут быть описаны так:

Так как матрицы имеют размерность 3×3 и 4×4, им необходимо 9 и 16 элементов соответственно.

На первый взгляд, использование одного линейного массива чисел может показаться не интуитивным. Использование двумерного массива кажется логичнее:

Однако, использование двух систем отсчета для каждого элемента матрицы часто ведет к путанице. В математике, сначала записывают строку(i), а затем колонку(j): \(M_\)

В C/C++, это будет так:

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

Так что, эффективнее использовать одномерные массивы. Однако останется решить ещё один вопрос. Как двумерный массив проецируется в линейный?

Есть только два решения: строка сначала, колонка потом, либо колонка сначала, а строка потом.

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

При использовании C/C++ порядок элементов в матрице следующий:

\(M = \begin 0 & 1 & 2 & 3\cr 4 & 5 & 6 & 7\cr 8 & 9 & 10 & 11\cr 12 & 13 & 14 & 15\cr \end\) \(M = \begin 0 & 1 & 2\cr 3 & 4 & 5\cr 6 & 7 & 8\cr \end\)

В чем плюсы от использования матриц?

Один из первых вопросов, задаваемых по использованию матриц в компьютерной анимации: «Зачем вообще они нужны?». Интуиция подсказывает, что придется хорошо потратиться на циклы, и тем самым матричные перемножения замедлят программу.

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

Также можно указать и на плюсы. Используя этот математический подход в описании 3D алгоритмов, можно предсказать и спланировать систему 3D анимации. Этот подход позволяет реализовать анимацию персонажа, сплайны и инверсную кинематику.

Но чаще всего звучит такой вопрос: «А не будет ли быстрее, просто умножить каждую пару координат на коэффициенты поворота для оси, вместо того чтобы производить полное векторно-матричное умножение?»

иначе говоря:
Вращение в X преобразует Y и Z
Вращение в Y преобразует X и Z
Вращение в Z преобразует X и Y

За это приводятся следующие аргументы:

Дана вершина V = (x, y, z), углы поворота (A,B и C) и перенос (D,E,F).

И следующий алгоритм:

Вместе они займут следующее количество процессорного времени:

Настройка На одну вершину
6 тригонометрических функций
6 присваиваний.
12 присваиваний
12 умножений
9 сложений

Те же самые операции, но при использовании матричного умножения.

С матрицей 4х4 они займут:

Настройка Изменение На одну вершину Изменение
6 тригонометрических функций 0 0
18 присваиваний -12 3 присваиваний -9
12 умножений +12 9 умножений -3
6 вычитаний +6 6 сложений -3

Сравнивая две таблицы, видно, что матрица поворота стоит как минимум 12 умножений и дополнительно 18 присваиваний.

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

Как матрицы влияют на систему координат?

Матрицы поворота, переноса, сдвига очень просто действуют на систему координат.

Первые три колонки матрицы описывают направление осей X,Y,Z соответственно.

Если описана матрица 4х4 как:
\(M = \begin A & B & C & D\cr E & F & G & H\cr I & J & K & L\cr M & N & O & P\cr \end\)

Вектор направления для каждой оси будет следующий:

ось \(X = [ A E I]\)
ось \(Y = [ B F J ]\)
ось \(Z = [ C G K]\)

С какого элемента считаются матрицы c

Матрица — это некоторая прямоугольная область (таблица), состоящая из строк и столбцов. Пересечения строк и столбцов образуют ячейки. Изобразим на рисунке прямоугольную матрицу a ( n × m ), состоящую из n строк и m столбцов:

Пусть n =3 и m =4. Строки и столбцы пронумеруем, начиная с 0. Заведём вспомогательные переменные:

i — текущее значение строки;

j — текущее значение столбца.

Прежде чем начать работу с матрицей, необходимо дать её описание. Но не всё так просто. У матрицы два измерения, а в языках С/С++ имеются только одномерные массивы и нет двумерных, трёхмерных и т.д. массивов, т.е. нет многомерных массивов, а есть только одномерные. Как же тогда работать с матрицами? Решение элементарное. Считаем матрицу одномерным массивом, состоящим из n строк, где каждая строка — это тоже массив, но из m элементов, т.е. рассматриваем матрицу как массив массивов. Формально это можно записать таким образом:

Тип_элементов Имя_матрицы [ число_строк ][ число_столбцов ];

Для нашей матрицы a описание будет выглядеть так (пусть элементы матрицы — действительные числа):

const int n = 3; // число строк

const int m = 4; // число столбцов

double a[n][m]; // выделяем память под матрицу

И теперь можно приступать к работе с матрицей. Например, присвоить значение какому-нибудь элементу матрицы:

Так мы присвоили значение элементу, расположенному в первой строке и во втором столбце (именно он отмечен на рисунке).

Индексы для матриц задаются так же, как и для одномерных массивов. И так же нежелательно выходить за пределы матрицы (по строкам или по столбцам — всё равно).

Разберём на простом примере некоторые приёмы работы с матрицами.

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

Матрица

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

Инициализация такого массива объявляется строкой

То есть, если у нас есть матрица с 3 строками и 4 столбцами, заполненная целыми числами, то объявить ее можно строкой

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

Теперь каждый элемент матрицы равен сумме строки и столбца. В программе добавляется еще 2 чтобы скомпенсировать то, что отсчет в массиве ведется с 0-ого элемента, а не с 1-ого.

Такого же результата можно достичь с помощью следующего кода:

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

Ссылка на основную публикацию