home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iritsm3s.zip / cagd_lib / cagdcmrg.c < prev    next >
C/C++ Source or Header  |  1991-06-02  |  11KB  |  353 lines

  1. /******************************************************************************
  2. * CagdCMrg.c - Curve/Point merging routines.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, May 91.                          *
  5. ******************************************************************************/
  6.  
  7. #include "string.h"
  8. #include "cagd_loc.h"
  9.  
  10. static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
  11.              CagdCrvStruct *SrcCrv);
  12. static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2);
  13.  
  14. /******************************************************************************
  15. * Merge two curves.                                  *
  16. ******************************************************************************/
  17. CagdCrvStruct *CagdMergeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
  18. {
  19.     CagdBType CrvsSharePt,
  20.     Crv1New = FALSE,
  21.     Crv2New = FALSE,
  22.     IsRational1 = CAGD_IS_RATIONAL_CRV(Crv1),
  23.     IsRational2 = CAGD_IS_RATIONAL_CRV(Crv2);
  24.     int Length, Order,
  25.     Order1 = Crv1 -> Order,
  26.     Order2 = Crv2 -> Order,
  27.     Len1 = Crv1 -> Length,
  28.     Len2 = Crv2 -> Length,
  29.     MaxCoord1 = CAGD_NUM_OF_PT_COORD(Crv1 -> PType),
  30.     MaxCoord2 = CAGD_NUM_OF_PT_COORD(Crv2 -> PType);
  31.     CagdRType E3Pt1[3], E3Pt2[3];
  32.     CagdPointType CrvPType = CAGD_PT_E2_TYPE;
  33.     CagdCrvStruct *Crv;
  34.  
  35.     /* Make orders compatible: */
  36.     if (Order1 < Order2) {
  37.     for (; Order1 < Order2; Order1++) {
  38.         Crv = CagdCrvDegreeRaise(Crv1);
  39.         if (Crv1New)
  40.         CagdCrvFree(Crv1);
  41.         Crv1 = Crv;
  42.         Len1 = Crv1 -> Length;
  43.         Crv1New = TRUE;
  44.     }
  45.     }
  46.     else if (Order2 < Order1) {
  47.     for (; Order2 < Order1; Order2++) {
  48.         Crv = CagdCrvDegreeRaise(Crv2);
  49.         if (Crv2New)
  50.         CagdCrvFree(Crv2);
  51.         Crv2 = Crv;
  52.         Len2 = Crv2 -> Length;
  53.         Crv2New = TRUE;
  54.     }
  55.     }
  56.     Order = Order1;
  57.  
  58.     /* Verify curve geometric types. */
  59.     switch (Crv1 -> GType) {
  60.     case CAGD_CBEZIER_TYPE:
  61.         Crv = CnvrtBezier2BsplineCrv(Crv1);
  62.         if (Crv1New)
  63.         CagdCrvFree(Crv1);
  64.         Crv1 = Crv;
  65.         Crv1New = TRUE;
  66.         break;
  67.     case CAGD_CBSPLINE_TYPE:
  68.         break;
  69.     case CAGD_CPOWER_TYPE:
  70.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  71.         break;
  72.     default:
  73.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  74.         break;
  75.     }
  76.  
  77.     switch (Crv2 -> GType) {
  78.     case CAGD_CBEZIER_TYPE:
  79.         Crv = CnvrtBezier2BsplineCrv(Crv2);
  80.         if (Crv2New)
  81.         CagdCrvFree(Crv2);
  82.         Crv2 = Crv;
  83.         Crv2New = TRUE;
  84.         break;
  85.     case CAGD_CBSPLINE_TYPE:
  86.         break;
  87.     case CAGD_CPOWER_TYPE:
  88.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  89.         break;
  90.     default:
  91.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  92.         break;
  93.     }
  94.  
  95.     /* Compute curve point types. */
  96.     CrvPType = CAGD_MAKE_PT_TYPE(IsRational1 || IsRational2,
  97.                  MAX(MaxCoord1, MaxCoord2));
  98.  
  99.  
  100.     /* Figure out if end point of Crv1 is equal to start point of Crv2 and   */
  101.     /* Compute the length of the resulting curve accordingly.             */
  102.     /* If the same point, then the result can omit one copy and therefore    */
  103.     /* has Len1 + Len2 - 1 Ctl points. If however a linear segment should be */
  104.     /* introduced between the two curves, it should hold Order colinear pts  */
  105.     /* including 2 end points shared with curves or Order - 2 new pts.       */
  106.     CagdCoerceToE3(E3Pt1, Crv1 -> Points, Len1 - 1, Crv1 -> PType);
  107.     CagdCoerceToE3(E3Pt2, Crv2 -> Points, 0, Crv2 -> PType);
  108.     CrvsSharePt = APX_EQ(E3Pt1[0], E3Pt2[0]) &&
  109.           APX_EQ(E3Pt1[1], E3Pt2[1]) &&
  110.           APX_EQ(E3Pt1[2], E3Pt2[2]);
  111.     Length = CrvsSharePt ? Len1 + Len2 - 1 : Len1 + Len2 + Order - 2;
  112.  
  113.     Crv = BspCrvNew(Length, Order, CrvPType);
  114.     CopyCrvOnCrv(Crv, 0, Crv1);
  115.     CopyCrvOnCrv(Crv, Length - Len2, Crv2);
  116.     InterpolateLinearSeg(Crv, Len1 - 1, Length - Len2);
  117.  
  118.     /* Update the knot vector. We assume open end condition here... */
  119.     GEN_COPY(Crv -> KnotVector, Crv1 -> KnotVector,
  120.          (Len1 + Order1 - 1) * sizeof(CagdRType));
  121.     if (CrvsSharePt) {
  122.     GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
  123.          &Crv2 -> KnotVector[Order2], Len2 * sizeof(CagdRType));
  124.     BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
  125.                Len2,
  126.                Crv -> KnotVector[Len1 + Order1 - 2] -
  127.                Crv2 -> KnotVector[0],
  128.                1.0);
  129.     }
  130.     else {
  131.     GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
  132.          &Crv2 -> KnotVector[1],
  133.          (Len2 + Order2 - 1) * sizeof(CagdRType));
  134.     BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
  135.                Len2 + Order2 - 1,
  136.                Crv -> KnotVector[Len1 + Order1 - 2] -
  137.                Crv -> KnotVector[Len1 + Order1 - 1] + 1.0,
  138.                1.0);
  139.     }
  140.  
  141.     if (Crv1New)
  142.     CagdCrvFree(Crv1);
  143.     if (Crv2New)
  144.     CagdCrvFree(Crv2);
  145.  
  146.     return Crv;
  147. }
  148.  
  149. /******************************************************************************
  150. * Merge a curve and a point.                              *
  151. ******************************************************************************/
  152. CagdCrvStruct *CagdMergeCrvPt(CagdCrvStruct *Crv, CagdPtStruct *Pt)
  153. {
  154.     CagdBType
  155.     CrvNew = FALSE,
  156.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  157.     int i, NewLen, NewMaxCoord,
  158.     Order = Crv -> Order,
  159.     Len = Crv -> Length,
  160.     PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
  161.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  162.     CagdPointType
  163.     CrvPType = CAGD_PT_E2_TYPE;
  164.     CagdRType t, **Points;
  165.     CagdCrvStruct *NewCrv;
  166.  
  167.     switch (Crv -> GType) {
  168.     case CAGD_CBEZIER_TYPE:
  169.         Crv = CnvrtBezier2BsplineCrv(Crv);
  170.         CrvNew = TRUE;
  171.     case CAGD_CBSPLINE_TYPE:
  172.         break;
  173.     case CAGD_CPOWER_TYPE:
  174.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  175.         break;
  176.     default:
  177.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  178.         break;
  179.     }
  180.  
  181.     /* Compute curve point types. */
  182.     NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
  183.     CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
  184.  
  185.     /* A linear segment is added at the end with Order colinear pts.        */
  186.     /* However since first point is curve last point, only Order - 1 new.   */
  187.     NewLen = Len + Order - 1;
  188.  
  189.     NewCrv = BspCrvNew(NewLen, Order, CrvPType);
  190.     Points = NewCrv -> Points;
  191.  
  192.     CopyCrvOnCrv(NewCrv, 0, Crv);
  193.     for (i = 1; i <= NewMaxCoord; i++) Points[i][NewLen - 1] = Pt -> Pt[i - 1];
  194.     if (IsRational) Points[W][NewLen - 1] = 1.0;
  195.     InterpolateLinearSeg(NewCrv, Len - 1, NewLen - 1);
  196.  
  197.     /* Update the knot vector. We assume open end condition here... */
  198.     GEN_COPY(NewCrv -> KnotVector, Crv -> KnotVector,
  199.          (Len + Order - 1) * sizeof(CagdRType));
  200.     t = Crv -> KnotVector[Len + Order - 1] + 1.0;
  201.     for (i = Len + Order - 1; i < NewLen + Order; i++)
  202.     NewCrv -> KnotVector[i] = t;
  203.  
  204.     if (CrvNew)
  205.     CagdCrvFree(Crv);
  206.  
  207.     return NewCrv;
  208. }
  209.  
  210. /******************************************************************************
  211. * Merge a point and a curve.                              *
  212. ******************************************************************************/
  213. CagdCrvStruct *CagdMergePtCrv(CagdPtStruct *Pt, CagdCrvStruct *Crv)
  214. {
  215.     CagdBType
  216.     CrvNew = FALSE,
  217.     IsRational = CAGD_IS_RATIONAL_CRV(Crv);
  218.     int i, NewLen, NewMaxCoord,
  219.     Order = Crv -> Order,
  220.     Len = Crv -> Length,
  221.     PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
  222.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  223.     CagdPointType
  224.     CrvPType = CAGD_PT_E2_TYPE;
  225.     CagdRType t, **Points;
  226.     CagdCrvStruct *NewCrv;
  227.  
  228.     switch (Crv -> GType) {
  229.     case CAGD_CBEZIER_TYPE:
  230.         Crv = CnvrtBezier2BsplineCrv(Crv);
  231.         CrvNew = TRUE;
  232.         break;
  233.     case CAGD_CBSPLINE_TYPE:
  234.         break;
  235.     case CAGD_CPOWER_TYPE:
  236.         FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
  237.         break;
  238.     default:
  239.         FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
  240.         break;
  241.     }
  242.  
  243.     /* Compute curve point types. */
  244.     NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
  245.     CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
  246.  
  247.     /* A linear segment is added at the end with Order colinear pts.        */
  248.     /* However since first point is curve last point, only Order - 1 new.   */
  249.     NewLen = Len + Order - 1;
  250.  
  251.     NewCrv = BspCrvNew(NewLen, Order, CrvPType);
  252.     Points = NewCrv -> Points;
  253.  
  254.     CopyCrvOnCrv(NewCrv, Order - 1, Crv);
  255.     for (i = 1; i <= NewMaxCoord; i++) Points[i][0] = Pt -> Pt[i - 1];
  256.     if (IsRational) Points[W][0] = 1.0;
  257.     InterpolateLinearSeg(NewCrv, 0, Order - 1);
  258.  
  259.     /* Update the knot vector. We assume open end condition here... */
  260.     GEN_COPY(&NewCrv -> KnotVector[Order], &Crv -> KnotVector[1],
  261.          (Len + Order - 1) * sizeof(CagdRType));
  262.     t = Crv -> KnotVector[0] - 1.0;
  263.     for (i = 0; i < Order; i++)
  264.     NewCrv -> KnotVector[i] = t;
  265.  
  266.     if (CrvNew)
  267.     CagdCrvFree(Crv);
  268.  
  269.     return NewCrv;
  270. }
  271.  
  272. /******************************************************************************
  273. * Merge two points into a linear Bezier curve.                      *
  274. ******************************************************************************/
  275. CagdCrvStruct *CagdMergePtPt(CagdPtStruct *Pt1, CagdPtStruct *Pt2)
  276. {
  277.     CagdPointType
  278.     CrvPType = APX_EQ(Pt1 -> Pt[2], 0.0) && APX_EQ(Pt2 -> Pt[2], 0.0) ?
  279.                     CAGD_PT_E2_TYPE : CAGD_PT_E3_TYPE;
  280.     CagdCrvStruct
  281.     *Crv = BzrCrvNew(2, CrvPType);
  282.     CagdRType
  283.     **Points = Crv -> Points;
  284.  
  285.     Points[X][0] = Pt1 -> Pt[0];
  286.     Points[X][1] = Pt2 -> Pt[0];
  287.     Points[Y][0] = Pt1 -> Pt[1];
  288.     Points[Y][1] = Pt2 -> Pt[1];
  289.     if (CrvPType == CAGD_PT_E3_TYPE) {
  290.         Points[Z][0] = Pt1 -> Pt[2];
  291.         Points[Z][1] = Pt2 -> Pt[2];
  292.     }
  293.  
  294.     return Crv;
  295. }
  296.  
  297. /******************************************************************************
  298. * Copy SrcCrv into DestCrv at point index Index.                  *
  299. * DestCrv PType is assumed to hold Src PType.                      *
  300. ******************************************************************************/
  301. static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
  302.              CagdCrvStruct *SrcCrv)
  303. {
  304.     CagdBType
  305.     IsNotRational = !CAGD_IS_RATIONAL_CRV(SrcCrv);
  306.     int i, j,
  307.     Len = SrcCrv -> Length,
  308.     MaxCoord = CAGD_NUM_OF_PT_COORD(SrcCrv -> PType);
  309.     CagdRType
  310.     **SrcPoints = SrcCrv -> Points,
  311.     **DestPoints = DestCrv -> Points;
  312.  
  313.     for (i = IsNotRational; i <= MaxCoord; i++)
  314.     GEN_COPY(&DestPoints[i][Index], SrcPoints[i],
  315.          Len * sizeof(CagdRType));
  316.  
  317.     /* Fix the weights if source did not have them. */
  318.     if (IsNotRational && CAGD_IS_RATIONAL_CRV(DestCrv))
  319.     for (i = Index; i < Index + Len; i++)
  320.         DestPoints[W][i] = 1.0;
  321.  
  322.     /* Fix the higher coordinates (by coercing them to zero. */
  323.     for (i = MaxCoord + 1; i < CAGD_NUM_OF_PT_COORD(DestCrv -> PType); i++)
  324.     for (j = Index; j < Index + Len; j++)
  325.         DestPoints[i][j] = 0.0;
  326.  
  327. }
  328.  
  329. /******************************************************************************
  330. * Linearly interpolate between the Crv points indices Index1 and Index2       *
  331. ******************************************************************************/
  332. static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2)
  333. {
  334.     CagdBType
  335.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  336.     int i, j,
  337.     DIndex = Index2 - Index1,
  338.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  339.     CagdRType
  340.     **Points = Crv -> Points;
  341.  
  342.     if (DIndex < 2) return;             /* No middle points to interp. */
  343.  
  344.     for (i = Index1 + 1; i < Index2; i++) {
  345.     CagdRType
  346.         t1 = ((CagdRType) (i - Index1)) / DIndex,
  347.         t2 = 1.0 - t1;
  348.  
  349.     for (j = IsNotRational; j <= MaxCoord; j++)
  350.         Points[j][i] = t2 * Points[j][Index1] + t1 * Points[j][Index2];
  351.     }
  352. }
  353.