Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ИГС / Lab_02 / labor_02.doc
Скачиваний:
34
Добавлен:
17.04.2018
Размер:
431.1 Кб
Скачать

Пример использования аффинных преобразований для моделирования движения в 2d-графике.

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

Для описания точек траектории введем функцию TrajA(). Пусть траекторией является парабола.

(31)

Уравнение траектории (31) удобно представить в параметрическом виде.

(32)

В этом случае параметр tможно считать временем. Ниже приведено описание функцииTrajA().

//структура для описания точек фигуры

struct Point

{

double x;

double y;

};

//траектория стрелки

Point TrajA(double t)

{

Point P;

P.x = t - 8;

P.y = 4 - (t - 8)*(t - 8)/10;

return P;

}

Теперь нужно описать стрелку. Пусть стрелка определяется 7-ю вершинами.

//координаты вершин стрелки текущие и начальные

Point PtA[7], PtA0[7];

//начальные координаты вершин стрелки

PtA0[0].x = 1.0; PtA0[0].y = 0.0;

PtA0[1].x = 2.0; PtA0[1].y = 0.0;

PtA0[2].x = 0.0; PtA0[2].y = 2.0;

PtA0[3].x = -2.0; PtA0[3].y = 0.0;

PtA0[4].x = -1.0; PtA0[4].y = 0.0;

PtA0[5].x = -1.0; PtA0[5].y = -2.0;

PtA0[6].x = 1.0; PtA0[6].y = -2.0;

Рис. 13.

Начальное положение стрелки.

В процессе движения стрелки координаты вершин Pбудут менять по законам аффинного преобразования.

(33)

Здесь A– матрица соответствующего аффинного преобразования. Приведем описание функцииaffine, которая выполняет аффинные преобразования над вершинами стрелки.

//аффинное преобразование координат точки P с помощью

//матрицы A

Point affine( Matrix2D A, Point P)

{

Point Pp;

Pp.x = A.x[0][0]*P.x + A.x[0][1]*P.y + A.x[0][2]*1;

Pp.y = A.x[1][0]*P.x + A.x[1][1]*P.y + A.x[1][2]*1;

return Pp;

}

Пусть цент стрелки находится в точки C(x1,y1). Нужно совершить поворот стрелки на уголвокруг этого центра. Изменить размеры стрелки относительно этого центра с коэффициентамиkx,ky. Перенести центр стрелки в точкуC*(x2,y2),как показано на Рис.14 .

Рис. 14.

Перенос цента стрелки на вектор трансляции (x2-x1,y2-y1).

Последовательность элементарных аффинных преобразований в этом примере будет следующей.

  1. Переносим стрелку в центр системы координат на вектор (-x1,-y1), с помощью матрицыT1.

  2. Поворачиваем стрелку относительно начала координат на угол с помощью матрицыR.

  3. Сжимаем стрелку относительно начала координат вдоль координатных осей, с коэффициентами kx,ky, с помощью матрицыD.

  4. Совершаем перенос стрелки на вектор трансляции (x2-x1,y2-y1) с помощью матицыT.

  5. Переносим стрелку на вектор (x1,y1), с помощью матрицыT2 в конечное положение.

В результате матрица аффинного преобразования будет найдена путем перемножения указанных матриц.

(34)

Ниже приводится фрагмент кода программы реализующий это аффинное преобразование.

//создаем 6 матриц аффинных преобразований

Matrix2D R, T, D, A, T1, T2;

//создаем матрицы аффинного преобразования

T1.transl(-x1,-y1);

R.rotate(fi);

D.displa(kx, ky);

T.transl(x2-x1,y2-y1);

T2.transl(x1,y1);

A = T2*T*D*R*T1;

//совершаем аффинное преобразование точек фигуры

for(int n=0; n<7; n++)

Pt[n] = affine(A,Pt[n]);

После определения нового положения стрелки, стрелка выводится на экран. Рассмотренное аффинное преобразование и вывод стрелки на экран осуществляется в функции Arrow(). Ниже приведено определение этой функции.

//рисует стрелку по координатам вершин Pt в точке x2, y2

void Arrow(HDC hdc, Point *Pt, int N, double x1,double y1,

double x2,double y2,double fi,double kx,double ky)

{

//создаем матрицы аффинного преобразования

T1.transl(-x1,-y1);

R.rotate(fi);

D.displa(kx, ky);

T.transl(x2-x1,y2-y1);

T2.transl(x1,y1);

A = T2*T*D*R*T1;

//совершаем аффинное преобразование точек фигуры

for(int n=0; n<7; n++)

Pt[n] = affine(A,Pt[n]);

HPEN hpen, hpenOld;

hpen = CreatePen(PS_SOLID,1,RGB(255,255,0));

hpenOld = (HPEN)SelectObject(hdc,hpen);

MoveToEx(hdc, xn(Pt[0].x),ym(Pt[0].y), 0);

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

{

int j = (i + 1)%N;

LineTo(hdc,xn(Pt[j].x),ym(Pt[j].y));

}

SelectObject(hdc,hpenOld);

DeleteObject(hpen);

}

В задачах анимации встречаются два типа графических объектов, динамические объекты и статические объекты. К динамическим объектам применяются аффинные преобразования, и затем эти объекты в измененном виде рисуются на экране. Статические объекты не подвергаются преобразованием. В нашем примере динамическим объектом является стрелка. В качестве статического объекта введем закрашенный эллипс с осями координат.

Статический объект рисуется с помощью функции Land(). Ниже приведено определение этой функции.

//рисует статический объект

void Land(HDC hdc)

{

HBRUSH hbrush, hbrushOld;

HPEN hpen1, hpen2, hpenOld;

hbrush = CreateSolidBrush(RGB(0,200,0));

hbrushOld = (HBRUSH)SelectObject(hdc,hbrush);

hpen1 = CreatePen(PS_SOLID,3,RGB(255,255,255));

hpenOld = (HPEN)SelectObject(hdc,hpen1);

Ellipse(hdc,nLeft+160,mTop+20,nRight-160,mBottom-20);

//рисуем координатные оси

hpen2 = CreatePen(PS_SOLID,1,RGB(0,255,255));

SelectObject(hdc,hpen2);

int nb, ne, mb, me;

nb = xn(xLeft); mb = ym(0);

MoveToEx(hdc, nb, mb, 0);

ne = xn(xRight); me = ym(0);

LineTo(hdc,ne,me);

nb = xn(0); mb = ym(yBottom);

MoveToEx(hdc, nb, mb, 0);

ne = xn(0); me = ym(yTop);

LineTo(hdc,ne,me);

SelectObject(hdc,hpenOld);

DeleteObject(hpen1);

DeleteObject(hpen2);

SelectObject(hdc,hbrushOld);

DeleteObject(hbrush);

}

Соседние файлы в папке Lab_02