home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CagdCMrg.c - Curve/Point merging routines. *
- *******************************************************************************
- * Written by Gershon Elber, May 91. *
- ******************************************************************************/
-
- #include "string.h"
- #include "cagd_loc.h"
-
- static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
- CagdCrvStruct *SrcCrv);
- static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2);
-
- /******************************************************************************
- * Merge two curves. *
- ******************************************************************************/
- CagdCrvStruct *CagdMergeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
- {
- CagdBType CrvsSharePt,
- Crv1New = FALSE,
- Crv2New = FALSE,
- IsRational1 = CAGD_IS_RATIONAL_CRV(Crv1),
- IsRational2 = CAGD_IS_RATIONAL_CRV(Crv2);
- int Length, Order,
- Order1 = Crv1 -> Order,
- Order2 = Crv2 -> Order,
- Len1 = Crv1 -> Length,
- Len2 = Crv2 -> Length,
- MaxCoord1 = CAGD_NUM_OF_PT_COORD(Crv1 -> PType),
- MaxCoord2 = CAGD_NUM_OF_PT_COORD(Crv2 -> PType);
- CagdRType E3Pt1[3], E3Pt2[3];
- CagdPointType CrvPType = CAGD_PT_E2_TYPE;
- CagdCrvStruct *Crv;
-
- /* Make orders compatible: */
- if (Order1 < Order2) {
- for (; Order1 < Order2; Order1++) {
- Crv = CagdCrvDegreeRaise(Crv1);
- if (Crv1New)
- CagdCrvFree(Crv1);
- Crv1 = Crv;
- Len1 = Crv1 -> Length;
- Crv1New = TRUE;
- }
- }
- else if (Order2 < Order1) {
- for (; Order2 < Order1; Order2++) {
- Crv = CagdCrvDegreeRaise(Crv2);
- if (Crv2New)
- CagdCrvFree(Crv2);
- Crv2 = Crv;
- Len2 = Crv2 -> Length;
- Crv2New = TRUE;
- }
- }
- Order = Order1;
-
- /* Verify curve geometric types. */
- switch (Crv1 -> GType) {
- case CAGD_CBEZIER_TYPE:
- Crv = CnvrtBezier2BsplineCrv(Crv1);
- if (Crv1New)
- CagdCrvFree(Crv1);
- Crv1 = Crv;
- Crv1New = TRUE;
- break;
- case CAGD_CBSPLINE_TYPE:
- break;
- case CAGD_CPOWER_TYPE:
- FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
- break;
- }
-
- switch (Crv2 -> GType) {
- case CAGD_CBEZIER_TYPE:
- Crv = CnvrtBezier2BsplineCrv(Crv2);
- if (Crv2New)
- CagdCrvFree(Crv2);
- Crv2 = Crv;
- Crv2New = TRUE;
- break;
- case CAGD_CBSPLINE_TYPE:
- break;
- case CAGD_CPOWER_TYPE:
- FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
- break;
- }
-
- /* Compute curve point types. */
- CrvPType = CAGD_MAKE_PT_TYPE(IsRational1 || IsRational2,
- MAX(MaxCoord1, MaxCoord2));
-
-
- /* Figure out if end point of Crv1 is equal to start point of Crv2 and */
- /* Compute the length of the resulting curve accordingly. */
- /* If the same point, then the result can omit one copy and therefore */
- /* has Len1 + Len2 - 1 Ctl points. If however a linear segment should be */
- /* introduced between the two curves, it should hold Order colinear pts */
- /* including 2 end points shared with curves or Order - 2 new pts. */
- CagdCoerceToE3(E3Pt1, Crv1 -> Points, Len1 - 1, Crv1 -> PType);
- CagdCoerceToE3(E3Pt2, Crv2 -> Points, 0, Crv2 -> PType);
- CrvsSharePt = APX_EQ(E3Pt1[0], E3Pt2[0]) &&
- APX_EQ(E3Pt1[1], E3Pt2[1]) &&
- APX_EQ(E3Pt1[2], E3Pt2[2]);
- Length = CrvsSharePt ? Len1 + Len2 - 1 : Len1 + Len2 + Order - 2;
-
- Crv = BspCrvNew(Length, Order, CrvPType);
- CopyCrvOnCrv(Crv, 0, Crv1);
- CopyCrvOnCrv(Crv, Length - Len2, Crv2);
- InterpolateLinearSeg(Crv, Len1 - 1, Length - Len2);
-
- /* Update the knot vector. We assume open end condition here... */
- GEN_COPY(Crv -> KnotVector, Crv1 -> KnotVector,
- (Len1 + Order1 - 1) * sizeof(CagdRType));
- if (CrvsSharePt) {
- GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
- &Crv2 -> KnotVector[Order2], Len2 * sizeof(CagdRType));
- BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
- Len2,
- Crv -> KnotVector[Len1 + Order1 - 2] -
- Crv2 -> KnotVector[0],
- 1.0);
- }
- else {
- GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
- &Crv2 -> KnotVector[1],
- (Len2 + Order2 - 1) * sizeof(CagdRType));
- BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
- Len2 + Order2 - 1,
- Crv -> KnotVector[Len1 + Order1 - 2] -
- Crv -> KnotVector[Len1 + Order1 - 1] + 1.0,
- 1.0);
- }
-
- if (Crv1New)
- CagdCrvFree(Crv1);
- if (Crv2New)
- CagdCrvFree(Crv2);
-
- return Crv;
- }
-
- /******************************************************************************
- * Merge a curve and a point. *
- ******************************************************************************/
- CagdCrvStruct *CagdMergeCrvPt(CagdCrvStruct *Crv, CagdPtStruct *Pt)
- {
- CagdBType
- CrvNew = FALSE,
- IsRational = CAGD_IS_RATIONAL_CRV(Crv);
- int i, NewLen, NewMaxCoord,
- Order = Crv -> Order,
- Len = Crv -> Length,
- PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdPointType
- CrvPType = CAGD_PT_E2_TYPE;
- CagdRType t, **Points;
- CagdCrvStruct *NewCrv;
-
- switch (Crv -> GType) {
- case CAGD_CBEZIER_TYPE:
- Crv = CnvrtBezier2BsplineCrv(Crv);
- CrvNew = TRUE;
- case CAGD_CBSPLINE_TYPE:
- break;
- case CAGD_CPOWER_TYPE:
- FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
- break;
- }
-
- /* Compute curve point types. */
- NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
- CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
-
- /* A linear segment is added at the end with Order colinear pts. */
- /* However since first point is curve last point, only Order - 1 new. */
- NewLen = Len + Order - 1;
-
- NewCrv = BspCrvNew(NewLen, Order, CrvPType);
- Points = NewCrv -> Points;
-
- CopyCrvOnCrv(NewCrv, 0, Crv);
- for (i = 1; i <= NewMaxCoord; i++) Points[i][NewLen - 1] = Pt -> Pt[i - 1];
- if (IsRational) Points[W][NewLen - 1] = 1.0;
- InterpolateLinearSeg(NewCrv, Len - 1, NewLen - 1);
-
- /* Update the knot vector. We assume open end condition here... */
- GEN_COPY(NewCrv -> KnotVector, Crv -> KnotVector,
- (Len + Order - 1) * sizeof(CagdRType));
- t = Crv -> KnotVector[Len + Order - 1] + 1.0;
- for (i = Len + Order - 1; i < NewLen + Order; i++)
- NewCrv -> KnotVector[i] = t;
-
- if (CrvNew)
- CagdCrvFree(Crv);
-
- return NewCrv;
- }
-
- /******************************************************************************
- * Merge a point and a curve. *
- ******************************************************************************/
- CagdCrvStruct *CagdMergePtCrv(CagdPtStruct *Pt, CagdCrvStruct *Crv)
- {
- CagdBType
- CrvNew = FALSE,
- IsRational = CAGD_IS_RATIONAL_CRV(Crv);
- int i, NewLen, NewMaxCoord,
- Order = Crv -> Order,
- Len = Crv -> Length,
- PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdPointType
- CrvPType = CAGD_PT_E2_TYPE;
- CagdRType t, **Points;
- CagdCrvStruct *NewCrv;
-
- switch (Crv -> GType) {
- case CAGD_CBEZIER_TYPE:
- Crv = CnvrtBezier2BsplineCrv(Crv);
- CrvNew = TRUE;
- break;
- case CAGD_CBSPLINE_TYPE:
- break;
- case CAGD_CPOWER_TYPE:
- FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
- break;
- }
-
- /* Compute curve point types. */
- NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
- CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
-
- /* A linear segment is added at the end with Order colinear pts. */
- /* However since first point is curve last point, only Order - 1 new. */
- NewLen = Len + Order - 1;
-
- NewCrv = BspCrvNew(NewLen, Order, CrvPType);
- Points = NewCrv -> Points;
-
- CopyCrvOnCrv(NewCrv, Order - 1, Crv);
- for (i = 1; i <= NewMaxCoord; i++) Points[i][0] = Pt -> Pt[i - 1];
- if (IsRational) Points[W][0] = 1.0;
- InterpolateLinearSeg(NewCrv, 0, Order - 1);
-
- /* Update the knot vector. We assume open end condition here... */
- GEN_COPY(&NewCrv -> KnotVector[Order], &Crv -> KnotVector[1],
- (Len + Order - 1) * sizeof(CagdRType));
- t = Crv -> KnotVector[0] - 1.0;
- for (i = 0; i < Order; i++)
- NewCrv -> KnotVector[i] = t;
-
- if (CrvNew)
- CagdCrvFree(Crv);
-
- return NewCrv;
- }
-
- /******************************************************************************
- * Merge two points into a linear Bezier curve. *
- ******************************************************************************/
- CagdCrvStruct *CagdMergePtPt(CagdPtStruct *Pt1, CagdPtStruct *Pt2)
- {
- CagdPointType
- CrvPType = APX_EQ(Pt1 -> Pt[2], 0.0) && APX_EQ(Pt2 -> Pt[2], 0.0) ?
- CAGD_PT_E2_TYPE : CAGD_PT_E3_TYPE;
- CagdCrvStruct
- *Crv = BzrCrvNew(2, CrvPType);
- CagdRType
- **Points = Crv -> Points;
-
- Points[X][0] = Pt1 -> Pt[0];
- Points[X][1] = Pt2 -> Pt[0];
- Points[Y][0] = Pt1 -> Pt[1];
- Points[Y][1] = Pt2 -> Pt[1];
- if (CrvPType == CAGD_PT_E3_TYPE) {
- Points[Z][0] = Pt1 -> Pt[2];
- Points[Z][1] = Pt2 -> Pt[2];
- }
-
- return Crv;
- }
-
- /******************************************************************************
- * Copy SrcCrv into DestCrv at point index Index. *
- * DestCrv PType is assumed to hold Src PType. *
- ******************************************************************************/
- static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
- CagdCrvStruct *SrcCrv)
- {
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(SrcCrv);
- int i, j,
- Len = SrcCrv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(SrcCrv -> PType);
- CagdRType
- **SrcPoints = SrcCrv -> Points,
- **DestPoints = DestCrv -> Points;
-
- for (i = IsNotRational; i <= MaxCoord; i++)
- GEN_COPY(&DestPoints[i][Index], SrcPoints[i],
- Len * sizeof(CagdRType));
-
- /* Fix the weights if source did not have them. */
- if (IsNotRational && CAGD_IS_RATIONAL_CRV(DestCrv))
- for (i = Index; i < Index + Len; i++)
- DestPoints[W][i] = 1.0;
-
- /* Fix the higher coordinates (by coercing them to zero. */
- for (i = MaxCoord + 1; i < CAGD_NUM_OF_PT_COORD(DestCrv -> PType); i++)
- for (j = Index; j < Index + Len; j++)
- DestPoints[i][j] = 0.0;
-
- }
-
- /******************************************************************************
- * Linearly interpolate between the Crv points indices Index1 and Index2 *
- ******************************************************************************/
- static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2)
- {
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j,
- DIndex = Index2 - Index1,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType
- **Points = Crv -> Points;
-
- if (DIndex < 2) return; /* No middle points to interp. */
-
- for (i = Index1 + 1; i < Index2; i++) {
- CagdRType
- t1 = ((CagdRType) (i - Index1)) / DIndex,
- t2 = 1.0 - t1;
-
- for (j = IsNotRational; j <= MaxCoord; j++)
- Points[j][i] = t2 * Points[j][Index1] + t1 * Points[j][Index2];
- }
- }
-