
- •Эволюция графического интерфейса операционных систем за последние 30 лет
- •Xerox 8010 Star (выпущен в 1981г)
- •Irix 3 (разработан в 1986г, самая первая версия - в 1984г)
- •Особенности векторной графики
- •Типичные примитивные объекты
- •Кодирование Хаффмана
- •Адаптивное сжатие
- •Переполнение
- •Основные этапы
- •[Править] Алгоритм вычисления кодов Шеннона — Фано
- •[Править] Пример кодового дерева
- •Характеристики цвета
- •[Править] Яркость
- •[Править] Насыщенность
- •[Править] Светлота
- •[Править] Цветовой тон
- •Виды перспективы
- •[Править] Прямая линейная перспектива
- •[Править] Обратная линейная перспектива
- •[Править] Панорамная перспектива
- •[Править] Аксонометрия
- •[Править] Сферическая перспектива
- •[Править] Тональная перспектива
- •[Править] Воздушная перспектива
- •[Править] Перцептивная перспектива
- •Косоугольная система координат
- •Однородные координаты
- •Поворот плоскости и его матричное представление
- •Матричное представление поворота плоскости
- •Программная реализация
- •Матрица поворота в двумерном пространстве
- •[Править] Матрица поворота в трёхмерном пространстве
- •Свойства матрицы поворота
- •Алгоритм
- •[Править] Рисование линий
- •Рисование окружностей
- •Алгоритм
- •Алгоритм закрашивания
- •2.Алгоритм разбиения средней точкой
Поворот плоскости и его матричное представление
Ниже речь пойдет о поворотах плоскости. С плоскостью все получается относительно несложно. Если мы делаем поворот относительно начала координат, то для задания вращения используется один угол (φ).
Прим. Принято считать направление вращения против часовой стрелки положительным. При этом удобно считать, что угол φ находится в интервале [–π; π].
Чтобы получить преобразование координат при повороте, возьмем произвольный вектор r, задающий некоторую точку. Его координаты:
При повороте на угол φ:
Т.о. при повороте на угол φ координаты x и y подвергаются преобразованию, написанному выше.
Прим. Здесь фактически была использована полярная система координат.
Матричное представление поворота плоскости
Написанное выше преобразование координат удобно представить в виде матрицы:
Прим. Умножение матриц производится по принципу строка на столбец. Поэтому количество столбцов (элементов в строке) в матрице слева должно совпадать с количеством строк (элементов в столбце) в матрице справа.
Какие преимущества дает матричное представление? Заметим, что если умножить две матрицы, задающие повороты на углы α и β, то получится матрица поворота на угол α + β. Это легко проверить, перемножив соответствующие матрицы и использовав формулы для косинуса и синуса суммы.
Программная реализация
Создадим программу, демонстрирующую приведенную выше теорию. Будем хранить текущий поворот системы, как матрицу и каждый раз ''доворачивать'' систему на нужный угол, используя умножение матриц.
Для начала нам понадобится инструментарий (framework) для работы с матрицами:
matrix.cpp
#include <math.h> #include <memory.h> #include "matrix.h" #include "geometry.h"
void SetRotationMatrix(double alpha, Matrix &matrix) { matrix[0] = cos(alpha); matrix[1] = -sin(alpha); matrix[2] = sin(alpha); matrix[3] = cos(alpha); }
void MultiplyMatrices(Matrix &dest, Matrix &left, Matrix &right) { double ldet = left[0] * left[3] - left[1] * left[2]; double rdet = right[0] * right[3] - right[1] * right[2]; Matrix _dest; _dest[0] = left[0] * right[0] + left[1] * right[2]; _dest[1] = left[0] * right[1] + left[1] * right[3]; _dest[2] = left[2] * right[0] + left[3] * right[2]; _dest[3] = left[2] * right[1] + left[3] * right[3]; memcpy(dest, _dest, sizeof(Matrix)); }
void ApplyMatrixtoPoint(Matrix rot, _Point &point) { double _x, _y; _x = point.x; _y = point.y; point.x = _x * rot[0] + _y * rot[1]; point.y = _x * rot[2] + _y * rot[3]; }
matrix.h
#include "geometry.h"
typedef double Matrix[4];
void SetRotationMatrix(double alpha, Matrix &matrix); void MultiplyMatrices(Matrix &dest, Matrix &left, Matrix &right); void ApplyMatrixtoPoint(Matrix rot, _Point &point);
Прим. Следует обратить ваше внимание на функцию MultiplyMatrices. Во многих случаях в роли dest и left выступает одна и та же матрица. Поэтому, если сразу записывать в dest, то получится некорректно.
Появляется модуль geometry.h и тип ’’точка’’ (_Point):
#ifndef _POINT struct _Point { double x, y; }; #define _POINT #endif
Достаточно существенно меняется модуль draw.cpp. Ниже он приведен целиком.
draw.cpp
#include <windows.h> #include "geometry.h" #include "matrix.h"
int Width, Height; Matrix current_rot;
const int MARGIN = 10;
void InitRotation() { SetRotationMatrix(0.0, current_rot); } void AddRotation(double alpha) { Matrix additional_rot; SetRotationMatrix(alpha, additional_rot); MultiplyMatrices(current_rot, current_rot, additional_rot); } void SetWindowSize(int _Width, int _Height) { Width = _Width; Height = _Height; } _Point T(_Point point) { _Point TPoint; TPoint.x = MARGIN + (1.0 / 2) * (point.x + 1) * (Width - 2 * MARGIN); TPoint.y = MARGIN + (-1.0 / 2) * (point.y - 1) * (Height - 2 * MARGIN); return TPoint; } void Draw(HDC hdc) { _Point triangle[3]; triangle[0].x = 0.0; triangle[0].y = 0.5; triangle[1].x = 0.5; triangle[1].y = 0.0; triangle[2].x = -0.5; triangle[2].y = -0.5; for (int i = 0; i < 3; i++) { ApplyMatrixtoPoint(current_rot, triangle[i]); triangle[i] = T(triangle[i]); } for (int i = 0; i <= 3; i++) { int j = i % 3; if (i == 0) { MoveToEx(hdc, triangle[j].x, triangle[j].y, NULL); } else { LineTo(hdc, triangle[j].x, triangle[j].y); } } }
draw.h
void Draw(HDC hdc); void SetWindowSize(int _Width, int _Height); void InitRotation(); void AddRotation(double alpha);
И наконец в модуле main.cpp добавляется обработчик WM_KEYPRESSED:
case WM_KEYDOWN: int KeyPressed; KeyPressed = int(wParam); if (KeyPressed == VK_RIGHT) { AddRotation(-PI / 10); } if (KeyPressed == VK_LEFT) { AddRotation(PI / 10); } InvalidateRect(hWnd, NULL, FALSE); break;
ИЛИ
Матрицей поворота (или матрицей направляющих косинусов) называется ортогональная матрица, которая используется для выполнения собственного ортогонального преобразования в евклидовом пространстве. При умножении матрицы поворота на вектор длина вектора сохраняется, при этом определитель матрицы поворота положителен (и равен 1).
В отличие от матрицы перехода матрица поворота при умножении на вектор-столбец преобразует координаты вектора в соответствии с поворотом вектора (а не поворотом координатных осей). При этом координаты повернутого вектора получаются в той же (неподвижной) системе координат.