/******************************************************************************
* CBzr_Pwr.c - Bezier to pawer basis conversion.			      *
*******************************************************************************
* Written by Gershon Elber, Jun. 90.					      *
******************************************************************************/

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "cagd_loc.h"

static CagdRType BinomCoef(int n, int i);

/******************************************************************************
* DESCRIPTION:                                                               M
* Converts the given curve from Bezier basis functions to a Power basis      M
* functions. Using:							     M
*									     M
*	  n								     V
*	  __								     V
*  n	  \	j-i n	j   j						     V
* B (t) = /  (-1)  ( ) ( ) t						     V
*  i	  --	    j   i						     V
*	 j=i								     V
*					     n-i			     V
* Which can be derived by expanding the (1-t)    term in bezier basis	     V
* function definition as:						     V
*	  								     V
* 	   n-i  							     V
*           __  							     V
*      n-i  \  n-i      j						     V
* (1-t)   = / (   ) (-t)	using binomial expansion.		     V
*	    --  j							     V
*	   j=0								     V
*                                               			     M
* This routine simply take the weight of each Bezier basis function B(t) and M
* spread it into the different power basis t^j function scaled by:	     M
*                                               			     M
*	j-i n	j							     V
*   (-1)   ( ) ( )                                             		     V
*           j   i                                 			     V
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:       To convert into Power basis function representation.          M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:  Same geometry, but in the Power basis.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   CnvrtBezier2PowerCrv, power basis, conversion                            M
*****************************************************************************/
CagdCrvStruct *CnvrtBezier2PowerCrv(CagdCrvStruct *Crv)
{
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
    int i, j, l,
	n = Crv -> Length,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
    CagdRType *PwrP, *BzrP;
    CagdCrvStruct
	*NewCrv = CagdCrvNew(CAGD_CPOWER_TYPE, Crv -> PType, n);

    NewCrv -> Order = n;

    for (l = IsNotRational; l <= MaxCoord; l++) {
	PwrP = NewCrv -> Points[l];
	BzrP = Crv -> Points[l];
	ZAP_MEM(PwrP, sizeof(CagdRType) * n);

	for (i = 0; i < n; i++) {
	    for (j = i; j < n; j++) {
		PwrP[j] += BzrP[i] * BinomCoef(n, j) * BinomCoef(j, i) *
						(((j - i) & 0x01) ? -1 : 1);
	    }
	}
    }

    return NewCrv;
}

/******************************************************************************
* DESCRIPTION:                                                               M
* Converts the given curve from Power basis functions to Bezier basis        M
* functions. Using:							     M
*									     M
*      n    j								     V
*      __  ( )								     V
*   i  \    i	 n							     V
*  t = /  ----- B (t)							     V
*      --   n	 j							     V
*      j=i ( )								     V
*	    i								     V
*                                               			     M
* This routine simply take the weight of each Power basis function t^i and   M
* spread it into the different basis basis function B(t) scaled by:	     M
*                                               			     M
*     j   / n								     V
*    ( ) / ( )                                             		     V
*     i /   i	                                 			     V
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:        To convert to Bezier basis functions.                        M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   Same geometry, in the Bezier basis functions.         M
*                                                                            *
* KEYWORDS:                                                                  M
*   CnvrtPower2BezierCrv, power basis, conversion                            M
*****************************************************************************/
CagdCrvStruct *CnvrtPower2BezierCrv(CagdCrvStruct *Crv)
{
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
    int i, j, l,
	n = Crv -> Length,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
    CagdRType *PwrP, *BzrP;
    CagdCrvStruct
	*NewCrv = BzrCrvNew(n, Crv -> PType);

    for (l = IsNotRational; l <= MaxCoord; l++) {
	PwrP = Crv -> Points[l];
	BzrP = NewCrv -> Points[l];
	ZAP_MEM(BzrP, sizeof(CagdRType) * n);

	for (i = 0; i < n; i++) {
	    for (j = i; j < n; j++) {
		BzrP[j] += PwrP[i] * BinomCoef(j, i) / BinomCoef(n, i);
	    }
	}
    }

    return NewCrv;
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Evaluate the following:						     *
*			 n         n!					     *
*			( ) = -------------				     *
*			 i    i! * (n - i)!				     *
*                                                                            *
* PARAMETERS:                                                                *
*   n, i:    Coefficients of the binom.                                      *
*                                                                            *
* RETURN VALUE:                                                              *
*   CagdRType:   Result in floating point form to prevent from overflows.    *
*****************************************************************************/
static CagdRType BinomCoef(int n, int i)
{
    int j;
    CagdRType c = 1.0;

    if ((n >> 1) > i) {				/* i is less than half of n: */
	for (j = n - i + 1; j <= n; j++) c *= j;
	for (j = 2; j <= i; j++) c /= j;
    }
    else {
	for (j = i + 1; j <= n; j++) c *= j;
	for (j = 2; j <= n - i; j++) c /= j;
    }

    return c;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Power to Bezier conversion from surfaces.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To convert into Power basis function representation.          M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:  Same geometry, but in the Power basis.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   CnvrtBezier2PowerSrf, power basis, conversion                            M
*****************************************************************************/
CagdSrfStruct *CnvrtBezier2PowerSrf(CagdSrfStruct *Srf)
{
    CAGD_FATAL_ERROR(CAGD_ERR_NOT_IMPLEMENTED);
    return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Bezier to Power conversion from surfaces.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To convert into Bezier basis function representation.         M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:  Same geometry, but in the Bezier basis.                M
*                                                                            *
* KEYWORDS:                                                                  M
*   CnvrtPower2BezierSrf, power basis, conversion                            M
*****************************************************************************/
CagdSrfStruct *CnvrtPower2BezierSrf(CagdSrfStruct *Srf)
{
    CAGD_FATAL_ERROR(CAGD_ERR_NOT_IMPLEMENTED);
    return NULL;
}
