Добавил:
farel
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:LAB2 / Unit1
.cpp//---------------------------------------------------------------------------
#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 = RadioGroup1->ItemIndex;
__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) {
this->x = __x;
this->y = __y;
}
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 = clWhite;
Form1->PaintBox1->Canvas->Pen->Color = clBlack;
Form1->PaintBox1->Canvas->Ellipse(this->Tx() - 4, this->Ty() - 4,
this->Tx() + 4, this->Ty() + 4);
}
void Point2D::setX(double __x) {
this->x = __x;
}
void Point2D::setY(double __y) {
this->y = __y;
}
// Point3D
Point3D::Point3D() {
this->x = 0;
this->y = 0;
this->z = 0;
}
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);
}
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(-99);
this->vertex[0].setY(1);
this->vertex[0].setZ(1);
this->vertex[1].setX(1);
this->vertex[1].setY(101);
this->vertex[1].setZ(1);
this->vertex[2].setX(101);
this->vertex[2].setY(1);
this->vertex[2].setZ(1);
this->vertex[3].setX(1);
this->vertex[3].setY(-99);
this->vertex[3].setZ(1);
this->vertex[4].setX(1);
this->vertex[4].setY(1);
this->vertex[4].setZ(-99);
this->vertex[5].setX(1);
this->vertex[5].setY(1);
this->vertex[5].setZ(101);
this->Update();
}
void Cube::Draw() {
for(int i = 0; i < 12; i++) {
this->lines[i].Draw();
}
for(int i = 0; i < 6; 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[4]);
this->lines[3].Set(this->vertex[0], this->vertex[5]);
this->lines[4].Set(this->vertex[1], this->vertex[2]);
this->lines[5].Set(this->vertex[1], this->vertex[4]);
this->lines[6].Set(this->vertex[1], this->vertex[5]);
this->lines[7].Set(this->vertex[2], this->vertex[3]);
this->lines[8].Set(this->vertex[2], this->vertex[4]);
this->lines[9].Set(this->vertex[2], this->vertex[5]);
this->lines[10].Set(this->vertex[3], this->vertex[4]);
this->lines[11].Set(this->vertex[3], this->vertex[5]);
}
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 < 6; i++) {
this->vertex[i].Rotate(__normVec, __A, angle);
}
this->Update();
}
void Cube::RotateL(Vector3 __normVec, Point3D __A, double __angle) {
for(int i = 0; i < 6; i++) {
this->vertex[i].Rotate(__normVec, __A, __angle);
}
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() {
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;
}