/*  $Id: triangle_math.cpp,v 1.2 2004/04/05 09:51:58 sphair Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
**
*/

#include "Core/precomp.h"
#include <cmath>
#include "API/Core/Math/triangle_math.h"

/*
	---- from comp.graphics.algorithms FAQ ----

	calculate the barycentric coordinates
	for a triangle {(x1,y1), (x2,y2), (x3,y3)} and some point (x0,y0)

	Then if b1, b2, and b3 are all > 0, (x0,y0) is strictly inside the triangle;

	if bi = 0 and the other two coordinates are positive,
	(x0,y0) lies on the edge opposite (xi,yi);
	
	if bi and bj = 0, (x0,y0) lies on (xk,yk); if bi < 0,
	(x0,y0) lies outside the edge opposite (xi,yi);

	if all three coordinates are negative, something else is wrong.
*/

bool CL_TriangleMath::point_inside_triangle(const CL_Pointf &P, float *vertices, bool on_edge_is_outside)
{
	return point_inside_triangle(P.x, P.y, vertices, on_edge_is_outside);
}

bool CL_TriangleMath::point_inside_triangle( float px, float py, float *vertices, bool on_edge_is_outside)
{
	const float &tx0 = vertices[0];
	const float &ty0 = vertices[1];
	const float &tx1 = vertices[2];
	const float &ty1 = vertices[3];
	const float &tx2 = vertices[4];
	const float &ty2 = vertices[5];

	float b0 =  (tx1 - tx0) * (ty2 - ty0) - (tx2 - tx0) * (ty1 - ty0);
	float b1 = ((tx1 - px)  * (ty2 - py)  - (tx2 - px)  * (ty1 - py)) / b0;
	float b2 = ((tx2 - px)  * (ty0 - py)  - (tx0 - px)  * (ty2 - py)) / b0;
	float b3 = ((tx0 - px)  * (ty1 - py)  - (tx1 - px)  * (ty0 - py)) / b0;
	
	if( (b1 > 0 && b2 > 0 && b3 > 0) ) // strictly inside
	{
		return true;
	}
	
	if( on_edge_is_outside == false ) // on edge?
		if( (b1>=0 && b2>=0 && b3>=0) && (b1+b2+b3) >= 0 )  
			return true;
	
	return false;
}
