Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
48
Добавлен:
02.05.2014
Размер:
23.64 Кб
Скачать
//---------------------------------------------------------------------------


#pragma hdrstop

#include "spatial.h"



Tspatial::Tspatial(TCanvas* tempc)
{
	 canva=tempc;
	 proection=ORT;
}
//---------------------------------------------------------------------------


void Tspatial::setParams(float oX, float oY, float temp_lengthos, float temp_alpha)
{
	O.x=oX;
	O.y=oY;
	lengthOS=temp_lengthos;
	alpha=temp_alpha;

	//Прямая не паралельна плоскости
	isExistCrossPoint = false;
	isCrossLines = false;
	isFrontal = false;
	E = 0;

	//Углы поворота вокруг осей
	angleX = 0;
	angleY = 0;
	//angleZ = 0;
	//Координаты наблюдателя
	Camera.x = 50;
	Camera.y = 50;
	Camera.z = 100;
	CameraReal = Camera;
	//Устанавливаем координаты точек
	A.x = 0;
	A.y = 80;
	A.z = 0;
	AReal = A;

	B.x = 50;
	B.y = 0;
	B.z = 0;
	BReal = B;

	C.x = 0;
	C.y = 0;
	C.z = 50;
	CReal = C;

	M.x = 0;
	M.y = 60;
	M.z = 0;
	MReal = M;

	N.x = 60;
	N.y = 0;
	N.z = 0;
	NReal = N;
}

void Tspatial::change()
{
	changeAngle(Form1->TrackBar4->Position, Form1->TrackBar5->Position, Form1->TrackBar6->Position);
	if (Form1->RadioButton1->Checked)
		changeProection(ORT);
	else if (Form1->RadioButton2->Checked)
		changeProection(PERSPECT);
	calculate();
	//Form1->setT(TReal.x, TReal.y, TReal.z);
	draw();
}

void Tspatial::changeAngle (int x, int y, int z)
{
	Camera.x = x;
	Camera.y = y;
	Camera.z = z;

	if (sqrt(Camera.x*Camera.x + Camera.z*Camera.z))
		angleY = acos((float)((float)Camera.z/(float)sqrt(Camera.x*Camera.x + Camera.z*Camera.z)));
	//else if (Camera.x==0) angleY = 90/(float)((float)180.0f/(float)M_PI);
	else angleY=0;

	if (sqrt(Camera.x*Camera.x + Camera.y*Camera.y + Camera.z*Camera.z))
		angleX = asin((float)((float)Camera.y/(float)sqrt(Camera.x*Camera.x + Camera.y*Camera.y + Camera.z*Camera.z)));
	else
		angleX = -90;

	angleY = -angleY*(float)((float)180.0f/(float)M_PI);
	angleX = angleX*(float)((float)180.0f/(float)M_PI);
}

void Tspatial::changePoint (int x, int y, int z)
{
	//P.x=(float)x;
	//P.y=(float)y;
	//P.z=(float)z;
}

void Tspatial::changeProection (char type)
{
	proection=type;
}

void Tspatial::calculate()
{
	if (Camera.x==0&&Camera.y==0&&Camera.z==0)
	{
		status=CAMERA_NULL;
		return;
	}
	status=GOOD;
	//Задаем коодинаты осей
	//Ось Х
	XBegin.x = lengthOS;
	XBegin.y = 0;
	XBegin.z = 0;

	XEnd.x = -lengthOS;
	XEnd.y = 0;
	XEnd.z = 0;

	//Ось Y
	YBegin.x = 0;
	YBegin.y = lengthOS;
	YBegin.z = 0;

	YEnd.x = 0;
	YEnd.y = -lengthOS;
	YEnd.z = 0;

	//Ось Z
	ZBegin.x = 0;
	ZBegin.y = 0;
	ZBegin.z = lengthOS;

	ZEnd.x = 0;
	ZEnd.y = 0;
	ZEnd.z = -lengthOS;

	//Нахождение коэффициентов плоскости
	findK();

  	findCrossPoint();

	//Поворот вокруг оси Х
	//Задаем матрицу поворота
	float a[4][4] = {{1, 0,                    0,                   0},
					 {0,  cos(radian(angleX)),  sin(radian(angleX)), 0},
					 {0,  -sin(radian(angleX)), cos(radian(angleX)), 0},
					 {0,  0,                    0,                   1}};
	TMatrix Rx(4, 4, *a);

	//Поворот вокруг оси У
	float a2[4][4] = {{cos(radian(angleY)), 0, -sin(radian(angleY)), 0},
					  {0,                    1, 0,                    0},
					  {sin(radian(angleY)),  0, cos(radian(angleY)),  0},
					  {0,                    0, 0,                    1}};
	TMatrix Ry(4, 4, *a2);

	if (proection==ORT)
	{
		A = AReal*Ry*Rx;
		B = BReal*Ry*Rx;
		C = CReal*Ry*Rx;
		M = MReal*Ry*Rx;
		N = NReal*Ry*Rx;
		T = TReal*Ry*Rx; 
	}
	else if(proection==PERSPECT)
	{
		//Проверим, не находится ли камера внутри
		/*if (P.x>=C.x&&P.y>=C.y&&P.z>=C.z)
		{
			status=CAMERA_IN;
			return;
		}*/
		float koren = sqrt(Camera.x*Camera.x + Camera.y*Camera.y +Camera.z*Camera.z);
  		if (koren == 0)
			koren = 1;
		//Матрица перспективы
		float pers[4][4] = {{1, 0, 0, 0},
							 {0, 1, 0, 0},
							 {0, 0, 0, -(float)1/(float)koren},
							 {0, 0, 0, 1}};
		TMatrix persMatrix(4, 4, *pers);
		A = AReal*Ry*Rx*persMatrix;
		B = BReal*Ry*Rx*persMatrix;
		C = CReal*Ry*Rx*persMatrix;
		M = MReal*Ry*Rx*persMatrix;
		N = NReal*Ry*Rx*persMatrix;
		T = TReal*Ry*Rx*persMatrix;


		// Проверим линии на выход за границы
		if (ifLineOut())
		{
			status=LINE_OUT;
			return;
		}
	}

	XBegin = XBegin*Ry*Rx;
	XEnd = XEnd*Ry*Rx;

	YBegin = YBegin*Ry*Rx;
	YEnd = YEnd*Ry*Rx;

	ZBegin = ZBegin*Ry*Rx;
	ZEnd = ZEnd*Ry*Rx;
}

void Tspatial::draw()
{
	//Зачистим область
	TRect r;
	r.Left = 0;
	r.Top = 0;
	r.Right = O.x*2;
	r.Bottom = O.y*2;
	canva->FillRect(r);

	if (status==CAMERA_IN)
	{
		canva->TextOutA(O.x-50, O.y, "Камера внутри объекта");
		return;
	}
	if (status==LINE_OUT)
	{
		canva->TextOutA(O.x-80, O.y, "Линии рисунка за пределами области ");
		return;
	}
	if (status==CAMERA_NULL)
	{
		canva->TextOutA(O.x-80, O.y, "Невозможно построить изображение");
		return;
	}
	//Оси
	//Х
	canva->Pen->Width=1;
	canva->Pen->Style=PS_SOLID;
	canva->Pen->Color=clBlue;
	canva->MoveTo(convert(XBegin).x, convert(XBegin).y);
	canva->LineTo(O.x, O.y);
	canva->Pen->Style=PS_DASH;
	canva->LineTo(convert(XEnd).x, convert(XEnd).y);
	//Y
	canva->Pen->Style=PS_SOLID;
	canva->Pen->Color=clGreen;
	canva->MoveTo(convert(YBegin).x, convert(YBegin).y);
	canva->LineTo(O.x, O.y);
	canva->Pen->Style=PS_DASH;
	canva->LineTo(convert(YEnd).x, convert(YEnd).y);
	//Z
	canva->Pen->Style=PS_SOLID;
	canva->Pen->Color=clRed;
	canva->MoveTo(convert(ZBegin).x, convert(ZBegin).y);
	canva->LineTo(O.x, O.y);
	canva->Pen->Style=PS_DASH;
	canva->LineTo(convert(ZEnd).x, convert(ZEnd).y);
	canva->Pen->Color=clBlack;
	canva->Pen->Style=PS_SOLID;

	//Подписываем оси
	TextOut (canva->Handle, convert(XBegin).x-indentx, convert(XBegin).y-indenty, "X", 1);
	TextOut (canva->Handle, convert(YBegin).x+indentx, convert(YBegin).y, "Y", 1);
	TextOut (canva->Handle, convert(ZBegin).x+indentx, convert(ZBegin).y-indenty, "Z", 1);

	//
	canva->Pen->Width = 1;
	canva->Pen->Color = (TColor)RGB(21, 183, 70);
	//Рисуем линию из A в B
	canva->MoveTo(convert(A).x, convert(A).y);
	canva->LineTo(convert(B).x, convert(B).y);
	//Рисуем линию из B в C
	canva->MoveTo(convert(B).x, convert(B).y);
	canva->LineTo(convert(C).x, convert(C).y);
	//Рисуем линию из C в A
	canva->MoveTo(convert(C).x, convert(C).y);
	canva->LineTo(convert(A).x, convert(A).y);
	//Делаем перо красным
	canva->Pen->Color = (TColor)RGB(207, 22, 46);

	//Рисуем линию из N в M

	//если нет точки пересечения и прямая перед плоскостью или плоскость является фронт. проец, то рисуем сплошной линией
	if ((!isExistCrossPoint && ScalM>E && ScalN>E) || isFrontal)
	{
		canva->Pen->Style=psSolid;
		canva->MoveTo(convert(N).x, convert(N).y);
		canva->LineTo(convert(M).x, convert(M).y);
	}

	//если нет точки пересечения и плоскость не фронт. проец. и прямая за плоскостью то рисуем пунктиром
	if (!isExistCrossPoint && !isFrontal && ScalM<-E && ScalN<-E)
	{
		canva->Pen->Style=psDot;
		canva->MoveTo(convert(N).x, convert(N).y);
		canva->LineTo(convert(M).x, convert(M).y);
	}

	//Обе точки(отрезок) лежат(ит) на плоскости то рисуем сплошной. Также по этому условию срабатывает
	//когда две прямые скрещиваются
	if (!isExistCrossPoint && fabs(ScalM)<=E && fabs(ScalN)<=E)
	{
		canva->Pen->Style=psSolid;
		canva->MoveTo(convert(N).x, convert(N).y);
		canva->LineTo(convert(M).x, convert(M).y);
	}


	//если есть точка пересечения и плоскость не явл. фронт. проец. то рисуем с учетом видимости
	if (isExistCrossPoint && !isFrontal)
	{
		//Точка М видима, а точка N невидима
		if (ScalM > E && ScalN < -E)
		{
			canva->Pen->Style = psDot;
			canva->MoveTo(convert(T).x, convert(T).y);
			canva->LineTo(convert(N).x, convert(N).y);

			canva->Pen->Style = psSolid;
			canva->MoveTo(convert(T).x, convert(T).y);
			canva->LineTo(convert(M).x, convert(M).y);
		}
		//Точка М невидима, а точка N видима
		if (ScalM < -E && ScalN > E)
		{
			canva->Pen->Style = psDot;
			canva->MoveTo(convert(T).x, convert(T).y);
			canva->LineTo(convert(M).x, convert(M).y);

			canva->Pen->Style = psSolid;
			canva->MoveTo(convert(T).x, convert(T).y);
			canva->LineTo(convert(N).x, convert(N).y);
		}
		//одна точка на плоскости, другая перед плоскостью
		if ((fabs(ScalM)<=E && ScalN>E)||(fabs(ScalN)<=E && ScalM>E))
		{
			canva->Pen->Style = psSolid;
			canva->MoveTo(convert(N).x, convert(N).y);
			canva->LineTo(convert(M).x, convert(M).y);
		}
		//одна точка на плоскости, другая за плоскостью
		if ((fabs(ScalM)<=E && ScalN<-E)||(fabs(ScalN)<=E && ScalM<-E))
		{
			canva->Pen->Style = psDot;
			canva->MoveTo(convert(N).x, convert(N).y);
			canva->LineTo(convert(M).x, convert(M).y);
		}
		//если идет пересечение прямых или плоскость-точка на прямой то рисуем сплошной
		if (isCrossLines || isPlanePointOnLine)
		{
			canva->Pen->Style = psSolid;
			canva->MoveTo(convert(N).x, convert(N).y);
			canva->LineTo(convert(M).x, convert(M).y);
		}
	}


	//Делаем перо черным
	canva->Pen->Color = clBlack;
	//и сплошным
	canva->Pen->Style=psSolid;

	//Рисуем точку A
	canva->Ellipse(convert(A).x-3, convert(A).y-3, convert(A).x+3, convert(A).y+3);
	//Рисуем точку B
	canva->Ellipse(convert(B).x-3, convert(B).y-3, convert(B).x+3, convert(B).y+3);
	//Рисуем точку C
	canva->Ellipse(convert(C).x-3, convert(C).y-3, convert(C).x+3, convert(C).y+3);
	//Рисуем точку N
	canva->Ellipse(convert(N).x-3, convert(N).y-3, convert(N).x+3, convert(N).y+3);
	//Рисуем точку M
	canva->Ellipse(convert(M).x-3, convert(M).y-3, convert(M).x+3, convert(M).y+3);
	if (isExistCrossPoint)
	//Рисуем точку T
	canva->Ellipse(convert(T).x-3, convert(T).y-3, convert(T).x+3, convert(T).y+3);

	//Подписываем точку A
	canva->TextOutA(convert(A).x+5, convert(A).y-18, "A");
	//Подписываем точку B
	canva->TextOutA(convert(B).x+5, convert(B).y-18, "B");
	//Подписываем точку C
	canva->TextOutA(convert(C).x+5, convert(C).y-18, "C");
	//Подписываем точку N
	canva->TextOutA(convert(N).x+5, convert(N).y-18, "N");
	//Подписываем точку M
	canva->TextOutA(convert(M).x+5, convert(M).y-18, "M");
	if (isExistCrossPoint)
	//Подписываем точку T
	canva->TextOutA(convert(T).x+5, convert(T).y-18, "T");
	
	
}
point2D Tspatial::convert(point3D point)
{
	point2D tempPoint;
	tempPoint.x = O.x + point.x;
	tempPoint.y = O.y - point.y;

	return tempPoint;
}

float Tspatial::radian(float alpha)
{
	return (float)((float)alpha*M_PI/(float)180.0f);
}

bool Tspatial::ifLineOut()
{
	if (convert(A).x < 0 || convert(A).x > O.x*2 || convert(A).y < 0 || convert(A).y > O.y*2)
		return true;

	if (convert(B).x < 0 || convert(B).x > O.x*2 || convert(B).y < 0 || convert(B).y > O.y*2)
		return true;

	if (convert(C).x < 0 || convert(C).x > O.x*2 || convert(C).y < 0 || convert(C).y > O.y*2)
		return true;

	if (convert(M).x < 0 || convert(M).x > O.x*2 || convert(M).y < 0 || convert(M).y > O.y*2)
		return true;

	if (convert(N).x < 0 || convert(N).x > O.x*2 || convert(N).y < 0 || convert(N).y > O.y*2)
		return true;

	return false;
}

void Tspatial::setA(int valueX, int valueY, int valueZ)
{
	AReal.x = valueX;
	AReal.y = valueY;
	AReal.z = valueZ;
}

void Tspatial::setB(int valueX, int valueY, int valueZ)
{
	BReal.x = valueX;
	BReal.y = valueY;
	BReal.z = valueZ;
}

void Tspatial::setC(int valueX, int valueY, int valueZ)
{
	CReal.x = valueX;
	CReal.y = valueY;
	CReal.z = valueZ;
}

void Tspatial::setN(int valueX, int valueY, int valueZ)
{
	NReal.x = valueX;
	NReal.y = valueY;
	NReal.z = valueZ;
}

void Tspatial::setM(int valueX, int valueY, int valueZ)
{
	MReal.x = valueX;
	MReal.y = valueY;
	MReal.z = valueZ;
}

point3D Tspatial::getA()
{
	return AReal;
}

point3D Tspatial::getB()
{
	return BReal;
}

point3D Tspatial::getC()
{
	return CReal;
}

point3D Tspatial::getN()
{
	return NReal;
}

point3D Tspatial::getM()
{
	return MReal;
}

void Tspatial::SetE(int value)
{
	E=value;
}
TPlaneType Tspatial::getPlaneType()
{
	float k = E/10000;

	//Плоскость является точкой
	if (fabs(C.x-A.x)<=k && fabs(C.x-B.x)<=k && fabs(C.y-A.y)<=k && fabs(C.y-B.y)<=k && fabs(C.z-A.z)<=k && fabs(C.z-B.z)<=k)
	{
		Form1->LabelPlane->Caption = "Плоскость - точка";
		return tpPoint;
	}

	//Плоскость является прямой
	//Параметрическое уравнение прямой
	float ur1=(CReal.x-AReal.x)*(BReal.y-AReal.y)-(CReal.y-AReal.y)*(BReal.x-AReal.x);
	float ur2=(CReal.x-AReal.x)*(BReal.z-AReal.z)-(CReal.z-AReal.z)*(BReal.x-AReal.x);
	float ur3=(CReal.y-AReal.y)*(BReal.z-AReal.z)-(CReal.z-AReal.z)*(BReal.y-AReal.y);

	if (fabs(ur1) < E/100 && fabs(ur2) < E/100 && fabs(ur3) < E/100)
	{
		Form1->LabelPlane->Caption = "Плоскость - прямая";
		return tpLine;
	}

	//Плоскость является плоскостью
	Form1->LabelPlane->Caption = "Плоскость - плоскость";
	return tpPlane;
}

TLineType Tspatial::getLineType()
{
	float k = E/10000;

	if(fabs(M.x-N.x) <= k && fabs(M.y-N.y) <= k && fabs(M.z-N.z) <= k)
	{
		Form1->LabelLine->Caption = "Отрезок - точка";
		return tlPoint;
	}


	//Прямая является прямой
	Form1->LabelLine->Caption = "Отрезок - отрезок";
	return tlLine;
}

void Tspatial::findCrossPoint()
{
	isExistCrossPoint = false;
	isCrossLines = false;
	isPlanePointOnLine = false;

	//Скалярное произведение точек прямой на коэф. плоскости
	ScalM = myltiplyPoint(MReal);
	ScalN = myltiplyPoint(NReal);

	//Узнаем типы прямой и плоскости
	TPlaneType plType = getPlaneType();
	TLineType lnType = getLineType();

	//нет точки пересечения
	if ((ScalM<-E && ScalN<-E) || (ScalM>E && ScalN>E))
	{
		Form1->LabelResult->Caption = "Нет точки перечения";
		return;
	}

	//есть точка пересечения и плоскость является плоскостью а прямая прямой
	if (((ScalM<-E && ScalN>E) || (ScalM>E && ScalN<-E)) && plType == tpPlane && lnType == tlLine)
	{
		isExistCrossPoint = true;

		float t = getT();

		TReal.x = NReal.x + t*(MReal.x - NReal.x);
		TReal.y = NReal.y + t*(MReal.y - NReal.y);
		TReal.z = NReal.z + t*(MReal.z - NReal.z);

		Form1->LabelResult->Caption = "Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
	}

	//Точка М лежит на плоскости, которая имеет вид плоскости
	if (fabs(ScalM)<=E && fabs(ScalN) > E && plType == tpPlane && lnType == tlLine)
	{
		isExistCrossPoint = true;

		TReal.x = MReal.x;
		TReal.y = MReal.y;
		TReal.z = MReal.z;

		Form1->LabelResult->Caption = "Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
	}

	//Точка N лежит на плоскости, которая имеет вид плоскости
	if (fabs(ScalN)<=E && fabs(ScalM) > E && plType == tpPlane && lnType == tlLine)
	{
		isExistCrossPoint = true;

		TReal.x = NReal.x;
		TReal.y = NReal.y;
		TReal.z = NReal.z;

		Form1->LabelResult->Caption = "Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
	}

	//Прямая лежит на плоскости, которая имеет вид плоскости
	if (fabs(ScalM)<=E && fabs(ScalN)<=E && plType == tpPlane && lnType == tlLine)
	{
		Form1->LabelResult->Caption = "Отрезок лежит на плоскости.";
	}

	//Прямая в виде точки лежит на плоскости
	if (fabs(ScalM)<=E && plType == tpPlane && lnType == tlPoint)
	{
		isExistCrossPoint = true;

		TReal.x = MReal.x;
		TReal.y = MReal.y;
		TReal.z = MReal.z;

		Form1->LabelResult->Caption = "Прямая, в виде точки лежит на плоскости. Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
	}

	//Прямая в виде точки, плоскость в виде прямой
	if (plType == tpLine && lnType == tlPoint)
	{
		//Подставляем прямую(точку) в уравнение
		float ur1=(MReal.x-BReal.x)*(CReal.y-BReal.y)-(MReal.y-BReal.y)*(CReal.x-BReal.x);
		float ur2=(MReal.x-BReal.x)*(CReal.z-BReal.z)-(MReal.z-BReal.z)*(CReal.x-BReal.x);
		float ur3=(MReal.y-BReal.y)*(CReal.z-BReal.z)-(MReal.z-BReal.z)*(CReal.y-BReal.y);

		float k = E/1000;

		if(fabs(ur1)<=k && fabs(ur2)<=k && fabs(ur3)<=k)
		{
			isExistCrossPoint = true;

			TReal.x = MReal.x;
			TReal.y = MReal.y;
			TReal.z = MReal.z;

			Form1->LabelResult->Caption = "Прямая, в виде точки лежит на плоскости, которая имеет вид прямой. Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
		}
		else
			Form1->LabelResult->Caption = "Прямая, в виде точки не принадлежит плоскости, которая имеет вид прямой";
	}

	//Прямая в виде прямой, а плоскость в виде точки
	if (plType == tpPoint && lnType == tlLine)
	{
		//Алгоритм: точка принадлежит отрезку, если сумма растояний от концов отрезков до точки
		//равна длине отрезка

		//Расстояние от М до точки (плоскости)
		float dist1 = sqrt((M.x-A.x)*(M.x-A.x) + (M.y-A.y)*(M.y-A.y) + (M.z-A.z)*(M.z-A.z));
		//Расстояние от N до точки (плоскости)
		float dist2 = sqrt((A.x-N.x)*(A.x-N.x) + (A.y-N.y)*(A.y-N.y) + (A.z-N.z)*(A.z-N.z));
		//Длина отрезка MN
		float dist3 = sqrt((M.x-N.x)*(M.x-N.x) + (M.y-N.y)*(M.y-N.y) + (M.z-N.z)*(M.z-N.z));

		float k = E/1000;

		if (fabs(dist1+dist2-dist3) <= k)
		{
			isExistCrossPoint = true;
			isPlanePointOnLine = true;

			TReal.x = AReal.x;
			TReal.y = AReal.y;
			TReal.z = AReal.z;

			Form1->LabelResult->Caption = "Плоскость, в виде точки принадлежит прямой. Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
		}
		else
			Form1->LabelResult->Caption = "Плоскость, в виде точки не принадлежит прямой.";
	}

	//Прямая в виде точки совпадает с плоскостью в виде точки
	if (plType == tpPoint && lnType == tlPoint)
	{
		float k = E/1000;

		if (fabs(M.x-A.x)<k && fabs(M.y-A.y)<k && fabs(M.z-A.z)<k)
		{
			isExistCrossPoint = true;

			TReal.x = AReal.x;
			TReal.y = AReal.y;
			TReal.z = AReal.z;

			Form1->LabelResult->Caption = "Прямая в виде точки совпадает с плоскостью (точкой). Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
		}
		else
			Form1->LabelResult->Caption = "Прямая в виде точки не совпадает с плоскостью (точкой).";
	}

	//Плоскость в виде прямой и прямая в виде прямой
	if (plType == tpLine && lnType == tlLine)
	{
		double x=0,y=0,z=0,xa1,xp1,ya1,yp1,za1,zp1,l1,l2,m1,m2,n1,n2;

		//Плоскость-прямая у нас определяется с погрешностью поэтому за 2 точки
		//плоскости-прямой берем точки расстояние между которыми наибольшее
		double p1p2 = sqrt((AReal.x-BReal.x)*(AReal.x-BReal.x) + (AReal.y-BReal.y)*(AReal.y-BReal.y) + (AReal.z-BReal.z)*(AReal.z-BReal.z) );
		double p1p3 = sqrt((AReal.x-CReal.x)*(AReal.x-CReal.x) + (AReal.y-CReal.y)*(AReal.y-CReal.y) + (AReal.z-CReal.z)*(AReal.z-CReal.z) );
		double p2p3 = sqrt((BReal.x-CReal.x)*(BReal.x-CReal.x) + (BReal.y-CReal.y)*(BReal.y-CReal.y) + (BReal.z-CReal.z)*(BReal.z-CReal.z) );

		if (p1p2>=p1p3 && p1p2>=p2p3)
		{
			xp1=AReal.x; l2=BReal.x-AReal.x;
			yp1=AReal.y; m2=BReal.y-AReal.y;
			zp1=AReal.z; n2=BReal.z-AReal.z;
		}

		if (p1p3>=p1p2 && p1p3>=p2p3)
		{
			xp1=AReal.x; l2=CReal.x-AReal.x;
			yp1=AReal.y; m2=CReal.y-AReal.y;
			zp1=AReal.z; n2=CReal.z-AReal.z;
		}

		if (p2p3>=p1p2&&p2p3>=p1p3)
		{
			xp1=BReal.x; l2=CReal.x-BReal.x;
			yp1=BReal.y; m2=CReal.y-BReal.y;
			zp1=BReal.z; n2=CReal.z-BReal.z;
		}


		xa1=MReal.x; ya1=MReal.y; za1=MReal.z;
		l1=NReal.x-xa1; m1=NReal.y-ya1; n1=NReal.z-za1;

		//определим лежат ли в одной плоскости
		if(fabs((xp1-xa1)*m1*n2+(zp1-za1)*l1*m2+(yp1-ya1)*n1*l2-(zp1-za1)*m1*l2-(xp1-xa1)*n1*m2-(yp1-ya1)*l1*n2) <= E)
		{
			Form1->LabelResult->Caption = "Прямые лежат в одной плоскости.";
		}
		else
		{
			Form1->LabelResult->Caption = "Прямые скрещиваются!";
			return;
		}

		//метод крамера
		double ta=0;
		double d1,d2,d3;//определители

		d1 = -l1*m2 + l2*m1;
		d2 = -l1*n2 + l2*n1;
		d3 = -m1*n2 + m2*n1;

		if(d1==0 && d2==0 && d3==0)
		{
			Form1->LabelResult->Caption = "Прямые параллельны или совпадают";
			return;
		}

		if( d1!=0 )
		{
			ta = (-(xp1-xa1)*m2+l2*(yp1-ya1))/d1;
			x=xa1+l1*ta;
			y=ya1+m1*ta;
			z=za1+n1*ta;
		}
		else if ( d2!=0 )
		{
			ta = (-n2*(xp1-xa1)+l2*(zp1-za1))/d2;
			x=xa1+l1*ta;
			y=ya1+m1*ta;
			z=za1+n1*ta;
		}
		else if ( d3!=0 )
		{
			ta = (-n2*(yp1-ya1)+m2*(zp1-za1))/d3;
			x=xa1+l1*ta;
			y=ya1+m1*ta;
			z=za1+n1*ta;
		}


		TReal.x = x;
		TReal.y = y;
		TReal.z = z;

		//Мы нашли точку пересечения прямых. А Теперь нужно определить принадлежит ли точка пересечения отрезку [M N]
		//Делается это так: Точка принадлежит отрезку, если сумма расстояний от этой точки до конечных точек отрезка равна длине отрезка
		double a = sqrt((MReal.x-TReal.x)*(MReal.x-TReal.x) + (MReal.y-TReal.y)*(MReal.y-TReal.y) + (MReal.z-TReal.z)*(MReal.z-TReal.z) );//расстояние от M до точки пересечения
		double b = sqrt((TReal.x-NReal.x)*(TReal.x-NReal.x) + (TReal.y-NReal.y)*(TReal.y-NReal.y) + (TReal.z-NReal.z)*(TReal.z-NReal.z) );//расстояние от точки пересечения до A2
		double c = sqrt((MReal.x-NReal.x)*(MReal.x-NReal.x) + (MReal.y-NReal.y)*(MReal.y-NReal.y) + (MReal.z-NReal.z)*(MReal.z-NReal.z) );//расстояние от A1 до A2

		float k = E/10000;

		if(fabs(a+b-c) <= k)
		{
			isExistCrossPoint = true;
			isCrossLines = true;
			Form1->LabelResult->Caption = "Прямые пересекаются. Точка пересечения T("+IntToStr((int)TReal.x)+", "+IntToStr((int)TReal.y)+", "+IntToStr((int)TReal.z)+")";
			return;
		}
		else
		{
			Form1->LabelResult->Caption = "Нет точки пересечения прямых.";
			return;
		}
	}
}

float Tspatial::getT()
{
	float t = -(float)(planeKoef.a*NReal.x + planeKoef.b*NReal.y +  planeKoef.c*NReal.z + planeKoef.d)/(float)(planeKoef.a*(MReal.x-NReal.x) + planeKoef.b*(MReal.y-NReal.y) + planeKoef.c*(MReal.z-NReal.z));

	return t;
}

float Tspatial::myltiplyPoint(point3D point, bool isCamera)
{
	if (isCamera)
		if (proection==PERSPECT)
			return point.x*planeKoef.a + point.y*planeKoef.b + point.z*planeKoef.c + planeKoef.d;
		else
			return point.x*planeKoef.a + point.y*planeKoef.b + point.z*planeKoef.c;
	else
		return point.x*planeKoef.a + point.y*planeKoef.b + point.z*planeKoef.c + planeKoef.d;
}

void Tspatial::findK()
{
	planeKoef.a = (AReal.y-BReal.y)*(AReal.z+BReal.z) + (BReal.y-CReal.y)*(BReal.z+CReal.z)+ (CReal.y-AReal.y)*(CReal.z+AReal.z);
	planeKoef.b = (AReal.z-BReal.z)*(AReal.x+BReal.x) + (BReal.z-CReal.z)*(BReal.x+CReal.x)+ (CReal.z-AReal.z)*(CReal.x+AReal.x);
	planeKoef.c = (AReal.x-BReal.x)*(AReal.y+BReal.y) + (BReal.x-CReal.x)*(BReal.y+CReal.y)+ (CReal.x-AReal.x)*(CReal.y+AReal.y);
	planeKoef.d = -(planeKoef.a*AReal.x + planeKoef.b*AReal.y + planeKoef.c*AReal.z);

	float value1 = -(planeKoef.a*AReal.x + planeKoef.b*AReal.y + planeKoef.c*AReal.z);
	float value2 = -(planeKoef.a*BReal.x + planeKoef.b*BReal.y + planeKoef.c*BReal.z);
	float value3 = -(planeKoef.a*CReal.x + planeKoef.b*CReal.y + planeKoef.c*CReal.z);

	//Скалярное произведение точки наблюдателя на коэф. плоскости
	float ScalCamera = myltiplyPoint(Camera, true);

	if (ScalCamera < 0)
	{
		//Перенаправляем плоскость
		planeKoef.a = -planeKoef.a;
		planeKoef.b = -planeKoef.b;
		planeKoef.c = -planeKoef.c;
		planeKoef.d = -planeKoef.d;
	}

	isFrontal = false;
	TPlaneType type = getPlaneType();
	if (type == tpPlane && fabs(ScalCamera) < E)
	isFrontal = true;
}

#pragma package(smart_init)
Соседние файлы в папке KG3