Metropoli BBS
VIEWER: cbzr_pwr.c MODE: TEXT (ASCII)
/******************************************************************************
* CBzr_Pwr.c - Bezier to pawer basis conversion.			      *
*******************************************************************************
* Written by Gershon Elber, Jun. 90.					      *
******************************************************************************/

#ifdef __MSDOS__
#include <stdlib.h>
#endif /* __MSDOS__ */

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

static CagdRType BinomCoef(int n, int i);

/******************************************************************************
* Convert the given curve from Bezier basis function to Power basis.	      *
* Using:								      *
*									      *
*	  n								      *
*	  __								      *
*  n	  \	j-i n	j   j						      *
* B (t) = /  (-1)  ( ) ( ) t						      *
*  i	  --	    j   i						      *
*	 j=i								      *
*					     n-i			      *
* Which can be derived by expanding the (1-t)    term in bezier basis	      *
* function definition as:						      *
*	  								      *
* 	   n-i  							      *
*           __  							      *
*      n-i  \  n-i      j						      *
* (1-t)   = / (   ) (-t)	using binomial expansion.		      *
*	    --  j							      *
*	   j=0								      *
*                                               			      *
* This routine simply take the weight of each Bezier basis function B(t) and  *
* spread it into the different power basis t^j function scaled by:	      *
*                                               			      *
*	j-i n	j							      *
*   (-1)   ( ) ( )                                             		      *
*           j   i                                 			      *
******************************************************************************/
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;
}

/******************************************************************************
* Convert the given curve from Power basis function to Bezier basis.	      *
* Using:								      *
*									      *
*      n    j								      *
*      __  ( )								      *
*   i  \    i	 n							      *
*  t = /  ----- B (t)							      *
*      --   n	 j							      *
*      j=i ( )								      *
*	    i								      *
*                                               			      *
* This routine simply take the weight of each Power basis function t^i and    *
* spread it into the different basis basis function B(t) scaled by:	      *
*                                               			      *
*     j   / n								      *
*    ( ) / ( )                                             		      *
*     i /   i	                                 			      *
******************************************************************************/
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;
}

/******************************************************************************
* Evaluate the following:						      *
*			 n         n!					      *
*			( ) = -------------				      *
*			 i    i! * (n - i)!				      *
******************************************************************************/
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;
}
[ RETURN TO DIRECTORY ]