home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / symb_lib / composit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-27  |  21.8 KB  |  624 lines

  1. /******************************************************************************
  2. * Composit.c - Composition computation (symbolic).                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Apr. 93.                          *
  5. ******************************************************************************/
  6.  
  7. #include <string.h>
  8. #include "symb_loc.h"
  9.  
  10. #define ZERO_SET_EPS 0.0001
  11.  
  12. static CagdCrvStruct *SymbComposeCrvCrvAux(CagdCrvStruct *Crv1,
  13.                        CagdCrvStruct *Crv2);
  14. static CagdCrvStruct *SymbComposeCrvCrvAux2(CagdCrvStruct *Crv1,
  15.                         CagdCrvStruct *Crv2);
  16. static CagdCrvStruct *SymbComposeSrfCrvAux(CagdSrfStruct *Srf,
  17.                        CagdCrvStruct *Crv);
  18. static CagdCrvStruct **SymbComputeCurvePowers(CagdCrvStruct *Crv, int Order);
  19.  
  20. /*****************************************************************************
  21. * DESCRIPTION:                                                               M
  22. * Given two curves, Crv1 and Crv2, computes the composition Crv1(Crv2(t)).   M
  23. *   Crv2 must be a scalar curve completely contained in Crv1's parametric    M
  24. * domain.                                     M
  25. *                                                                            *
  26. * PARAMETERS:                                                                M
  27. *   Crv1, Crv2:   The two curve to compose together.                         M
  28. *                                                                            *
  29. * RETURN VALUE:                                                              M
  30. *   CagdCrvStruct *:   The composed curve.                                   M
  31. *                                                                            *
  32. * KEYWORDS:                                                                  M
  33. *   SymbComposeCrvCrv, composition                                           M
  34. *****************************************************************************/
  35. CagdCrvStruct *SymbComposeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  36. {
  37.     CagdCrvStruct *CmpsCrv;
  38.     CagdRType TMax, TMin, CTMax, CTMin;
  39.  
  40.     switch (Crv1 -> GType) {
  41.     case CAGD_CBEZIER_TYPE:
  42.     case CAGD_CBSPLINE_TYPE:
  43.         break;
  44.     case CAGD_CPOWER_TYPE:
  45.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  46.         break;
  47.     default:
  48.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  49.         break;
  50.     }
  51.  
  52.     switch (Crv2 -> GType) {
  53.     case CAGD_CBEZIER_TYPE:
  54.     case CAGD_CBSPLINE_TYPE:
  55.         break;
  56.     case CAGD_CPOWER_TYPE:
  57.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  58.         break;
  59.     default:
  60.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  61.         break;
  62.     }
  63.  
  64.     CmpsCrv = SymbComposeCrvCrvAux(Crv1, Crv2);
  65.  
  66.     /* Now map the domain of the curve to be crv2 domain. */
  67.     CagdCrvDomain(Crv2, &TMin, &TMax);
  68.     CagdCrvDomain(CmpsCrv, &CTMin, &CTMax);
  69.     if (CmpsCrv -> GType == CAGD_CBEZIER_TYPE) {
  70.     CagdCrvStruct
  71.         *CTmp = CnvrtBezier2BsplineCrv(CmpsCrv);
  72.  
  73.     CagdCrvFree(CmpsCrv);
  74.     CmpsCrv = CTmp;
  75.     }
  76.     BspKnotAffineTrans(CmpsCrv -> KnotVector,
  77.                CmpsCrv -> Length + CmpsCrv -> Order,
  78.                TMin - CTMin,
  79.                (TMax - TMin) / (CTMax - CTMin));
  80.  
  81.     return CmpsCrv;
  82. }
  83.  
  84. /*****************************************************************************
  85. * DESCRIPTION:                                                               *
  86. * Subdivides Crv2 until it is a Bezier curve, invokes the Bezier composition *
  87. * code on each, and merges them back to a complete curve.             *
  88. *   At this point, curves can be either Bezier or Bspline only.             *
  89. *   Curves are both assumed to have open end condition.                 *
  90. *                                                                            *
  91. *                                                                            *
  92. * PARAMETERS:                                                                *
  93. *   Crv1, Crv2:   The two curve to compose together.                         *
  94. *                                                                            *
  95. * RETURN VALUE:                                                              *
  96. *   CagdCrvStruct *:   The composed curve.                                   *
  97. *****************************************************************************/
  98. static CagdCrvStruct *SymbComposeCrvCrvAux(CagdCrvStruct *Crv1,
  99.                        CagdCrvStruct *Crv2)
  100. {
  101.     CagdCrvStruct *CmpsCrv;
  102.  
  103.     if (Crv2 -> Length > Crv2 -> Order) {
  104.     CagdRType t;
  105.  
  106.     /* Crv2 is not a Bezier segment. Subdivide, compute for each segment */
  107.     /* and merge back.                             */
  108.     CagdCrvStruct *Crv2a, *Crv2b, *CmpsCrvA, *CmpsCrvB;
  109.  
  110.     t = Crv2 -> KnotVector[(Crv2 -> Order + Crv2 -> Length) / 2];
  111.  
  112.     Crv2a = CagdCrvSubdivAtParam(Crv2, t);
  113.     Crv2b = Crv2a -> Pnext;
  114.  
  115.     CmpsCrvA = SymbComposeCrvCrvAux(Crv1, Crv2a);
  116.     CmpsCrvB = SymbComposeCrvCrvAux(Crv1, Crv2b);
  117.     CagdCrvFree(Crv2a);
  118.     CagdCrvFree(Crv2b);
  119.  
  120.     CmpsCrv = CagdMergeCrvCrv(CmpsCrvA, CmpsCrvB, FALSE);
  121.     CagdCrvFree(CmpsCrvA);
  122.     CagdCrvFree(CmpsCrvB);
  123.     }
  124.     else {
  125.         /* Crv2 is a Bezier segment - compute its composition. */
  126.         CmpsCrv = SymbComposeCrvCrvAux2(Crv1, Crv2);
  127.     }
  128.  
  129.     return CmpsCrv;    
  130. }
  131.  
  132. /*****************************************************************************
  133. * DESCRIPTION:                                                               *
  134. * See SymbComposeCrvCrvAux.                                                  *
  135. *****************************************************************************/
  136. static CagdCrvStruct *SymbComposeCrvCrvAux2(CagdCrvStruct *Crv1,
  137.                         CagdCrvStruct *Crv2)
  138. {
  139.     CagdRType t, TMin, TMax, CTMax, CTMin;
  140.     CagdCrvStruct *CmpsCrv;
  141.  
  142.     if (Crv1 -> Length > Crv1 -> Order) {
  143.     /* Needs to compose in pieces after subdividing Crv2 at the interior */
  144.     /* knots of Crv1, by finding where Crv2(r) = t, the interior knot.   */
  145.     CagdCrvStruct *Crv1a, *Crv1b, *Crv2a, *Crv2b, *CmpsCrvA, *CmpsCrvB;
  146.     CagdPtStruct *Pts;
  147.  
  148.     t = Crv1 -> KnotVector[(Crv1 -> Order + Crv1 -> Length) / 2];
  149.     Crv1a = CagdCrvSubdivAtParam(Crv1, t);
  150.     Crv1b = Crv1a -> Pnext;
  151.  
  152.     Pts = SymbCrvConstSet(Crv2, 1, ZERO_SET_EPS, t);
  153.     if (Pts) {
  154.         if (Pts -> Pnext != NULL)
  155.         SYMB_FATAL_ERROR(SYMB_ERR_REPARAM_NOT_MONOTONE);
  156.         t = Pts -> Pt[0];
  157.         CagdPtFreeList(Pts);
  158.         Crv2a = CagdCrvSubdivAtParam(Crv2, t);
  159.         Crv2b = Crv2a -> Pnext;
  160.     }
  161.     else
  162.         Crv2a = Crv2b = NULL;
  163.  
  164.     CmpsCrvA = SymbComposeCrvCrvAux2(Crv1a, Crv2a ? Crv2a : Crv2);
  165.     CmpsCrvB = SymbComposeCrvCrvAux2(Crv1b, Crv2b ? Crv2b : Crv2);
  166.     CagdCrvFree(Crv1a);
  167.     CagdCrvFree(Crv1b);
  168.     if (Crv2a)
  169.         CagdCrvFree(Crv2a);
  170.     if (Crv2b)
  171.         CagdCrvFree(Crv2b);
  172.  
  173.     CmpsCrv = CagdMergeCrvCrv(CmpsCrvA, CmpsCrvB, FALSE);
  174.     CagdCrvFree(CmpsCrvA);
  175.     CagdCrvFree(CmpsCrvB);
  176.     }
  177.     else {
  178.     /* We can compose the curves, but first make sure the domain of */
  179.     /* Crv1 is [0, 1] which is also the range of Crv2.        */
  180.     CagdCrvDomain(Crv1, &TMin, &TMax);
  181.     if (!APX_EQ(TMin, 0.0) || !APX_EQ(TMax, 1.0)) {
  182.         CagdRType
  183.         Translate = -TMin;
  184.  
  185.         Crv2 = CagdCrvCopy(Crv2);
  186.         CagdCrvTransform(Crv2, &Translate, 1.0 / (TMax - TMin));
  187.         CmpsCrv = BzrComposeCrvCrv(Crv1, Crv2);
  188.         CagdCrvFree(Crv2);
  189.     }
  190.     else
  191.         CmpsCrv = BzrComposeCrvCrv(Crv1, Crv2);
  192.  
  193.     /* Now map the domain of the curve to be crv2 domain. */
  194.     CagdCrvDomain(Crv2, &TMin, &TMax);
  195.     CagdCrvDomain(CmpsCrv, &CTMin, &CTMax);
  196.     if (CmpsCrv -> GType == CAGD_CBEZIER_TYPE) {
  197.         CagdCrvStruct
  198.         *CTmp = CnvrtBezier2BsplineCrv(CmpsCrv);
  199.  
  200.         CagdCrvFree(CmpsCrv);
  201.         CmpsCrv = CTmp;
  202.     }
  203.     BspKnotAffineTrans(CmpsCrv -> KnotVector,
  204.                CmpsCrv -> Length + CmpsCrv -> Order,
  205.                TMin - CTMin,
  206.                (TMax - TMin) / (CTMax - CTMin));
  207.     }
  208.  
  209.     return CmpsCrv;
  210. }
  211.  
  212. /*****************************************************************************
  213. * DESCRIPTION:                                                               M
  214. * Given two Bezier curves, Crv1 and Crv2, computes their composition         M
  215. * Crv1(Crv2(t)).                                 M
  216. *   Crv2 must be a scalar curve completely contained in Crv1's parametric    M
  217. * domain.                                     M
  218. *   See: "Freeform surfcae analysis using a hybrid of symbolic and numeric   M
  219. * computation" by Gershon Elber, PhD thesis, University of Utah, 1992.         M
  220. *                                                                            *
  221. * PARAMETERS:                                                                M
  222. *   Crv1, Crv2:   The two curve to compose together.                         M
  223. *                                                                            *
  224. * RETURN VALUE:                                                              M
  225. *   CagdCrvStruct *:   The composed curve.                                   M
  226. *                                                                            *
  227. * KEYWORDS:                                                                  M
  228. *   BzrComposeCrvCrv, composition                                            M
  229. *****************************************************************************/
  230. CagdCrvStruct *BzrComposeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  231. {
  232.     CagdBType
  233.     IsRational = CAGD_IS_RATIONAL_CRV(Crv1);
  234.     int i, j, k, CmpsOrder,
  235.     Order = Crv1 -> Order,
  236.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv1 -> PType);
  237.     CagdRType
  238.     Translate = 0.0;
  239.     CagdCrvStruct **Crv2Factors,
  240.         *CmpsCrv = NULL;
  241.  
  242.     if (CAGD_NUM_OF_PT_COORD(Crv2 -> PType) != 1)
  243.     SYMB_FATAL_ERROR(SYMB_ERR_WRONG_PT_TYPE);
  244.  
  245.     Crv2Factors = SymbComputeCurvePowers(Crv2, Order);
  246.     CmpsCrv = BzrCrvNew(Crv2Factors[0] -> Length, Crv1 -> PType);
  247.     CmpsOrder = CmpsCrv -> Order;
  248.  
  249.     for (j = !IsRational; j <= MaxCoord; j++) {
  250.         CagdRType
  251.         *CmpsPoints = CmpsCrv -> Points[j],
  252.         *Crv1Points = Crv1 -> Points[j];
  253.  
  254.     for (i = 0; i < Order; i++) {
  255.         CagdCrvStruct
  256.         *CTmp = CagdCrvCopy(Crv2Factors[i]);
  257.         CagdRType
  258.             *CTmpPoints = CTmp -> Points[1];
  259.  
  260.         CagdCrvTransform(CTmp, &Translate, *Crv1Points++);
  261.         if (i == 0) {
  262.                SYMB_GEN_COPY(CmpsPoints, CTmpPoints,
  263.                   CmpsOrder * sizeof(CagdRType));
  264.         }
  265.         else {
  266.             for (k = 0; k < CmpsOrder; k++)
  267.                 CmpsPoints[k] += CTmpPoints[k];
  268.         }
  269.     }
  270.     }
  271.  
  272.     for (i = 0; i < Order; i++)
  273.     CagdCrvFree(Crv2Factors[i]);
  274.  
  275.     if (CAGD_IS_RATIONAL_CRV(Crv2)) {
  276.     CagdCrvStruct *CrvW, *CrvX, *CrvY, *CrvZ, *CTmp;
  277.  
  278.     SymbCrvSplitScalar(CmpsCrv, &CrvW, &CrvX, &CrvY, &CrvZ);
  279.     CTmp = SymbCrvMergeScalar(Crv2Factors[Order], CrvX, CrvY, CrvZ);
  280.     CagdCrvFree(CmpsCrv);
  281.     CmpsCrv = CTmp;
  282.  
  283.     if (CrvX)
  284.         CagdCrvFree(CrvX);
  285.     if (CrvY)
  286.         CagdCrvFree(CrvY);
  287.     if (CrvZ)
  288.         CagdCrvFree(CrvZ);
  289.     
  290.     CagdCrvFree(Crv2Factors[Order]);
  291.     }
  292.  
  293.     IritFree((VoidPtr) Crv2Factors);
  294.  
  295.     return CmpsCrv;
  296. }
  297.  
  298. /*****************************************************************************
  299. * DESCRIPTION:                                                               M
  300. * Given a curve Crv and surface Srf, computes the composition Srf(Crv(t)).   M
  301. *   Crv must be a two dimensional curve completely contained in the          M
  302. * parametric domain of Srf.                                                  M
  303. *                                                                            *
  304. * PARAMETERS:                                                                M
  305. *   Srf, Crv:   The curve and surface to compose.                            M
  306. *                                                                            *
  307. * RETURN VALUE:                                                              M
  308. *   CagdCrvStruct *:    The resulting composition.                           M
  309. *                                                                            *
  310. * KEYWORDS:                                                                  M
  311. *   SymbComposeSrfCrv, composition                                           M
  312. *****************************************************************************/
  313. CagdCrvStruct *SymbComposeSrfCrv(CagdSrfStruct *Srf, CagdCrvStruct *Crv)
  314. {
  315.     CagdCrvStruct *CmpsCrv;
  316.  
  317.     switch (Srf -> GType) {
  318.     case CAGD_SBEZIER_TYPE:
  319.         break;
  320.     case CAGD_SBSPLINE_TYPE:
  321.         SYMB_FATAL_ERROR(SYMB_ERR_BSPLINE_NO_SUPPORT);
  322.         break;
  323.     case CAGD_SPOWER_TYPE:
  324.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  325.         break;
  326.     default:
  327.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  328.         break;
  329.     }
  330.  
  331.     switch (Crv -> GType) {
  332.     case CAGD_CBEZIER_TYPE:
  333.     case CAGD_CBSPLINE_TYPE:
  334.         break;
  335.     case CAGD_CPOWER_TYPE:
  336.         SYMB_FATAL_ERROR(SYMB_ERR_POWER_NO_SUPPORT);
  337.         break;
  338.     default:
  339.         SYMB_FATAL_ERROR(SYMB_ERR_UNDEF_CRV);
  340.         break;
  341.     }
  342.  
  343.     CmpsCrv = SymbComposeSrfCrvAux(Srf, Crv);
  344.  
  345.     return CmpsCrv;
  346. }
  347.  
  348. /*****************************************************************************
  349. * DESCRIPTION:                                                               *
  350. * Aux. function. Subdivides Crv until it is a Bezier curve, invokes the      *
  351. * Bezier composition code on each, and merges them back to a complete curve. *
  352. *   At this point, the curve can be either Bezier or Bspline only.           *
  353. *   Curve is assumed to have open end condition.                 *
  354. *                                                                            *
  355. * PARAMETERS:                                                                *
  356. *   Srf, Crv:   The curve and surface to compose together.                   *
  357. *                                                                            *
  358. * RETURN VALUE:                                                              *
  359. *   CagdCrvStruct *:  The composed curve.                                    *
  360. *****************************************************************************/
  361. static CagdCrvStruct *SymbComposeSrfCrvAux(CagdSrfStruct *Srf,
  362.                        CagdCrvStruct *Crv)
  363. {
  364.     CagdRType t, TMin, TMax;
  365.     CagdCrvStruct *CmpsCrv;
  366.  
  367.     if (Crv -> Length > Crv -> Order) {
  368.     /* Crv is not a Bezier segment. Subdivide, compute for each segment  */
  369.     /* and merge back.                             */
  370.     CagdCrvStruct *CrvA, *CrvB, *CmpsCrvA, *CmpsCrvB;
  371.  
  372.     t = Crv -> KnotVector[(Crv -> Order + Crv -> Length) / 2];
  373.  
  374.     CrvA = CagdCrvSubdivAtParam(Crv, t);
  375.     CrvB = CrvA -> Pnext;
  376.  
  377.     CmpsCrvA = SymbComposeSrfCrvAux(Srf, CrvA);
  378.     CmpsCrvB = SymbComposeSrfCrvAux(Srf, CrvB);
  379.     CagdCrvFree(CrvA);
  380.     CagdCrvFree(CrvB);
  381.  
  382.     CmpsCrv = CagdMergeCrvCrv(CmpsCrvA, CmpsCrvB, FALSE);
  383.     CagdCrvFree(CmpsCrvA);
  384.     CagdCrvFree(CmpsCrvB);
  385.     }
  386.     else {
  387.         /* Crv is a Bezier segment - compute its composition. */
  388.         CmpsCrv = BzrComposeSrfCrv(Srf, Crv);
  389.  
  390.     /* Now map the domain of the composed curve to be crv's domain. */
  391.     CagdCrvDomain(Crv, &TMin, &TMax);
  392.     if (CmpsCrv -> GType == CAGD_CBEZIER_TYPE) {
  393.         CagdCrvStruct
  394.         *CTmp = CnvrtBezier2BsplineCrv(CmpsCrv);
  395.  
  396.         CagdCrvFree(CmpsCrv);
  397.         CmpsCrv = CTmp;
  398.     }
  399.     BspKnotAffineTrans(CmpsCrv -> KnotVector,
  400.                CmpsCrv -> Length + CmpsCrv -> Order,
  401.                TMin - CmpsCrv -> KnotVector[0],
  402.                TMax - TMin);
  403.     }
  404.  
  405.     return CmpsCrv;    
  406. }
  407.  
  408. /*****************************************************************************
  409. * DESCRIPTION:                                                               M
  410. * Given a Bezier curve Crv and a Bezier surface Srf, computes their          M
  411. * coomposition Srf(Crv(t)).                             M
  412. *   Crv must be a two dimensional curve completely contained in the          M
  413. * parametric domain of Srf.                                                  M
  414. *   See: "Freeform surfcae analysis using a hybrid of symbolic and numeric   M
  415. * computation" by Gershon Elber, PhD thesis, University of Utah, 1992.         M
  416. *                                                                            *
  417. * PARAMETERS:                                                                M
  418. *   Srf, Crv:     The curve and surface to compose.                          M
  419. *                                                                            *
  420. * RETURN VALUE:                                                              M
  421. *   CagdCrvStruct *:    The resulting composition.                           M
  422. *                                                                            *
  423. * KEYWORDS:                                                                  M
  424. *   BzrComposeSrfCrv, composition                                            M
  425. *****************************************************************************/
  426. CagdCrvStruct *BzrComposeSrfCrv(CagdSrfStruct *Srf, CagdCrvStruct *Crv)
  427. {
  428.     CagdBType
  429.     IsRational = CAGD_IS_RATIONAL_SRF(Srf);
  430.     int i, j, k, l, CmpsOrder,
  431.     UOrder = Srf -> UOrder,
  432.     VOrder = Srf -> VOrder,
  433.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  434.     CagdRType
  435.     Translate = 0.0;
  436.     CagdCrvStruct **CrvUFactors, **CrvVFactors, *CrvW, *CrvX, *CrvY, *CrvZ,
  437.     *CrvU, *CrvV,
  438.         *CmpsCrv = NULL;
  439.  
  440.     if (CAGD_NUM_OF_PT_COORD(Crv -> PType) != 2)
  441.     SYMB_FATAL_ERROR(SYMB_ERR_WRONG_PT_TYPE);
  442.     SymbCrvSplitScalar(Crv, &CrvW, &CrvX, &CrvY, &CrvZ);
  443.     CrvU = CrvW == NULL ? CagdCrvCopy(CrvX)
  444.                 : SymbCrvMergeScalar(CrvW, CrvX, NULL, NULL);
  445.     CrvV = CrvW == NULL ? CagdCrvCopy(CrvY)
  446.             : SymbCrvMergeScalar(CrvW, CrvY, NULL, NULL);
  447.     if (CrvW)
  448.     CagdCrvFree(CrvW);
  449.     CagdCrvFree(CrvX);
  450.     CagdCrvFree(CrvY);
  451.  
  452.     CrvUFactors = SymbComputeCurvePowers(CrvU, UOrder);
  453.     CrvVFactors = SymbComputeCurvePowers(CrvV, VOrder);
  454.  
  455.     CmpsCrv = BzrCrvNew(CrvUFactors[0] -> Length + 
  456.             CrvVFactors[0] -> Length - 1, Srf -> PType);
  457.     CmpsOrder = CmpsCrv -> Order;
  458.  
  459.     for (k = !IsRational; k <= MaxCoord; k++) {
  460.         CagdRType
  461.         *CmpsPoints = CmpsCrv -> Points[k],
  462.         *SPoints = Srf -> Points[k];
  463.  
  464.     for (j = 0; j < VOrder; j++) {
  465.         for (i = 0; i < UOrder; i++) {
  466.         CagdCrvStruct
  467.             *CTmp = SymbCrvMult(CrvUFactors[i], CrvVFactors[j]);
  468.         CagdRType
  469.             *CTmpPoints = CTmp -> Points[1];
  470.  
  471.         CagdCrvTransform(CTmp, &Translate, *SPoints++);
  472.  
  473.         if (i == 0 && j == 0) {
  474.             SYMB_GEN_COPY(CmpsPoints, CTmpPoints,
  475.                   CmpsOrder * sizeof(CagdRType));
  476.         }
  477.         else {
  478.             for (l = 0; l < CmpsOrder; l++)
  479.             CmpsPoints[l] += CTmpPoints[l];
  480.         }
  481.         }
  482.     }
  483.     }
  484.  
  485.     for (i = 0; i < UOrder; i++)
  486.         CagdCrvFree(CrvUFactors[i]);
  487.     for (i = 0; i < VOrder; i++)
  488.         CagdCrvFree(CrvVFactors[i]);
  489.  
  490.     if (CAGD_IS_RATIONAL_CRV(Crv)) {
  491.     CagdCrvStruct *CTmp,
  492.         *NewCrvW = SymbCrvMult(CrvUFactors[UOrder], CrvVFactors[VOrder]);
  493.  
  494.     SymbCrvSplitScalar(CmpsCrv, &CrvW, &CrvX, &CrvY, &CrvZ);
  495.     CTmp = SymbCrvMergeScalar(NewCrvW, CrvX, CrvY, CrvZ);
  496.     CagdCrvFree(NewCrvW);
  497.     CagdCrvFree(CmpsCrv);
  498.     CmpsCrv = CTmp;
  499.  
  500.     if (CrvX)
  501.         CagdCrvFree(CrvX);
  502.     if (CrvY)
  503.         CagdCrvFree(CrvY);
  504.     if (CrvZ)
  505.         CagdCrvFree(CrvZ);
  506.  
  507.     CagdCrvFree(CrvUFactors[UOrder]);
  508.     CagdCrvFree(CrvVFactors[VOrder]);
  509.     }
  510.  
  511.     IritFree((VoidPtr) CrvUFactors);
  512.     IritFree((VoidPtr) CrvVFactors);
  513.  
  514.     CagdCrvFree(CrvU);
  515.     CagdCrvFree(CrvV);
  516.  
  517.     return CmpsCrv;
  518. }
  519.  
  520. /*****************************************************************************
  521. * DESCRIPTION:                                                               *
  522. * Computes the factors of the Bernstein polynomials where crv is a scalar    *
  523. * curve.                                     *
  524. *                                         *
  525. *   n            n              n-i         i                     *
  526. *  B (crv(t)) = ( ) (1 - crv(t))    (crv(t))                     *
  527. *   i            i                                 *
  528. *                                         *
  529. *   The curve crv(t) is a scalar, possibly rational curve.             *
  530. *   The constant 1 is equal to wcrv(t) if crv(t) is rational.             *
  531. *   If rational, the returned vector, index Order will contain               *
  532. * wcrv(t)^(Order-1).                                  *
  533. * See: "Freeform surface analysis using a hybrid of symbolic and numeric     *
  534. * computation" by Gershon Elber, PhD thesis, University of Utah, 1992.         *
  535. *                                                                            *
  536. * PARAMETERS:                                                                *
  537. *   Crv:      Scalar curve to compute factor.                                *
  538. *   Order:    Order is n + 1.                                                *
  539. *                                                                            *
  540. * RETURN VALUE:                                                              *
  541. *   CagdCrvStruct **:   A vector of all possibly factors for i equal to      *
  542. *                       zero to i equal to n.                                *
  543. *****************************************************************************/
  544. static CagdCrvStruct **SymbComputeCurvePowers(CagdCrvStruct *Crv, int Order)
  545. {
  546.     CagdBType
  547.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  548.     int i;
  549.     CagdCrvStruct *Crv_1,
  550.     **CrvFactors1_Crv = (CagdCrvStruct **)
  551.                 IritMalloc((Order + 1) * sizeof(CagdCrvStruct *)),
  552.     **CrvFactorsCrv = (CagdCrvStruct **)
  553.                 IritMalloc((Order + 1) * sizeof(CagdCrvStruct *)),
  554.     **CrvFactors = (CagdCrvStruct **)
  555.                 IritMalloc((Order + 1) * sizeof(CagdCrvStruct *));
  556.     CagdRType *Points,
  557.     Translate = 0.0;
  558.  
  559.     if (IsRational) {
  560.     CagdCrvStruct *CrvX, *CrvY, *CrvZ, *CrvW, *CTmp;
  561.  
  562.     SymbCrvSplitScalar(Crv, &CrvW, &CrvX, &CrvY, &CrvZ);
  563.     Crv_1 = SymbCrvSub(CrvW, CrvX);
  564.  
  565.     /* Set CrvFactors[Order] to CrvW(t)^(Order-1) if curve is rational. */
  566.     CrvFactors[Order] = CagdCrvCopy(CrvW);
  567.     for (i = 1; i < Order - 1; i++) {
  568.         CTmp = SymbCrvMult(CrvFactors[Order], CrvW);
  569.         CagdCrvFree(CrvFactors[Order]);
  570.         CrvFactors[Order] = CTmp;
  571.     }
  572.  
  573.     CagdCrvFree(CrvW);
  574.     CagdCrvFree(CrvX);
  575.     }
  576.     else {
  577.         Crv_1 = CagdCrvCopy(Crv);
  578.     Points = Crv_1 -> Points[1];
  579.         for (i = 0; i < Crv -> Order; i++, Points++)
  580.             *Points = 1.0 - *Points;
  581.  
  582.     CrvFactors[Order] = NULL;
  583.     }
  584.  
  585.     for (i = 0; i < Order; i++) {
  586.         if (i == 0) {
  587.             CrvFactors1_Crv[0] = NULL;
  588.             CrvFactorsCrv[0] = NULL;
  589.     }
  590.         else if (i == 1) {
  591.             CrvFactors1_Crv[1] = Crv_1;
  592.             CrvFactorsCrv[1] = CagdCrvCopy(Crv);
  593.         }
  594.         else {
  595.             CrvFactors1_Crv[i] = SymbCrvMult(CrvFactors1_Crv[i - 1], Crv_1);
  596.             CrvFactorsCrv[i] = SymbCrvMult(CrvFactorsCrv[i - 1], Crv);
  597.         }
  598.     }
  599.  
  600.     for (i = 0; i < Order; i++) {
  601.     if (i == 0) {
  602.         CrvFactors[i]= CagdCrvCopy(CrvFactors1_Crv[Order - 1]);
  603.     }
  604.     else if (i == Order - 1) {
  605.         CrvFactors[i] = CagdCrvCopy(CrvFactorsCrv[Order - 1]);
  606.     }
  607.     else {
  608.         CrvFactors[i] = SymbCrvMult(CrvFactors1_Crv[Order - 1 - i],
  609.                     CrvFactorsCrv[i]);
  610.     }
  611.     CagdCrvTransform(CrvFactors[i],
  612.              &Translate, CagdIChooseK(i, Order - 1));
  613.     }
  614.  
  615.     for (i = 1; i < Order; i++) {
  616.         CagdCrvFree(CrvFactorsCrv[i]);
  617.         CagdCrvFree(CrvFactors1_Crv[i]);
  618.     }
  619.     IritFree((VoidPtr) CrvFactorsCrv);
  620.     IritFree((VoidPtr) CrvFactors1_Crv);
  621.  
  622.     return CrvFactors;
  623. }
  624.