//-----------------------------------------------------------------------------------------------
// ConvexPolygon2D.cpp
//
#include "GypsyPrecompiledHeader.hpp"

//-----------------------------------------------------------------------------------------------
#include "Engine/Core/ConvexPolygon2D.hpp"
#include "Engine/Core/ErrorWarningAssert.hpp"
#include <stdlib.h>


//-----------------------------------------------------------------------------------------------
ConvexPolygon2D::ConvexPolygon2D( const char* asText )
{
	SetFromText( asText );
}


//-----------------------------------------------------------------------------------------------
void ConvexPolygon2D::SetFromText( const char* asText )
{
	UNUSED( asText );
	FATAL_ERROR( "ConvexPolygon2D::SetFromText() not yet implemented!" );
}


//-----------------------------------------------------------------------------------------------
void ConvexPolygon2D::ClipToBackOfLine( const LineSegment2D& line )
{
	if( m_ccwVertexes.empty() )
		return;

	const int MAX_STACK_LOCAL_VERTEXES = -1;
	int numStartingVertexes = (int) m_ccwVertexes.size();
	if( numStartingVertexes <= MAX_STACK_LOCAL_VERTEXES )
	{
		FATAL_ERROR( "ConvexPolygon2D::ClipToBackOfLine() - stack local case not yet implemented" );
	}
	else
	{
		std::vector< Vector2 > oldVertexes = m_ccwVertexes;
		m_ccwVertexes.clear(); // We don't use the swap() trick here since it's likely to realloc to the same size
		for( int vertexIndex = 0; vertexIndex < (int) oldVertexes.size(); ++ vertexIndex )
		{
			Vector2& startVertex = oldVertexes[ vertexIndex ];
			Vector2& endVertex = (vertexIndex == numStartingVertexes-1) ? oldVertexes[ 0 ] : oldVertexes[ vertexIndex + 1 ];
			bool isStartVertexBehind = line.IsPointOnOrBehind( startVertex );
			bool isEndVertexBehind = line.IsPointOnOrBehind( endVertex );
			if( isStartVertexBehind )
				m_ccwVertexes.push_back( startVertex );

			if( isStartVertexBehind != isEndVertexBehind )
			{
				Vector2 newVertex = CalcLineCrossoverPoint( line, startVertex, endVertex );
				m_ccwVertexes.push_back( newVertex );
			}
		}
	}

}


//-----------------------------------------------------------------------------------------------
void ConvexPolygon2D::ClipToFrontOfLine( const LineSegment2D& line )
{
	LineSegment2D reversedLine( line );
	reversedLine.ScaleLength( -1.f );
	ClipToBackOfLine( reversedLine );
}


//-----------------------------------------------------------------------------------------------
Vector2 ConvexPolygon2D::CalcLineCrossoverPoint( const LineSegment2D& line, const Vector2& pointOnOneSide, const Vector2& pointOnOtherSide ) const
{
	Vector2 startToOne = pointOnOneSide - line.m_startPosition;
	Vector2 startToOther = pointOnOtherSide - line.m_startPosition;
	Vector2 perpendicular( -line.m_displacement.y, line.m_displacement.x ); // Note: Non-normalized
	float perpendicularDotToOne = DotProduct( startToOne, perpendicular ); // Not true projections/distances, as perpendicular is non-normalized
	float perpendicularDotToOther = DotProduct( startToOther, perpendicular );
	if( perpendicularDotToOne == 0.f )
		return pointOnOneSide;

	if( perpendicularDotToOther == 0.f )
		return pointOnOtherSide;

	if( perpendicularDotToOne * perpendicularDotToOther > 0.f )
		return pointOnOneSide;

	float totalPerpendicularDistance = perpendicularDotToOne - perpendicularDotToOther; // Should be guaranteed positive by this point.  Subtract because signs are opposite.
	float lerpFractionFromOneToOther = perpendicularDotToOne / totalPerpendicularDistance;
	return pointOnOneSide + lerpFractionFromOneToOther * (pointOnOtherSide - pointOnOneSide);
}


