You are on page 1of 13

Федеральное агентство по образованию

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


профессионального образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет автоматики и вычислительной техники


Направление (специальность) – Информационные системы

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

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


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

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

Исполнитель
студент, 8960 Е. И. Блеч
(подпись)
_____________________
(дата)

Руководитель
доцент, к.т.н О.С. Токарева
(подпись)
_____________________
(дата)

Томск –2009

Цель работы: Изучить Базовые алгоритмы 3D-геометрии.


Задание №23:
Даны следующие координаты:
• (5;-15;5) (0;0;0);
• (0;0;0) (5;15;5);
• (5;-15;5) (0;0;10);
• (0;0;10) (5;15;5);
• (5;-15;5) (10;0;10);
• (10;0;10) (5;15;5);
• (5;-15;5) (10;0;00);
• (10;0;0) (5;15;5);

○ Написать программу, которая по заданным координатам


строит проекцию Кaвалье.
○ Реализовать в данной программе вращение по разным осям,
масштабирование и перенос.
○ Все действия производить по нажатию горячих клавиш.
○ Предусмотреть возможность возврата к первоначальной
проекции.
1. Исходный текст программы:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include "unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
double Dots[6][3], //вершины
DotsN[6][3],
DotOZ[3]; //новые вершины
double Transf[4][4]; //матрица преобразований

double K;

int ImgWidth, ImgHeight,


x0, y0;

double XWmin, YWmin, XWmax,YWmax,


XSmin, YSmin, XSmax,YSmax;
#define min(a,b) (a <= b) ? a:b
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ImgWidth = Img->Width;
ImgHeight = Img->Height;
x0 = ImgWidth/2;
y0 = ImgHeight/2;
//матр. преобр.
Transf[0][0] = 1; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = 1; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = 1; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0; Transf[3][2] = 0; Transf[3][3] = 1;

//уст. вершин
Dots[0][0] = 0; Dots[0][1] = 0; Dots[0][2] = 0;
Dots[1][0] = 10; Dots[1][1] = 0; Dots[1][2] = 0;
Dots[2][0] = 5; Dots[2][1] = -15; Dots[2][2] = 5;
Dots[3][0] = 5; Dots[3][1] = 15; Dots[3][2] = 5;
Dots[4][0] = 10; Dots[4][1] = 0; Dots[4][2] = 10;
Dots[5][0] = 0; Dots[5][1] = 0; Dots[5][2] = 10;

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


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

ImgWidth = Img->Width;
ImgHeight = Img->Height;
x0 = ImgWidth/2;
y0 = ImgHeight/2;

XWmin = -45; XWmax = 45;


YWmin = -45; YWmax = 45;
XSmin= 0; XSmax = ImgWidth;
YSmin= 0; YSmax = ImgHeight;

double Kx = (XSmax - XSmin)/(XWmax - XWmin);


double Ky = (YSmax - YSmin)/(YWmax - YWmin);
K = min(Kx, Ky);
DrawForm();
}
//---------------------------------------------------------------------------

//умножение матриц
void __fastcall TForm1::Multiplication(double D[][3], int Div)
{
doubleA[6][4]; //Dots + 4 единичный столб.
for(int i = 0; i < 6; i++)
{
A[i][0] = D[i][0];
A[i][1] = D[i][1];
A[i][2] = D[i][2];
A[i][3] = 1;
}
doubleC[6][4]; //результат
double buf = 0;
for(int i = 0; i < 6; i++)
for(int j = 0; j < 4; j++)
{
for(int k = 0; k < 4; k++)
{
buf += A[i][k]*Transf[k][j];
}
C[i][j] = buf;
buf = 0;
}
if(Div)
for(int i = 0; i < 6; i++)
{
C[i][0] /= C[i][3];
C[i][1] /= C[i][3];
}
for(int i = 0; i < 6; i++)
for(int j = 0; j < 3; j++)
D[i][j] = C[i][j];
}

//---------------------------------------------------------------------------
void __fastcall TMainForm::FindOZ(double D[3])
{
double A[4];
for(intj = 0; j < 3; j++) A[j] = D[j];
A[3] = 1;

double C[4];
double buf = 0;
for(int j = 0; j < 4; j++)
{
for(int k = 0; k < 4; k++)
{
buf += A[k]*Transf[k][j];
}
C[j] = buf;
buf = 0;
}
for(int j = 0; j < 3; j++)
D[j] = C[j];
}
//---------------------------------------------------------------------------
void __fastcall TForm1::DrawForm()
{
//закраска белым с черной рамкой
TCanvas* C = Img->Canvas;
C->Pen->Width = 1;
C->Pen->Color = clBlack;
C->Rectangle(0,0,ImgWidth,ImgHeight);
//матрица координат проекции
double Pro[6][3];
for(int i = 0; i < 6; i++)
for(int j = 0; j < 3; j++)
Pro[i][j] = DotsN[i][j];

double angle = M_PI/4*45,


l = 1; // Кавалье
Transf[0][0] = 1; Transf[0][1] = 0;
Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = 1;
Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = l*cos(angle); Transf[2][1] = l*sin(angle);
Transf[2][2] = 1; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0;
Transf[3][2] = 0; Transf[3][3] = 1;

C->MoveTo(x0,y0);
C->LineTo(ImgWidth-10,y0);

C->MoveTo(x0,y0);
C->LineTo(x0,10);

DotOZ[0] = 0;
DotOZ[1] = 0;
DotOZ[2] = 45;
FindOZ(DotOZ);
DotOZ[0] = (XSmin + (int)( K* (double)(DotOZ[0] - XWmin )));
DotOZ[1] = (YSmax - (int)( K* (double)(DotOZ[1] - YWmin )));

C->MoveTo(x0,y0);
C->LineTo(DotOZ[0], DotOZ[1]);

Multiplication(Pro, 0);

//перевод в координаты канвы


for(int i = 0; i < 6; i++)
{
Pro[i][0] = (XSmin + (int)( K* (double)(Pro[i][0] - XWmin )));
Pro[i][1] = (YSmax - (int)( K* (double)(Pro[i][1] - YWmin )));
}
//фигура
C->Pen->Width = 2;
C->MoveTo(Pro[0][0],Pro[0][1]);
C->LineTo(Pro[3][0],Pro[3][1]);
C->LineTo(Pro[4][0],Pro[4][1]);
C->LineTo(Pro[2][0],Pro[2][1]);
C->LineTo(Pro[1][0],Pro[1][1]);
C->LineTo(Pro[3][0],Pro[3][1]);
C->LineTo(Pro[5][0],Pro[5][1]);
C->LineTo(Pro[2][0],Pro[2][1]);
C->LineTo(Pro[0][0],Pro[0][1]);
C->LineTo(Pro[1][0],Pro[1][1]);
C->LineTo(Pro[4][0],Pro[4][1]);
C->LineTo(Pro[5][0],Pro[5][1]);
C->LineTo(Pro[0][0],Pro[0][1]);

}
//---------------------------------------------------------------------------
//инверсия отн-но xy
void __fastcall TForm1::InvBtnXYClick(TObject *Sender)
{
Transf[0][0] = 1; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = 1; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = -1; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0; Transf[3][2] = 0; Transf[3][3] = 1;
Multiplication(DotsN, 0);
DrawForm();
}
//---------------------------------------------------------------------------
//инверсия отн-но xz
void __fastcall TForm1::InvBtnXZClick(TObject *Sender)
{
Transf[0][0] = 1; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = -1; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = 1; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0; Transf[3][2] = 0; Transf[3][3] = 1;
Multiplication(DotsN, 0);
DrawForm();
}
//---------------------------------------------------------------------------
//перемещение
void __fastcall TForm1::TransfBtnClick(TObject *Sender)
{
int dx, dy, dz;
dx = StrToInt(DxEdit->Text);
dy = StrToInt(DyEdit->Text);
dz = StrToInt(DzEdit->Text);
Transf[0][0] = 1; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = 1; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = 1; Transf[2][3] = 0;
Transf[3][0] = dx; Transf[3][1] = dy; Transf[3][2] = dz; Transf[3][3] = 1;
Multiplication(DotsN, 0);
DrawForm();
}
//---------------------------------------------------------------------------
//инверсия отно-но yz
void __fastcall TForm1::InvBtnYZClick(TObject *Sender)
{
Transf[0][0] = -1; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = 1; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = 1; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0; Transf[3][2] = 0; Transf[3][3] = 1;
Multiplication(DotsN, 0);
DrawForm();
}

//---------------------------------------------------------------------------
//масштабирование по X Y Z
void __fastcall TForm1::ScaleBtnClick(TObject *Sender)
{
double kx, ky, kz;
kx = double(StrToInt(ScEditX->Text))/100;
ky = double(StrToInt(ScEditY->Text))/100;
kz = double(StrToInt(ScEditZ->Text))/100;
Transf[0][0] = kx; Transf[0][1] = 0; Transf[0][2] = 0; Transf[0][3] = 0;
Transf[1][0] = 0; Transf[1][1] = ky; Transf[1][2] = 0; Transf[1][3] = 0;
Transf[2][0] = 0; Transf[2][1] = 0; Transf[2][2] = kz; Transf[2][3] = 0;
Transf[3][0] = 0; Transf[3][1] = 0; Transf[3][2] = 0; Transf[3][3] = 1;
Multiplication(DotsN, 0);
DrawForm();
}
//---------------------------------------------------------------------------
//сброс изменений
void __fastcall TForm1::ResetBtnClick(TObject *Sender)
{
for(int i = 0; i < 8; i++)
{
DotsN[i][0] = Dots[i][0];
DotsN[i][1] = Dots[i][1];
DotsN[i][2] = Dots[i][2];
}
DrawForm();
}
//---------------------------------------------------------------------------
//поворот
void __fastcall TForm1::RotateBtnClick(TObject *Sender)
{
double a = StrToInt(EditAngle->Text);
a = M_PI/180*a;
if(RdBtnX->Checked)
{
Transf[0][0]= 1; Transf[0][1]= 0; Transf[0][2]= 0; Transf[0][3]=0;
Transf[1][0]= 0; Transf[1][1]= cos(a); Transf[1][2]= sin(a); Transf[1][3]=0;
Transf[2][0]= 0; Transf[2][1]= -sin(a); Transf[2][2]= cos(a); Transf[2][3]=0;
Transf[3][0]= 0; Transf[3][1]= 0; Transf[3][2]= 0; Transf[3][3]=1;
}
if(RdBtnY->Checked)
{
Transf[0][0]= cos(a); Transf[0][1]= 0; Transf[0][2]= -sin(a); Transf[0][3]=0;
Transf[1][0]= 0; Transf[1][1]= 1; Transf[1][2]= 0; Transf[1][3]=0;
Transf[2][0]= sin(a); Transf[2][1]= 0; Transf[2][2]= cos(a); Transf[2][3]=0;
Transf[3][0]= 0; Transf[3][1]= 0; Transf[3][2]= 0; Transf[3][3]=1;
}
if(RdBtnZ->Checked)
{
Transf[0][0]= cos(a); Transf[0][1]= sin(a); Transf[0][2]= 0; Transf[0][3]=0;
Transf[1][0]= -sin(a); Transf[1][1]= cos(a); Transf[1][2]= 0; Transf[1][3]=0;
Transf[2][0]= 0; Transf[2][1]= 0; Transf[2][2]= 1; Transf[2][3]=0;
Transf[3][0]= 0; Transf[3][1]= 0; Transf[3][2]= 0; Transf[3][3]=1;
}
Multiplication(DotsN, 0);
DrawForm();
}
//---------------------------------------------------------------------------
2. Выполнение программы:
Исходное состояние:

Отражение по XY- Ctrl + A


Отражение по YZ - Ctrl + C

Отражение смещение на 100 по Y - Ctrl + D


И затем по ZX - Ctrl + B

Смещение по Х и по Y на 100 (Ctrl + D) и увеличение масштаба по Х в 2 раза


–( Ctrl + E).
Увеличить масштаб в 1,5 раза по Y, Z и повернуть по оси Х на 90 градусов
(Ctrl + R).

Потом из текущего положения по оси Y (Ctrl + R).


И в заключение по оси Z (Ctrl + R).

Сбросить изменения Ctrl+Z


Вывод: Изучена проекция Кaвалье, разобраны алгоритмы вращения по
разным осям, масштабирования и переноса в 3D-геометрии.