Добавил:
farel
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:LAB1_B5 / Unit1
.cpp//---------------------------------------------------------------------------
#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;
}
//---------------------------------------------------------------------------