/****************************************************************************** * TrivSTrv.c - Construct a trivariate using a set of surfaces. * ******************************************************************************* * (C) Gershon Elber, Technion, Israel Institute of Technology * ******************************************************************************* * Written by Gershon Elber, Sep. 91. * ******************************************************************************/ #include "triv_loc.h" /***************************************************************************** * DESCRIPTION: M * Constructs a trivariate using a set of surfaces. Surfaces are made to be M * compatible and then each is substituted into the new trivariate's mesh as M * a row. M * If the OtherOrder is less than the number of curves, number of curves is M * used. M * A knot vector is formed with uniform open end for the other direction, M * so it interpolates the first and last surfaces. M * Note, however, that only the first and the last surfaces are M * interpolated if OtherOrder is greater than 2. M * * * PARAMETERS: M * SrfList: List of surfaces to consturct a trivariate with. M * OtherOrder: Other, third, order of trivariate. M * OtherEC: End condition in the other, third, trivar direction. M * * * RETURN VALUE: M * TrivTVStruct *: Constructed trivariate from surfaces. M * * * KEYWORDS: M * TrivTVFromSrfs, trivar constructors M *****************************************************************************/ TrivTVStruct *TrivTVFromSrfs(CagdSrfStruct *SrfList, int OtherOrder, CagdEndConditionType OtherEC) { CagdBType IsNotRational; int i, j, NumSrfs, UOrder, VOrder, WOrder, MaxCoord, Length; CagdRType **TVPoints; CagdSrfStruct *Srf, **SrfVec; TrivTVStruct *TV; /* 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 (NumSrfs = 0, Srf = SrfList; Srf != NULL; NumSrfs++, Srf = Srf -> Pnext); SrfVec = (CagdSrfStruct **) IritMalloc(sizeof(CagdSrfStruct *) * NumSrfs); for (i = 0, Srf = SrfList; i < NumSrfs; i++, Srf = Srf -> Pnext) SrfVec[i] = CagdSrfCopy(Srf); /* Traverse vector in a O(n) fashion and make all curves compatible. */ for (i = 0; i < NumSrfs - 1; i++) CagdMakeSrfsCompatible(&SrfVec[i], &SrfVec[i + 1], TRUE, TRUE, TRUE, TRUE); for (i = NumSrfs - 2; i >= 0; i--) CagdMakeSrfsCompatible(&SrfVec[i], &SrfVec[i + 1], TRUE, TRUE, TRUE, TRUE); /* Construct the surface. All required information is now available. */ UOrder = SrfVec[0] -> UOrder; VOrder = SrfVec[0] -> VOrder; WOrder = MIN(NumSrfs, OtherOrder); if (NumSrfs == WOrder && SrfVec[0] -> GType == CAGD_SBEZIER_TYPE && OtherEC == CAGD_END_COND_OPEN) { /* Allocate a bezier surface. */ TV = TrivBzrTVNew(SrfVec[0] -> ULength, SrfVec[0] -> VLength, NumSrfs, SrfVec[0] -> PType); } else { /* Allocate a bspline surface. */ TV = TrivBspTVNew(SrfVec[0] -> ULength, SrfVec[0] -> VLength, NumSrfs, UOrder, VOrder, WOrder, SrfVec[0] -> PType); if (SrfVec[0] -> GType == CAGD_SBEZIER_TYPE) { BspKnotUniformOpen(UOrder, UOrder, TV -> UKnotVector); BspKnotUniformOpen(VOrder, VOrder, TV -> VKnotVector); } else { BspKnotCopy(TV -> UKnotVector, SrfVec[0] -> UKnotVector, CAGD_SRF_UPT_LST_LEN(SrfVec[0]) + UOrder); BspKnotCopy(TV -> VKnotVector, SrfVec[0] -> VKnotVector, CAGD_SRF_VPT_LST_LEN(SrfVec[0]) + VOrder); } switch (OtherEC) { case CAGD_END_COND_OPEN: BspKnotUniformOpen(NumSrfs, WOrder, TV -> WKnotVector); break; case CAGD_END_COND_FLOAT: BspKnotUniformFloat(NumSrfs, WOrder, TV -> WKnotVector); break; case CAGD_END_COND_PERIODIC: IritFree(TV -> WKnotVector); /* Not long enough. */ TV -> WKnotVector = BspKnotUniformPeriodic(NumSrfs, WOrder, NULL); TV -> WPeriodic = TRUE; break; } } /* Substitute each surface as a plane into the trivar's mesh and delete. */ TVPoints = TV -> Points; i = 0; MaxCoord = CAGD_NUM_OF_PT_COORD(SrfVec[0] -> PType), IsNotRational = !CAGD_IS_RATIONAL_SRF(SrfVec[0]); Length = SrfVec[0] -> ULength * SrfVec[0] -> VLength; for (j = 0; j < NumSrfs; j++) { int k; CagdRType **SrfPoints = SrfVec[j] -> Points; for (k = IsNotRational; k <= MaxCoord; k++) CAGD_GEN_COPY(&TVPoints[k][i], SrfPoints[k], sizeof(CagdRType) * Length); CagdSrfFree(SrfVec[j]); i += Length; } IritFree(SrfVec); return TV; }