/****************************************************************************** * CagdCSrf.c - Construct a surface using a set of curves. * ******************************************************************************* * (C) Gershon Elber, Technion, Israel Institute of Technology * ******************************************************************************* * Written by Gershon Elber, Sep. 91. * ******************************************************************************/ #include "cagd_loc.h" /***************************************************************************** * DESCRIPTION: M * Constructs a surface using a set of curves. Curves are made to be M * compatible and then each is substituted into the new surface's mesh as a M * row. M * If the OtherOrder is less than the number of curves, number of curves is M * used. If OtherOrder is negative, the absolute value is employed and a M * periodic surface is constructed in the other direction. M * A knot vector is formed with uniform open end for the other direction, M * so it interpolates the first and last curves. M * Note, however, that only the first and the last curves are interpolated M * if OtherOrder is greater than 2. M * * * PARAMETERS: M * CrvList: List of curves to consturct a surface with. M * OtherOrder: Other order of surface. M * OtherEC: End condition in the other (non CrvList) srf direction. M * * * RETURN VALUE: M * CagdSrfStruct *: Constructed surface from curves. M * * * KEYWORDS: M * CagdSrfFromCrvs, surface constructors M *****************************************************************************/ CagdSrfStruct *CagdSrfFromCrvs(CagdCrvStruct *CrvList, int OtherOrder, CagdEndConditionType OtherEC) { CagdBType IsNotRational, OtherPeriodic = OtherEC == CAGD_END_COND_PERIODIC; int i, j, NumCrvs, UOrder, VOrder, MaxCoord, Length; CagdRType **SrfPoints; CagdCrvStruct *Crv, **CrvVec; CagdSrfStruct *Srf; OtherOrder = ABS(OtherOrder); /* Find out how many curves we have and put them in a linear vector. */ /* Note the vector have a COPY of the curves so we can modify them. */ for (NumCrvs = 0, Crv = CrvList; Crv != NULL; NumCrvs++, Crv = Crv -> Pnext); CrvVec = (CagdCrvStruct **) IritMalloc(sizeof(CagdCrvStruct *) * NumCrvs); for (i = 0, Crv = CrvList; i < NumCrvs; i++, Crv = Crv -> Pnext) CrvVec[i] = CagdCrvCopy(Crv); /* Traverse vector in a O(n) fashion and make all curves compatible. */ for (i = 0; i < NumCrvs - 1; i++) CagdMakeCrvsCompatible(&CrvVec[i], &CrvVec[i + 1], TRUE, TRUE); for (i = NumCrvs - 2; i >= 0; i--) CagdMakeCrvsCompatible(&CrvVec[i], &CrvVec[i + 1], TRUE, TRUE); /* Construct the surface. All required information is now available. */ UOrder = CrvVec[0] -> Order; VOrder = MIN(NumCrvs, OtherOrder); if (NumCrvs == VOrder && CAGD_IS_BEZIER_CRV(CrvVec[0]) && OtherEC == CAGD_END_COND_OPEN) { /* Allocate a bezier surface. */ Srf = BzrSrfNew(CrvVec[0] -> Length, NumCrvs, CrvVec[0] -> PType); } else { /* Allocate a bspline surface. */ Srf = BspPeriodicSrfNew(CrvVec[0] -> Length, NumCrvs, UOrder, VOrder, CrvVec[0] -> Periodic, OtherPeriodic, CrvVec[0] -> PType); if (CAGD_IS_BEZIER_CRV(CrvVec[0])) BspKnotUniformOpen(Srf -> ULength, Srf -> UOrder, Srf -> UKnotVector); else { BspKnotCopy(Srf -> UKnotVector, CrvVec[0] -> KnotVector, CAGD_CRV_PT_LST_LEN(CrvVec[0]) + UOrder); } switch (OtherEC) { case CAGD_END_COND_OPEN: BspKnotUniformOpen(NumCrvs, VOrder, Srf -> VKnotVector); break; case CAGD_END_COND_FLOAT: BspKnotUniformFloat(NumCrvs, VOrder, Srf -> VKnotVector); break; case CAGD_END_COND_PERIODIC: BspKnotUniformPeriodic(NumCrvs, VOrder, Srf -> VKnotVector); break; } } /* Substitute each curve as a row into the surface mesh and delete it. */ SrfPoints = Srf -> Points; i = 0; MaxCoord = CAGD_NUM_OF_PT_COORD(CrvVec[0] -> PType), IsNotRational = !CAGD_IS_RATIONAL_CRV(CrvVec[0]); Length = CrvVec[0] -> Length; for (j = 0; j < NumCrvs; j++) { int k; CagdRType **CrvPoints = CrvVec[j] -> Points; for (k = IsNotRational; k <= MaxCoord; k++) CAGD_GEN_COPY(&SrfPoints[k][i], CrvPoints[k], sizeof(CagdRType) * Length); CagdCrvFree(CrvVec[j]); i += Length; } IritFree(CrvVec); return Srf; }