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

LAB1_B5 / Unit1

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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Math.hpp"
#include "math.h"
#include "ctime.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

#define NPOINTS 15

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	srand(time(0));
	Timer->Enabled = false;
	Timer->Interval = 1000 / 120;
	ScaleOn = RotateOn = false;
	rPoints = new point [NPOINTS];
	rPointsIsCreate = false;
	InitAxes();
	Image1Repaint();
}
//---------------------------------------------------------------------------
bool pnpoly(point p[4], double x, double y) {
	bool c = false;
	for (int i = 0, j = 3; i < 4; j = i++)
	{
		if ((((p[i].realY <=y) && (y < p[j].realY)) || ((p[j].realY <= y) && (y < p[i].realY))) &&
			(x > (p[j].realX - p[i].realX) * (y - p[i].realY) / (p[j].realY - p[i].realY) + p[i].realX))
			c = !c;
	}
	return c;
}
void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X,
		  int Y)
{
	if (!t.isCreate) {
		Image1Repaint();
		point centre, currentTop;
		currentTop.x = X;
		currentTop.y = Y;
		centre.x = Image1->Width/2;
		centre.y = Image1->Height/2;
		if ((t.stepCreate == 0 && (X > centre.x || X < centre.x/2 || Y > centre.y || Y < centre.y/2)) ||
			(t.stepCreate == 1 && (X < centre.x || X > centre.x * 1.5 || Y > centre.y || Y < centre.y/2)) ||
			(t.stepCreate == 2 && (X < centre.x || X > centre.x * 1.5 || Y < centre.y || Y > centre.y * 1.5)) ||
			(t.stepCreate == 3 && (X > centre.x || X < centre.x /2 || Y < centre.y || Y > centre.y * 1.5))) {
			currentTop.color = clRed;
			DrawTop(currentTop);
		}
		else {
			currentTop.color = clBlack;
			DrawTop(currentTop);
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1Repaint() {
	Image1->Canvas->Brush->Style = TBrushStyle(clWhite);
	Image1->Canvas->FillRect(Image1->Canvas->ClipRect);
	Image1->Canvas->Rectangle(0, 0, Image1->Width, Image1->Height);
	DrawAxes();
	DrawTop(centre);
	if (t.isCreate == 0) {
		Image1->Canvas->Brush->Style = bsClear;
		Image1->Canvas->Pen->Color = clInactiveBorder;
		Image1->Canvas->Rectangle(centre.x/2, centre.y/2, centre.x * 1.5, centre.y * 1.5);
		if (t.stepCreate == 0) {
			Image1->Canvas->Pen->Color = clActiveBorder;
			Image1->Canvas->Rectangle(centre.x/2, centre.y/2, centre.x, centre.y);
		}
		else if (t.stepCreate == 1) {
			Image1->Canvas->Pen->Color = clActiveBorder;
			Image1->Canvas->Rectangle(centre.x, centre.y/2, centre.x * 1.5, centre.y);
		}
		else if (t.stepCreate == 2) {
			Image1->Canvas->Pen->Color = clActiveBorder;
			Image1->Canvas->Rectangle(centre.x, centre.y, centre.x * 1.5, centre.y * 1.5);
		}
		else if (t.stepCreate == 3) {
			Image1->Canvas->Pen->Color = clActiveBorder;
			Image1->Canvas->Rectangle(centre.x/2, centre.y, centre.x, centre.y * 1.5);
		}
		Image1->Canvas->Pen->Color = clBlack;
	}
	if (t.stepCreate > 0) {
		for(int i = 0; i < t.stepCreate; i++)
			DrawTop(t.top[i]);
	}
	if (t.isCreate > 0) {
		for(int i = 0; i < t.stepCreate; i++)
			DrawLine(t.edges[i]);
	}
	if (rPointsIsCreate > 0) {
		for(int i = 0; i < NPOINTS; i++)
			DrawTop(rPoints[i]);
	}
}

tetragon::tetragon() {
	isCreate = -1;
	stepCreate = 0;
}

void tetragon::Create() {
	for(int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);
	if(!Check()) {
		Application->MessageBoxW(L"Четырехугольник должен быть выпуклым", L"Error", MB_OK);
		ShowCursor(False);
		Reset();
		return;
	}
	isCreate = 1;
}

void tetragon::Reset() {
	isCreate = 0;
	stepCreate = 0;
	Form1->rPointsIsCreate = 0;
}

bool tetragon::Check() {
	double sum = 0;
	for (int i = 0; i < 4; i++)
		sum += RoundTo(edges[i].GetCos(edges[(i < 3 ? i+1 : 0)]) * 180/3.14, -3);
	return (sum > 360.2 ? false : true);
}

void __fastcall TForm1::StartClick(TObject *Sender)
{
	if (t.isCreate < 0) {
		t.isCreate = 0;
		Image1Repaint();
	}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
		  int X, int Y)
{
	if(t.isCreate == 0) {
		point centre;
		centre.x = Image1->Width / 2;
		centre.y = Image1->Height / 2;

		if (t.stepCreate == 0 && (X > centre.x || X < centre.x/2 || Y > centre.y || Y < centre.y/2)) {
			Application->MessageBoxW(L"Выбрана неверная область для вершины", L"Error", MB_OK);
		}
		else if (t.stepCreate == 1 && (X < centre.x || X > centre.x * 1.5 || Y > centre.y || Y < centre.y/2)) {
			Application->MessageBoxW(L"Выбрана неверная область для вершины", L"Error", MB_OK);
		}
		else if (t.stepCreate == 2 && (X < centre.x || X > centre.x * 1.5 || Y < centre.y || Y > centre.y * 1.5)) {
			Application->MessageBoxW(L"Выбрана неверная область для вершины", L"Error", MB_OK);
		}
		else if (t.stepCreate == 3 && (X > centre.x || X < centre.x /2 || Y < centre.y || Y > centre.y * 1.5)) {
			Application->MessageBoxW(L"Выбрана неверная область для вершины", L"Error", MB_OK);
		}
		else {
			point * p = new point(X, Y);
			t.top[t.stepCreate++] = *p;
			delete p;
			if(t.stepCreate == 4) {
				t.Create();
				ShowCursor(True);
				Image1Repaint();
			}
		}
	}
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Image1MouseEnter(TObject *Sender)
{
	if(t.isCreate == 0) ShowCursor(False);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseLeave(TObject *Sender)
{
	if(t.isCreate == 0) {
		ShowCursor(True);
		Image1Repaint();
	}
}
//---------------------------------------------------------------------------
void TForm1::DrawLine(line _line) {
	Image1->Canvas->Pen->Color = clBlack;
	Image1->Canvas->MoveTo(_line.start.x, _line.start.y);
	Image1->Canvas->LineTo(_line.end.x, _line.end.y);
}

void TForm1::DrawTop(point _top) {
	Graphics::TBitmap * p = new Graphics::TBitmap;
	p->Width = 8;
	p->Height = 8;
	p->Canvas->Pen->Color = _top.color;
	p->Canvas->Brush->Color = _top.color;
	p->Canvas->Ellipse(0, 0, 8, 8);
	Image1->Canvas->Draw(_top.x - 4, _top.y - 4, p);
	delete p;
}

void TForm1::InitAxes() {
	centre.x = Image1->Width / 2;
	centre.y = Image1->Height / 2;
	centre.realX = 0;
	centre.realY = 0;
	centre.color = clBlue;
	AxisX.Set(point(0, centre.y), point(centre.x * 2, centre.y));
	AxisY.Set(point(centre.x, 0), point(centre.x, centre.y * 2));
}

void TForm1::DrawAxes() {
	DrawLine(AxisX);
	DrawLine(AxisY);
}

double line::GetCos(line l) {
	return acos((this->dir * l.dir)/(this->dir.length() * l.dir.length()));
}

void __fastcall TForm1::ResetClick(TObject *Sender)
{
	t.Reset();
	Image1Repaint();
}
//---------------------------------------------------------------------------
vector::vector(double _x, double _y) {
	x = _x;
	y = _y;
}

double vector::operator *(vector vec) const {
	return (this->x * vec.x + this->y * vec.y);
}

double vector::length() {
	return sqrt(x * x + y * y);
}

line::line(point _start, point _end) {
	start = _start;
	end = _end;
	GetDir();
}

void line::Set(point _start, point _end) {
	start = _start;
	end = _end;
}

void line::GetDir() {
    dir.x = end.x - start.x;
	dir.y = end.y - start.y;
}

point::point(double _x, double _y) {
	x = _x;
	y = _y;
	realX = x - Form1->centre.x;
	realY = (y < Form1->centre.y ? fabs(y - Form1->centre.y) : -y + Form1->centre.y);
	color = clBlack;
}

void point::Scale(double pX, double pY, double sX, double sY) {
	matrix mPoint(1, 3), mScale(3, 3);
	mPoint.array[0][0] = realX;   mPoint.array[0][1] = realY;   mPoint.array[0][2] = 1;
	// Перенос
	mScale.array[0][0] = 1;			mScale.array[0][1] = 0;			mScale.array[0][2] = 0;
	mScale.array[1][0] = 0;			mScale.array[1][1] = 1;			mScale.array[1][2] = 0;
	mScale.array[2][0] = -pX;	mScale.array[2][1] = -pY;	mScale.array[2][2] = 1;
	mPoint = mPoint * mScale;
	// Масштаб
	mScale.array[0][0] = sX;	mScale.array[0][1] = 0;		mScale.array[0][2] = 0;
	mScale.array[1][0] = 0;		mScale.array[1][1] = sY;	mScale.array[1][2] = 0;
	mScale.array[2][0] = 0;		mScale.array[2][1] = 0;		mScale.array[2][2] = 1;
	mPoint = mPoint * mScale;
	// Возврат в первоначальные координаты
	mScale.array[0][0] = 1;			mScale.array[0][1] = 0; 		mScale.array[0][2] = 0;
	mScale.array[1][0] = 0;			mScale.array[1][1] = 1;			mScale.array[1][2] = 0;
	mScale.array[2][0] = pX;	mScale.array[2][1] = pY;	mScale.array[2][2] = 1;
	mPoint = mPoint * mScale;
	realX = mPoint.array[0][0];
	realY = mPoint.array[0][1];
	x = realX + Form1->centre.x;
	y = -realY + Form1->centre.y;
}

void tetragon::Scale(double pX, double pY, double sX, double sY) {
	for(int i = 0; i < 4; i++)
		top[i].Scale(pX, pY, sX, sY);
	for(int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);
}

matrix::matrix(int _m, int _n) {
	m = _m;
	n = _n;
	array = new double* [m];
	for(int rows = 0; rows < m; rows++)
		array[rows] = new double[n];
	for(int rows = 0; rows < m; rows++)
		for(int cols = 0; cols < n; cols++)
			array[rows][cols] = 0;
}

matrix matrix::operator * (matrix right) {
	if (n != right.m) {
		matrix temp(1,1);
		return temp;
	}
	matrix temp(m, right.n);
	for(int i = 0; i < m; i++)
		for(int j = 0; j < right.n; j++)
			for (int k = 0; k < n; k++)
				temp.array[i][j] += array[i][k] * right.array[k][j];
	return temp;
}

void point::mirrorOX() {
	matrix mPoint(1, 3), mMirror(3, 3);
	mPoint.array[0][0] = realX;   mPoint.array[0][1] = realY;   mPoint.array[0][2] = 1;
	mMirror.array[0][0] = 1;  mMirror.array[0][1] = 0;	mMirror.array[0][2] = 0;
	mMirror.array[1][0] = 0;  mMirror.array[1][1] = -1;	mMirror.array[1][2] = 0;
	mMirror.array[2][0] = 0;  mMirror.array[2][1] = 0;	mMirror.array[2][2] = 1;
	mPoint = mPoint * mMirror;
	realX = mPoint.array[0][0];
	realY = mPoint.array[0][1];
	x = realX + Form1->centre.x;
	y = -realY + Form1->centre.y;
}

void point::mirrorOY() {
	matrix mPoint(1, 3), mMirror(3, 3);
	mPoint.array[0][0] = realX;   mPoint.array[0][1] = realY;   mPoint.array[0][2] = 1;
	mMirror.array[0][0] = -1;  mMirror.array[0][1] = 0;	mMirror.array[0][2] = 0;
	mMirror.array[1][0] = 0;   mMirror.array[1][1] = 1;	mMirror.array[1][2] = 0;
	mMirror.array[2][0] = 0;   mMirror.array[2][1] = 0;	mMirror.array[2][2] = 1;
	mPoint = mPoint * mMirror;
	realX = mPoint.array[0][0];
	realY = mPoint.array[0][1];
	x = realX + Form1->centre.x;
	y = -realY + Form1->centre.y;
}

void tetragon::mirrorOX() {
	for (int i = 0; i < 4; i++)
		top[i].mirrorOX();
	for (int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);
}

void tetragon::mirrorOY() {
	for (int i = 0; i < 4; i++)
		top[i].mirrorOY();
	for (int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);
}

void __fastcall TForm1::MirrorOXClick(TObject *Sender)
{
	t.mirrorOX();
	if (rPointsIsCreate) CheckPoints();
	Image1Repaint();
}

void point::rotate(double pX, double pY, double a) {
	double rad;
	rad = (3.14 * a) / 180;
	matrix mPoint(1, 3), mRotate(3, 3);
	mPoint.array[0][0] = realX;   mPoint.array[0][1] = realY;   mPoint.array[0][2] = 1;
	// Перенос в начало координат
	mRotate.array[0][0] = 1;		mRotate.array[0][1] = 0;	mRotate.array[0][2] = 0;
	mRotate.array[1][0] = 0;		mRotate.array[1][1] = 1;	mRotate.array[1][2] = 0;
	mRotate.array[2][0] = -pX;		mRotate.array[2][1] = -pY;	mRotate.array[2][2] = 1;
	mPoint = mPoint * mRotate;
	// Поворот на заданный угол
	mRotate.array[0][0] = cos(rad);		mRotate.array[0][1] = sin(rad);	mRotate.array[0][2] = 0;
	mRotate.array[1][0] = -sin(rad);	mRotate.array[1][1] = cos(rad);	mRotate.array[1][2] = 0;
	mRotate.array[2][0] = 0;			mRotate.array[2][1] = 0;		mRotate.array[2][2] = 1;
	mPoint = mPoint * mRotate;
	// Возврат в первоначальные координаты
	mRotate.array[0][0] = 1;		mRotate.array[0][1] = 0; 	mRotate.array[0][2] = 0;
	mRotate.array[1][0] = 0;		mRotate.array[1][1] = 1;	mRotate.array[1][2] = 0;
	mRotate.array[2][0] = pX;		mRotate.array[2][1] = pY;	mRotate.array[2][2] = 1;
	mPoint = mPoint * mRotate;
	realX = mPoint.array[0][0];
	realY = mPoint.array[0][1];
	x = realX + Form1->centre.x;
	y = -realY + Form1->centre.y;
}
//---------------------------------------------------------------------------
void tetragon::rotate(double pX, double pY, double a) {
	for (int i = 0; i < 4; i++)
		top[i].rotate(pX, pY, a);
	for (int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);

}
void __fastcall TForm1::RotateClick(TObject *Sender)
{
	if(t.isCreate > 0) {
		RotateOn = true;
		Timer->Enabled = true;
    }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::MirrorOYClick(TObject *Sender)
{
	if(t.isCreate > 0) {
		t.mirrorOY();
		if (rPointsIsCreate) CheckPoints();
		Image1Repaint();
	}
}
//---------------------------------------------------------------------------
void TForm1::RandomPoints() {
	for (int i = 0; i < NPOINTS; i++)
		rPoints[i] = point(rand() % (int)(centre.x * 2), rand() % (int)(centre.y * 2));
}

void TForm1::CheckPoints() {
	for (int i = 0; i < NPOINTS; i++) {
		if(pnpoly(t.top, rPoints[i].realX, rPoints[i].realY))
			rPoints[i].color = clBlack;
		else
			rPoints[i].color = clRed;
	}
}

void __fastcall TForm1::CreatePointsClick(TObject *Sender)
{
	if(t.isCreate > 0) {
		RandomPoints();
		rPointsIsCreate = true;
		CheckPoints();
		Image1Repaint();
	}
}
//---------------------------------------------------------------------------



void __fastcall TForm1::ScaleClick(TObject *Sender)
{
	if(t.isCreate > 0) {
		ScaleOn = true;
		Timer->Enabled = true;
	}
}
//---------------------------------------------------------------------------


void tetragon::Recalc() {
	for (int i = 0; i < 4; i++) {
		top[i].x = top[i].realX + Form1->centre.x;
		top[i].y = -top[i].realY + Form1->centre.y;
	}
	for (int i = 0; i < 4; i++)
		edges[i] = line(top[i], top[(i < 3 ? i+1 : 0)]);
}

void __fastcall TForm1::TimerTimer(TObject *Sender)
{
	static pX, pY;
	if (rPointsIsCreate) CheckPoints();
	if(RotateOn) {
		static double angle = StrToFloat(Edit3->Text);
		pX = StrToFloat(Edit4->Text);
		pY = StrToFloat(Edit5->Text);
		static double step = angle / 120;
		if (angle > 0) {
			t.rotate(pX, pY, step);
			angle -= step;
			Image1Repaint();
			if (angle <= 0) {
				if(!ScaleOn) Timer->Enabled = false;
				RotateOn = false;
			}
		}
		else {
			angle = StrToFloat(Edit3->Text);
			pX = StrToFloat(Edit4->Text);
			pY = StrToFloat(Edit5->Text);
			step = angle / 120;
		}
	}
	if(ScaleOn) {
		static double sX = StrToFloat(Edit1->Text);
		static double sY = StrToFloat(Edit2->Text);
		static int i = 0;
		static double stepX = (--sX) / 120;
		static double stepY = (--sY) / 120;
		pX = StrToFloat(Edit4->Text);
		pY = StrToFloat(Edit5->Text);
		if (i < 120) {
			i = i + 1;
			t.Scale(pX, pY, 1/(1 + stepX * (i - 1)), 1/(1 + stepY * (i - 1)));
			t.Scale(pX, pY, 1 + stepX*i, 1 + stepY*i);
			Image1Repaint();
			if (i == 120) {
				if(!RotateOn) Timer->Enabled = false;
				ScaleOn = false;
			}
		}
		else {
			i = 0;
			sX = StrToFloat(Edit1->Text);
			sY = StrToFloat(Edit2->Text);
            pX = StrToFloat(Edit4->Text);
			pY = StrToFloat(Edit5->Text);
			stepX = (--sX) / 120;
			stepY = (--sY) / 120;
		}
    }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
	if(!(Key >= '0' && Key <= '9' || Key == VK_BACK || Key == ',')) {
		Key = 0x00;
	}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit2KeyPress(TObject *Sender, System::WideChar &Key)
{
	if(!(Key >= '0' && Key <= '9' || Key == VK_BACK || Key == ',')) {
		Key = 0x00;
	}
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Edit3KeyPress(TObject *Sender, System::WideChar &Key)
{
	if(!(Key >= '0' && Key <= '9' || Key == VK_BACK)) Key = 0x00;
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Edit4KeyPress(TObject *Sender, System::WideChar &Key)
{
	if(!(Key >= '0' && Key <= '9' || Key == VK_BACK || Key == '-')) Key = 0x00;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit5KeyPress(TObject *Sender, System::WideChar &Key)
{
	if(!(Key >= '0' && Key <= '9' || Key == VK_BACK || Key == '-')) Key = 0x00;
}
//---------------------------------------------------------------------------

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