4.2. Клас відрізка

Клас відрізка зберігає інформацію про відрізок, дозволяє його опрацьовувати та виконувати пошук перетину між двома відрізками.


#pragma once

#include <GL\glut.h>

#include "IDrawable.h"

#include "GLPoint.h"

#include "Constants.h"

using namespace System;

ref class GLSegment : IDrawable

{

//структура, що повертає інформацію про перетин відрізків

public: ref struct CrossAnswer {

CrossAnswer(bool isFlat)

{

Type = CrossType::NONE;

Point1 = gcnew GLPoint();

Point2 = gcnew GLPoint();

Point1->IsInAnswer = true;

Point2->IsInAnswer = true;

Point1->Flat = isFlat;

Point2->Flat = isFlat;

}

enum class CrossType { NONE, POINT, SEGMENT } Type;

GLPoint^ Point1;

GLPoint^ Point2;

property System::String^ Answer

{

System::String^ get()

{

System::String^ answer = gcnew System::String("");

switch (Type)

{

case CrossType::NONE:

answer = "Відрізки не перетинаються.";

break;

case CrossType::POINT:

answer = "Відрізки перетинаються у точці " + Constants::AnswerPoint + ".";

break;

case CrossType::SEGMENT:

answer = "Відрізки перетинаються на проміжку [" + Point1->ToString() + ", " + Point2->ToString() + "].";

break;

}

return answer;

}

}

};

public:

GLSegment(GLPoint^ point1, GLPoint^ point2);

~GLSegment() {}

//функція малювання відрізка

virtual void Draw() override;

//чи перетинаються відрізки

CrossAnswer^ Cross(GLSegment^ segment2);

//довжина відрізка

double Magnitude();

//відстань між двома точками

static double Magnitude(GLPoint^ p1, GLPoint^ p2);

//створює проекцію відрізка на вісь координат

GLSegment^ ProjectionTo(Constants::Projection proj);

//перевіряє, чи містить відрізок точку

bool Contains(GLPoint^ point);

property cli::array<GLPoint^>^ Point

{

void set(cli::array<GLPoint^>^ value)

{

this->_point1 = value[0];

this->_point2 = value[1];

}

cli::array<GLPoint^>^ get()

{

cli::array<GLPoint^>^ tmp = gcnew cli::array<GLPoint^>(2);

tmp[0] = this->_point1;

tmp[1] = this->_point2;

return tmp;

}

}

System::String^ ToString() override;

private:

GLPoint^ _point1;

GLPoint^ _point2;

//перевіряє чи перетинаються проекції відрізків

CrossAnswer^ cross2d(GLSegment^ s2, Constants::Projection proj);

//перевіряє чи перетинаються відрізки у просторі

CrossAnswer^ cross3d(GLSegment^ segment2);

};

#include "GLSegment.h"

GLSegment::GLSegment(GLPoint^ point1, GLPoint^ point2)

{

_point1 = point1;

_point2 = point2;

}

void GLSegment::Draw()

{

glBegin(GL_LINES);

glColor3f(_r, _g, _b);

if (Flat)

{

glVertex2f(_point1->X, _point1->Y);

glVertex2f(_point2->X, _point2->Y);

}

else

{

glVertex3f(_point1->X, _point1->Y, _point1->Z);

glVertex3f(_point2->X, _point2->Y, _point2->Z);

}

glEnd();

}

GLSegment::CrossAnswer^ GLSegment::Cross(GLSegment^ segment2)

{

if (Flat)

return cross2d(segment2, Constants::Projection::XY);

else

return cross3d(segment2);

}

double GLSegment::Magnitude()

{

return Magnitude(this->_point1, this->_point2);

}

double GLSegment::Magnitude(GLPoint^ p1, GLPoint^ p2)

{

return Math::Sqrt(

(double)System::Decimal::Add(

System::Decimal::Add(

System::Decimal::Multiply(

System::Decimal::Subtract(

(System::Decimal)p2->X,

(System::Decimal)p1->X

),

System::Decimal::Subtract(

(System::Decimal)p2->X,

(System::Decimal)p1->X

)

),

System::Decimal::Multiply(

System::Decimal::Subtract(

(System::Decimal)p2->Y,

(System::Decimal)p1->Y

),

System::Decimal::Subtract(

(System::Decimal)p2->Y,

(System::Decimal)p1->Y

)

)

),

System::Decimal::Multiply(

System::Decimal::Subtract(

(System::Decimal)p2->Z,

(System::Decimal)p1->Z

),

System::Decimal::Subtract(

(System::Decimal)p2->Z,

(System::Decimal)p1->Z

)

)

)

);

}

GLSegment^ GLSegment::ProjectionTo(Constants::Projection proj)

{

GLSegment^ val = gcnew GLSegment(gcnew GLPoint(this->_point1->X, this->_point1->Y, this->_point1->Z), gcnew GLPoint(this->_point2->X, this->_point2->Y, this->_point2->Z));

switch (proj)

{

case Constants::Projection::XY:

val->_point1->Z = 0;

val->_point2->Z = 0;

break;

case Constants::Projection::XZ:

val->_point1->Y = 0;

val->_point2->Y = 0;

break;

case Constants::Projection::YZ:

val->_point1->X = 0;

val->_point2->X = 0;

break;

}

return val;

}

bool GLSegment::Contains(GLPoint^ point)

{

if (Math::Abs(Magnitude(_point1, point) + Magnitude(point, _point2) - Magnitude()) < Constants::DELTA)

return true;

else

return false;

}

System::String^ GLSegment::ToString()

{

return System::String::Format("[{0}, {1}]", this->_point1->ToString(), this->_point2->ToString());

}

GLSegment::CrossAnswer^ GLSegment::cross2d(GLSegment^ s2, Constants::Projection proj)

{

//перехід до координат проекції

double U1, U2, V1, V2;//перший відрізок

double U3, U4, V3, V4;//другий відрізок

double UN1, VN1, UN2, VN2;//точки перетину

switch (proj)

{

case Constants::Projection::XY:

U1 = this->_point1->X;

U2 = this->_point2->X;

V1 = this->_point1->Y;

V2 = this->_point2->Y;

U3 = s2->_point1->X;

U4 = s2->_point2->X;

V3 = s2->_point1->Y;

V4 = s2->_point2->Y;

break;

case Constants::Projection::XZ:

U1 = this->_point1->X;

U2 = this->_point2->X;

V1 = this->_point1->Z;

V2 = this->_point2->Z;

U3 = s2->_point1->X;

U4 = s2->_point2->X;

V3 = s2->_point1->Z;

V4 = s2->_point2->Z;

break;

case Constants::Projection::YZ:

U1 = this->_point1->Y;

U2 = this->_point2->Y;

V1 = this->_point1->Z;

V2 = this->_point2->Z;

U3 = s2->_point1->Y;

U4 = s2->_point2->Y;

V3 = s2->_point1->Z;

V4 = s2->_point2->Z;

break;

}

CrossAnswer^ value = gcnew CrossAnswer(this->Flat);

//матриці рівняння прямих

double A[2][2], B[2];

A[0][0] = V2 - V1; A[0][1] = U1 - U2;

A[1][0] = V4 - V3; A[1][1] = U3 - U4;

B[1] = U3 * V4 - V3 * U4;

B[0] = U1 * V2 - V1 * U2;

//визначники матриць

double d = A[0][0] * A[1][1] - A[1][0] * A[0][1];

double d1 = B[0] * A[1][1] - B[1] * A[0][1];

double d2 = A[0][0] * B[1] - A[1][0] * B[0];

//чи паралельні прямі

if (Math::Abs(d) < Constants::DELTA)

{

//чи співпадають прямі

if (Math::Abs(d1) < Constants::DELTA && Math::Abs(d2) < Constants::DELTA)

{

value->Type = CrossAnswer::CrossType::SEGMENT;

//визначаємо відносні позиції кінців відрізків

double s1MaxX = Math::Max(U1, U2);

double s1MinX = Math::Min(U1, U2);

double s1MaxY = Math::Max(V1, V2);

double s1MinY = Math::Min(V1, V2);

double s2MaxX = Math::Max(U3, U4);

double s2MinX = Math::Min(U3, U4);

double s2MaxY = Math::Max(V3, V4);

double s2MinY = Math::Min(V3, V4);

if ((s1MinX > s2MaxX || s2MinX > s1MaxX) && (s1MinY > s2MaxY || s2MinY > s1MaxY))

{

//відрізки не перетинаються

value->Type = CrossAnswer::CrossType::NONE;

return value;

}

else

{

//проміжок перетину відрізків

UN1 = Math::Max(s1MinX, s2MinX);

VN1 = Math::Max(s1MinY, s2MinY);

UN2 = Math::Min(s1MaxX, s2MaxX);

VN2 = Math::Min(s1MaxY, s2MaxY);

if (Math::Abs(UN1 - UN2) < Constants::DELTA && Math::Abs(VN1 - VN2) < Constants::DELTA)

value->Type = CrossAnswer::CrossType::POINT;

}

}

else

value->Type = CrossAnswer::CrossType::NONE;

}

else

{

//точка перетину

value->Type = CrossAnswer::CrossType::POINT;

UN1 = d1 / d;

VN1 = d2 / d;

}

//переходимо від проекції назад до реальних координат

switch (proj)

{

case Constants::Projection::XY:

value->Point1->X = UN1;

value->Point1->Y = VN1;

value->Point2->X = UN2;

value->Point2->Y = VN2;

break;

case Constants::Projection::XZ:

value->Point1->X = UN1;

value->Point1->Z = VN1;

value->Point2->X = UN2;

value->Point2->Z = VN2;

break;

case Constants::Projection::YZ:

value->Point1->Y = UN1;

value->Point1->Z = VN1;

value->Point2->Y = UN2;

value->Point2->Z = VN2;

break;

default:

break;

}

if (value->Type == CrossAnswer::CrossType::POINT)

//чи знаходиться точка на відрізках

if (!this->ProjectionTo(proj)->Contains(value->Point1->ProjectionTo(proj)) ||

!s2->ProjectionTo(proj)->Contains(value->Point1->ProjectionTo(proj)))

value->Type = CrossAnswer::CrossType::NONE;

return value;

}

GLSegment::CrossAnswer^ GLSegment::cross3d(GLSegment^ segment2)

{

CrossAnswer^ value = gcnew CrossAnswer(this->Flat);

//Аналізуємо 3 проекції

array<CrossAnswer^>^ crossProj = gcnew array<CrossAnswer^>(3);

crossProj[0] = cross2d(segment2, Constants::Projection::XY);

crossProj[1] = cross2d(segment2, Constants::Projection::XZ);

crossProj[2] = cross2d(segment2, Constants::Projection::YZ);

//чи накладаються відрізки один на одного

if (crossProj[0]->Type == CrossAnswer::CrossType::SEGMENT &&

crossProj[1]->Type == CrossAnswer::CrossType::SEGMENT &&

crossProj[2]->Type == CrossAnswer::CrossType::SEGMENT)

{

value->Type = CrossAnswer::CrossType::SEGMENT;

value->Point1 = crossProj[0]->Point1;

value->Point2 = crossProj[0]->Point2;

value->Point1->Z = crossProj[1]->Point1->Z;

value->Point2->Z = crossProj[1]->Point2->Z;

}

//чи перетинаються відрізки у точці

else if ((crossProj[0]->Type == CrossAnswer::CrossType::SEGMENT || crossProj[0]->Type == CrossAnswer::CrossType::POINT) &&

(crossProj[1]->Type == CrossAnswer::CrossType::SEGMENT || crossProj[1]->Type == CrossAnswer::CrossType::POINT) &&

(crossProj[2]->Type == CrossAnswer::CrossType::SEGMENT || crossProj[2]->Type == CrossAnswer::CrossType::POINT))

{

//шукаємо, які з проекцій є точками

bool isPoint[3];

int pointCount = 0;

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

if (crossProj[i]->Type == CrossAnswer::CrossType::POINT)

{

isPoint[i] = true;

pointCount++;

}

else

isPoint[i] = false;

value->Type = CrossAnswer::CrossType::POINT;

if (pointCount == 1)

{

//якщо точка одна, третю координату вибираємо з іншої відповіді

if (isPoint[0])

{

value->Point1 = crossProj[0]->Point1;

value->Point2 = crossProj[0]->Point2;

value->Point1->Z = crossProj[1]->Point1->Z;

value->Point2->Z = crossProj[1]->Point2->Z;

}

else if (isPoint[1])

{

value->Point1 = crossProj[1]->Point1;

value->Point2 = crossProj[1]->Point2;

value->Point1->Y = crossProj[0]->Point1->Y;

value->Point2->Y = crossProj[0]->Point2->Y;

}

else if (isPoint[2])

{

value->Point1 = crossProj[2]->Point1;

value->Point2 = crossProj[2]->Point2;

value->Point1->X = crossProj[0]->Point1->X;

value->Point2->X = crossProj[0]->Point2->X;

}

}

else

{

//шукаємо 2 проекції, на яких видно точку перетину

//якщо на першій проекції видно точку, шкуаємо наступну

if (isPoint[0])

{

value->Point1 = crossProj[0]->Point1;

value->Point2 = crossProj[0]->Point2;

for (int i = 1; i <= 2; i++)

if (isPoint[i])

{

value->Point1->Z = crossProj[i]->Point1->Z;

value->Point2->Z = crossProj[i]->Point2->Z;

}



Информация о работе «Програма пошуку перетину відрізків та побудови чотирикутників»
Раздел: Информатика, программирование
Количество знаков с пробелами: 73364
Количество таблиц: 0
Количество изображений: 11

Похожие работы

Скачать
218746
21
0

... нтуватися на використання підручників [53; 54; 5]. У класах фізико-математичного спрямування доцільно орієнтуватись на використання підручників [53; 54; 5; 1].   РОЗДІЛ 2 ОСОБЛИВОСТІ ВИВЧЕННЯ МАТЕМАТИКИ У ПРОФІЛЬНИХ КЛАСАХ В СУЧАСНИХ УМОВАХ 2.1. ОСНОВНІ ПОЛОЖЕННЯ ПРОФІЛЬНОЇ ДИФЕРЕНЦІАЦІЇ НАВЧАННЯ МАТЕМАТИКИ Математика є універсальною мовою, яка широко застосовується в усіх ...

Скачать
70664
8
1

... здійснювати на ведучому навчальному матеріалі. 6.       Формування прийомів розумової діяльності вимагає врахування індивідуально-вікових особливостей учнів.   1.2 Формування уміння порівнювати в процесі навчання математики   Порівняння в навчанні – це розумова операція, за допомогою якої встановлюються риси подібності і відмінності між визначеними предметами і явищами. Пізнання будь-якого ...

Скачать
111254
0
31

... враховуючи їх невелику кількість у підручниках, посібниках та майже повну відсутність серед добірок завдань контролюючого характеру.   2.2 Загальні методичні рекомендації вивчення елементів стереометрії у курсі геометрії 9 класу   2.2.1 Формування уявлень і понять про стереометричні фігури та деякі їх властивості Формування понять – складний психологічний процес, який починається з утворення ...

Скачать
129908
0
0

... або світлішим за колір елементів узору. 2.3 Результати дослідницько-експериментальної роботи На підтвердження наведених теоретичних положень ми проводили дослідження особливостей формування відчуття кольору на уроках образотворчого мистецтва у початкових класах. Це дослідження мало практичний характер і проводилося у два етапи. На першому етапі (2006-2007 навч. рік) була визначена сфера і ...

0 комментариев


Наверх