/****************************************************************************** * CagdCmpt.c - Make objects compatible. * ******************************************************************************* * Written by Gershon Elber, Sep. 91. * ******************************************************************************/ #ifdef __MSDOS__ #include #include #include #endif /* __MSDOS__ */ #include "cagd_loc.h" /****************************************************************************** * Given two curves, make the compatible by: * * 1. Coercing their point type to be the same. * * 2. Make them have the same curve type. * * 3. Raising the degree of the lower one to be the same. * * 4. Refine them to a common knot vector (If Bspline). * * Note 3 is preformed if SameOrder TRUE, 4 if SameKV TRUE. * * Returns TRUE if succesfull. Both Curves are modified IN PLACE. * ******************************************************************************/ CagdBType CagdMakeCrvsCompatible(CagdCrvStruct **Crv1, CagdCrvStruct **Crv2, CagdBType SameOrder, CagdBType SameKV) { int i, KV1Len, KV2Len, RefLen; CagdRType *KV1, *KV2, *RefKV; CagdCrvStruct *TCrv; CagdPointType CommonPType = CagdMergePointType((*Crv1) -> PType, (*Crv2) -> PType); /* Make the point types compatible. */ if (CommonPType != (*Crv1) -> PType) { TCrv = CagdCoerceCrvTo(*Crv1, CommonPType); CagdCrvFree(*Crv1); *Crv1 = TCrv; } if (CommonPType != (*Crv2) -> PType) { TCrv = CagdCoerceCrvTo(*Crv2, CommonPType); CagdCrvFree(*Crv2); *Crv2 = TCrv; } /* If incompatible curve type - make it the same as well. */ if ((*Crv1) -> GType != (*Crv2) -> GType) { /* If power basis - promote to bezier: */ if ((*Crv1) -> GType == CAGD_CPOWER_TYPE) { TCrv = CnvrtPower2BezierCrv(*Crv1); CagdCrvFree(*Crv1); *Crv1 = TCrv; } if ((*Crv2) -> GType == CAGD_CPOWER_TYPE) { TCrv = CnvrtPower2BezierCrv(*Crv2); CagdCrvFree(*Crv2); *Crv2 = TCrv; } /* Now both curves may be either bezier or bspline curves. */ if ((*Crv1) -> GType != (*Crv2) -> GType) { /* If bezier basis - promote to bspline: */ if ((*Crv1) -> GType == CAGD_CBEZIER_TYPE) { TCrv = CnvrtBezier2BsplineCrv(*Crv1); CagdCrvFree(*Crv1); *Crv1 = TCrv; } if ((*Crv2) -> GType == CAGD_CBEZIER_TYPE) { TCrv = CnvrtBezier2BsplineCrv(*Crv2); CagdCrvFree(*Crv2); *Crv2 = TCrv; } } } if (SameOrder) { /* Raise the degree of the lower one. */ for (i = (*Crv1) -> Order; i < (*Crv2) -> Order; i++) { TCrv = CagdCrvDegreeRaise(*Crv1); CagdCrvFree(*Crv1); *Crv1 = TCrv; } for (i = (*Crv2) -> Order; i < (*Crv1) -> Order; i++) { TCrv = CagdCrvDegreeRaise(*Crv2); CagdCrvFree(*Crv2); *Crv2 = TCrv; } } if (SameKV) { /* If bspline curve - make sure knot vectors are the same. */ if ((*Crv1) -> GType == CAGD_CBSPLINE_TYPE) { KV1 = (*Crv1) -> KnotVector; KV2 = (*Crv2) -> KnotVector; KV1Len = (*Crv1) -> Length + (*Crv1) -> Order; KV2Len = (*Crv2) -> Length + (*Crv2) -> Order; /* Affine map second knot vector to span same parametric domain. */ BspKnotAffineTrans(KV2, KV2Len, KV1[0] - KV2[0], (KV1[KV1Len - 1] - KV1[0]) / (KV2[KV2Len - 1] - KV2[0])); /* Find knots in KV2 which are not in KV1 and refine Crv1 there. */ RefKV = BspKnotSubtrTwo(KV2, KV2Len, KV1, KV1Len, &RefLen); if (RefLen > 0) { TCrv = CagdCrvRefineAtParams(*Crv1, FALSE, RefKV, RefLen); CagdCrvFree(*Crv1); *Crv1 = TCrv; KV1 = (*Crv1) -> KnotVector; KV1Len = (*Crv1) -> Length + (*Crv1) -> Order; } CagdFree((VoidPtr) RefKV); /* Find knots in KV1 which are not in KV2 and refine Crv2 there. */ RefKV = BspKnotSubtrTwo(KV1, KV1Len, KV2, KV2Len, &RefLen); if (RefLen > 0) { TCrv = CagdCrvRefineAtParams(*Crv2, FALSE, RefKV, RefLen); CagdCrvFree(*Crv2); *Crv2 = TCrv; } CagdFree((VoidPtr) RefKV); } } return TRUE; }