home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CBzrEval.c - Bezier curves handling routines - evaluation routines. *
- *******************************************************************************
- * Written by Gershon Elber, Mar. 90. *
- ******************************************************************************/
-
- #ifdef __MSDOS__
- #include <stdlib.h>
- #endif /* __MSDOS__ */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include "cagd_loc.h"
-
- static int BezierCacheEnabled = FALSE;
- static int CacheFineNess = 0, PowerCacheFineNess;
- static CagdRType *BezierCache[CAGD_MAX_BEZIER_CACHE_ORDER + 1]
- [CAGD_MAX_BEZIER_CACHE_ORDER + 1];
-
- static int IChooseK[CAGD_MAX_BEZIER_CACHE_ORDER + 1]
- [CAGD_MAX_BEZIER_CACHE_ORDER + 1] =
- {
- { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 1, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0 },
- { 1, 4, 6, 4, 1, 0, 0, 0, 0, 0, 0 },
- { 1, 5, 10, 10, 5, 1, 0, 0, 0, 0, 0 },
- { 1, 6, 15, 20, 15, 6, 1, 0, 0, 0, 0 },
- { 1, 7, 21, 35, 35, 21, 7, 1, 0, 0, 0 },
- { 1, 8, 28, 56, 70, 56, 28, 8, 1, 0, 0 },
- { 1, 9, 36, 84, 126, 126, 84, 36, 9, 1, 0 },
- { 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1 }
- };
-
- static CagdRType BzrCrvEvalFuncAux(int i, int k, CagdRType t);
-
- /******************************************************************************
- * Sets the bezier sampling cache - if enabled, a bezier can be evaluated *
- * directly from pre sampled basis function. *
- ******************************************************************************/
- void BzrCrvSetCache(int FineNess, CagdBType EnableCache)
- {
- int i, j, k;
-
- if (BezierCacheEnabled == EnableCache && FineNess == CacheFineNess)
- return;
-
- if (BezierCacheEnabled) {
- /* Free old cache if was one. */
- for (k = 2; k <= CAGD_MAX_BEZIER_CACHE_ORDER; k++)
- for (i = 0; i < k; i++)
- if (BezierCache[k][i] != NULL) {
- CagdFree((VoidPtr) BezierCache[k][i]);
- BezierCache[k][i] = NULL;
- }
- }
-
- if ((BezierCacheEnabled = EnableCache) != FALSE) {
- /* Allocate the new cache and initalize it: */
- if (FineNess < 2) FineNess = 2;
- if (FineNess > CAGD_MAX_BEZIER_CACHE_FINENESS)
- FineNess = CAGD_MAX_BEZIER_CACHE_FINENESS;
- CacheFineNess = FineNess;
- PowerCacheFineNess = 1 << FineNess;
-
- for (k = 2; k <= CAGD_MAX_BEZIER_CACHE_ORDER; k++)/* For all orders. */
- for (i = 0; i < k; i++) { /* Allocate and set all basis func. */
- BezierCache[k][i] = (CagdRType *)
- CagdMalloc(sizeof(CagdRType) * PowerCacheFineNess);
- for (j = 0; j < PowerCacheFineNess; j++)
- BezierCache[k][i][j] = BzrCrvEvalFuncAux(i, k,
- ((CagdRType) j) / (PowerCacheFineNess - 1));
- }
- }
- }
-
- /******************************************************************************
- * Assumes Vec holds control points for scalar bezier curve of order Order, *
- * and evaluates and returns that curve value at parameter value t. *
- * Vec is incremented by VecInc (usually by 1) after each iteration. *
- ******************************************************************************/
- CagdRType BzrCrvEvalVecAtParam(CagdRType *Vec, int VecInc, int Order, CagdRType t)
- {
- int i;
- CagdRType R = 0.0;
-
- if (VecInc == 1)
- for (i = 0; i < Order; i++)
- R += BzrCrvEvalFuncAux(i, Order, t) * *Vec++;
- else
- for (i = 0; i < Order; i++) {
- R += BzrCrvEvalFuncAux(i, Order, t) * *Vec;
- Vec += VecInc;
- }
-
- return R;
- }
-
- /******************************************************************************
- * Returns a pointer to a static data, holding the value of the curve at given *
- * parametric location t. The curve is assumed to be Bezier. *
- ******************************************************************************/
- CagdRType *BzrCrvEvalAtParam(CagdCrvStruct *Crv, CagdRType t)
- {
- static CagdRType Pt[CAGD_MAX_PT_COORD];
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j,
- k = Crv -> Order,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType B;
-
- for (j = IsNotRational; j <= MaxCoord; j++) Pt[j] = 0.0;
-
- for (i = 0; i < k; i++) {
- B = BzrCrvEvalFuncAux(i, k, t);
- for (j = IsNotRational; j <= MaxCoord; j++)
- Pt[j] += B * Crv -> Points[j][i];
- }
-
- return Pt;
- }
-
- /******************************************************************************
- * Samples the curves at FineNess location equally spaced in the Bezier *
- * parametric domain [0..1]. If Cache is enabled, and FineNess is power of *
- * two, upto or equal to CacheFineNess, the cache is used, otherwise the *
- * points are evaluated manually for each of the samples. *
- * Data is saved at the Points array of vectors (according to Curve PType), *
- * each vector is assumed to be allocated for FineNess CagdRType points. *
- ******************************************************************************/
- void BzrCrvEvalToPolyline(CagdCrvStruct *Crv, int FineNess,
- CagdRType *Points[])
- {
- CagdBType
- UseCache = BezierCacheEnabled && FineNess == CacheFineNess,
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j, Count,
- k = Crv -> Order,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType B;
-
- if (UseCache) {
- for (Count = 0; Count < PowerCacheFineNess; Count++) {
- for (j = IsNotRational; j <= MaxCoord; j++) Points[j][Count] = 0.0;
- for (i = 0; i < k; i++) {
- B = BezierCache[k][i][Count];
- for (j = IsNotRational; j <= MaxCoord; j++)
- Points[j][Count] += B * Crv -> Points[j][i];
- }
- }
- }
- else {
- FineNess = 1 << FineNess;
- for (Count = 0; Count < FineNess; Count++) {
- for (j = IsNotRational; j <= MaxCoord; j++) Points[j][Count] = 0.0;
- for (i = 0; i < k; i++) {
- B = BzrCrvEvalFuncAux(i, k,
- ((CagdRType) Count) / (FineNess - 1));
- for (j = IsNotRational; j <= MaxCoord; j++)
- Points[j][Count] += Crv -> Points[j][i] * B;
- }
- }
- }
- }
-
- /******************************************************************************
- * Evaluate the i bezier function of order k, at parametric value t *
- * (t in [0..1]). *
- * This function is: i k - i - 1 i *
- * Bi,k(t) = ( ) * t * (1 - t) *
- * k *
- ******************************************************************************/
- static CagdRType BzrCrvEvalFuncAux(int i, int k, CagdRType t)
- {
- if (APX_EQ(t, 0.0))
- return (CagdRType) (i == 0);
- else if (APX_EQ(t, 1.0))
- return (CagdRType) (i == k - 1);
- else
- return (CagdRType) IChooseK[k - 1][i] *
- pow(1.0 - t, k - i - 1.0) * pow(t, (CagdRType) i);
- }
-
- #ifdef K_CHOOSE_I_GEN
-
- /******************************************************************************
- * Evaluate the following: *
- * k k! *
- * ( ) = ------------- *
- * i i! * (k - i)! *
- ******************************************************************************/
- static int IChooseKGenOne(int i, int k)
- {
- int j;
- long c = 1;
-
- if ((k >> 1) > i) { /* i is less than half of k: */
- for (j = k - i + 1; j <= k; j++) c *= j;
- for (j = 2; j <= i; j++) c /= j;
- }
- else {
- for (j = i + 1; j <= k; j++) c *= j;
- for (j = 2; j <= k - i; j++) c /= j;
- }
-
- return (int) c;
- }
-
- /******************************************************************************
- * Evaluate IChooseK for all possiblities and print them for the *
- * IChooseK table defined in the beginning of this file. *
- ******************************************************************************/
- void IChooseKGen(void)
- {
- int i, j;
-
- for (i = 0; i <= MAX_BEZIER_CACHE_ORDER; i++) {
- printf(" },\n {");
- for (j = 0; j <= MAX_BEZIER_CACHE_ORDER; j++)
- printf(" %4d,", j <= i ? IChooseKGenOne(j ,i) : 0);
- }
- }
-
- /******************************************************************************
- * main to create the table in the befinning of this file. *
- ******************************************************************************/
- void main(void)
- {
- IChooseKGen();
- }
-
- #endif /* K_CHOOSE_I_GEN */
-