home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
i
/
iritsm3s.zip
/
cagd_lib
/
cbzr_aux.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-20
|
10KB
|
280 lines
/******************************************************************************
* 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;
}