Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

LAB2. / Unit1

.cpp
Скачиваний:
6
Добавлен:
01.02.2019
Размер:
14.83 Кб
Скачать
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	rotate_vec = false;
	rotate_line = false;
	Timer1->Interval = 1000 / 120;
	Timer1->Enabled = false;
	PI = 3.14159265359;
}

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
	PaintBox1->Canvas->Pen->Color = clBlack;
	PaintBox1->Canvas->Pen->Width = 1;
	PaintBox1->Canvas->Brush->Style = bsSolid;
	PaintBox1->Canvas->Brush->Color = clWhite;
	PaintBox1->Canvas->Rectangle(0, 0, PaintBox1->Width, PaintBox1->Height);
	cube.Draw();
}

int TForm1::round(double n) {
	return ((int) n % 2 ? (n - (int) n < 0.5 ? (int) n : (int) n + 1) : (n - (int) n > 0.5 ? (int) n + 1 : (int) n));
}

void __fastcall TForm1::Button3Click(TObject *Sender)
{
	kof -= 10.0;
	cube.Update();
	PaintBox1->Repaint();
}

void __fastcall TForm1::Button4Click(TObject *Sender)
{
	kof += 10.0;
	cube.Update();
	PaintBox1->Repaint();
}

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
	static int iter = 120;
	static unsigned int nLine;
	static Vector3 __vec;
	static Point3D __p;
	static double angle;
	if(iter < 120) {
		iter++;
		cube.RotateL(__vec, __p, angle);
		PaintBox1->Repaint();
		if(iter == 120) {
			if(rotate_vec) {
				rotate_vec = false;
			}
			else if(rotate_line) {
				rotate_line = false;
			}
			Timer1->Enabled = false;
		}
	} else {
		iter = 0;
		angle = (double) StrToFloat(Edit3->Text) / 120;
		angle = PI * angle / 180;
		if(rotate_vec) {
			__vec.l = StrToFloat(Edit5->Text);
			__vec.m = StrToFloat(Edit6->Text);
			__vec.n = StrToFloat(Edit7->Text);
			__p.setX(StrToFloat(Edit1->Text));
			__p.setY(StrToFloat(Edit2->Text));
			__p.setZ(StrToFloat(Edit8->Text));
		}
		if(rotate_line) {
			nLine = StrToInt(Edit4->Text);
			if(nLine < 0 || nLine > 11) {
				iter = 120;
				Timer1->Enabled = false;
				rotate_vec = false;
				rotate_line = false;
			}
			__vec = cube.lines[nLine].dirVector;
			__p = cube.lines[nLine].a;
		}
	}
}

void __fastcall TForm1::Button5Click(TObject *Sender)
{
	if(!rotate_vec && !rotate_line) {
		rotate_line = true;
		Timer1->Enabled = true;
	}
}

void __fastcall TForm1::Button6Click(TObject *Sender)
{
	if(!rotate_vec && !rotate_line) {
		rotate_vec = true;
		Timer1->Enabled = true;
	}	
}
// Mat
Mat::Mat() {
	this->rows = 4;
	this->cols = 4;
	for(int i = 0; i < this->rows; i++) {
		for(int j = 0; j < this->cols; j++) {
			this->values[i][j] = 0;
		}
	}
}

Mat::Mat(ROW __rows, COL __cols) {
	this->rows = __rows;
	this->cols = __cols;
	for(int i = 0; i < this->rows; i++) {
		for(int j = 0; j < this->cols; j++) {
			this->values[i][j] = 0;
		}
	}
}

Mat::~Mat() {
}

const double& Mat::at(ROW __row, COL __col) const {
	if((__row < 0) || (__row >= this->rows) || (__col < 0) || (__col >= this->cols)) {
		throw std::out_of_range("Invalid index");
	}
	return this->values[__row][__col];
}

double& Mat::at(ROW __row, COL __col) {
	if((__row < 0) || (__row >= this->rows) || (__col < 0) || (__col >= this->cols)) {
	   throw std::out_of_range("Invalid index");
	}
	return this->values[__row][__col];
}

Mat Mat::operator *(Mat right) const {
	if(this->cols != right.rows) {
		throw "Cols left mat could = rows right mat";
	}
	Mat resultMat(this->rows, right.cols);
	for(int i = 0; i < this->rows; i++) {
		for(int j = 0; j < right.cols; j++) {
			for(int k = 0; k < this->cols; k++) {
				resultMat.at(i, j) += this->at(i, k) * right.at(k, j);
			}
		}
	}
	return resultMat;
}
// Point2D
Point2D::Point2D() {
	this->x = 0;
	this->y = 0;
}

Point2D::Point2D(double __x, double __y, TColor __color) {
	this->x = __x;
	this->y = __y;
	this->color = __color;
}

int Point2D::Tx() {
	return Form1->round(this->x + Form1->PaintBox1->Width/2);
}

int Point2D::Ty() {
	return Form1->round(-this->y + Form1->PaintBox1->Height/2);
}

void Point2D::Draw() {
	Form1->PaintBox1->Canvas->Brush->Color = this->color;
	Form1->PaintBox1->Canvas->Pen->Color = this->color;
	if(this->color == clRed) {
		Form1->PaintBox1->Canvas->Ellipse(this->Tx() - 2, this->Ty() - 2,
			this->Tx() + 2, this->Ty() + 2);
	} else {
		Form1->PaintBox1->Canvas->Ellipse(this->Tx() - 1, this->Ty() - 1,
			this->Tx() + 1, this->Ty() + 1);
    }
}

void Point2D::setX(double __x) {
	this->x = __x;
}

void Point2D::setY(double __y) {
	this->y = __y;
}

TColor Point2D::getColor() {
	return this->color;
}
// Point3D
Point3D::Point3D() {
	this->x = 0;
	this->y = 0;
	this->z = 0;
	this->color = clBlack;
}

Point3D::Point3D(double __x, double __y, double __z) {
	this->x = __x;
	this->y = __y;
	this->z = __z;
}

Point2D Point3D::T() {
	double Tx, Ty;
	/*Point3D E(1, 1, -100);
	Point3D D(0, 0, 1);
	Mat SrcMat(1, 4), ResMat(1, 4), matD, matE, matF, matG, matH;
	double R, S, P, W, T;
	R = sqrt(E.getX() * E.getX() + E.getY() * E.getY());
	S = sqrt(E.getX() * E.getX() + E.getY() * E.getY() + E.getZ() * E.getZ());
	P = -E.getY() * E.getZ();
	W = S * E.getX();
	T = sqrt(W * W + P * P);
	SrcMat.at(0, 0) = this->x;
	SrcMat.at(0, 1) = this->y;
	SrcMat.at(0, 2) = this->z;
	SrcMat.at(0, 3) = 1;

	matD.at(0, 0) = 1;
	matD.at(1, 1) = 1;
	matD.at(2, 2) = 1;
	matD.at(3, 3) = 1;
	matD.at(3 ,0) = -D.getX(); matD.at(3, 1) = -D.getY(); matD.at(3, 2) = -D.getZ();

	matE.at(0, 0) = E.getX() / R;
	matE.at(0, 1) = -E.getY() / R;
	matE.at(1, 0) = E.getY() / R;
	matE.at(1, 1) = E.getX() / R;
	matE.at(2, 2) = 1;
	matE.at(3, 3) = 1;

	matF.at(0, 0) = -E.getZ() / S;
	matF.at(0, 2) = -R / S;
	matF.at(1, 1) = 1;
	matF.at(2, 0) = R / S;
	matF.at(2, 2) = -E.getZ() / R;
	matF.at(3, 3) = 1;

	matG.at(0, 0) = 1;
	matG.at(1, 1) = 1;
	matG.at(2, 2) = 1;
	matG.at(3, 2) = S; matG.at(3, 3) = 1;

	matH.at(0, 0) = W / T;
	matH.at(0, 1) = P / T;
	matH.at(1, 0) = -P / T;
	matH.at(1, 1) = W / T;
	matH.at(2, 2) = 1;
	matH.at(3, 3) = 1;

	ResMat = SrcMat * matD * matE * matF * matH * matG;
	Tx = ResMat.at(0, 0);
	Ty = ResMat.at(0, 1);*/
	Tx = (Form1->kof * this->x)/(this->z + Form1->kof);
	Ty = (Form1->kof * this->y)/(this->z + Form1->kof);
	return Point2D(Tx, Ty, this->color);
}

double Point3D::getX() {
	return this->x;
}

double Point3D::getY() {
	return this->y;
}

double Point3D::getZ() {
	return this->z;
}

void Point3D::setX(double __x) {
	this->x = __x;
}

void Point3D::setY(double __y) {
	this->y = __y;
}

void Point3D::setZ(double __z) {
	this->z = __z;
}

void Point3D::Rotate(Vector3 __norm, Point3D __p, double angle) {
	Mat SrcMat(1, 4), ResMat(1, 4), tMat, rxMat, ryMat, rzMat, rxxMat, ryyMat, ttMat;
	SrcMat.at(0, 0) = this->x;
	SrcMat.at(0, 1) = this->y;
	SrcMat.at(0, 2) = this->z;
	SrcMat.at(0, 3) = 1;
	double P, O, F;
	P = sqrt(__norm.l * __norm.l + __norm.m * __norm.m + __norm.n * __norm.n);
	if(!P) {
		O = 0;
		F = 0;
	} else {
		if(__norm.l > 0) {
			O = atan(__norm.m / __norm.l);
		} else if (__norm.l < 0) {
			O = Form1->PI + atan(__norm.m / __norm.l);
		} else if(__norm.l == 0 && __norm.n >= 0) {
			O = Form1->PI / 2;
		} else if(__norm.l == 0 && __norm.n < 0) {
			O = 3 * Form1->PI / 2;
		}
		F = acos(__norm.n / P);
    }

	tMat.at(0, 0) = 1; 			 tMat.at(0, 1) = 0;           tMat.at(0, 2) = 0; 		   tMat.at(0, 3) = 0;
	tMat.at(1, 0) = 0; 			 tMat.at(1, 1) = 1; 		  tMat.at(1, 2) = 0; 		   tMat.at(1, 3) = 0;
	tMat.at(2, 0) = 0; 			 tMat.at(2, 1) = 0; 		  tMat.at(2, 2) = 1; 		   tMat.at(2, 3) = 0;
	tMat.at(3, 0) = -__p.getX(); tMat.at(3, 1) = -__p.getY(); tMat.at(3, 2) = -__p.getZ(); tMat.at(3, 3) = 1;
	ResMat = SrcMat * tMat;

	rzMat.at(0, 0) = cos(O);      rzMat.at(0, 1) = -sin(O);    rzMat.at(0, 2) = 0; rzMat.at(0, 3) = 0;
	rzMat.at(1, 0) = sin(O); 	  rzMat.at(1, 1) = cos(O);     rzMat.at(1, 2) = 0; rzMat.at(1, 3) = 0;
	rzMat.at(2, 0) = 0;			  rzMat.at(2, 1) = 0;		   rzMat.at(2, 2) = 1; rzMat.at(2, 3) = 0;
	rzMat.at(3, 0) = 0;           rzMat.at(3, 1) = 0;		   rzMat.at(3, 2) = 0; rzMat.at(3, 3) = 1;
	ResMat = ResMat * rzMat;

	ryMat.at(0, 0) = cos(F);   ryMat.at(0, 1) = 0; ryMat.at(0, 2) = sin(F);	  ryMat.at(0, 3) = 0;
	ryMat.at(1, 0) = 0; 	   ryMat.at(1, 1) = 1; ryMat.at(1, 2) = 0; 		  ryMat.at(1, 3) = 0;
	ryMat.at(2, 0) = -sin(F);  ryMat.at(2, 1) = 0; ryMat.at(2, 2) = cos(F);   ryMat.at(2, 3) = 0;
	ryMat.at(3, 0) = 0; 	   ryMat.at(3, 1) = 0; ryMat.at(3, 2) = 0;        ryMat.at(3, 3) = 1;
	if(this->y) {
		ResMat = ResMat * ryMat;
	}

	rxMat.at(0, 0) = cos(angle); rxMat.at(0, 1) = sin(angle); rxMat.at(0, 2) = 0; rxMat.at(0, 3) = 0;
	rxMat.at(1, 0) = -sin(angle); rxMat.at(1, 1) = cos(angle); rxMat.at(1, 2) = 0; rxMat.at(1, 3) = 0;
	rxMat.at(2, 0) = 0; rxMat.at(2, 1) = 0;rxMat.at(2, 2) = 1; rxMat.at(2, 3) = 0;
	rxMat.at(3, 0) = 0; rxMat.at(3, 1) = 0; rxMat.at(3, 2) = 0; rxMat.at(3, 3) = 1;
	if(this->x) {
		ResMat = ResMat * rxMat;
	}

	ryyMat.at(0, 0) = cos(F); ryyMat.at(0, 1) = 0; ryyMat.at(0, 2) = -sin(F); 	  	 ryyMat.at(0, 3) = 0;
	ryyMat.at(1, 0) = 0; 	    ryyMat.at(1, 1) = 1; ryyMat.at(1, 2) = 0; 		 ryyMat.at(1, 3) = 0;
	ryyMat.at(2, 0) = sin(F); 	    ryyMat.at(2, 1) = 0; ryyMat.at(2, 2) = cos(F); ryyMat.at(2, 3) = 0;
	ryyMat.at(3, 0) = 0; 	    ryyMat.at(3, 1) = 0; ryyMat.at(3, 2) = 0;        ryyMat.at(3, 3) = 1;
	if(this->y) {
		ResMat = ResMat * ryyMat;
	}

	rxxMat.at(0, 0) = cos(O); rxxMat.at(0, 1) = sin(O); rxxMat.at(0, 2) = 0;  rxxMat.at(0, 3) = 0;
	rxxMat.at(1, 0) = -sin(O); rxxMat.at(1, 1) = cos(O); rxxMat.at(1, 2) = 0; rxxMat.at(1, 3) = 0;
	rxxMat.at(2, 0) = 0; rxxMat.at(2, 1) = 0; rxxMat.at(2, 2) = 1;  rxxMat.at(2, 3) = 0;
	rxxMat.at(3, 0) = 0; rxxMat.at(3, 1) = 0; rxxMat.at(3, 2) = 0;  rxxMat.at(3, 3) = 1;
	if(this->x) {
		ResMat = ResMat * rxxMat;
	}

	ttMat.at(0, 0) = 1; 		 ttMat.at(0, 1) = 0;          ttMat.at(0, 2) = 0; 		   ttMat.at(0, 3) = 0;
	ttMat.at(1, 0) = 0; 		 ttMat.at(1, 1) = 1; 		  ttMat.at(1, 2) = 0; 		   ttMat.at(1, 3) = 0;
	ttMat.at(2, 0) = 0; 		 ttMat.at(2, 1) = 0; 		  ttMat.at(2, 2) = 1; 		   ttMat.at(2, 3) = 0;
	ttMat.at(3, 0) = __p.getX(); ttMat.at(3, 1) = __p.getY(); ttMat.at(3, 2) = __p.getZ(); ttMat.at(3, 3) = 1;
	ResMat = ResMat * ttMat;

	this->x = ResMat.at(0, 0);
	this->y = ResMat.at(0, 1);
	this->z = ResMat.at(0, 2);
}
// Cube
Cube::Cube() {
	Form1->kof = 500.0;
	this->vertex[0].setX(-100);
	this->vertex[0].setY(-100);
	this->vertex[0].setZ(0);

	this->vertex[1].setX(-100);
	this->vertex[1].setY(100);
	this->vertex[1].setZ(0);

	this->vertex[2].setX(100);
	this->vertex[2].setY(100);
	this->vertex[2].setZ(0);

	this->vertex[3].setX(100);
	this->vertex[3].setY(-100);
	this->vertex[3].setZ(0);

	this->vertex[4].setX(100);
	this->vertex[4].setY(-100);
	this->vertex[4].setZ(200);

	this->vertex[5].setX(100);
	this->vertex[5].setY(100);
	this->vertex[5].setZ(200);

	this->vertex[6].setX(-100);
	this->vertex[6].setY(100);
	this->vertex[6].setZ(200);

	this->vertex[7].setX(-100);
	this->vertex[7].setY(-100);
	this->vertex[7].setZ(200);
	this->Update();
}

void Cube::Draw() {
	VertexDepth();
	for(int i = 0; i < 12; i++) {
		this->lines[i].Draw();
	}
	for(int i = 0; i < 8; i++) {
		this->vertex[i].T().Draw();
	}
}

void Cube::Update() {
	this->lines[0].Set(this->vertex[0], this->vertex[1]);
	this->lines[1].Set(this->vertex[0], this->vertex[3]);
	this->lines[2].Set(this->vertex[0], this->vertex[7]);
	this->lines[3].Set(this->vertex[1], this->vertex[2]);
	this->lines[4].Set(this->vertex[1], this->vertex[6]);
	this->lines[5].Set(this->vertex[2], this->vertex[3]);
	this->lines[6].Set(this->vertex[2], this->vertex[5]);
	this->lines[7].Set(this->vertex[3], this->vertex[4]);
	this->lines[8].Set(this->vertex[4], this->vertex[5]);
	this->lines[9].Set(this->vertex[4], this->vertex[7]);
	this->lines[10].Set(this->vertex[5], this->vertex[6]);
	this->lines[11].Set(this->vertex[6], this->vertex[7]);
}

void Cube::Rotate(unsigned int __nLine, double angle) {
	Vector3 __normVec = this->lines[__nLine].normVector;
	Point3D __A = this->lines[__nLine].b;
	for(int i = 0; i < 8; i++) {
		this->vertex[i].Rotate(__normVec, __A, angle);
	}
	this->Update();
}

void Cube::RotateL(Vector3 __normVec, Point3D __A, double __angle) {
	for(int i = 0; i < 8; i++) {
		this->vertex[i].Rotate(__normVec, __A, __angle);
	}
	this->Update();
}

void Cube::VertexDepth() {
	Point3D *pVertex[8];
	for(int i = 0; i < 8; i++) {
		pVertex[i] = &this->vertex[i];
	}
	Point3D *tmp;
	for(int i = 0; i < 7; ++i)
	{
		for(int j = 0; j < 7; ++j)
		{
			if (pVertex[j + 1]->getZ() < pVertex[j]->getZ())
			{
				tmp = pVertex[j + 1];
				pVertex[j + 1] = pVertex[j];
				pVertex[j] = tmp;
			}
		}
	}
	for (int i = 0; i < 8; i++) {
		pVertex[i]->color = clBlack;
    }
	for (int i = 0; i < 4; i++) {
		pVertex[i]->color = clRed;
	}
	this->Update();
}
// Line
Line::Line() {
	this->a.setX(0);
	this->a.setY(0);
	this->a.setZ(0);
	this->b.setX(0);
	this->b.setY(0);
	this->b.setZ(0);
}

void Line::Set(Point3D __a, Point3D __b) {
	this->a = __a;
	this->b = __b;
	this->FindNorm();
}

void Line::Draw() {
	if(this->a.color == clBlack && this->b.color == clBlack) {
		Form1->PaintBox1->Canvas->Pen->Color = RGB(192, 192, 192);
		Form1->PaintBox1->Canvas->Pen->Width = 2;
	} else {
		Form1->PaintBox1->Canvas->Pen->Color = clBlack;
		Form1->PaintBox1->Canvas->Pen->Width = 2;
	}
	Form1->PaintBox1->Canvas->MoveTo(this->a.T().Tx(), this->a.T().Ty());
	Form1->PaintBox1->Canvas->LineTo(this->b.T().Tx(), this->b.T().Ty());
}

void Line::FindNorm() {
	this->dirVector.l = this->b.getX() - this->a.getX();
	this->dirVector.m = this->b.getY() - this->a.getY();
	this->dirVector.n = this->b.getZ() - this->a.getZ();
	/*double inv = 1.0f / sqrt(this->dirVector.l * this->dirVector.l +
		this->dirVector.m * this->dirVector.m +
		this->dirVector.n * this->dirVector.n);
	this->normVector.l = this->dirVector.l * inv;
	this->normVector.m = this->dirVector.m * inv;
	this->normVector.n = this->dirVector.n * inv;
	Form1->Memo1->Lines->Add("l1: " + FloatToStr(this->dirVector.l) + 
	"; m1: " + this->dirVector.m + "; n1: " + this->dirVector.n);
	Form1->Memo1->Lines->Add("l: " + FloatToStr(this->normVector.l) + 
	"; m: " + this->normVector.m + "; n: " + this->normVector.n); */
}
// Axis
Axis::Axis() {
	this->size = 50;
}
// Vector3
Vector3::Vector3() {
	l = 0;
	m = 0;
	n = 0;
}

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