Двумерные преобразования координат
Преобразование координат графических объектов используется с целью модификации, зеркального отображения и перемещения объекта. Основные случаи :
- преобразование системы координат, например, из полярной в декартову,
- изображение типовых или повторяющихся деталей объекта,
- построение проекций трехмерных объектов,
- направленная деформация при синтезе новых форм,
- мультипликация и создание узоров.
Различают двумерные ( 2D ) и трехмерные ( 3D) преобразования. Рассмотрим двумерные аффинные преобразования, когда в получаемом новом изображении объекта сохраняется прямолинейность и параллельность прямых, а также деление отрезков в заданных соотношениях.
Общий вид формул двумерных аффинных преобразований:
x1= a11 x + a12 y + a13 или в x1a11 a12 a13 x
матричном y1= a21 a22 a23 * y
y1= a21 x + a22 y + a23 виде: z1 0 0 1z
Здесь x, y - координаты исходного, а x1, y1 - преобразованного объекта.
Коэффициенты преобразований a I J сохраняют в виде матрицы, расширенной до квадратной, - при для вычисления коэффициентов составного преобразования перемножают соответствующие матрицы коэффициентов типовых преобразований.
Примеры типовых преобразований и соответствующие им матрицы:
( Ф - исходная фигура, Ф1 - преобразованная )
Y
dx Ф1 Параллельный 1 0 dx
dy перенос 0 1 dy
Ф 0 0 1
X
Y
Ф1 Масштабирование Sx 0 0
Sx = x1/x; Sy = y1/y 0 Sy 0
Ф 0 0 1
X
Y
Ф1
Поворот относительно cos a -sin a 0
начала координат sin a cos a 0
Ф 0 0 1
a
X
Зеркальное отображение:
Y
Ф1 cos(2*A) sin(2*A) 0
относительно оси Y=Х sin(2*A) - cos(2*a) 0
Ф проходящей под углом “A” 0 0 1
0 X
Ф1 относительно начала -1 0 0
координат 0 -1 0
0 0 1
Y
Y1
a Ф1
Деформация сдвига : 1 tg(a) 0
Ф X1 в направлении X - a tg(b) 1 0
в направлении Y - b 0 0 1
b
X
Составные преобразования обычно представляют в виде комбинаций типовых преобразований. Например, поворот относительно произвольной точки ( Xc, Yc) можно представить как комбинацию трех преобразований:
- параллельный перенос, переводящий центр поворота в начало координат,
- поворот относительно начала координат,
- параллельный перенос, противоположный первоначальному.
Перемножение матриц выполняется следующим образом:
a11 a12 a13 b11 b12 b13 c11 c12 c13
a21 a22 a23 * b21 b22 b23 = c21 c22 c23
a31 a32 a33 b31 b32 b33 c31 c32 c33
где cI J = aI 1* b1 J + aI 2* b2 J + aI 3* bJ 3 , i= 1, 2, 3; j= 1, 2, 3.
то есть элемент матрицы “C”, расположенный в I-строке и J-столбце, равен сумме произведений элементов I -ой строки матрицы “A“ на соответствующие элементы J-го столбца матрицы B.
В приведенной ниже программе плоская фигура задается в виде линий, последовательно соединяющих координаты массива точек (xa, ya) на чертеже ( x, y - в системе координат экрана ). Эти координаты подвергаются аффинным преобразованиям, коэффициенты преобразования хранятся в двумерном массиве r. Начальному положению фигуры соответствует единичная матрица R (единицы на главной диагонали, остальные члены - нули). При очередном преобразовании коэффициенты матрицы R пересчитываются путем умножения на нее матрицы этого преобразования (А), получаемая матрица (В) снова записывается в R. Новые координаты x, y высчитываются в процедуре NEW_XY, которая вызывается непосредственно при выводе фигуры на экран процедурой PICTURE.
uses Graph, Crt;{------- Аффинные преобразования плоских фигур -------- }
var Gd,Gm,n,i,j,k,l,m,xc,yc,xc1,yc1: integer;{-- описание --}
{ глобальных переменных}
xa, ya: array[1..50] of real;{ исходные координаты фигуры }
x, y : array[1..50] of integer;{ новые координаты фигуры }
a, b, r: array[1..3, 1..3] of real; { массивы коэффициентов матриц 3*3 }
PROCEDURE I_R; {-------- присвоение матрице R значения единичной ---------}
Begin
for i:=1 to 3 do begin { 1 0 0 }
for j:=1 to 3 do r[i, j]:=0; { 0 1 0 }
r[i, i]:=1; end; { 0 0 1 }
end;
PROCEDURE MULT; {---------- умножение матриц А и R: R = B = A*R ------------}
var z: real;
Begin
for i:=1 to 3 do
for j:=1 to 3 do begin z:=0;
for k:=1 to 3 do z:=z+a[i,k]*r[k,j];
b[i,j]:=z end;
for i:=1 to 3 do
for j:=1 to 3 do r[i,j]:=b[i,j] end;
PROCEDURE MOVE(dx,dy:real); {----расчет матриц А и R для переноса фигуры ---}
begin { ---на dx, dy--- }
for i:=1 to 3 do begin { 1 0 dx }
for j:=1 to 3 do a[i,j]:=0; { 0 1 dy }
a[i,i]:=1 end; { 0 0 1 }
a[1,3]:=dx; a[2,3]:=dy;
MULT; end;
PROCEDURE SCALE(sx,sy:real); {-расчет матриц А и R для масштабирования ----}
begin{--фигуры: по оси Х - умножение на sx, по оси Y - на sy --}
for i:=1 to 3 do
for j:=1 to 3 do a[i,j]:=0; { sx 0 0 }
a[1,1]:=sx; { 0 sy 0 }
a[2,2]:=sy; a[3, 3]:=1; { 0 0 1 }
MULT; end;
PROCEDURE ROTATE(alfa: real);{- расчет матриц А и R для поворота фигуры--}
var c, s: real; {---на угол alfa(рад)---}
begin { cos(alfa) -sin(alfa) 0 }
for i:=1 to 3 do { sin(alfa) cos(alfa) 0 }
for j:=1 to 3 do a[i,j]:=0; { 0 0 1 }
a[3,3]:=1;
c:=cos(alfa); a[1,1]:= c; a[2,2]:=c;
s:=sin(alfa); a[1,2]:=-s; a[2,1]:=s;
MULT; end;
PROCEDURE MIRROR(alfa: real);{---- расчет матриц А и R для зеркального ----}
var c, s: real; {----отражения объекта на угол alfa(рад)--}
begin { cos(2*alfa) sin(2*alfa) 0 }
for i:=1 to 3 do { sin(2*alfa) -cos(2*alfa) 0 }
for j:=1 to 3 do a[i,j]:=0; { 0 0 1 }
a[3,3]:=1;
c:=cos(2*alfa); a[1,1]:=c; a[2,2]:=-c;
s:=sin(2*alfa); a[1,2]:=s; a[2,1]:=s;
MULT; end;
PROCEDURE AXES(alfa,beta:real); {расчет матриц А и R сдвига осей координат }
{--- ось x смещается на угол alfa, ось y - на угол beta --}
Begin
for i:=1 to 3 do begin { 1 tg(beta) 0 }
for j:=1 to 3 do a[i,j]:=0; { tg(alfa) 1 0 }
a[i,i]:=1 end; { 0 0 1 }
a[1,2]:=sin(beta)/cos(beta);
a[2,1]:=sin(alfa)/cos(alfa); MULT;
end;
PROCEDURE NEW_XY; {---- расчет новых координат фигуры по исходным ------ }
begin{----- с использованием матрицы преобразования R ------}
for i:=1 to n do begin
x[i]:=round( xa[i]*r[1, 1]+ ya[i]*r[1, 2]+ r[1, 3] );
y[i]:=round( xa[i]*r[2, 1]+ ya[i]*r[2, 2]+ r[2, 3] ) end;
end;
PROCEDURE PICTURE;{--- рисование фигуры по координатам X, Y --- }
begin moveto(x[n], y[n]);
for i:=1 to n do lineto(x[i], y[i]);
end;
PROCEDURE ROT_XY(xc,yc,beta:real);{- поворот фигуры вокруг точки ( хс, ус)--}
begin{-- на угол beta --}
MOVE(-xc, -yc); { Смещение центра поворота в центр начала координат }
ROTATE(beta); { поворот относительно начала координат }
MOVE(xc, yc);{ обратное смещение фигуры }
end;
{------примеры аффинных преобразований исходной фигуры ------}
Var alfa: real;
BEGIN n:=4;{ число вершин фигуры }
m:=12;{ число зеркальных отображений фигуры }
xc:=5; yc:=5;{"центр" фигуры}
xa[1]:=5; ya[1]:=5;{ координаты вершин фигуры на чертеже }
xa[2]:=70; ya[2]:=20;
xa[3]:=15; ya[3]:=55; 0 X
xa[4]:=20; ya[4]:=20;
Gd:= Detect;
InitGraph(Gd, Gm, 'C:\tp7\bgi'); Y
xc1:=GetMaxX div 2; yc1:=GetMaxY div 2;{ центр экрана }
I_R; NEW_XY;{ исходные координаты фигуры }
SetWriteMode(1);
{-------------- Вращение вокруг смещающегося центра -----------}
for l:=1 to 150 do begin
PICTURE;
xc:=xc+3; yc:=yc+2; putpixel(xc, yc, 12);{ смещение центра xc, yc }
MOVE(3,2); { перенос фигуры соответственно смещению центра }
ROT_XY(xc, yc, -0.3);{ поворот на 0.3 рад относительно xc, yc }
delay(2); PICTURE; NEW_XY;
end;
readln; ClearDevice;
SetWriteMode(0);
{--------- Зеркальные отображения фигуры -------------}
I_R; PICTURE;
for i:=1 to n do begin
xa[i]:=x[i]; ya[i]:=y[i] end; {задание исходных координат фигуры}
for l:=1 to m do begin alfa:=2*Pi*(l-1)/m;{угол наклона зеркала к оси X}
{ Line(xc1-round(xc1*cos(alfa)), yc1-round(xc1*sin(alfa)),
xc1+round(xc1*cos(alfa)), yc1+round(xc1*sin(alfa)));{линия зеркала}
MOVE(-xc1,-yc1); MIRROR(alfa); MOVE(xc1,yc1); { преобразования}
NEW_XY; PICTURE;{ расчет и рисование новых координат фигуры}
end;
readln;
CloseGraph;
END.
В первой части программы фигура вращается вокруг точки, перемещающейся по диагонали экрана. Во второй части программы фигура последовательно отображается вокруг осей, проходящих через центр экрана.
Дата добавления: 2016-06-29; просмотров: 1499;