// Face.cpp : implementation of the CFace class
//

#include "stdafx.h"

#include "Face.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// C3DPoint construction/destruction

CFace::CFace()
{
	// TODO: add one-time construction code here

}

CFace::~CFace()
{
	//delete the list of points
	int count = m_points.GetCount();
	while (count > 0){
		C3DPoint* obj = m_points.RemoveHead();
		delete(obj);
		count--;
	}
}


/////////////////////////////////////////////////////////////////////////////
// CFace serialization

void CFace::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

void CFace::AddPoint(C3DPoint* point)
{
	m_points.AddTail(point);
}

//return true if this face is in between the given two points
C3DPoint* CFace::IsInBetween(C3DPoint p1, C3DPoint p2)
{
	C3DPoint planeVect = p1 - m_centerPoint;
	C3DPoint lineVect = p2 - p1;
	double dResult1 = m_normalPoint.DotProduct(planeVect);
	double dResult2 = m_normalPoint.DotProduct(lineVect);

	double dT = 0;
	C3DPoint intersect;
	if (dResult2 != 0)
	{
		dT = (dResult1 / dResult2) * -1;
		//if dt is between 0 and 1 its between these two points
		if (!(dT >= 0 && dT <= 1))
			return NULL;
		//this gives us what we need for the equation
		intersect = p1 + ((p2 - p1) * dT);
	}
	else
	{
		//we are dealing with the same plane
		//intersect = p1 + (p2 - p1);
		return NULL;
	}

	//so we need so see if this point is in this face
	//create a plane for each point and make sure the 
	//distance from point is positive for all of them
	CList<CFace* , CFace* > planes;
	POSITION pos = m_points.GetHeadPosition();
	while (pos != NULL)
	{
			C3DPoint* point1 = m_points.GetAt(pos);
			CFace* node = new CFace();
			node->AddPoint(new C3DPoint(point1));
			m_points.GetNext(pos);
			if (pos == NULL)
			{
				//we are at the end so use the starting point
				POSITION posHead = m_points.GetHeadPosition();
				C3DPoint* pointHead = m_points.GetAt(posHead);
				node->AddPoint(new C3DPoint(pointHead));
				node->AddPoint(new C3DPoint(&(*pointHead + m_normalPoint)));
			}
			else
			{
				C3DPoint* point2 = m_points.GetAt(pos);
				node->AddPoint(new C3DPoint(point2));
				node->AddPoint( new C3DPoint(&(*point2 + m_normalPoint)));
				//want to go back one point
				//so we start off with the second one
				//so don't advance here
			}
			node->CalculateNormalAndCenter();
			planes.AddHead(node);
	}

	//now sequnce through planes and make sure we are
	//a positive distance from all of them
	pos = planes.GetHeadPosition();
	BOOL bNoGood = false;
	while(pos)
	{
		CFace *TestNode = planes.GetAt(pos);
		C3DPoint vDistance = TestNode->m_centerPoint - intersect;
		long double dDistance = TestNode->m_normalPoint.DotProduct(vDistance) / (TestNode->m_normalPoint.DotProduct(TestNode->m_normalPoint));
		if (dDistance < 0)
			bNoGood = true;
		
		planes.GetNext(pos);
	
	}
	
	//now deallocate all the memory we allocated here
	int count = planes.GetCount();
	while (count > 0){
		CFace* obj = planes.RemoveHead();
		delete(obj);
		count--;
	}
	if (bNoGood)
		return NULL;
	else
		return new C3DPoint(&intersect);
	
}

void CFace::CalculateNormalAndCenter(void)
{
	//do the center
	m_centerPoint.m_x = m_centerPoint.m_y = m_centerPoint.m_z = 0.0;

	POSITION pos = m_points.GetHeadPosition();
	while (pos != NULL)
	{
			C3DPoint* point = m_points.GetAt(pos);
			m_centerPoint.m_x += point->m_x;
			m_centerPoint.m_y += point->m_y;
			m_centerPoint.m_z += point->m_z;
			m_points.GetNext(pos);
	}

	m_centerPoint.m_x /= m_points.GetCount();
	m_centerPoint.m_y /= m_points.GetCount();
	m_centerPoint.m_z /= m_points.GetCount();

	//do the normal
	C3DPoint a, b, c;
	C3DPoint n1, n2;
	pos = m_points.GetHeadPosition();
	a = *m_points.GetAt(pos);
	m_points.GetNext(pos);
	b = *m_points.GetAt(pos);
	m_points.GetNext(pos);
	c = *m_points.GetAt(pos);
	m_points.GetNext(pos);

	n1 = b - a;
	n2 = c - a;

	m_normalPoint = n1.CrossProduct(n2);
	m_normalPoint.Normalize();

	if (m_normalPoint.m_z < 0)
	{
		int x = 5;
		//m_normalPoint.m_z = abs(m_normalPoint.m_z);

	}

}

