/****************************************************************************** * CBzr_Pwr.c - Bezier to pawer basis conversion. * ******************************************************************************* * Written by Gershon Elber, Jun. 90. * ******************************************************************************/ #ifdef __MSDOS__ #include #endif /* __MSDOS__ */ #include #include #include #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; }