/****************************************************************************** * CagdBSum.c - Boolean sum surface constructor out of given four curves. * ******************************************************************************* * Written by Gershon Elber, Sep. 91. * ******************************************************************************/ #ifdef __MSDOS__ #include #include #include #endif /* __MSDOS__ */ #include "cagd_loc.h" /****************************************************************************** * Constructs a boolean sum surface using the four provided boundary curves. * * Curve end points must meet at the corners if surface boundary should be the * * same as the four curves. * ******************************************************************************/ CagdSrfStruct *CagdBoolSumSrf(CagdCrvStruct *CrvLeft, CagdCrvStruct *CrvRight, CagdCrvStruct *CrvTop, CagdCrvStruct *CrvBottom) { int i, j; CagdCrvStruct *Crv1, *Crv2; CagdSrfStruct *Ruled1, *Ruled2, *Ruled3, *Srf; CagdPtStruct Pt1, Pt2; CagdRType **SrfPoints, **Ruled1Pts, **Ruled2Pts, **Ruled3Pts; CrvLeft = CagdCrvCopy(CrvLeft); CrvRight = CagdCrvCopy(CrvRight); CrvTop = CagdCrvCopy(CrvTop); CrvBottom = CagdCrvCopy(CrvBottom); /* The Left-Right and Top-Bottom curves should share same point/curve */ /* type as well as same order and knot vector (if Bspline representation).*/ CagdMakeCrvsCompatible(&CrvLeft, &CrvRight, TRUE, TRUE); CagdMakeCrvsCompatible(&CrvTop, &CrvBottom, TRUE, TRUE); /* The Left-Right and Top-Bottom pairs must share same point/curve type. */ CagdMakeCrvsCompatible(&CrvLeft, &CrvTop, FALSE, FALSE); CagdMakeCrvsCompatible(&CrvLeft, &CrvBottom, FALSE, FALSE); CagdMakeCrvsCompatible(&CrvRight, &CrvTop, FALSE, FALSE); CagdMakeCrvsCompatible(&CrvRight, &CrvBottom, FALSE, FALSE); /* Now that the curves are in the right representation, form surface(s). */ /* The two ruled surface between the respective curves, in right orders: */ Ruled1 = CagdRuledSrf(CrvLeft, CrvRight, CrvTop -> Order, CrvTop -> Length); Ruled2 = CagdRuledSrf(CrvTop, CrvBottom, CrvRight -> Order, CrvRight -> Length); Srf = CagdSrfReverse2(Ruled2); CagdSrfFree(Ruled2); Ruled2 = Srf; /* The ruled surface between the four corner points in the right orders. */ CagdCoerceToE3(Pt1.Pt, CrvLeft -> Points, 0, CrvLeft -> PType); CagdCoerceToE3(Pt2.Pt, CrvLeft -> Points, CrvLeft -> Length - 1, CrvLeft -> PType); Crv1 = CagdMergePtPt(&Pt1, &Pt2); CagdCoerceToE3(Pt1.Pt, CrvRight -> Points, 0, CrvRight -> PType); CagdCoerceToE3(Pt2.Pt, CrvRight -> Points, CrvRight -> Length - 1, CrvRight -> PType); Crv2 = CagdMergePtPt(&Pt1, &Pt2); /* Should not change CrvLeft/Right only Crv1/2: */ CagdMakeCrvsCompatible(&Crv1, &CrvLeft, TRUE, TRUE); CagdMakeCrvsCompatible(&Crv2, &CrvRight, TRUE, TRUE); Ruled3 = CagdRuledSrf(Crv1, Crv2, CrvTop -> Order, CrvTop -> Length); CagdCrvFree(Crv1); CagdCrvFree(Crv2); /* The boolean sum is equal to Ruled1 + Ruled2 - Ruled3. This boolean */ /* sum as computed is not exactly as defined in the literature for non */ /* uniform Bsplines since the ruled surfaces are computed with uniform */ /* distribution along the other axis even if it is non uniform. */ if (CrvRight -> GType == CAGD_CBSPLINE_TYPE) { Srf = BspSrfNew(Ruled1 -> ULength, Ruled1 -> VLength, Ruled1 -> UOrder, Ruled1 -> VOrder, Ruled1 -> PType); CagdFree((VoidPtr) Srf -> UKnotVector); Srf -> UKnotVector = BspKnotCopy(CrvLeft -> KnotVector, CrvLeft -> Length + CrvLeft -> Order); CagdFree((VoidPtr) Srf -> VKnotVector); Srf -> VKnotVector = BspKnotCopy(CrvTop -> KnotVector, CrvTop -> Length + CrvTop -> Order); } else if (CrvRight -> GType == CAGD_CBEZIER_TYPE) Srf = BzrSrfNew(Ruled1 -> ULength, Ruled1 -> VLength, Ruled1 -> PType); else FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT); SrfPoints = Srf -> Points; Ruled1Pts = Ruled1 -> Points; Ruled2Pts = Ruled2 -> Points; Ruled3Pts = Ruled3 -> Points; for (i = !CAGD_IS_RATIONAL_SRF(Srf); i <= CAGD_NUM_OF_PT_COORD(Srf -> PType); i++) { CagdRType *Ruled1PtsPtr = Ruled1Pts[i], *Ruled2PtsPtr = Ruled2Pts[i], *Ruled3PtsPtr = Ruled3Pts[i], *SrfPointsPtr = SrfPoints[i]; for (j = Srf -> ULength * Srf -> VLength; j > 0; j--) *SrfPointsPtr++ = *Ruled1PtsPtr++ + *Ruled2PtsPtr++ - *Ruled3PtsPtr++; } CagdSrfFree(Ruled1); CagdSrfFree(Ruled2); CagdSrfFree(Ruled3); return Srf; }