Лабораторна робота №2
Основи комп‘ютерної графіки. Робота в просторовій системі координат
Мета: Ознайомлення з основами комп‘ютерної графіки в просторовій системі координат.
ТЕОРЕТИЧНІ ОСНОВИ
2.1 Вступ
Для кращого сприйняття форми об'єкта необхідно мати його зображення в тривимірному просторі. У багатьох випадках наочне представлення про об'єкт можна одержати шляхом виконання операцій обертання і переносу, а також побудови проекцій. Введемо однорідні координати. Точка в тривимірному просторі задається чотиримірним вектором або ж . Перетворення з однорідних координат описується співвідношеннями
де T - деяка матриця перетворення.
Ця матриця може бути представлена у вигляді 4 окремих частин
Матриця 3x3 здійснює лінійне перетворення у виді зміни масштабу, зсуву й обертання. Матриця-рядок 1х3 робить перенос, а матриця-стовпець 3х1 - перетворення в перспективі. Останній скалярний елемент виконує загальну зміну масштабу. Повне перетворення, отримане шляхом впливу на вектор положення матрицею 4x4 і нормалізації перетвореного вектора, будемо називати білінійним перетворенням. Воно забезпечує виконання комплексу операцій зсуву, часткової зміни масштабу, обертання, відображення, переносу, а також зміни масштабу зображення в цілому.
2.2 Тривимірна зміна масштабу
Діагональні елементи основної матриці перетворення 4х4 здійснюють часткову і повну зміну масштабу. Розглянемо перетворення
,
яке робить часткову зміну масштабу. На мал.2.1 показане масштабне збільшення кубу в три рази. Загальна зміна масштабу:
.
мал. 2.1
Зменшення масштабу можна досагнути при рівних коефіцієнтах часткових змін масштабів. Зменшення масштабу представлене на мал. 2.2. У цьому випадку матриця перетворення повинна бути рівна
.
мал. 2.2
2.3 Перетворення трьохвимірні координати в двовимірні
Нехай в трьохвимірному середовищі точка задана координатами (x,y,z). При переході у двовимірне середовище маємо
x=x-z*sin()
y=y-z*sin(), де - це кут між осями x та z .
2.4 Тривимірний зсув
Недіагональні елементи верхньої лівої під матриці 3х3 від загальної матриці перетворення розміру 4х4 здійснюють зсуви в трьох вимірах, тобто .
Нехай матриця перетворення має такий вигляд:
мал. 2.3
2.5 Тривимірні обертання
Раніше було показано, що матриця 3х3 забезпечувала комбінацію операцій зміни масштабу і зсуву. Однак, якщо визначник матриці 3х3 дорівнює +1, то має місце чисте обертання навколо початку координат. Перед розглядом загального випадку тривимірного обертання навколо довільної осі дослідимо кілька окремих випадків. При обертанні навколо осі х розміри уздовж осі х не змінюються. Таким чином, матриця перетворень буде мати нулі в першому рядку і першому стовпці, за винятком одиниці на головній діагоналі. Це приводить до матриці перетворення, що відповідає повороту на кут навколо осі х і задається співвідношенням
Обертання вважається додатнім, тобто за годинниковою стрілкою, якщо дивитися з початку координат вздовж осі обертання. На мал.2.4 показаний поворот на 45° навколо осі x.
мал. 2.4
Для обертання на кут Ф навколо осі y - нулі ставлять у другому рядку і другому стовпці матриці перетворення, за винятком одиниці на головній діагоналі. Повна матриця задається виразом
Приклад обертання навколо осі у на мал. 2.5
мал. 2.5
Аналогічно матриця перетворення для обертання на кут навколо осі z має вид
Приклад обертання навколо осі у на мал. 2.6
мал. 2.6
Аналіз визначників для матриць (4.6)-(4.8) показує, що для будь-якої матриці обертання детермінант дорівнює +1.
Тому що обертання описуються множенням матриць, то тривимірні обертання некомутативні, тобто порядок множення буде впливати на кінцевий результат. Для того щоб показати це, розглянемо обертання навколо осі х, за яким слідує обертання на такий же кут навколо осі y. Використовуючи рівняння (4.6) і (4.7) при = Ф, одержимо
Зворотна послідовність дій, тобто обертання навколо осі y і наступне за ним обертання на такий же кут навколо осі x при = Ф дає
2.6 Відображення в просторі
Іноді потрібно виконати дзеркальне відображення тривимірного зображення. У трьох вимірах найпростіше відображення здійснюється щодо площини. Для відображення без зміни масштабів необхідно, щоб визначник перетворення дорівнював -1,0. При відображенні щодо площини xy змінюється тільки знак координати z. Отже, матриця перетворення для відображення щодо площини xy має вигляд
Відображення одиничного куба щодо площини ху показане на мал.2.7. Для відображення щодо площини уz
мал. 2.7
а для відображення щодо площини xz
мал. 2.8
Відображення щодо інших площин можна одержати шляхом комбінації обертання і відображення.
2.7 Просторовий перенос
Тривимірний лінійний перенос зображення задається виразом
Після перемножування одержимо
приклад, просторового переносу (l=2;m=-2;n=0)
мал. 2.9
2.8 Тривимірне обертання навколо довільної осі
Метод двовимірного плоского обертання навколо довільної осі був розглянений раніше. Узагальненням цього методу є спосіб обертання навколо довільної осі в тривимірному просторі. Як і для плоского випадку, розглянена процедура полягає в переносі зображення і заданої осі обертання, що забезпечує обертання навколо осі, що проходить через початок координат. Метод тривимірного обертання полягає в лінійному переносі, обертанні навколо початку координат і зворотньому лінійному переносі у вихідне положення. Якщо вісь, навколо якої виконується обертання, проходить через точку А = , то матриця перетворення визначається наступним виразом:
де елементи матриці обертання R розміру 4х4 визначаються в загальному випадку співвідношенням
Результат добутку матриць:
мал. 2.10
Порядок роботи
ЗМІСТ ЗВІТУ
Звіт повинен містити:
1) назву роботи;
2) мету роботи;
3) короткий теоретичний вступ;
4) завдання до лабораторної роботи;
5) тексти розроблених і відлагоджених програм
6) малюнки з реалізацією програми
7) висновки
Контрольні запитання
Література
Приклад реалізації програми
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls,math;
const
qw=2;
fon=clPurple;
type
b=array[1..8,1..4] of Extended;
m=array[1..4,1..4] of Extended;
TForm1 = class(TForm)
E1_1: TEdit;
e1_2: TEdit;
Label1: TLabel;
e2_3: TEdit;
e2_4: TEdit;
e3_1: TEdit;
Button1: TButton;
P: TPaintBox;
Button2: TButton;
e3_2: TEdit;
e1_3: TEdit;
e1_4: TEdit;
e2_1: TEdit;
E2_2: TEdit;
e3_3: TEdit;
e3_4: TEdit;
e4_1: TEdit;
e4_2: TEdit;
e4_3: TEdit;
e4_4: TEdit;
C: TCheckBox;
Button3: TButton;
Grad: TEdit;
Panel1: TPanel;
r1: TRadioButton;
r2: TRadioButton;
r3: TRadioButton;
r4: TRadioButton;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Label3: TLabel;
procedure PPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
z,y2,x2,x,y,i,j,k,kk,x_temp:integer;
box:b;
matrix:m;
cikl:boolean=false;
implementation
{$R *.DFM}
procedure mat(var p:b;pp:m);
var temp:array[1..8,1..4]of real;
begin
for i:=1 to 8 do
for j:=1 to 4 do
temp[i,j]:=0 ;
for i:=1 to 8 do
for j:=1 to 4 do
for z:=1 to 4 do
temp[i,j]:=temp[i,j]+(p[i,z]*pp[j,z]);
for i:=1 to 8 do
for j:=1 to 4 do
p[i,j]:=temp[i,j];
end;
function X_ (a:real):integer;
begin
result:=round((form1.P.Width div 2)+(a*x_temp));
end;
function y_ (a:real):integer;
begin
result:=round((form1.P.height div 2)-a*(x_temp ));
end;
procedure getparam;
begin
with form1 do
for i:=1 to 4 do
for j:=1 to 4 do
if TEdit(FindComponent('E' +
IntToStr(i)+'_'+IntToStr(j))).Text <>'' then
matrix[i,j]:=StrTofloat(TEdit(FindComponent('E' +
IntToStr(i)+'_'+IntToStr(j))).Text);
end;
procedure Draw; //x=x-z*sin(alpha)
begin //y=y-z*sin(alpha)
with form1.p.Canvas do //alpha=30
begin
pen.Width:=pen.Width+2;
MoveTo(x_(box[1,1]-box[1,3]/2),y_(box[1,2]-box[1,3]/2));//000
pen.Color:=cllime;
lineto(x_(box[2,1]-box[2,3]/2),Y_(box[2,2]-box[2,3]/2));//001
lineto(x_(box[6,1]-box[6,3]/2),Y_(box[6,2]-box[6,3]/2));//101
lineto(x_(box[5,1]-box[5,3]/2),Y_(box[5,2]-box[5,3]/2));//100
lineto(x_(box[1,1]-box[1,3]/2),Y_(box[1,2]-box[1,3]/2));//000
moveto(x_(box[3,1]-box[3,3]/2),Y_(box[3,2]-box[3,3]/2));//010
lineto(x_(box[4,1]-box[4,3]/2),Y_(box[4,2]-box[4,3]/2));//011
lineto(x_(box[8,1]-box[8,3]/2),Y_(box[8,2]-box[8,3]/2));//111
lineto(x_(box[7,1]-box[7,3]/2),Y_(box[7,2]-box[7,3]/2));//110
lineto(x_(box[3,1]-box[3,3]/2),Y_(box[3,2]-box[3,3]/2));//010
moveto(x_(box[4,1]-box[4,3]/2),Y_(box[4,2]-box[4,3]/2));//011
lineto(x_(box[2,1]-box[2,3]/2),Y_(box[2,2]-box[2,3]/2));//001
moveto(x_(box[8,1]-box[8,3]/2),Y_(box[8,2]-box[8,3]/2));//111
lineto(x_(box[6,1]-box[6,3]/2),Y_(box[6,2]-box[6,3]/2));//101
moveto(x_(box[7,1]-box[7,3]/2),Y_(box[7,2]-box[7,3]/2));//110
lineto(x_(box[5,1]-box[5,3]/2),Y_(box[5,2]-box[5,3]/2));//100
moveto(x_(box[3,1]-box[3,3]/2),Y_(box[3,2]-box[3,3]/2));//010
lineto(x_(box[1,1]-box[1,3]/2),Y_(box[1,2]-box[1,3]/2));//000
pen.Color:=fon;
pen.Width:=pen.Width-2;
end;
end;
procedure TForm1.PPaint(Sender: TObject);
begin
with p.Canvas do
begin
p.Canvas.FillRect(rect(0,0,p.width,p.height));
pen.Color:=clwhite;
moveto(p.Width div 2,0);
lineto(p.Width div 2,(p.Height div 2));
moveto(p.Width div 2,p.Height div 2);
lineto(p.Width ,p.Height div 2);
moveto(p.Width div 2,p.Height div 2);
lineto(70,p.Height-70);
i:=(p.width div 2)+x_temp;
while i<p.Width do
begin
moveto(i,(p.Height div 2)-10);
lineto(i,(p.height div 2)+10);
i:=i+x_temp ;
end;
i:=0;
while i<(p.Height div 2)-x_temp do
begin
moveto((p.width div 2)-10,i);
lineto((p.width div 2)+10,i);
i:=i+x_temp;
end;
i:=52+x_temp;
j:=p.Height-i;
while i<(p.Width div 2) do
begin
moveto(i-14,j);
lineto(i+1,j+10);
i:=i+x_temp div 2;
j:=j-x_temp div 2;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var t,tt:integer;
begin
x_temp:=p.Width div 20;
t:=1;
tt:=1;
label1.Caption:='y\x 1 2 3 4'+
#10+#13+'1'+#10+#13+'2'+#10+#13+'3'+#10+#13+'4';
// kub 1x1x1
for j:=1 to 4 do
for i:=1 to 8 do
case j of
4:box[i,j]:=qw;
1: if i<=4 then box[i,j]:=0 else box[i,j]:=qw;
3: if (i mod 2)=0 then box[i,j]:=qw else box[i,j]:=0;
2: begin
if t>2 then
begin
t:=1;
tt:=tt*-1;
end;
if tt=1 then box[i,j]:=0 else box[i,j]:=qw;
inc(t);
end;
end;
button1.Caption:='Ïîáóäîâà îäèíè÷íîãî êóáà';
button1.Caption:='Îïåðàö³¿ íàä êóáîì';
button1.Caption:='Ïîâîðîò';
label3.Caption:=' N1 N2 N3';
label2.Caption:='ÊÓÒ :';
R1.Caption:='Ïî X';
r2.Caption:='Ïî Y';
r3.Caption:='Ïî Z';
r4.Caption:='Ïî óÿâí³é (XYZ)';
c.Caption:='ÏÅÐÅÌÀËÜÎÂÊÀ';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
formcreate(form1);
if c.Checked then ppaint(form1);
draw;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
formcreate(form1);
getparam;
if c.Checked then ppaint(form1);
mat(box,matrix);
draw;
end;
procedure TForm1.Button3Click(Sender: TObject);
var matrix_:m;
begin
if c.Checked then ppaint(form1);
for i:=1 to 4 do
for j:=1 to 4 do
matrix[i,j]:=0 ;
if r1.Checked then
begin
matrix[1,1]:=1;
matrix[4,4]:=1;
matrix[2,2]:=cos(DegToRad(StrTofloat(grad.text)));
matrix[2,3]:=SIN(DegToRad(StrTofloat(grad.text)));
matrix[3,2]:=-matrix[2,3];
matrix[3,3]:=matrix[2,2];
end;
if r2.Checked then
begin
matrix[2,2]:=1;
matrix[4,4]:=1;
matrix[1,1]:=cos(DegToRad(StrToFloat(grad.text)));
matrix[1,3]:=-sin(DegToRad(StrToFloat(grad.text)));
matrix[3,1]:=-matrix[1,3];
matrix[3,3]:=matrix[1,1];
end;
if r3.Checked then
begin
matrix[3,3]:=1;
matrix[4,4]:=1;
matrix[1,1]:=cos(DegToRad(StrToFloat(grad.text)));
matrix[1,2]:=sin(DegToRad(StrToFloat(grad.text)));
matrix[2,1]:=-matrix[1,2];
matrix[2,2]:=matrix[1,1];
end;
if r4.Checked then
begin
getparam;
matrix_[1,4]:=cos(DegToRad(StrToFloat(Edit1.Text)));
matrix_[2,4]:=cos(DegToRad(StrToFloat(Edit2.Text)));
matrix_[3,4]:=cos(DegToRad(StrToFloat(Edit3.Text)));
matrix_[1,1]:=sqr(StrToFloat(Edit1.Text))+(1-sqr(StrToFloat(Edit1.Text)))*cos(DegToRad(StrToFloat(grad.text)));
matrix_[1,2]:=StrToFloat(Edit2.Text)*StrToFloat(Edit1.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))-(StrToFloat(Edit3.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[1,3]:=StrToFloat(Edit3.Text)*StrToFloat(Edit1.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))+(StrToFloat(Edit2.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[1,4]:=0;
matrix_[2,1]:=StrToFloat(Edit2.Text)*StrToFloat(Edit1.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))+(StrToFloat(Edit3.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[2,2]:=sqr(StrToFloat(Edit2.Text))+(1-sqr(StrToFloat(Edit2.Text)))*cos(DegToRad(StrToFloat(grad.text)));
matrix_[2,3]:=StrToFloat(Edit2.Text)*StrToFloat(Edit3.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))-(StrToFloat(Edit1.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[2,4]:=0;
matrix_[3,1]:=StrToFloat(Edit3.Text)*StrToFloat(Edit1.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))-(StrToFloat(Edit2.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[3,2]:=StrToFloat(Edit2.Text)*StrToFloat(Edit3.Text)*(1-cos(DegToRad(StrToFloat(grad.text))))+(StrToFloat(Edit1.Text)*sin(DegToRad(StrToFloat(grad.text))));
matrix_[3,3]:=sqr(StrToFloat(Edit3.Text))+(1-sqr(StrToFloat(Edit3.Text)))*cos(DegToRad(StrToFloat(grad.text)));
matrix_[3,4]:=0;
matrix_[4,1]:=0;
matrix_[4,2]:=0;
matrix_[4,3]:=0;
matrix_[4,4]:=1;
mat(box,matrix_);
end;
for i:=1 to 4 do
for j:=1 to 4 do
if (r1.Checked) and (r2.Checked) and(r3.Checked) then
matrix[i,j]:=matrix[i,j]/3*2.07 ;
if not r4.Checked then
mat(box,matrix);
draw;
end;
end.