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;
}
... нтуватися на використання підручників [53; 54; 5]. У класах фізико-математичного спрямування доцільно орієнтуватись на використання підручників [53; 54; 5; 1]. РОЗДІЛ 2 ОСОБЛИВОСТІ ВИВЧЕННЯ МАТЕМАТИКИ У ПРОФІЛЬНИХ КЛАСАХ В СУЧАСНИХ УМОВАХ 2.1. ОСНОВНІ ПОЛОЖЕННЯ ПРОФІЛЬНОЇ ДИФЕРЕНЦІАЦІЇ НАВЧАННЯ МАТЕМАТИКИ Математика є універсальною мовою, яка широко застосовується в усіх ...
... здійснювати на ведучому навчальному матеріалі. 6. Формування прийомів розумової діяльності вимагає врахування індивідуально-вікових особливостей учнів. 1.2 Формування уміння порівнювати в процесі навчання математики Порівняння в навчанні – це розумова операція, за допомогою якої встановлюються риси подібності і відмінності між визначеними предметами і явищами. Пізнання будь-якого ...
... враховуючи їх невелику кількість у підручниках, посібниках та майже повну відсутність серед добірок завдань контролюючого характеру. 2.2 Загальні методичні рекомендації вивчення елементів стереометрії у курсі геометрії 9 класу 2.2.1 Формування уявлень і понять про стереометричні фігури та деякі їх властивості Формування понять – складний психологічний процес, який починається з утворення ...
... або світлішим за колір елементів узору. 2.3 Результати дослідницько-експериментальної роботи На підтвердження наведених теоретичних положень ми проводили дослідження особливостей формування відчуття кольору на уроках образотворчого мистецтва у початкових класах. Це дослідження мало практичний характер і проводилося у два етапи. На першому етапі (2006-2007 навч. рік) була визначена сфера і ...
0 комментариев