42253

Выполнение базовых преобразований на плоскости

Лабораторная работа

Информатика, кибернетика и программирование

Трансляция точки выполняется путем добавления смещения [m n] к ее координатам [x y], в результате чего получается точка с новыми координатами. Для объекта, описываемого множеством точек, все точки объекта перемещаются на одинаковые расстояния вдоль параллельных прямых. В матричной форме трансляция выполняется путем умножения однородных координат точки на матрицу трансляции

Русский

2013-10-28

98.5 KB

3 чел.

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего профессионального образования

«НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ

ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Институт кибернетики

Информационные системы и технологии

Кафедра вычислительной техники

Базовые алгоритмы 2D-геометрии

Отчет по лабораторной работе № 3

по дисциплине  «Компьютерная геометрия и графика»

Студент

гр. 8990             ____________ А.С. Цуркова

                   (подпись)

                                       _    

                      (дата)

Руководитель

доцент каф. ВТ____________ О.С. Токарева

                   (подпись)

                             _

                (дата)

Томск – 2012

Цель работы

Изучить способы выполнения базовых преобразований на плоскости.

Задание

Написать программу, выполняющие следующие функции:

  •  чтение из файла координат вершин многоугольника, заданных в мировой системе координат;
  •  переход от мировых координат к экранным координатам, используя формулы (см. лекции);
  •  отрисовка фигур и осей координат в окне, так чтобы было место для отображения фигур после выполнения геометрических преобразований;
  •  выполнение преобразований над фигурами в соответствии с заданием по командам пользователя (использовать меню, кнопки, горячие клавиши).

Требования:

  •  реализация всех преобразований через перемножение матриц с использованием однородных координат;
  •  равномерное масштабирование реализовать через правый нижний элемент s матрицы преобразований;
  •  для построения эллипса и окружности использовать параметрическое описание;
  •  после выполнения преобразования должна производиться перерисовка содержимого окна (старое изображение заменяется на новое);
  •  необходимо реализовать возврат фигуры в исходное положение по нажатию на кнопку в окне (или при выборе пункта меню);
  •   предусмотреть возможность выполнить композицию преобразований по нажатию одной кнопки.

• Повернуть относительно точки L на 30 градусов по часовой стрелке.

Теоретические положения

В ходе выполнения данной работы были созданы массивы trgl[3][3],okr[9][3],oval[9][3] для хранения точек треугольника, окружности и овала соответственно. Был реализован пересчет мировых координат в экранные: perevod() .

Все преобразования над фигурами были выполнены через перемножение матриц. Были использованы: трансляция, отображение, двухмерный поворот и масштабирование.

Трансляция точки выполняется путем добавления смещения [m n] к ее координатам [x y], в результате чего получается точка с новыми координатами. Для объекта, описываемого множеством точек, все точки объекта перемещаются на одинаковые расстояния вдоль параллельных прямых. В матричной форме трансляция выполняется путем умножения однородных координат точки на матрицу трансляции:

.

Отражение – преобразование, генерирующее зеркальное отображение объекта.

- отражение относительно оси x (y=0),

 - отражение относительно оси y (x=0),

- отражение относительно начала координат,

- отражение относительно оси y=x,

 - отражение относительно оси y=x.

Двумерный поворот – перемещение объекта по круговой траектории на плоскости xoy. В этом случае объект поворачивается относительно оси вращения, перпендикулярной плоскости xoy. Для двумерного поворота задается точка, вокруг которой будет производится поворот и угол вращения. Поворот точки на угол φ вокруг начала координат выполняется путем умножения однородных координат точки на матрицу поворота R:

.

В компьютерной графике поворот на положительный угол φ выполняется против часовой стрелки.

Масштабирование выполняется путем умножения однородных координат точки на матрицу масштабирования S:

, где sx, sy – любые положительные числа, sx – коэффициент масштабирования по x, sy – коэффициент масштабирования по y. При sx>1 и sy>1 масштаб увеличивается, при sx<1 (sx>0) и sy<1 (sy >0)–  уменьшается.

Все преобразования были реализованы в среде C++ Builder при помощи синтаксиса языка C++.

Текст программы

#include <vcl.h>

#include <stdio.h>

#include <math.h>

#pragma hdrstop

#include "lab3.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

float trgl[3][3],okr[9][3],oval[9][3];

float trglR[3][3],okrR[9][3],ovalR[9][3];

void novii();

void trglris();

void okrris();

void ovalris();

void novkord();

void perevod();

int pointpov[1][2];

float matrix[3][3],massiv[42];

void reading();

void multiply();

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void perevod()

{

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

{

 trglR[i][0]=trgl[i][0]*10+Form1->Plosk->Width/2;

 trglR[i][1]=Form1->Plosk->Height/2-trgl[i][1]*10;

}

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

{

 okrR[i][0]=okr[i][0]*10+Form1->Plosk->Width/2;

 okrR[i][1]=Form1->Plosk->Height/2-okr[i][1]*10;

}

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

{

 ovalR[i][0]=oval[i][0]*10+Form1->Plosk->Width/2;

 ovalR[i][1]=Form1->Plosk->Height/2-oval[i][1]*10;

}

}

//---------------------------------------------------------------------------

void trglris()

{

Form1->Plosk->Canvas->MoveTo(trglR[0][0],trglR[0][1]);

Form1->Plosk->Canvas->LineTo(trglR[1][0],trglR[1][1]);

Form1->Plosk->Canvas->LineTo(trglR[2][0],trglR[2][1]);

Form1->Plosk->Canvas->LineTo(trglR[0][0],trglR[0][1]);

}

//--------------------------------------------------------------------------

void okrris()

{

Form1->Plosk->Canvas->MoveTo(okrR[0][0],okrR[0][1]);

for (int i=1;i<8;i++)

{

 Form1->Plosk->Canvas->LineTo(okrR[i+1][0],okrR[i+1][1]);

}

Form1->Plosk->Canvas->LineTo(okrR[0][0],okrR[0][1]);

}

//-------------------------------------------------------------------------

void ovalris()

{

Form1->Plosk->Canvas->MoveTo(ovalR[0][0],ovalR[0][1]);

for (int i=1;i<8;i++)

{

 Form1->Plosk->Canvas->LineTo(ovalR[i][0],ovalR[i][1]);

}

Form1->Plosk->Canvas->LineTo(ovalR[0][0],ovalR[0][1]);

}

//-------------------------------------------------------------------------

void novkord()

{

Form1->Plosk->Canvas->Brush->Color=clWhite;

Form1->Plosk->Canvas->FillRect(Form1->Canvas->ClipRect);

Form1->Plosk->Canvas->Rectangle((pointpov[0][0]*10+Form1->Plosk->Width/2)

       ,(Form1->Plosk->Height/2-pointpov[0][1]*10)

       ,(pointpov[0][0]*10+Form1->Plosk->Width/2)+3

       ,(Form1->Plosk->Height/2-pointpov[0][1]*10)+3);

Form1->Plosk->Canvas->MoveTo(0,(Form1->Plosk->Height)/2);

Form1->Plosk->Canvas->LineTo(Form1->Plosk->Width,(Form1->Plosk->Height)/2);

int incr=0;

for (int i=(Form1->Plosk->Width)/2;;incr=incr+10)

{

 if (((i-incr)>=0)&&((i+incr)<=(Form1->Plosk->Width)))

   {

 Form1->Plosk->Canvas->MoveTo(i-incr,(Form1->Plosk->Height)/2-3);

 Form1->Plosk->Canvas->LineTo(i-incr,(Form1->Plosk->Height)/2+3);

 Form1->Plosk->Canvas->MoveTo(i+incr,(Form1->Plosk->Height)/2-3);

 Form1->Plosk->Canvas->LineTo(i+incr,(Form1->Plosk->Height)/2+3);

   }

 else break;

}

Form1->Plosk->Canvas->MoveTo(Form1->Plosk->Width-10,(Form1->Plosk->Height)/2-4);

Form1->Plosk->Canvas->LineTo(Form1->Plosk->Width,(Form1->Plosk->Height)/2);

Form1->Plosk->Canvas->MoveTo(Form1->Plosk->Width-10,(Form1->Plosk->Height)/2+4);

Form1->Plosk->Canvas->LineTo(Form1->Plosk->Width,(Form1->Plosk->Height)/2);

//---------------------------------------------------------//

Form1->Plosk->Canvas->MoveTo((Form1->Plosk->Width)/2,0);

Form1->Plosk->Canvas->LineTo((Form1->Plosk->Width)/2,Form1->Plosk->Height);

incr=0;

for (int i=(Form1->Plosk->Height)/2;;incr=incr+10)

{

 if (((i-incr)>=0)&&((i+incr)<=(Form1->Plosk->Height)))

   {

 Form1->Plosk->Canvas->MoveTo((Form1->Plosk->Width)/2-3,i-incr);

 Form1->Plosk->Canvas->LineTo((Form1->Plosk->Width)/2+3,i-incr);

 Form1->Plosk->Canvas->MoveTo((Form1->Plosk->Width)/2-3,i+incr);

 Form1->Plosk->Canvas->LineTo((Form1->Plosk->Width)/2+3,i+incr);

   }

 else break;

}

Form1->Plosk->Canvas->MoveTo((Form1->Plosk->Width)/2-4,10);

Form1->Plosk->Canvas->LineTo((Form1->Plosk->Width)/2,0);

Form1->Plosk->Canvas->MoveTo((Form1->Plosk->Width)/2+4,10);

Form1->Plosk->Canvas->LineTo((Form1->Plosk->Width)/2,0);

}

//-----------------------------------------------------------------------------

void novii()

{

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

 for(int j=0;j<3;j++)matrix[i][j]=0;

trgl[0][0]=massiv[0]; trgl[0][1]=massiv[1];

trgl[1][0]=massiv[2];   trgl[1][1]=massiv[3];

trgl[2][0]=massiv[4];   trgl[2][1]=massiv[5];

okr[0][0]=massiv[6];   okr[0][1]=massiv[7]; okr[0][2]=1;

okr[1][0]=massiv[8];   okr[1][1]=massiv[9]; okr[1][2]=1;

okr[2][0]=massiv[10];   okr[2][1]=massiv[11]; okr[2][2]=1;

okr[3][0]=massiv[12];   okr[3][1]=massiv[13]; okr[3][2]=1;

okr[4][0]=massiv[14];   okr[4][1]=massiv[15]; okr[4][2]=1;

okr[5][0]=massiv[16];   okr[5][1]=massiv[17]; okr[5][2]=1;

okr[6][0]=massiv[18];   okr[6][1]=massiv[19]; okr[6][2]=1;

okr[7][0]=massiv[20];   okr[7][1]=massiv[21]; okr[7][2]=1;

okr[8][0]=massiv[22];   okr[8][1]=massiv[23]; okr[8][2]=1;

oval[0][0]=massiv[24];   oval[0][1]=massiv[25]; oval[0][2]=1;

oval[1][0]=massiv[26];   oval[1][1]=massiv[27]; oval[1][2]=1;

oval[2][0]=massiv[28];   oval[2][1]=massiv[29]; oval[2][2]=1;

oval[3][0]=massiv[30];   oval[3][1]=massiv[31]; oval[3][2]=1;

oval[4][0]=massiv[32];   oval[4][1]=massiv[33]; oval[4][2]=1;

oval[5][0]=massiv[34];   oval[5][1]=massiv[35]; oval[5][2]=1;

oval[6][0]=massiv[36];   oval[6][1]=massiv[37]; oval[6][2]=1;

oval[7][0]=massiv[38];   oval[7][1]=massiv[39]; oval[7][2]=1;

pointpov[0][0]=massiv[40]; pointpov[0][1]=massiv[41];

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)

{

reading();

pointpov[0][0]=1; pointpov[0][1]=-2;

novkord();

novii();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::retrnClick(TObject *Sender)

{

Form1->Plosk->Canvas->Brush->Color=clWhite;

Form1->Plosk->Canvas->FillRect(Canvas->ClipRect);

novkord();

novii();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::SdvigVNClick(TObject *Sender)

{

Form1->Canvas->Brush->Color=clBlack;

novkord();

matrix[0][0]=1;

matrix[0][1]=0;

matrix[1][0]=0;

matrix[1][1]=1;

matrix[0][2]=0;

matrix[1][2]=0;

if(Form1->CheckBox1->Checked==true)matrix[2][1]=2;

else matrix[2][1]=-2;

matrix[2][0]=0;

matrix[2][2]=1;

trgl[0][2]=1;

trgl[1][2]=1;

trgl[2][2]=1;

multiply();

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::SdvigPLClick(TObject *Sender)

{

Form1->Canvas->Brush->Color=clBlack;

novkord();

matrix[0][0]=1;

matrix[0][1]=0;

matrix[1][0]=0;

matrix[1][1]=1;

matrix[0][2]=0;

matrix[1][2]=0;

if(Form1->CheckBox2->Checked==true)matrix[2][0]=2;

else matrix[2][0]=-2;

matrix[2][1]=0;

matrix[2][2]=1;

trgl[0][2]=1;

trgl[1][2]=1;

trgl[2][2]=1;

multiply();

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::povorotClick(TObject *Sender)

{

novkord();

double ugol;

ugol=M_PI/6;

matrix[0][0]=cos(ugol);

matrix[0][1]=-sin(ugol);

matrix[1][0]=sin(ugol);

matrix[1][1]=cos(ugol);

matrix[0][2]=0;

matrix[1][2]=0;

matrix[2][0]=-pointpov[0][0]*cos(ugol)-pointpov[0][1]*sin(ugol)+pointpov[0][0];

matrix[2][1]=pointpov[0][0]*sin(ugol)-pointpov[0][1]*cos(ugol)+pointpov[0][1];

matrix[2][2]=1;

trgl[0][2]=1;

trgl[1][2]=1;

trgl[2][2]=1;

multiply();

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::OtrXClick(TObject *Sender)

{

Form1->Plosk->Canvas->Pen->Color=clWhite;

perevod();

trglris();

okrris();

ovalris();

matrix[0][0]=1;

matrix[0][1]=0;

matrix[1][0]=0;

matrix[1][1]=-1;

multiply();

Form1->Plosk->Canvas->Pen->Color=clBlack;

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::otrYClick(TObject *Sender)

{

Form1->Plosk->Canvas->Pen->Color=clWhite;

perevod();

trglris();

okrris();

ovalris();

matrix[0][0]=-1;

matrix[0][1]=0;

matrix[1][0]=0;

matrix[1][1]=1;

multiply();

Form1->Plosk->Canvas->Pen->Color=clBlack;

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::ScaleClick(TObject *Sender)

{

Form1->Plosk->Canvas->Pen->Color=clWhite;

perevod();

trglris();

okrris();

ovalris();

matrix[0][1]=0;

matrix[1][0]=0;

if (Form1->CheckBox3->Checked==true)

  {

matrix[0][0]=2.0;

matrix[1][1]=2.0;

  }

else

  {

matrix[0][0]=0.5;

matrix[1][1]=0.5;

  }

multiply();

Form1->Plosk->Canvas->Pen->Color=clBlack;

perevod();

trglris();

okrris();

ovalris();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)

{

if(Key=='1')Form1->retrnClick(Sender);

if(Key=='2')Form1->povorotClick(Sender);

if(Key=='3')Form1->SdvigVNClick(Sender);

if(Key=='4')Form1->SdvigPLClick(Sender);

if(Key=='5')Form1->OtrXClick(Sender);

if(Key=='6')Form1->otrYClick(Sender);

if(Key=='7')Form1->ScaleClick(Sender);

}

//---------------------------------------------------------------------------

void reading()

{

TFileStream *file=new TFileStream("figuri.dat",fmOpenRead);

TStringList *list=new TStringList;

list->LoadFromStream(file);

AnsiString Spisok=list->Text;

delete list;

delete file;

AnsiString temp="";

int mas[42],i1=0;

for (int i = 0; i < (Spisok.Length()-2); i++)

{

 if ((Spisok.c_str()[i] != ' '))

   temp=temp+Spisok.c_str()[i];

 else

 {

  mas[i1] = StrToInt(temp);

  temp = "";

  i1++;

 }

}

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

   massiv[i]=mas[i]/10;

}

//----------------------------------------------------------------------------

void multiply ()

{

float tmpshape[3][3];

for (int k = 0; k < 3; k++)

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

{

  tmpshape[k][i] = 0;

  for (int j = 0; j < 3; j++)

  {

 tmpshape[k][i] =tmpshape[k][i]+ matrix[j][i]*trgl[k][j];

  }

}

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

for (int j = 0; j < 2; j++) trgl[i][j]=tmpshape[i][j];

float tmpokr[9][3];

 for (int k = 0; k < 9; k++)

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

{

  tmpokr[k][i] = 0;

  for (int j = 0; j < 3; j++)

  {

 tmpokr[k][i] =tmpokr[k][i]+ matrix[j][i]*okr[k][j];

  }

}

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

for (int j = 0; j < 2; j++) okr[i][j]=tmpokr[i][j];

 float tmpoval[9][3];

 for (int k = 0; k < 9; k++)

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

{

  tmpoval[k][i] = 0;

  for (int j = 0; j < 3; j++)

  {

 tmpoval[k][i] =tmpoval[k][i]+ matrix[j][i]*oval[k][j];

  }

}

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

for (int j = 0; j < 2; j++) oval[i][j]=tmpoval[i][j]

}

ВЫВОД

В ходе выполнения лабораторной работы было получено представление об основных преобразованиях плоских фигур. Это было реализовано через перемножение матриц с использованием однородных координат, без накопления ошибок в исходной матрице. Использование матриц является очень удобным т.к. все изменения происходят путем их перемножения, следовательно, это не требует сложных математических преобразований, достаточно реализовать функцию перемножения матриц.   В соответствии с заданием была выполнена работа по преобразованию окружности, овала и треугольника (перенос, отражение, масштабирование, поворот).


 

А также другие работы, которые могут Вас заинтересовать

74424. Осевой цилиндр корня 39 KB
  В осевом цилиндре корня можно различать сложный радиальный проводящий пучок и паренхиму ткань периферическая часть которой в виде кольца клеток называется перициклом рис. Эти клетки удлиняются в радиальном направлении делятся тангентальными перегородками и образуют корнеродную дугу со слоями клеток функционирующими по тому же типу как в кончике корня. Заложение боковых корешков происходит весьма близко к конусу нарастания образующего их корня выход же их наружу на значительном расстоянии.
74425. Строение типичного зеленого листа 58 KB
  В пластинке листа уже с помощью лупы можно различить 4 группы тканей: 1 покровную кожицу или эпидермис; 2 основную питательную мезофилл1; 3 проводящую сосудистоволокнистые пучки жилки; 4 механическую придающую листу жесткость определяющую положение листа в пространстве. Эпидермис стебля переходит на черешок и пластинку листа. Местами преимущественно на нижней стороне листа в эпидермисе находятся устьица.
74426. Флоэма 39 KB
  При изучении формирования члеников ситовидной трубки можно видеть что сначала членик представляет живую тонкостенную клетку с протоплазмой ядром лейкопластами и центральной вакуолей через полость которой проходят тяжи протоплазмы. Клетка членик ситовидной трубки растет; замыкающие пленки пор при этом растягиваются утоньшаются; в них образуются мелкие перфорации; в остальной части клеточная оболочка значительно утолщается под микроскопом она сильно блестит. Денатурация протоплазмы обнаруживается тем что членики трубки уже не...
74427. Бесполое и половое размножение хвощей 29 KB
  Благодаря этим лентам споры обычно сцепляются в рыхлые комочки разносимые ветром из вскрывшихся спорангиев и заростки развивающиеся из спор бывают скучены группами. Раньше заростки хвощей считали раздельнополыми: одни более мелкие только с антеридиями другие более крупные только с архегониями. Однако в недавнее время у некоторых видов были обнаружены и обоеполые заростки. Возможно что они потенциально обоеполы у многих видов и что кажущаяся их однополость объясняется неодновременностью развития архегониев и антеридиев архегонии...
74428. ЧЕРЕДОВАНИЕ ПОЛОВОГО И БЕСПОЛОГО ПОКОЛЕНИЙ И СМЕНА ЯДЕРНЫХ ФАЗ 37.5 KB
  У большинства же зигота немедленно начинает делиться и образует новое растение или зародыш его; последний у семенных растений временно задерживается в дальнейшем развитии. У большинства оно способно размножаться вегетативно; кроме того у очень многих растений на нем или в нем образуются бесполым путем специальные клетки служащие для размножения носящие нередко различные названия и объединяемые под общим наименованием спор бесполого размножения. Каждый вид растений характеризуется определенным диплоидным и вдвое меньшим гаплоидным числом...
74429. Эпиблема (волосконосный слой) 31 KB
  На расстоянии 0110 мм обычно на расстоянии 123 мм от крайней точки корня клетки эпиблемы начинают образовывать корневые волоски. Корневые волоски многих травянистых растений длиннее чем у большинства древесных пород. При свободном росте при развитии корней в воде или во влажном воздухе волоски имеют форму цилиндра или конуса с закруглением на конце. Корневые волоски играют и механическую роль давая опору верхушке корня пробивающейся при росте между частицами почвы и способствуя заякориванию корневой системы в земле.
74430. Бесполое и половое размножение равноспоровых папоротников 31.5 KB
  Стенка спорангиев однослойная; содержимое их археспорий образует после редукционного деления клеточных ядер многочисленные темные споры служащие для бесполого размножения папоротников. Раскрывание созревших и начинающих подсыхать спорангиев происходит у громадного большинства папоротников при содействии группы клеток его стенок расположенных у многих кольцом и имеющих частичные утолщения...
74431. Бесполое и половое размножение разноспоровых, или водяных, папоротников 31.5 KB
  У некоторых разноспоровых папоротников а также других представителей высших споровых растений селагинелл изоэтеса произошла еще большая редукция мужских и женских заростков а также потеря и женским гаметофитом способности к фотосинтезу. У селагинелл близких к плаунам мега и микроспорофиллы собраны в колоски; мегаспоры прорастают в мегаспорангиях еще на материнском растении; у некоторых видов микроспоры переносятся на мегаспорофиллы и мегаспорангии где происходит оплодотворение начинается развитие зародыша и мегаспорангии отпадает...
74432. ПОЛОВОЕ РАЗМНОЖЕНИЕ СЕМЕННЫХ РАСТЕНИЙ 31 KB
  Для рассеивания распространения растения служат следовательно не споры как у типичных споровых растений а семена; бесполого размножения спорами нет чередование поколений выражено неясно и выявляется лишь путем сравнительноморфологических и цитологических исследований. Спорофиллы покрытосеменных растений тесно скученные на концах побегов и у большинства окруженные еще метаморфизированными верхушечными листьями образуют вместе с ними цветок; мы можем охарактеризовать его как укороченный побег листья которого метаморфизированы в связи с...