/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Cubic::ComputeLocalBasis( GW_GeodesicFace& Face )
{
    if( !bIsLocalBasisComputed_ )
    {
        GW_GeodesicVertex* pV0 = (GW_GeodesicVertex*) Face.GetVertex(0);    GW_ASSERT( pV0!=NULL );
        GW_GeodesicVertex* pV1 = (GW_GeodesicVertex*) Face.GetVertex(1);    GW_ASSERT( pV1!=NULL );
        GW_GeodesicVertex* pV2 = (GW_GeodesicVertex*) Face.GetVertex(2);    GW_ASSERT( pV2!=NULL );
        GW_Vector3D& V0 = pV0->GetPosition();
        GW_Vector3D& V1 = pV1->GetPosition();
        GW_Vector3D& V2 = pV2->GetPosition();
        GW_Vector3D e0 = V0-V2;
        GW_Vector3D e1 = V1-V2;
        GW_Vector3D e2 = V1-V0;
        u = e0/e0.Norm();
        v = ( (u^e1)^u );
        v.Normalize();
        w = V2;
    }
    bIsLocalBasisComputed_ = GW_True;
}
/*------------------------------------------------------------------------------*/
void GW_TriangularInterpolation_Cubic::SetUpTriangularInterpolation( GW_GeodesicFace& Face )
{
    /* retrieve vertex and length */
    GW_GeodesicVertex* pV0 = (GW_GeodesicVertex*) Face.GetVertex(0);    GW_ASSERT( pV0!=NULL );
    GW_GeodesicVertex* pV1 = (GW_GeodesicVertex*) Face.GetVertex(1);    GW_ASSERT( pV1!=NULL );
    GW_GeodesicVertex* pV2 = (GW_GeodesicVertex*) Face.GetVertex(2);    GW_ASSERT( pV2!=NULL );

    GW_Face* pFace0 = Face.GetFaceNeighbor(0);
    GW_Face* pFace1 = Face.GetFaceNeighbor(1);
    GW_Face* pFace2 = Face.GetFaceNeighbor(2);
    GW_GeodesicVertex *pW0 = NULL, *pW1 = NULL, *pW2 = NULL;

    if( pFace0!=NULL )
        pW0 = (GW_GeodesicVertex*) pFace0->GetVertex( *pV1, *pV2 );
    if( pFace1!=NULL )
        pW1 = (GW_GeodesicVertex*) pFace1->GetVertex( *pV0, *pV2 );
    if( pFace2!=NULL )
        pW2 = (GW_GeodesicVertex*) pFace2->GetVertex( *pV0, *pV1 );

    GW_Vector3D& V0 = pV0->GetPosition();
    GW_Vector3D& V1 = pV1->GetPosition();
    GW_Vector3D& V2 = pV2->GetPosition();
    GW_Vector3D W0, W1, W2;

    if( pW0!=NULL )
        W0 = pW0->GetPosition();
    else
        W0 = (V1+V2)*0.5;
    if( pW1!=NULL )
        W1 = pW1->GetPosition();
    else
        W1 = (V0+V1)*0.5;
    if( pW2!=NULL )
        W2 = pW2->GetPosition();
    else
        W2 = (V0+V1)*0.5;

    /* edge of the main triangle */
    GW_Vector3D e0 = V0-V2;
    GW_Vector3D e1 = V1-V2;
    GW_Vector3D e2 = V1-V0;
    /* edge of side triangles */
    GW_Vector3D s0 = W0 - V2;
    GW_Vector3D s1 = W1 - V2;
    GW_Vector3D s2 = W2 - V0;

    GW_Float l0 = ~e0;
    GW_Float l1 = ~e1;
    GW_Float l2 = ~e2;
    GW_Float m0 = ~s0;
    GW_Float m1 = ~s1;
    GW_Float m2 = ~s2;


    /* compute the orthonormal basis in which the interpolation is performed */
    u = e0/l0;
    v = ( (u^e1)^u );
    v.Normalize();
    w = V2;    // origin

    /* now compute angles */
    GW_Float a = acos( (e0*e1)/(l0*l1) );
    GW_Float b = acos( (e1*s0)/(l1*m0) );
    GW_Float c = acos( (e0*s1)/(l0*m1) );
    GW_Float d = acos(-(e0*e2)/(l0*l2) );
    GW_Float e = acos( (e2*s2)/(l2*m2) );

    /* compute 2D position of points.
    Point 0,1,2 are V0,V1,V2    Points 3,4,5 are W0,W1,W2 */
    GW_Float Points[6][2];

    Points[0][0] = l0;
    Points[0][1] = 0;

    Points[1][0] = l1*cos(a);
    Points[1][1] = l1*sin(a);

    Points[2][0] = 0;
    Points[2][1] = 0;


    Points[3][0] =  m0*cos(a+b);
    Points[3][1] =  m0*sin(a+b);

    Points[4][0] =  m1*cos(c);
    Points[4][1] = -m1*sin(c);

    Points[5][0] =  l0 - m2*cos(d+e);
    Points[5][1] =  m2*sin(d+e);

    /* compute values */
    GW_Float Values[6];
    Values[0] = pV0->GetDistance();
    Values[1] = pV1->GetDistance();
    Values[2] = pV2->GetDistance();

    if( pW0!=NULL )
        Values[3] = pW0->GetDistance();
    else
        Values[3] = (Values[1]+Values[2])*0.5;

    if( pW1!=NULL )
        Values[4] = pW1->GetDistance();
    else
        Values[4] = (Values[0]+Values[2])*0.5;

    if( pW2!=NULL )
        Values[5] = pW2->GetDistance();
    else
        Values[5] = (Values[0]+Values[1])*0.5;

    /* compute the coefficients, given in that order : 0->cst, 1->X, 2->Y, 3->XY, 4->X^2, 5->Y^2. */
    GW_Maths::Fit2ndOrderPolynomial2D( Points, Values, Coeffs );
}
/*------------------------------------------------------------------------------*/
void GW_GeodesicDisplayer::DisplayPath( GW_GeodesicPath& CurPath, GW_Vector3D& Color, GW_Float rLineWidth )
{
	glLineWidth( (GLfloat) rLineWidth );
	glPointSize( (GLfloat) rLineWidth );
	T_GeodesicPointList& PointList = CurPath.GetPointList();
	glDisable( GL_LIGHTING );
	glColor( Color );
	glBegin( GL_LINE_STRIP );
	for( IT_GeodesicPointList it = PointList.begin(); it!=PointList.end(); ++it )
	{
		GW_GeodesicPoint* pPoint = *it;
		GW_ASSERT( pPoint->GetVertex1()!=NULL );
		GW_ASSERT( pPoint->GetVertex2()!=NULL );
		GW_Vector3D Pos = pPoint->GetVertex1()->GetPosition()*pPoint->GetCoord() + 
						  pPoint->GetVertex2()->GetPosition()*(1-pPoint->GetCoord());
		glColor( Color );
		glVertex( Pos );
		GW_GeodesicFace* pFace = pPoint->GetCurFace();
		GW_ASSERT( pFace!=NULL );
		T_SubPointVector& SubPointVector = pPoint->GetSubPointVector();
		GW_Vector3D& v0 = pPoint->GetVertex1()->GetPosition();
		GW_Vector3D& v1 = pPoint->GetVertex2()->GetPosition();
		GW_Vertex* pLastVert = pFace->GetVertex( *pPoint->GetVertex1(), *pPoint->GetVertex2() );
		GW_ASSERT( pLastVert!=NULL );
		GW_Vector3D& v2 = pLastVert->GetPosition();
		for( IT_SubPointVector it=SubPointVector.begin(); it!=SubPointVector.end(); ++it )
		{
			GW_Vector3D& coord = *it;
			Pos = v0*coord[0] + v1*coord[1] + v2*coord[2];
			glVertex( Pos );
		}
	}
	glEnd();
#if 0
	glColor3f( 0,0,0 );
	glPointSize(4);
	glBegin( GL_POINTS );
	for( IT_GeodesicPointList it = PointList.begin(); it!=PointList.end(); ++it )
	{
		GW_GeodesicPoint* pPoint = *it;
		GW_ASSERT( pPoint->GetVertex1()!=NULL );
		GW_ASSERT( pPoint->GetVertex2()!=NULL );
		GW_Vector3D Pos = pPoint->GetVertex1()->GetPosition()*pPoint->GetCoord() + 
			pPoint->GetVertex2()->GetPosition()*(1-pPoint->GetCoord());
		glVertex( Pos );
		GW_GeodesicFace* pFace = pPoint->GetCurFace();
		GW_ASSERT( pFace!=NULL );
		T_SubPointVector& SubPointVector = pPoint->GetSubPointVector();
		GW_Vector3D& v0 = pPoint->GetVertex1()->GetPosition();
		GW_Vector3D& v1 = pPoint->GetVertex2()->GetPosition();
		GW_Vertex* pLastVert = pFace->GetVertex( *pPoint->GetVertex1(), *pPoint->GetVertex2() );
		GW_ASSERT( pLastVert!=NULL );
		GW_Vector3D& v2 = pLastVert->GetPosition();
		for( IT_SubPointVector it=SubPointVector.begin(); it!=SubPointVector.end(); ++it )
		{
			GW_Vector3D& coord = *it;
			Pos = v0*coord[0] + v1*coord[1] + v2*coord[2];
			glVertex( Pos );
		}
	}
	glEnd();

	glEnable( GL_LIGHTING );
	glLineWidth( 1 );
#endif
}