home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CBzr-Aux.c - Bezier curve auxilary routines. *
- *******************************************************************************
- * Written by Gershon Elber, Mar. 90. *
- ******************************************************************************/
-
- #ifdef __MSDOS__
- #include <stdlib.h>
- #endif /* __MSDOS__ */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include "cagd_loc.h"
-
- /******************************************************************************
- * Given a bezier curve - subdivide it into two at the given parametric value. *
- * Returns pointer to first curve in a list of two curves (subdivided ones). *
- * The subdivision is exact result of evaluating the curve at t using the *
- * recursive algorithm - the left resulting points are the left curve, and the *
- * right resulting points are the right curve (left is below t). *
- ******************************************************************************/
- CagdCrvStruct *BzrCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t)
- {
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j, l,
- k = Crv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType
- t1 = 1.0 - t;
- CagdCrvStruct
- *RCrv = BzrCrvNew(k, Crv -> PType),
- *LCrv = BzrCrvNew(k, Crv -> PType);
-
- /* Copy Curve into RCrv, so we can apply the recursive algo. to it. */
- for (i = 0; i < k; i++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][i] = Crv -> Points[j][i];
-
- for (j = IsNotRational; j <= MaxCoord; j++)
- LCrv -> Points[j][0] = Crv -> Points[j][0];
-
- /* Apply the recursive algorithm to RCrv, and update LCrv with the */
- /* temporary results. Note we updated the first point of LCrv above. */
- for (i = 1; i < k; i++) {
- for (l = 0; l < k - i; l++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
- RCrv -> Points[j][l+1] * t;
- /* Copy temporary result to LCrv: */
- for (j = IsNotRational; j <= MaxCoord; j++)
- LCrv -> Points[j][i] = RCrv -> Points[j][0];
- }
- LCrv -> Pnext = RCrv;
-
- return LCrv;
- }
-
- /******************************************************************************
- * Return a new curve, identical to the original but with one degree higher *
- * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then: *
- * i k-i *
- * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1). *
- * k k *
- ******************************************************************************/
- CagdCrvStruct *BzrCrvDegreeRaise(CagdCrvStruct *Crv)
- {
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j,
- k = Crv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdCrvStruct
- *RaisedCrv = BzrCrvNew(k + 1, Crv -> PType);
-
- for (j = IsNotRational; j <= MaxCoord; j++) /* Q(0). */
- RaisedCrv -> Points[j][0] = Crv -> Points[j][0];
-
- for (i = 1; i < k; i++) /* Q(i). */
- for (j = IsNotRational; j <= MaxCoord; j++)
- RaisedCrv -> Points[j][i] =
- Crv -> Points[j][i-1] * (i / ((CagdRType) k)) +
- Crv -> Points[j][i] * ((k - i) / ((CagdRType) k));
-
- for (j = IsNotRational; j <= MaxCoord; j++) /* Q(k). */
- RaisedCrv -> Points[j][k] = Crv -> Points[j][k-1];
-
- return RaisedCrv;
- }
-
- /******************************************************************************
- * Return a normalized vector, equal to the tangent to Crv at parameter t. *
- * Algorithm: pseudo subdivide Crv at t and using control point of subdivided *
- * curve find the tangent as the difference of the 2 end points. *
- ******************************************************************************/
- CagdVecStruct *BzrCrvTangent(CagdCrvStruct *Crv, CagdRType t)
- {
- static CagdVecStruct P2;
- CagdVecStruct P1;
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j, l,
- k = Crv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType
- t1 = 1.0 - t;
- CagdCrvStruct *RCrv;
-
- if (APX_EQ(t, 0.0)) {
- /* Use Crv starting tangent direction. */
- CagdCoerceToE3(P1.Vec, Crv -> Points, 0, Crv -> PType);
- CagdCoerceToE3(P2.Vec, Crv -> Points, 1, Crv -> PType);
- }
- else if (APX_EQ(t, 1.0)) {
- /* Use Crv ending tangent direction. */
- CagdCoerceToE3(P1.Vec, Crv -> Points, k - 2, Crv -> PType);
- CagdCoerceToE3(P2.Vec, Crv -> Points, k - 1, Crv -> PType);
- }
- else {
- RCrv = BzrCrvNew(k, Crv -> PType);
-
- /* Copy Crv into RCrv, so we can apply the recursive algo. to it. */
- for (i = 0; i < k; i++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][i] = Crv -> Points[j][i];
-
- /* Apply the recursive algorithm to RCrv. */
- for (i = 1; i < k; i++)
- for (l = 0; l < k - i; l++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
- RCrv -> Points[j][l+1] * t;
-
- CagdCoerceToE3(P1.Vec, RCrv -> Points, 0, RCrv -> PType);
- CagdCoerceToE3(P2.Vec, RCrv -> Points, 1, RCrv -> PType);
-
- CagdCrvFree(RCrv);
- }
-
- CAGD_SUB_VECTOR(P2, P1);
-
- CAGD_NORMALIZE_VECTOR(P2); /* Normalize the vector. */
-
- return &P2;
- }
-
- /******************************************************************************
- * Return a normalized vector, equal to the binormal to Crv at parameter t. *
- * Algorithm: pseudo subdivide Crv at t and using 3 consecutive control point *
- * (p1, p2, p3) of subdivided curve find the bi-normal as the cross product of *
- * the difference (p1 - p2) and (p2 - p3). *
- * Since a curve may have not BiNormal at inflection points or if the 3 *
- * points are colinear, NULL will be returned at such cases. *
- ******************************************************************************/
- CagdVecStruct *BzrCrvBiNormal(CagdCrvStruct *Crv, CagdRType t)
- {
- static CagdVecStruct P3;
- CagdVecStruct P1, P2;
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j, l,
- k = Crv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdRType
- t1 = 1.0 - t;
- CagdCrvStruct *RCrv;
-
- /* Can not compute for linear curves. */
- if (k <= 2) return NULL;
-
- if (APX_EQ(t, 0.0)) {
- /* Use Crv starting tangent direction. */
- CagdCoerceToE3(P1.Vec, Crv -> Points, 0, Crv -> PType);
- CagdCoerceToE3(P2.Vec, Crv -> Points, 1, Crv -> PType);
- CagdCoerceToE3(P3.Vec, Crv -> Points, 2, Crv -> PType);
- }
- else if (APX_EQ(t, 1.0)) {
- /* Use Crv ending tangent direction. */
- CagdCoerceToE3(P1.Vec, Crv -> Points, k - 3, Crv -> PType);
- CagdCoerceToE3(P2.Vec, Crv -> Points, k - 2, Crv -> PType);
- CagdCoerceToE3(P3.Vec, Crv -> Points, k - 1, Crv -> PType);
- }
- else {
- RCrv = BzrCrvNew(k, Crv -> PType);
-
- /* Copy Crv into RCrv, so we can apply the recursive algo. to it. */
- for (i = 0; i < k; i++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][i] = Crv -> Points[j][i];
-
- /* Apply the recursive algorithm to RCrv. */
- for (i = 1; i < k; i++)
- for (l = 0; l < k - i; l++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
- RCrv -> Points[j][l+1] * t;
-
- CagdCoerceToE3(P1.Vec, RCrv -> Points, 0, RCrv -> PType);
- CagdCoerceToE3(P2.Vec, RCrv -> Points, 1, RCrv -> PType);
- CagdCoerceToE3(P3.Vec, RCrv -> Points, 2, RCrv -> PType);
-
- CagdCrvFree(RCrv);
- }
-
- CAGD_SUB_VECTOR(P1, P2);
- CAGD_SUB_VECTOR(P2, P3);
-
- CROSS_PROD(P3.Vec, P1.Vec, P2.Vec);
-
- if ((t = CAGD_LEN_VECTOR(P3)) < EPSILON)
- return NULL;
- else
- CAGD_DIV_VECTOR(P3, t); /* Normalize the vector. */
-
- return &P3;
- }
-
- /******************************************************************************
- * Return a normalized vector, equal to the normal to Crv at parameter t. *
- * Algorithm: returns the cross product of the curve tangent and binormal. *
- ******************************************************************************/
- CagdVecStruct *BzrCrvNormal(CagdCrvStruct *Crv, CagdRType t)
- {
- static CagdVecStruct N, *T, *B;
-
- T = BzrCrvTangent(Crv, t);
- B = BzrCrvBiNormal(Crv, t);
-
- if (T == NULL || B == NULL) return NULL;
-
- CROSS_PROD(N.Vec, T -> Vec, B -> Vec);
-
- CAGD_NORMALIZE_VECTOR(N); /* Normalize the vector. */
-
- return &N;
- }
-
- /******************************************************************************
- * Return a new curve, equal to the derived curve. If the original curve is *
- * rational, NULL is return (curve must be non-rational for this one). *
- * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then: *
- * Q(i) = (k - 1) * P(i+1) - P(i), i = 0 to k-2. *
- ******************************************************************************/
- CagdCrvStruct *BzrCrvDerive(CagdCrvStruct *Crv)
- {
- CagdBType
- IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
- int i, j,
- k = Crv -> Length,
- MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
- CagdCrvStruct *DerivedCrv;
-
- if (!IsNotRational || k < 3)
- FATAL_ERROR(CAGD_ERR_RAT_LIN_NO_SUPPORT);
-
- DerivedCrv = BzrCrvNew(k - 1, Crv -> PType);
-
- for (i = 0; i < k - 1; i++)
- for (j = IsNotRational; j <= MaxCoord; j++)
- DerivedCrv -> Points[j][i] =
- (k - 1) * (Crv -> Points[j][i+1] - Crv -> Points[j][i]);
-
- return DerivedCrv;
- }
-
- /******************************************************************************
- * Convert a Bezier curve into Bspline curve by adding an open knot vector. *
- ******************************************************************************/
- CagdCrvStruct *CnvrtBezier2BsplineCrv(CagdCrvStruct *Crv)
- {
- CagdCrvStruct *BspCrv = CagdCrvCopy(Crv);
-
- BspCrv -> Order = BspCrv -> Length;
- BspCrv -> KnotVector = BspKnotUniformOpen(BspCrv -> Length,
- BspCrv -> Order, NULL);
- BspCrv -> GType = CAGD_CBSPLINE_TYPE;
- return BspCrv;
- }
-