Типовая задача, решаемая при помощи растровой изобразительной графики – преобразование изображения в целом и его отдельных фрагментов: перемещение, поворот вокруг заданного центра, изменение линейных размеров и т.п. Такая задача решается использованием аффинных преобразований [1, 2, 3].
Введем несколько определений.
Определение 1. Преобразование плоскости называется аффинным, если оно взаимно однозначно и образом любой прямой является прямая.
Определение 2. Преобразование называется взаимно однозначным, если оно разные точки переводит в разные, и в каждую точку переходит какая-то точка.
Определение 3. Аффинное преобразование – отображение плоскости или пространства в себя, при котором параллельные прямые переходят в параллельные прямые, пересекающиеся в пересекающиеся, скрещивающиеся в скрещивающиеся.
Аффинные преобразования используются в следующих ситуациях:
1. Для составления плоского изображения или трехмерной сцены путем компоновки из однотипных элементов с помощью их копирования, преобразования и перемещения в различные места изображения.
2. Для просмотра трехмерных объектов с различных точек зрения.
3. Для проецирования трехмерных объектов на плоскость и отображения сцены в окне.
Аффинные преобразования на плоскости в общем виде описываются следующими формулами:
(1)
где A, B, C, D, E, F – константы.
Преобразование (1) можно записать в матричной форме
Аффинным преобразованиям может подвергаться как сама система координат, так и объекты на плоскости. Если преобразование производится над системой координат, то значения (х, у) в выражении (1) интерпретируются как координаты точки в старой системе координат, а значения (Х, Y) – координаты точки в новой системе координат.
Частным случаем аффинных преобразований являются просто движения (без какого-либо сжатия или растяжения). Движения – это преобразования, которые сохраняют расстояние между любыми двумя точками неизменным, а именно параллельные переносы, повороты, различные симметрии и их комбинации.
Перемещение в пространстве задается с помощью матрицы размера 3x3. Для этого необходимо использование однородных координат.
Определение 4. Однородные координаты – координаты, обладающие тем свойством, что определяемый ими объект не меняется при умножении всех координат на одно и то же число.
Однородными координатами вектора (х, у) является тройка чисел (x’, y’, h), где х = х’ / h, у = y’/h, а h – некоторое вещественное число (случай, когда h = 0 является особым).
Аналогичные преобразования происходят и для трехмерных объектов. Приведем пример программы, написанной на языке Pascal, которая вращает аббревиатуру «СФУ» и ее части.
program program1;
uses GraphABC;
type
TVector = array [1..4] of Real;
TMatrix = array [1..4, 1..4] of Real;
function Vector(x, y, z: Real): TVector;
begin
Result[1]:=x;
Result[2]:=y;
Result[3]:=z;
Result[4]:=1;
end;
function Vector(x, y: Real): TVector;
begin
Result[1]:=x;
Result[2]:=y;
Result[3]:=0;
Result[4]:=1;
end;
….
procedure DrawLine(a, b: TVector; transform: TMatrix);
begin
ApplyTransform(a, transform);
ApplyTransform(b, transform);
Line(Round(a[1]), Round(a[2]), Round(b[1]), Round(b[2]));
end;
procedure DrawLine(x1, y1, x2, y2: Real; transform: TMatrix);
begin
DrawLine(Vector(x1, y1), Vector(x2, y2), transform);
end;
procedure DrawArc(x, y, r, alf, bet: Real; m: TMatrix);
var
x1, y1, x2, y2: Real;
i, b, e: Integer;
begin
b:=Round(alf/Pi*180);
e:=Round(bet/Pi*180);
if b > e then
begin
i:=b; e:=b; b:=i;
end;
for i:=b to e do
begin
x2:=x+r*cos(i/180*Pi);
y2:=y-r*sin(i/180*Pi);
if i > b then
DrawLine(x1, y1, x2, y2, m);
x1:=x2;
y1:=y2;
end;
end;
var// t – матрица преобразования // p – матрица проекции // m – временная матрица
t, p, m: TMatrix;
//picture: Integer;
begin// Создание матрицы проекции
SetWindowSize(600, 600);
//picture:=CreatePicture(600, 600);
//SetDrawingSurface(picture);
SetPenColor(rgb(255, 128, 0));
SetPenWidth(50);
// Создание матрицы проекции
CreateSimpleProjectionMatrix(100, p);
// Матрица переноса в центр изображения
CreateTranslationMatrix(300, 300, 0, m); MatrixProduct(p, m); // применение матрицы m // Создание матрицы преобразования
IdentityMatrix(t);
CreateScaleMatrix(100, 100, 100, m); MatrixProduct(t, m); ); // Создание и применение матрицы масштабирования к матрице преобразования
CreateZAxisRotationMatrix(-PI / 8, m); MatrixProduct(t, m); // Создание и применение матрицы вращения к матрице преобразования
CreateTranslationMatrix(0, 0, 200, m); MatrixProduct(t, m);
// Объединение матриц преобразования и проекции
CopyMatrix(t, m); // копировать матрицу преобразования в m
MatrixProduct(m, p); // применить матрицу проекции к матрице m // m – готовая матрица преобразования // С
DrawArc(-4, -2, 1, 0, Pi/2, m);
DrawLine(-4, -3, -6, -3, m);
DrawArc(-6, -2, 1, Pi/2, Pi, m);
DrawLine(-7, -2, -7, +2, m);
DrawArc(-6, +2, 1, Pi, Pi*3/2, m);
DrawLine(-6, +3, -4, +3, m);
DrawArc(-4, +2, 1, Pi*3/2, Pi*2, m);
// Ф
DrawLine(+0, +3, +0, -3, m);
DrawArc(-sqrt(2)/2*3/2, -1.5, 3/2, pi*1/4, pi*7/4, m);
DrawArc(+sqrt(2)/2*3/2, -1.5, 3/2, -pi*3/4, pi*3/4, m);
// У
DrawLine(+3, +3, +7, -3, m);
DrawLine(+3, -3, +5, +0, m);
//RestoreDrawingSurface;
//DrawPicture(picture, 0, 0);
//SavePicture(picture, ‘Картинка.bmp’);
end.