Полная версия

Главная arrow Информатика arrow Компьютерная Графика arrow
Построение программы, реализующей трехмерное преобразование с тетраэдром

  • Увеличить шрифт
  • Уменьшить шрифт


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


Фигура должна отображаться в контурном виде без удаления невидимых линий и уметь вращаться вокруг произвольной оси. Управление преобразованием по осям осуществлять с помощью девяти клавиш (<1>…<9>) на цифровой клавиатуре.

Отражение одновременно относительно плоскостей XOZ и YOZ, XOZ иXOY, XOYи YOZ

Описание метода решения задачи

Первоначально отображается тетраэдр с координатами. Все координаты хранятся в массиве.

(350;205;0;1) (400;220;0;1) (460;190;0;1) (420;120;0;1)

Далее в зависимости от выбора тетраэдр отображается относительно выбранных плоскостей или осуществляет вращение.

Отражение относительно плоскостей

Первоначально происходит обнуление матрицы преобразования, т.к. основные компоненты матрицы, это нули.

for i:=1 to 4 do {stolbec} {Obnulenie matrici preobrazovania}

for j:=1 to 4 do MatPreob[i,j]:=0; {stroka}

Далее в зависимости от необходимых преобразований расставляются значения главной диагонали и коэффициента сдвига.

Например для XOZ

MatPreob[1,1]:=1;MatPreob[2,2]:=-1;MatPreob[3,3]:=1;MatPreob[4,4]:=1;MatPreob[4,2]:=500;я первоначальные координаты

В результате проделанных операций поучается следующая матрица:

В нашем случае первоначальные координаты, четырех вершин имеют вид:

a[1]:=350;a[2]:=205;a[3]:=0;a[4]:=1; (350,205,0,1)

b[1]:=400;b[2]:=220;b[3]:=0;b[4]:=1; (400,220,0,1)

c[1]:=460;c[2]:=190;c[3]:=0;c[4]:=1; (460,190,0,1)

d[1]:=420;d[2]:=120;d[3]:=0;d[4]:=1; (420,120,0,1)

В результате преобразований происходит следующее:

Умножаем координаты тетраэдра на матрицу перехода.

В результате имеем преобразования относительно XOZ. Но ведь на экране монитора координата -205 не будет видна, поэтому ее необходимо сдвинуть относительно осиOY. Т.к. осьOXпроходит через координаты (0, 250), то путем не хитрых вычислений сдвигать необходимо на 500.

В результате матрицу преобразований удобнее записать следующим образом.

В результате все координаты будут преобразоваться аналогично примеру.

Вращение

Рассмотрим вращение на примере одной из координат.

Первоначально имеем точку с вершиной (350,205,0,1). Для осуществления ее вращения на 1? используем матрицу преобразования. Т.к. по заданию вращение необходимо произвести вокруг произвольной оси, возьмем точку с координатами (410,180)

Как известно ,

Таким образом для поворота точки в пространстве на 1? имеем следующую матрицу:

Далее для преобразование нашей точки необходимо, ее перемножить с матрицей преобразования:

Остается только убрать дробную часть и соединить все вершины линиями.

Для осуществления эффекта вращения используем задержку.

После запуска программы, на экран выводится меню:

  • 1: Obshi vid
  • 2: XOZ end YOZ
  • 3: XOZ end XOY
  • 4: XOY end YOZ
  • 5: Vrashenie
  • 6: Exit

Меню не на русском. Не знаю, как сделать в графическом режиме русский язык.

Выбрав требуемый пункт, видим отражение относительно выбранных плоскостей. Если нажать вращение, то тетраэдр будет вращаться, периодически делая запрос, остановится или продолжить.

Листинг исходного кода

program setfill;

uses crt, Graph;

var ch:char;

grDriver:integer; {Графический режим}

grMode:integer;

grPath:string;

a,b,c,d:array[1..4] of integer; {Массивы – координаты вершин тетраэдра}

koord:array[1..4] of real; {Массив с координатами той вершины для которой осуществляется преобразования}

MatPreob:array[1..4,1..4] of real; {Массив для хранения матрицы преобразования}

rez:array[1..4] of real; {Результат преобразований }

x1,x2,y1,y2:integer; {Координаты вершин, для их прорисовки}

i,j:integer; {Счетчик}

vr:integer; {Переменная для расчетов при умножении матрицы на матрицу}

procedure ossim; {Процедура выводящая на экран ось симметрии}

begin

OutTextXY(600,260, 'X');

OutTextXY(310,10, 'Y');

OutTextXY(100,460, 'Z');

OutTextXY(300,260, 'O');

line(300,10,300,250);{Y}

line(300,250,600,250);{X}

line(300,250,100,450); {Z}

end;

procedure graphika; {Процедура подключающая графические возможности}

begin

grDriver:=VGA;

grmode:=VGAHi;

grPath:='e:progTp7BGI';

initGraph(grDriver, grMode, grPath);

end;

procedure vivod; {Вывод на экран основного меню для выбора отображения или вращения}

begin

gotoxy(25,6); writeln('1: Obshi vid');

gotoxy(25,8);writeln('2: XOZ end YOZ');

gotoxy(25,10);writeln('3: XOZ end XOY');

gotoxy(25,12);writeln('4: XOY end YOZ');

gotoxy(25,14);writeln('5: Vrashenie');

gotoxy(25,16);writeln('6: Exit');

end;

procedure obsh; {Процедура создающая ребра тетраэдра}

begin

line(b[1],b[2],c[1],c[2]);

line(b[1],b[2],a[1],a[2]);

line(a[1],a[2],c[1],c[2]);

line(a[1],a[2],d[1],d[2]);

line(b[1],b[2],d[1],d[2]);

line(c[1],c[2],d[1],d[2]);

end;

procedure preobraz; {Процедура осуществляющая умножение матрицы с координатами, на матрицу преобразования}

var schet:real;

begin

for i:=1 to 4 do

begin

schet:=0;

for j:=1 to 4 do

begin

schet:=schet+(koord[j]*MatPreob[j,i]);

end;

rez[i]:=schet;

end;

end;

procedure coordinat; {Процедура хранящая первоначальные координаты тетраэдра}

begin

a[1]:=350;a[2]:=205;a[3]:=0;a[4]:=1;

b[1]:=400;b[2]:=220;b[3]:=0;b[4]:=1;

c[1]:=460;c[2]:=190;c[3]:=0;c[4]:=1;

d[1]:=420;d[2]:=120;d[3]:=0;d[4]:=1;

end;

procedure izmen; {Процедура в которой присваиваются новые координаты вершин после преобразования}

begin

for i:=1 to 4 do koord[i]:=a[i];

preobraz; for i:=1 to 4 do a[i]:=round(rez[i]);

for i:=1 to 4 do koord[i]:=b[i];

preobraz; for i:=1 to 4 do b[i]:=round(rez[i]);

for i:=1 to 4 do koord[i]:=c[i];

preobraz; for i:=1 to 4 do c[i]:=round(rez[i]);

for i:=1 to 4 do koord[i]:=d[i];

preobraz; for i:=1 to 4 do d[i]:=round(rez[i]);

end;

procedure XOZ; {Отображение относительноXOZ}

begin

coordinat;

{Создание матрицы перехода}

for i:=1 to 4 do {stolbec} {Обнуление}

for j:=1 to 4 do MatPreob[i,j]:=0;

MatPreob[1,1]:=1;MatPreob[2,2]:=-1;MatPreob[3,3]:=1;MatPreob[4,4]:=1;MatPreob[4,2]:=500; {расстановка цифр в матрицы не равных нулю}

izmen;

obsh;

end;

procedure YOZ; {Аналогично предыдущей процедуре, только со своей матрицей перехода}

begin

coordinat;

for i:=1 to 4 do {stolbec}

for j:=1 to 4 do MatPreob[i,j]:=0;

MatPreob[1,1]:=-1;MatPreob[2,2]:=1;MatPreob[3,3]:=1;MatPreob[4,4]:=1;MatPreob[4,1]:=600;

izmen;

obsh;

end;

procedure XOY; {Аналогично предыдущей}

begin

coordinat;

for i:=1 to 4 do {stolbec}

for j:=1 to 4 do MatPreob[i,j]:=0;

MatPreob[1,1]:=1;MatPreob[2,2]:=1;MatPreob[3,3]:=-1;MatPreob[4,4]:=1;MatPreob[4,1]:=0;

izmen;

obsh;

end;

{Основная программа}

begin

repeat

clrscr;

vivod;

ch:=readkey;

if (ord(ch)=49) then {Вывод общего вида}

begin

graphika;

XOY;

ossim;

obsh;

OutTextXY(440,10, 'Obshi vid');

OutTextXY(440,450, 'For exit fire ENTER');

readln;

closeGraph;

end;

if (ord(ch)=50) then {2 Отражение относительно XOZ end YOZ}

begin

graphika;

OutTextXY(440,10, '2: XOZ end YOZ');

OutTextXY(440,450, 'For exit fire ENTER');

XOZ;

YOZ;

ossim;

readln;

closeGraph;

end;

if (ord(ch)=51) then {3 Отражение относительно XOZ end XOY}

begin

graphika;

OutTextXY(440,10, '3: XOZ end XOY');

OutTextXY(440,450, 'For exit fire ENTER');

XOZ;

XOY;

ossim;

readln;

closeGraph;

end;

if (ord(ch)=52) then {4: Отражение относительно XOY end YOZ}

begin

graphika;

OutTextXY(440,10, '4: XOY end YOZ');

OutTextXY(440,450, 'For exit fire ENTER');

YOZ;

XOY;

ossim;

readln;

closeGraph;

end;

if (ord(ch)=53) then {5: Вращение}

begin

graphika;

coordinat;

{Создание матрицы движения}

MatPreob[1,1]:=1; MatPreob[1,2]:=0.017; MatPreob[1,3]:=0; MatPreob[1,4]:=0;

MatPreob[2,1]:=-0.017; MatPreob[2,2]:=1; MatPreob[2,3]:=0; MatPreob[2,4]:=0;

MatPreob[3,1]:=0; MatPreob[3,2]:=0; MatPreob[3,3]:=1; MatPreob[3,4]:=0;

MatPreob[4,1]:=3.204; MatPreob[4,2]:=-7.129; MatPreob[4,3]:=0; MatPreob[4,4]:=1;

vr:=0;

repeat

ClearViewPort; {Очистка экрана}

izmen;

SetFillStyle(0,0);

obsh;

delay(3000);

vr:=vr+1;

if vr=180 then

begin

OutTextXY(440,440, 'Next fire ENTER');

OutTextXY(440,455, 'For Exit fire ESC');

ch:=readkey;

if (ord(ch)<>27) then vr:=0;

end;

until (vr=180) and (ord(ch)=27);

closeGraph;

end;

until ord(ch)=54;

end.

 

Похожие темы