/******************************************************************************
* Cagd_lib.h - header file for the CAGD library.			      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* Written by Gershon Elber, Mar. 90.					      *
******************************************************************************/

#ifndef CAGD_LIB_H
#define CAGD_LIB_H

#include <stdio.h>
#include "irit_sm.h"
#include "imalloc.h"
#include "miscattr.h"
#include "genmat.h"

typedef int CagdBType;
typedef RealType CagdRType;
typedef RealType CagdUVType[2];
typedef PointType CagdPType;
typedef VectorType CagdVType;
typedef MatrixType CagdMType;
typedef LineType CagdLType;

typedef enum {
    CAGD_ERR_180_ARC = 1000,
    CAGD_ERR_AFD_NO_SUPPORT,
    CAGD_ERR_ALLOC_ERR,
    CAGD_ERR_BSPLINE_NO_SUPPORT,
    CAGD_ERR_BZR_CRV_EXPECT,
    CAGD_ERR_BZR_SRF_EXPECT,
    CAGD_ERR_BSP_CRV_EXPECT,
    CAGD_ERR_BSP_SRF_EXPECT,
    CAGD_ERR_CRV_FAIL_CMPT,
    CAGD_ERR_CRVS_INCOMPATIBLE,
    CAGD_ERR_CUBIC_EXPECTED,
    CAGD_ERR_DEGEN_ALPHA,
    CAGD_ERR_DIR_NOT_CONST_UV,
    CAGD_ERR_DIR_NOT_VALID,
    CAGD_ERR_INDEX_NOT_IN_MESH,
    CAGD_ERR_KNOT_NOT_ORDERED,
    CAGD_ERR_LIN_NO_SUPPORT,
    CAGD_ERR_NO_CROSS_PROD,
    CAGD_ERR_NOT_ENOUGH_MEM,
    CAGD_ERR_NOT_IMPLEMENTED,
    CAGD_ERR_NUM_KNOT_MISMATCH,
    CAGD_ERR_OUT_OF_RANGE,
    CAGD_ERR_PARSER_STACK_OV,
    CAGD_ERR_POWER_NO_SUPPORT,
    CAGD_ERR_PT_OR_LEN_MISMATCH,
    CAGD_ERR_POLYNOMIAL_EXPECTED,
    CAGD_ERR_RATIONAL_EXPECTED,
    CAGD_ERR_SCALAR_EXPECTED,
    CAGD_ERR_SRF_FAIL_CMPT,
    CAGD_ERR_SRFS_INCOMPATIBLE,
    CAGD_ERR_UNDEF_CRV,
    CAGD_ERR_UNDEF_SRF,
    CAGD_ERR_UNDEF_GEOM,
    CAGD_ERR_UNSUPPORT_PT,
    CAGD_ERR_T_NOT_IN_CRV,
    CAGD_ERR_U_NOT_IN_SRF,
    CAGD_ERR_V_NOT_IN_SRF,
    CAGD_ERR_WRONG_DOMAIN,
    CAGD_ERR_W_NOT_SAME,
    CAGD_ERR_WRONG_CRV,
    CAGD_ERR_WRONG_INDEX,
    CAGD_ERR_WRONG_ORDER,
    CAGD_ERR_WRONG_SRF,
    CAGD_ERR_WRONG_PT_TYPE,
    CAGD_ERR_CANNOT_COMP_VEC_FIELD,
    CAGD_ERR_CANNOT_COMP_NORMAL,
    CAGD_ERR_REPARAM_NOT_MONOTONE,
    CAGD_ERR_RATIONAL_NO_SUPPORT,
    CAGD_ERR_NO_SOLUTION,
    CAGD_ERR_TOO_COMPLEX,
    CAGD_ERR_REF_LESS_ORIG,
    CAGD_ERR_ONLY_2D_OR_3D,
    CAGD_ERR_DOMAIN_TOO_SMALL,
    CAGD_ERR_PERIODIC_EXPECTED,
    CAGD_ERR_PERIODIC_NO_SUPPORT,
    CAGD_ERR_OPEN_EC_EXPECTED,

    CAGD_ERR_UNDEFINE_ERR
} CagdFatalErrorType;

typedef enum {		/* Type of control point. The P-types are rationals. */
    CAGD_PT_NONE = 0,
    CAGD_PT_BASE = 1100,			  /* Must be an even number. */
    CAGD_PT_E1_TYPE = 1100,
    CAGD_PT_P1_TYPE,
    CAGD_PT_E2_TYPE,
    CAGD_PT_P2_TYPE,
    CAGD_PT_E3_TYPE,
    CAGD_PT_P3_TYPE,
    CAGD_PT_E4_TYPE,
    CAGD_PT_P4_TYPE,
    CAGD_PT_E5_TYPE,
    CAGD_PT_P5_TYPE
} CagdPointType;

#define CAGD_IS_RATIONAL_PT(PType)  (((int) ((PType) - CAGD_PT_BASE)) & 0x01)
#define CAGD_NUM_OF_PT_COORD(PType) ((((int) ((PType) - CAGD_PT_BASE)) >> 1) + 1)
#define CAGD_MAKE_PT_TYPE(IsRational, NumCoords) \
				    ((CagdPointType) (CAGD_PT_BASE + \
				         ((((IsRational) ? -1 : -2) \
						       + ((NumCoords) << 1)))))
#define CAGD_MAX_PT_SIZE		6	/* Rational P5 has 6 coords. */
#define CAGD_MAX_PT_COORD		5		       /* Without w. */

#define CAGD_IS_RATIONAL_CRV(Crv)	CAGD_IS_RATIONAL_PT((Crv) -> PType)
#define CAGD_IS_RATIONAL_SRF(Srf)	CAGD_IS_RATIONAL_PT((Srf) -> PType)

/* Bezier curves may be evaluated using a predefined cache. The cache must   */
/* be of size (FINENESS) which is power of 2 up to the maximum order below.  */
/* See CrvBzrSetCache routine below.					     */
#define CAGD_MAX_BEZIER_CACHE_ORDER	10
#define CAGD_MAX_BEZIER_CACHE_FINENESS	1024

/* If a curve or a surface is periodic, their control polygon/mesh should    */
/* warp up. Length does hold the real allocated length but the virtual       */
/* periodic length is a little larger. Note allocated KV's are larger.       */
#define CAGD_CRV_PT_LST_LEN(Crv) ((Crv) -> Length + \
				  ((Crv) -> Periodic ? (Crv) -> Order - 1 : 0))
#define CAGD_SRF_UPT_LST_LEN(Srf)	((Srf) -> ULength + \
					 ((Srf) -> UPeriodic ? \
					      (Srf) -> UOrder - 1 : 0))
#define CAGD_SRF_VPT_LST_LEN(Srf)	((Srf) -> VLength + \
					 ((Srf) -> VPeriodic ? \
					      (Srf) -> VOrder - 1 : 0))
#define CAGD_IS_PERIODIC_CRV(Crv)	((Crv) -> Periodic)
#define CAGD_IS_UPERIODIC_SRF(Srf)	((Srf) -> UPeriodic)
#define CAGD_IS_VPERIODIC_SRF(Srf)	((Srf) -> VPeriodic)
#define CAGD_IS_PERIODIC_SRF(Srf)	(CAGD_IS_UPERIODIC_SRF(Srf) || \
					 CAGD_IS_VPERIODIC_SRF(Srf))


#define CAGD_RESET_BBOX(BBox) { \
    BBox -> Min[0] = BBox -> Min[1] = BBox -> Min[2] = INFINITY; \
    BBox -> Max[0] = BBox -> Max[1] = BBox -> Max[2] = -INFINITY; }

typedef enum {
    CAGD_UNDEF_TYPE = 1200,
    CAGD_CBEZIER_TYPE,
    CAGD_CBSPLINE_TYPE,
    CAGD_CPOWER_TYPE,
    CAGD_SBEZIER_TYPE,
    CAGD_SBSPLINE_TYPE,
    CAGD_SPOWER_TYPE
} CagdGeomType;

typedef enum {
    CAGD_NO_DIR = 1300,
    CAGD_CONST_U_DIR,
    CAGD_CONST_V_DIR
} CagdSrfDirType;
#define CAGD_OTHER_DIR(Dir) ((Dir) == CAGD_CONST_U_DIR ? CAGD_CONST_V_DIR \
						       : CAGD_CONST_U_DIR)

typedef enum {
    CAGD_REG_POLY_PER_LIN = 1400,
    CAGD_ONE_POLY_PER_LIN,
    CAGD_ONE_POLY_PER_COLIN
} CagdLin2PolyType;

typedef enum {
    CAGD_UNIFORM_PARAM = 1500,
    CAGD_CENTRIPETAL_PARAM,
    CAGD_CHORD_LEN_PARAM
} CagdParametrizationType;

typedef struct CagdGenericStruct {
    struct CagdGenericStruct *Pnext;
    struct IPAttributeStruct *Attr;
} CagdGenericStruct;

typedef struct CagdUVStruct {
    struct CagdUVStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdUVType UV;
} CagdUVStruct;

typedef struct CagdPtStruct {
    struct CagdPtStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPType Pt;
} CagdPtStruct;

typedef struct CagdCtlPtStruct {
    struct CagdCtlPtStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPointType PtType;
    CagdRType Coords[CAGD_MAX_PT_SIZE];
} CagdCtlPtStruct;

typedef struct CagdVecStruct {
    struct CagdVecStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdVType Vec;
} CagdVecStruct;

typedef struct CagdPlaneStruct {
    struct CagdPlaneStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdRType Plane[4];
} CagdPlaneStruct;

typedef struct CagdBBoxStruct {
    struct CagdBBoxStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPType Min;
    CagdPType Max;
} CagdBBoxStruct;

typedef struct CagdCrvStruct {
    struct CagdCrvStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdGeomType GType;
    CagdPointType PType;
    int Length;            /* Number of control points (== order in Bezier). */
    int Order;	    /* Order of curve (only for Bspline, ignored in Bezier). */
    CagdBType Periodic;			   /* Valid only for Bspline curves. */
    CagdRType *Points[CAGD_MAX_PT_SIZE];     /* Pointer on each axis vector. */
    CagdRType *KnotVector;
} CagdCrvStruct;

typedef struct CagdSrfStruct {
    struct CagdSrfStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdGeomType GType;
    CagdPointType PType;
    int ULength, VLength;	 /* Mesh size in the tensor product surface. */
    int UOrder, VOrder;   /* Order in tensor product surface (Bspline only). */
    CagdBType UPeriodic, VPeriodic;      /* Valid only for Bspline surfaces. */
    CagdRType *Points[CAGD_MAX_PT_SIZE];     /* Pointer on each axis vector. */
    CagdRType *UKnotVector, *VKnotVector;
} CagdSrfStruct;

typedef struct CagdPolygonStruct {
    struct CagdPolygonStruct *Pnext;
    struct IPAttributeStruct *Attr;
    struct {
	CagdPType Pt;			      /* Polygon is always triangle. */
	CagdVType Nrml;
	CagdUVType UV;
    } Polygon[3];
} CagdPolygonStruct;

typedef struct {
    CagdPType Pt;
} CagdPolylnStruct;

typedef struct CagdPolylineStruct {
    struct CagdPolylineStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPolylnStruct *Polyline; /* Polyline length is defined using Length. */
    int Length;
} CagdPolylineStruct;

typedef struct {
    int Order, Length, RefLength;     /* The dimensions of the alpha matrix. */
    CagdRType *Matrix;
    CagdRType **Rows;		     /* A column of pointers to Matrix rows. */
    int *ColIndex;	 /* A row of indices of first non zero value in col. */
    int *ColLength;	      /* A row of lengths of non zero values in col. */
} BspKnotAlphaCoeffType;

typedef void (*CagdPrintfFuncType)(char *Line);
typedef CagdCrvStruct *(*CagdCrvFuncType)(CagdCrvStruct *Crv, CagdRType R);

#define CAGD_IS_BEZIER_CRV(Crv)		(Crv -> GType == CAGD_CBEZIER_TYPE)
#define CAGD_IS_BEZIER_SRF(Srf)		(Srf -> GType == CAGD_SBEZIER_TYPE)
#define CAGD_IS_BSPLINE_CRV(Crv)	(Crv -> GType == CAGD_CBSPLINE_TYPE)
#define CAGD_IS_BSPLINE_SRF(Srf)	(Srf -> GType == CAGD_SBSPLINE_TYPE)
#define CAGD_IS_POWER_CRV(Crv)		(Crv -> GType == CAGD_CPOWER_TYPE)
#define CAGD_IS_POWER_SRF(Srf)		(Srf -> GType == CAGD_SPOWER_TYPE)

/******************************************************************************
*		U -->			    The mesh is ordered raw after raw *
*       +-----------------------+	or the increments along U are 1 while *
*   V | |P0                 Pi-1|	the increment along V is full raw.    *
*     v	|Pi                P2i-1|	    To encapsulate it, NEXTU/V are    *
*	|			|	defined below.			      *
*	|Pn-i		    Pn-1|					      *
*	+-----------------------+					      *
******************************************************************************/
#define CAGD_NEXT_U(Srf)	(1)
#define CAGD_NEXT_V(Srf)	(Srf -> ULength)
#define CAGD_MESH_UV(Srf, i, j)	((i) + (Srf -> ULength) * (j))



#define CAGD_GEN_COPY(Dst, Src, Size) memcpy((char *) (Dst), (char *) (Src), \
					     Size)

#define CAGD_GEN_COPY_STEP(Dst, Src, Size, DstStep, SrcStep, Type) \
			{ \
			    int ii; \
			    Type *DstType = (Type *) Dst, \
				 *SrcType = (Type *) Src; \
 \
			    for (ii = 0; ii < Size; ii++) { \
				*DstType = *SrcType; \
				DstType += DstStep; \
				SrcType += SrcStep; \
			    } \
			}

/******************************************************************************
* Some points/ectors simplifying operators.				      *
******************************************************************************/
#define	CAGD_COPY_POINT(DstPt, SrcPt)	{ (DstPt) = (SrcPt); }
#define	CAGD_ADD_POINT(DstPt, SrcPt)    { (DstPt).Pt[0] += (SrcPt).Pt[0]; \
					  (DstPt).Pt[1] += (SrcPt).Pt[1]; \
					  (DstPt).Pt[2] += (SrcPt).Pt[2]; }
#define	CAGD_SUB_POINT(DstPt, SrcPt)    { (DstPt).Pt[0] -= (SrcPt).Pt[0]; \
					  (DstPt).Pt[1] -= (SrcPt).Pt[1]; \
					  (DstPt).Pt[2] -= (SrcPt).Pt[2]; }
#define	CAGD_MULT_POINT(DstPt, Scaler)  { (DstPt).Pt[0] *= (Scaler); \
					  (DstPt).Pt[1] *= (Scaler); \
					  (DstPt).Pt[2] *= (Scaler); }

#define	CAGD_COPY_VECTOR(DstVec, SrcVec) { (DstVec) = (SrcVec); }
#define	CAGD_ADD_VECTOR(DstVec, SrcVec) { (DstVec).Vec[0] += (SrcVec).Vec[0]; \
					  (DstVec).Vec[1] += (SrcVec).Vec[1]; \
					  (DstVec).Vec[2] += (SrcVec).Vec[2]; }
#define	CAGD_SUB_VECTOR(DstVec, SrcVec) { (DstVec).Vec[0] -= (SrcVec).Vec[0]; \
					  (DstVec).Vec[1] -= (SrcVec).Vec[1]; \
					  (DstVec).Vec[2] -= (SrcVec).Vec[2]; }
#define	CAGD_MULT_VECTOR(DstVec, Scaler){ (DstVec).Vec[0] *= (Scaler); \
					  (DstVec).Vec[1] *= (Scaler); \
					  (DstVec).Vec[2] *= (Scaler); }
#define	CAGD_DIV_VECTOR(DstVec, Scaler) { (DstVec).Vec[0] /= (Scaler); \
					  (DstVec).Vec[1] /= (Scaler); \
					  (DstVec).Vec[2] /= (Scaler); }
#define CAGD_LEN_VECTOR(V)		sqrt(SQR((V).Vec[0]) + \
					     SQR((V).Vec[1]) + \
					     SQR((V).Vec[2]))
#define CAGD_NORMALIZE_VECTOR(V)	{ CagdRType __t = CAGD_LEN_VECTOR(V); \
					  if (__t < PT_NORMALIZE_ZERO) { \
					      fprintf(stderr, "Attempt to cagd normalize a zero length vector\n"); \
					  } \
					  else { \
					      CAGD_DIV_VECTOR((V), __t); \
					  } \
				        }


#define	CAGD_COPY_UVVAL(DstUV, SrcUV) { (DstUV) = (SrcUV); }

/******************************************************************************
* This macro is called when the library has detected an unrecoverable error.  *
* Default action is to call CagdFatalError, but you may want to reroute this  *
* to invoke your handler and recover yourself (by long jump for example).     *
******************************************************************************/
#define CAGD_FATAL_ERROR(Msg)	CagdFatalError(Msg)

/******************************************************************************
* Macros to verify the validity of the parametric domain.		      *
******************************************************************************/
#ifdef DOUBLE
#define CAGD_DOMAIN_EPSILON 1e-13
#else
#define CAGD_DOMAIN_EPSILON 1e-5
#endif /* DOUBLE */

#define CAGD_DOMAIN_T_VERIFY(t, TMin, TMax) \
    { \
	if (t < TMin) \
	    t += CAGD_DOMAIN_EPSILON; \
	if (t > TMax) \
	    t -= CAGD_DOMAIN_EPSILON; \
	if (t < TMin || t > TMax) \
	    CAGD_FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV); \
    }

#define CAGD_DOMAIN_GET_AND_VERIFY_CRV(t, Crv, TMin, TMax) \
    { \
	CagdCrvDomain(Crv, &TMin, &TMax); \
	CAGD_DOMAIN_T_VERIFY(t, TMin, TMax); \
    }

#define CAGD_DOMAIN_GET_AND_VERIFY_SRF(u, v, Srf, UMin, UMax, VMin, VMax) \
    { \
	CagdSrfDomain(Srf, &UMin, &UMax, &VMin, &VMax); \
	CAGD_DOMAIN_T_VERIFY(u, UMin, UMax); \
	CAGD_DOMAIN_T_VERIFY(v, VMin, VMax); \
    }

/******************************************************************************
* A fast macro to blend the original control polygon with the Alpha matrix.   *
******************************************************************************/
#define CAGD_ALPHA_BLEND( A, Index, OrigPts, OrigLen, Pt ) \
    { \
	if (A -> ColLength[Index] == 1) \
	    *Pt = OrigPts[A -> ColIndex[Index] % OrigLen]; \
	else { \
	    int Tmp; \
 \
	    *Pt = 0.0; \
	    for (Tmp = A -> ColLength[Index] - 1; Tmp >= 0; Tmp--) { \
		int Idx = A -> ColIndex[Index] + Tmp; \
 \
		*Pt += OrigPts[Idx % OrigLen] * A -> Rows[Idx][Index]; \
	    } \
	} \
    }

/* Same as CAGD_ALPHA_BLEND but Allow step for OrigPts. */
#define CAGD_ALPHA_BLEND_STEP( A, Index, OrigPts, OrigLen, Pt, OrigPtsStep ) \
    { \
	if (A -> ColLength[Index] == 1) \
	    *Pt = OrigPts[A -> ColIndex[Index] * OrigPtsStep]; \
	else { \
	    int Tmp; \
 \
	    *Pt = 0.0; \
	    for (Tmp = A -> ColLength[Index] - 1; Tmp >= 0; Tmp--) { \
		int Idx = A -> ColIndex[Index] + Tmp; \
 \
		*Pt += OrigPts[Idx * OrigPtsStep] * A -> Rows[Idx][Index]; \
	    } \
	} \
    }

/******************************************************************************
* There are some circular links to symb_lib and we include symb.lib.h         *
* to resolve that. This may cause some problems in linkage time.              *
* These are the known circularities:				              *
* Bsp/BzrCrvMult, Bsp/BzrSrfMult, Bsp/BzrCrvDeriveRational.	              *
******************************************************************************/
#include "symb_lib.h"

/******************************************************************************
* Routines prototypes. Routines are prefixed as follows:		      *
* Cagd    - General routines such as dynamic memory handlers etc.	      *
* BzrCrv  - Bezier curves routines.					      *
* BzrSrf  - Bezier surface routines.					      *
* BspKnot - Bspline knot vector routines.				      *
* BspCrv  - Bspline curves routines.					      *
* BspSrf  - Bspline surface routines.					      *
* Cnvrt   - Conversion routines such as Bezier to Power basis.		      *
******************************************************************************/

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

/******************************************************************************
* General routines of the Cagd library:					      *
******************************************************************************/

CagdUVStruct *CagdUVNew(void);
CagdPtStruct *CagdPtNew(void);
CagdCtlPtStruct *CagdCtlPtNew(CagdPointType PtType);
CagdVecStruct *CagdVecNew(void);
CagdPlaneStruct *CagdPlaneNew(void);
CagdBBoxStruct *CagdBBoxNew(void);
CagdCrvStruct *CagdCrvNew(CagdGeomType GType, CagdPointType PType, int Length);
CagdCrvStruct *CagdPeriodicCrvNew(CagdGeomType GType,
				  CagdPointType PType,
				  int Length,
				  CagdBType Periodic);
CagdSrfStruct *CagdSrfNew(CagdGeomType GType,
			  CagdPointType PType,
			  int ULength,
			  int VLength);
CagdSrfStruct *CagdPeriodicSrfNew(CagdGeomType GType,
				  CagdPointType PType,
				  int ULength,
				  int VLength,
				  CagdBType UPeriodic,
				  CagdBType VPeriodic);
CagdPolygonStruct *CagdPolygonNew(void);
CagdPolylineStruct *CagdPolylineNew(int Length);

CagdUVStruct *CagdUVArrayNew(int Size);
CagdPtStruct *CagdPtArrayNew(int Size);
CagdCtlPtStruct *CagdCtlPtArrayNew(CagdPointType PtType, int Size);
CagdVecStruct *CagdVecArrayNew(int Size);
CagdPlaneStruct *CagdPlaneArrayNew(int Size);
CagdBBoxStruct *CagdBBoxArrayNew(int Size);
CagdPolygonStruct *CagdPolygonArrayNew(int Size);
CagdPolylineStruct *CagdPolylineArrayNew(int Length, int Size);

CagdCrvStruct *CagdCrvCopy(CagdCrvStruct *Crv);
CagdSrfStruct *CagdSrfCopy(CagdSrfStruct *Srf);
CagdUVStruct *CagdUVCopy(CagdUVStruct *UV);
CagdPtStruct *CagdPtCopy(CagdPtStruct *Pt);
CagdCtlPtStruct *CagdCtlPtCopy(CagdCtlPtStruct *CtlPt);
CagdVecStruct *CagdVecCopy(CagdVecStruct *Vec);
CagdPlaneStruct *CagdPlaneCopy(CagdPlaneStruct *Plane);
CagdBBoxStruct *CagdBBoxCopy(CagdBBoxStruct *BBoc);
CagdPolygonStruct *CagdPolygonCopy(CagdPolygonStruct *Poly);
CagdPolylineStruct *CagdPolylineCopy(CagdPolylineStruct *Poly);

CagdCrvStruct *CagdCrvCopyList(CagdCrvStruct *CrvList);
CagdSrfStruct *CagdSrfCopyList(CagdSrfStruct *SrfList);
CagdUVStruct *CagdUVCopyList(CagdUVStruct *UVList);
CagdPtStruct *CagdPtCopyList(CagdPtStruct *PtList);
CagdCtlPtStruct *CagdCtlPtCopyList(CagdCtlPtStruct *CtlPtList);
CagdVecStruct *CagdVecCopyList(CagdVecStruct *VecList);
CagdPlaneStruct *CagdPlaneCopyList(CagdPlaneStruct *PlaneList);
CagdBBoxStruct *CagdBBoxCopyList(CagdBBoxStruct *BBoxList);
CagdPolylineStruct *CagdPolylineCopyList(CagdPolylineStruct *PolyList);
CagdPolygonStruct *CagdPolygonCopyList(CagdPolygonStruct *PolyList);

void CagdCrvFree(CagdCrvStruct *Crv);
void CagdCrvFreeList(CagdCrvStruct *CrvList);
void CagdSrfFree(CagdSrfStruct *Srf);
void CagdSrfFreeList(CagdSrfStruct *SrfList);
void CagdUVFree(CagdUVStruct *UV);
void CagdUVFreeList(CagdUVStruct *UVList);
void CagdUVArrayFree(CagdUVStruct *UVArray, int Size);
void CagdPtFree(CagdPtStruct *Pt);
void CagdPtFreeList(CagdPtStruct *PtList);
void CagdPtArrayFree(CagdPtStruct *PtArray, int Size);
void CagdCtlPtFree(CagdCtlPtStruct *CtlPt);
void CagdCtlPtFreeList(CagdCtlPtStruct *CtlPtList);
void CagdCtlPtArrayFree(CagdCtlPtStruct *CtlPtArray, int Size);
void CagdVecFree(CagdVecStruct *Vec);
void CagdVecFreeList(CagdVecStruct *VecList);
void CagdVecArrayFree(CagdVecStruct *VecArray, int Size);
void CagdPlaneFree(CagdPlaneStruct *Plane);
void CagdPlaneFreeList(CagdPlaneStruct *PlaneList);
void CagdPlaneArrayFree(CagdPlaneStruct *PlaneArray, int Size);
void CagdBBoxFree(CagdBBoxStruct *BBox);
void CagdBBoxFreeList(CagdBBoxStruct *BBoxList);
void CagdBBoxArrayFree(CagdBBoxStruct *BBoxArray, int Size);
void CagdPolylineFree(CagdPolylineStruct *Poly);
void CagdPolylineFreeList(CagdPolylineStruct *PolyList);
void CagdPolylineArrayFree(CagdPolylineStruct *PolyArray, int Size);
void CagdPolygonFree(CagdPolygonStruct *Poly);
void CagdPolygonFreeList(CagdPolygonStruct *PolyList);
void CagdPolygonArrayFree(CagdPolygonStruct *PolyArray, int Size);

int CagdListLength(VoidPtr CrvList);
VoidPtr CagdListReverse(VoidPtr List);
VoidPtr CagdListLast(VoidPtr List);
void CagdCoerceToE2(CagdRType *E2Point,
		    CagdRType *Points[CAGD_MAX_PT_SIZE],
		    int Index,
		    CagdPointType PType);
void CagdCoerceToE3(CagdRType *E3Point,
		    CagdRType *Points[CAGD_MAX_PT_SIZE],
		    int Index,
		    CagdPointType PType);
void CagdCoerceToP2(CagdRType *P2Point,
		    CagdRType *Points[CAGD_MAX_PT_SIZE],
		    int Index,
		    CagdPointType PType);
void CagdCoerceToP3(CagdRType *P3Point,
		    CagdRType *Points[CAGD_MAX_PT_SIZE],
		    int Index,
		    CagdPointType PType);
void CagdCoercePointTo(CagdRType *NewPoint,
		       CagdPointType NewPType,
		       CagdRType *Points[CAGD_MAX_PT_SIZE],
		       int Index,
		       CagdPointType OldPType);
void CagdCoercePointsTo(CagdRType *Points[],
			int Len,
			CagdPointType OldPType,
			CagdPointType NewPType);
CagdCrvStruct *CagdCoerceCrvTo(CagdCrvStruct *Crv, CagdPointType PType);
CagdSrfStruct *CagdCoerceSrfTo(CagdSrfStruct *Srf, CagdPointType PType);
CagdPointType CagdMergePointType(CagdPointType PType1, CagdPointType PType2);
void CagdDbg(void *Obj);
void CagdSetCagdFprintf(CagdPrintfFuncType Func);
void CagdSetLinear2Poly(CagdLin2PolyType Lin2Poly);
void CagdMergeBBox(CagdBBoxStruct *DestBBox, CagdBBoxStruct *SrcBBox);
void CagdPointsBBox(CagdRType **Points, int Length, CagdBBoxStruct *BBox);
CagdRType CagdIChooseK(int i, int k);
void CagdTransform(CagdRType **Points,
		   int Len,
		   int MaxCoord,
		   CagdBType IsNotRational,
		   CagdRType *Translate,
		   CagdRType Scale);
void CagdMatTransform(CagdRType **Points,
		      int Len,
		      int MaxCoord,
		      CagdBType IsNotRational,
		      CagdMType Mat);

/******************************************************************************
* Matrix/Vector/Plane/Transformation routines:				      *
******************************************************************************/
CagdRType CagdDistanceTwoCtlPts(CagdRType **Points,
				int Index1,
				int Index2,
				CagdPointType PType);
CagdRType CagdFitPlaneThruCtlPts(CagdPlaneStruct *Plane,
				 CagdPointType PType,
			         CagdRType **Points,
			         int Index1,
				 int Index2,
				 int Index3,
				 int Index4);
CagdRType CagdDistPtPlane(CagdPlaneStruct *Plane,
			  CagdRType **Points,
			  int Index,
			  int MaxDim);

void CagdCrvMatTransform(CagdCrvStruct *Crv, CagdMType Mat);
void CagdSrfMatTransform(CagdSrfStruct *Srf, CagdMType Mat);
void CagdCrvTransform(CagdCrvStruct *Crv,
		      CagdRType *Translate,
		      CagdRType Scale);
void CagdSrfTransform(CagdSrfStruct *Srf,
		      CagdRType *Translate,
		      CagdRType Scale);

/******************************************************************************
* Routines to handle curves generically.				      *
******************************************************************************/
CagdRType *CagdCrvNodes(CagdCrvStruct *Crv);
CagdRType CagdEstimateCrvColinearity(CagdCrvStruct *Crv);
void CagdCrvDomain(CagdCrvStruct *Crv, CagdRType *TMin, CagdRType *TMax);
CagdRType *CagdCrvEval(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *CagdCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvIntegrate(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *CagdCrvRegionFromCrv(CagdCrvStruct *Crv,
				    CagdRType t1,
				    CagdRType t2);
CagdCrvStruct *CagdCrvRefineAtParams(CagdCrvStruct *Crv,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
CagdVecStruct *CagdCrvTangent(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *CagdCrvBiNormal(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *CagdCrvNormal(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *CagdCrvReverse(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *CagdMergeCrvCrv(CagdCrvStruct *Crv1,
			       CagdCrvStruct *Crv2,
			       int InterpDiscont);
CagdCrvStruct *CagdMergeCrvList(CagdCrvStruct *CrvList, int InterpDiscont);
CagdCrvStruct *CagdMergeCrvPt(CagdCrvStruct *Crv, CagdPtStruct *Pt);
CagdCrvStruct *CagdMergePtCrv(CagdPtStruct *Pt, CagdCrvStruct *Crv);
CagdCrvStruct *CagdMergePtPt(CagdPtStruct *Pt1, CagdPtStruct *Pt2);
CagdPolylineStruct *CagdCrv2CtrlPoly(CagdCrvStruct *Crv);
CagdCrvStruct *CagdEditSingleCrvPt(CagdCrvStruct *Crv,
				   CagdCtlPtStruct *CtlPt,
				   int Index,
				   CagdBType Write);
CagdBType CagdMakeCrvsCompatible(CagdCrvStruct **Crv1,
				 CagdCrvStruct **Crv2,
				 CagdBType SameOrder,
				 CagdBType SameKV);
void CagdCrvBBox(CagdCrvStruct *Crv, CagdBBoxStruct *BBox);
void CagdCrvListBBox(CagdCrvStruct *Crvs,
		     CagdBBoxStruct *BBox);
void CagdCrvMinMax(CagdCrvStruct *Crv,
		   int Axis,
		   CagdRType *Min,
		   CagdRType *Max);
int CagdCrvEvalToPolyline(CagdCrvStruct *Crv,
			  int FineNess,
			  CagdRType *Points[],
			  BspKnotAlphaCoeffType *A,
			  CagdBType OptiLin);
void CagdCrvFirstMoments(CagdCrvStruct *Crv,
			 int n,
			 CagdPType Pt,
			 CagdVType Dir);

/******************************************************************************
* Routines to handle surfaces generically.				      *
******************************************************************************/
CagdRType *CagdSrfNodes(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdRType CagdEstimateSrfPlanarity(CagdSrfStruct *Srf);
void CagdSrfDomain(CagdSrfStruct *Srf,
		   CagdRType *UMin,
		   CagdRType *UMax,
		   CagdRType *VMin,
		   CagdRType *VMax);
CagdRType *CagdSrfEval(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
void CagdEvaluateSurfaceVecField(CagdVType Vec,
				 CagdSrfStruct *VecFieldSrf,
				 CagdRType U,
				 CagdRType V);
CagdSrfStruct *CagdSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdCrvStruct *CagdCrvFromSrf(CagdSrfStruct *Srf,
			      CagdRType t,
			      CagdSrfDirType Dir);
CagdCrvStruct *CagdCrvFromMesh(CagdSrfStruct *Srf,
			       int Index,
			       CagdSrfDirType Dir);
void CagdCrvToMesh(CagdCrvStruct *Crv,
		   int Index,
		   CagdSrfDirType Dir,
		   CagdSrfStruct *Srf);
CagdSrfStruct *CagdSrfSubdivAtParam(CagdSrfStruct *Srf,
				    CagdRType t,
				    CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfRegionFromSrf(CagdSrfStruct *Srf,
				    CagdRType t1,
				    CagdRType t2,
				    CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfRefineAtParams(CagdSrfStruct *Srf,
				     CagdSrfDirType Dir,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
CagdVecStruct *CagdSrfTangent(CagdSrfStruct *Srf,
			      CagdRType u,
			      CagdRType v,
			      CagdSrfDirType Dir);
CagdVecStruct *CagdSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdSrfStruct *CagdSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfReverse(CagdSrfStruct *Srf);
CagdSrfStruct *CagdSrfReverse2(CagdSrfStruct *Srf);
CagdPolylineStruct *CagdSrf2CtrlMesh(CagdSrfStruct *Srf);
CagdSrfStruct *CagdMergeSrfSrf(CagdSrfStruct *Srf1,
			       CagdSrfStruct *Srf2,
			       CagdSrfDirType Dir,
			       CagdBType SameEdge,
			       int InterpolateDiscont);
CagdSrfStruct *CagdMergeSrfList(CagdSrfStruct *SrfList,
				CagdSrfDirType Dir,
				CagdBType SameEdge,
				int InterpolateDiscont);
CagdSrfStruct *CagdExtrudeSrf(CagdCrvStruct *Crv, CagdVecStruct *Vec);
CagdSrfStruct *CagdSurfaceRev(CagdCrvStruct *Crv);
CagdSrfStruct *CagdSurfaceRevPolynomialApprox(CagdCrvStruct *Crv);
CagdSrfStruct *CagdSweepSrf(CagdCrvStruct *CrossSection,
			    CagdCrvStruct *Axis,
			    CagdCrvStruct *ScalingCrv,
			    CagdRType Scale,
			    VoidPtr Frame,
			    CagdBType FrameIsCrv);
CagdCrvStruct *CagdSweepAxisRefine(CagdCrvStruct *Axis,
				   CagdCrvStruct *ScalingCrv,
				   int RefLevel);
CagdSrfStruct *CagdBoolSumSrf(CagdCrvStruct *CrvLeft,
			      CagdCrvStruct *CrvRight,
			      CagdCrvStruct *CrvTop,
			      CagdCrvStruct *CrvBottom);
CagdSrfStruct *CagdOneBoolSumSrf(CagdCrvStruct *BndryCrv);
CagdSrfStruct *CagdRuledSrf(CagdCrvStruct *Crv1,
			    CagdCrvStruct *Crv2,
			    int OtherOrder,
			    int OtherLen);
CagdSrfStruct *CagdBilinearSrf(CagdPtStruct *Pt00,
			       CagdPtStruct *Pt01,
			       CagdPtStruct *Pt10,
			       CagdPtStruct *Pt11);
CagdSrfStruct *CagdPromoteCrvToSrf(CagdCrvStruct *Crv, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfFromCrvs(CagdCrvStruct *CrvList, int OtherOrder);
CagdBType CagdMakeSrfsCompatible(CagdSrfStruct **Srf1,
				 CagdSrfStruct **Srf2,
				 CagdBType SameUOrder,
				 CagdBType SameVOrder,
				 CagdBType SameUKV,
				 CagdBType SameVKV);
CagdSrfStruct *CagdEditSingleSrfPt(CagdSrfStruct *Srf,
				   CagdCtlPtStruct *CtlPt,
				   int UIndex,
				   int VIndex,
				   CagdBType Write);
void CagdSrfBBox(CagdSrfStruct *Srf, CagdBBoxStruct *BBox);
void CagdSrfListBBox(CagdSrfStruct *Srfs, CagdBBoxStruct *BBox);
void CagdSrfMinMax(CagdSrfStruct *Srf,
		   int Axis,
		   CagdRType *Min,
		   CagdRType *Max);

/******************************************************************************
* Routines to handle Bezier curves.					      *
******************************************************************************/
CagdCrvStruct *BzrCrvNew(int Length, CagdPointType PType);
CagdRType BzrCrvEvalVecAtParam(CagdRType *Vec,
			       int VecInc,
			       int Order,
			       CagdRType t);
CagdRType *BzrCrvEvalAtParam(CagdCrvStruct *Crv, CagdRType t);
void BzrCrvSetCache(int FineNess, CagdBType EnableCache);
void BzrCrvEvalToPolyline(CagdCrvStruct *Crv,
			  int FineNess,
			  CagdRType *Points[]);
CagdCrvStruct *BzrCrvCreateArc(CagdPtStruct *Start,
			       CagdPtStruct *Center,
			       CagdPtStruct *End);
CagdCrvStruct *BzrCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BzrCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *BzrCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvIntegrate(CagdCrvStruct *Crv);
CagdVecStruct *BzrCrvTangent(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *BzrCrvBiNormal(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *BzrCrvNormal(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BzrCrvInterpolate(int Size,
				 CagdRType *XVec,
				 CagdRType *YVec,
				 CagdRType *ZVec);
CagdPolylineStruct *BzrCrv2Polyline(CagdCrvStruct *Crv, int SamplesPerCurve);

/******************************************************************************
* Routines to handle Bezier surfaces.					      *
******************************************************************************/
CagdSrfStruct *BzrSrfNew(int ULength, int VLength, CagdPointType PType);
CagdRType *BzrSrfEvalAtParam(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdCrvStruct *BzrSrfCrvFromSrf(CagdSrfStruct *Srf,
				CagdRType t,
				CagdSrfDirType Dir);
CagdCrvStruct *BzrSrfCrvFromMesh(CagdSrfStruct *Srf,
				 int Index,
				 CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfSubdivAtParam(CagdSrfStruct *Srf,
				   CagdRType t,
				   CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdVecStruct *BzrSrfTangent(CagdSrfStruct *Srf,
			     CagdRType u,
			     CagdRType v,
			     CagdSrfDirType Dir);
CagdVecStruct *BzrSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdPolygonStruct *BzrSrf2Polygons(CagdSrfStruct *Srf,
				   int FineNess,
				   CagdBType ComputeNormals,
				   CagdBType FourPerFlat,
				   CagdBType ComputeUV);
CagdPolylineStruct *BzrSrf2Polylines(CagdSrfStruct *Srf,
				     int NumOfIsocurves[2],
				     int SamplesPerCurve);
CagdCrvStruct *BzrSrf2Curves(CagdSrfStruct *Srf, int NumOfIsocurves[2]);

/******************************************************************************
* Routines to handle Bspline knot vectors.				      *
******************************************************************************/
CagdBType BspCrvHasBezierKV(CagdCrvStruct *Crv);
CagdBType BspSrfHasBezierKVs(CagdSrfStruct *Srf);
CagdBType BspKnotHasBezierKV(CagdRType *KnotVector, int Len, int Order);
CagdBType BspCrvHasOpenEC(CagdCrvStruct *Crv);
CagdBType BspSrfHasOpenEC(CagdSrfStruct *Srf);
CagdBType BspSrfHasOpenECDir(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdBType BspKnotHasOpenEC(CagdRType *KnotVector, int Len, int Order);
CagdBType BspKnotParamInDomain(CagdRType *KnotVector,
			       int Len,
			       int Order,
			       CagdBType Periodic,
			       CagdRType t);
int BspKnotLastIndexLE(CagdRType *KnotVector, int Len, CagdRType t);
int BspKnotLastIndexL(CagdRType *KnotVector, int Len, CagdRType t);
int BspKnotFirstIndexG(CagdRType *KnotVector, int Len, CagdRType t);
CagdRType *BspKnotUniformPeriodic(int Len, int Order, CagdRType *KnotVector);
CagdRType *BspKnotUniformFloat(int Len, int Order, CagdRType *KnotVector);
CagdRType *BspKnotUniformOpen(int Len, int Order, CagdRType *KnotVector);
CagdRType *BspKnotSubtrTwo(CagdRType *KnotVector1,
			   int Len1,
			   CagdRType *KnotVector2,
			   int Len2,
			   int *NewLen);
CagdRType *BspKnotMergeTwo(CagdRType *KnotVector1,
			   int Len1,
			   CagdRType *KnotVector2,
			   int Len2,
			   int Mult,
			   int *NewLen);
CagdRType *BspKnotContinuityMergeTwo(CagdRType *KnotVector1,
				     int Len1,
				     int Order1,
				     CagdRType *KnotVector2,
				     int Len2,
				     int Order2,
				     int ResOrder,
				     int *NewLen);
CagdRType *BspKnotAverage(CagdRType *KnotVector, int Len, int Ave);
CagdRType *BspKnotNodes(CagdRType *KnotVector, int Len, int Order);
CagdRType BspCrvMaxCoefParam(CagdCrvStruct *Crv, int Axis, CagdRType *MaxVal);
CagdRType *BspSrfMaxCoefParam(CagdSrfStruct *Srf, int Axis, CagdRType *MaxVal);
CagdRType *BspKnotPrepEquallySpaced(int n, CagdRType Tmin, CagdRType Tmax);
CagdRType *BspKnotReverse(CagdRType *KnotVector, int Len);
void BspKnotAffineTrans(CagdRType *KnotVector,
			int Len,
			CagdRType Translate,
			CagdRType Scale);
void BspKnotAffineTrans2(CagdRType *KnotVector,
			 int Len,
			 CagdRType MinVal,
			 CagdRType MaxVal);
CagdRType *BspKnotCopy(CagdRType *KnotVector, int Len);
BspKnotAlphaCoeffType *BspKnotEvalAlphaCoef(int k,
					    CagdRType *KVT,
					    int LengthKVT,
					    CagdRType *KVt,
					    int LengthKVt);
BspKnotAlphaCoeffType *BspKnotEvalAlphaCoefMerge(int k,
						 CagdRType *KVT,
						 int LengthKVT,
						 CagdRType *NewKV,
						 int LengthNewKV);
void BspKnotFreeAlphaCoef(BspKnotAlphaCoeffType *A);
CagdRType *BspKnotInsertOne(CagdRType *KnotVector,
			    int Order,
			    int Len,
			    CagdRType t);
CagdRType *BspKnotInsertMult(CagdRType *KnotVector,
			     int Order,
			     int *Len,
			     CagdRType t,
			     int Mult);
int BspKnotFindMult(CagdRType *KnotVector, int Order, int Len, CagdRType t);
CagdBType BspKnotC1Discont(CagdRType *KnotVector,
			   int Order,
			   int Length,
			   CagdRType *t);
CagdRType *BspKnotAllC1Discont(CagdRType *KnotVector,
			       int Order,
			       int Length,
			       int *n);
CagdRType *BspKnotParamValues(CagdRType PMin,
			      CagdRType PMax,
			      int NumSamples,
			      CagdRType *C1Disconts,
			      int NumC1Disconts);
void BspKnotMakeRobustKV(CagdRType *KV, int Len);

/******************************************************************************
* Routines to handle Bspline curves.					      *
******************************************************************************/
CagdCrvStruct *BspCrvNew(int Length, int Order, CagdPointType PType);
CagdCrvStruct *BspPeriodicCrvNew(int Length,
				 int Order,
				 CagdBType Periodic,
				 CagdPointType PType);
void BspCrvDomain(CagdCrvStruct *Crv, CagdRType *TMin, CagdRType *TMax);

CagdRType *BspCrvCoxDeBoorBasis(CagdRType *KnotVector,
				int Order,
				int Len,
				CagdRType t,
				int *IndexFirst);
CagdRType *BspCrvEvalCoxDeBoor(CagdCrvStruct *Crv, CagdRType t);
CagdRType BspCrvEvalVecAtParam(CagdRType *Vec,
			       int VecInc,
			       CagdRType *KnotVector,
			       int Order,
			       int Len,
			       CagdBType Periodic,
			       CagdRType t);
CagdRType *BspCrvEvalAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BspCrvCreateCircle(CagdPtStruct *Center, CagdRType Radius);
CagdCrvStruct *BspCrvCreateUnitCircle(void);
CagdCrvStruct *BspCrvCreatePCircle(CagdPtStruct *Center, CagdRType Radius);
CagdCrvStruct *BspCrvCreateUnitPCircle(void);
CagdCrvStruct *BspCrvKnotInsert(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BspCrvKnotInsertNSame(CagdCrvStruct *Crv, CagdRType t, int n);
CagdCrvStruct *BspCrvKnotInsertNDiff(CagdCrvStruct *Crv,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
CagdCrvStruct *BspCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BspCrvOpenEnd(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *BspCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvIntegrate(CagdCrvStruct *Crv);
CagdVecStruct *BspCrvTangent(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *BspCrvBiNormal(CagdCrvStruct *Crv, CagdRType t);
CagdVecStruct *BspCrvNormal(CagdCrvStruct *Crv, CagdRType t);
CagdPolylineStruct *BspCrv2Polyline(CagdCrvStruct *Crv,
				    int SamplesPerCurve,
				    BspKnotAlphaCoeffType *A,
				    CagdBType OptiLin);
CagdCrvStruct *BspCrvInterpPts(CagdPtStruct *PtList,
			       int Order,
			       int CrvSize,
			       CagdParametrizationType ParamType);
CagdCrvStruct *BspCrvInterpolate(CagdCtlPtStruct *PtList,
				 int NumPts,
				 CagdRType *Params,
				 CagdRType *KV,
				 int Length,
				 int Order,
				 CagdBType Periodic);
CagdRType BspCrvInterpPtsError(CagdCrvStruct *Crv,
			       CagdPtStruct *PtList,
			       CagdParametrizationType ParamType);

/******************************************************************************
* Routines to handle Bspline surfaces.					      *
******************************************************************************/
CagdSrfStruct *BspSrfNew(int ULength,
			 int VLength,
			 int UOrder,
			 int VOrder,
			 CagdPointType PType);
CagdSrfStruct *BspPeriodicSrfNew(int ULength,
				 int VLength,
				 int UOrder,
				 int VOrder,
				 CagdBType UPeriodic,
				 CagdBType VPeriodic,
				 CagdPointType PType);
void BspSrfDomain(CagdSrfStruct *Srf,
		  CagdRType *UMin,
		  CagdRType *UMax,
		  CagdRType *VMin,
		  CagdRType *VMax);
CagdRType *BspSrfEvalAtParam(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdCrvStruct *BspSrfCrvFromSrf(CagdSrfStruct *Srf,
				CagdRType t,
				CagdSrfDirType Dir);
CagdCrvStruct *BspSrfCrvFromMesh(CagdSrfStruct *Srf,
				 int Index,
				 CagdSrfDirType Dir);
CagdSrfStruct *BspSrfKnotInsert(CagdSrfStruct *Srf,
				CagdSrfDirType Dir,
				CagdRType t);
CagdSrfStruct *BspSrfKnotInsertNSame(CagdSrfStruct *Srf,
				     CagdSrfDirType Dir,
				     CagdRType t, int n);
CagdSrfStruct *BspSrfKnotInsertNDiff(CagdSrfStruct *Srf,
				     CagdSrfDirType Dir,
				     int Replace,
				     CagdRType *t, int n);
CagdSrfStruct *BspSrfSubdivAtParam(CagdSrfStruct *Srf,
				   CagdRType t,
				   CagdSrfDirType Dir);
CagdSrfStruct *BspSrfOpenEnd(CagdSrfStruct *Srf);
CagdSrfStruct *BspSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BspSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdVecStruct *BspSrfTangent(CagdSrfStruct *Srf,
			     CagdRType u,
			     CagdRType v,
			     CagdSrfDirType Dir);
CagdVecStruct *BspSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdVecStruct *BspSrfMeshNormals(CagdSrfStruct *Srf,
				 int UFineNess,
				 int VFineNess);
CagdPolygonStruct *BspSrf2Polygons(CagdSrfStruct *Srf,
				   int FineNess,
				   CagdBType ComputeNormals,
				   CagdBType FourPerFlat,
				   CagdBType ComputeUV);
CagdPolylineStruct *BspSrf2Polylines(CagdSrfStruct *Srf,
				     int NumOfIsocurves[2],
				     int SamplesPerCurve);
CagdCrvStruct *BspSrf2Curves(CagdSrfStruct *Srf, int NumOfIsocurves[2]);
CagdSrfStruct *BspSrfInterpPts(CagdPtStruct **PtList,
			       int UOrder,
			       int VOrder,
			       int SrfUSize,
			       int SrfVSize,
			       CagdParametrizationType ParamType);
CagdSrfStruct *BspSrfInterpolate(CagdCtlPtStruct *PtList,
				 int NumUPts,
				 int NumVPts,
				 CagdRType *UParams,
				 CagdRType *VParams,
				 CagdRType *UKV,
				 CagdRType *VKV,
				 int ULength,
				 int VLength,
				 int UOrder,
				 int VOrder);

/******************************************************************************
* Routines to handle basis function conversions.			      *
******************************************************************************/
CagdCrvStruct *CnvrtPower2BezierCrv(CagdCrvStruct *Crv);
CagdCrvStruct *CnvrtBezier2PowerCrv(CagdCrvStruct *Crv);
CagdCrvStruct *CnvrtBspline2BezierCrv(CagdCrvStruct *Crv);
CagdCrvStruct *CnvrtBezier2BsplineCrv(CagdCrvStruct *Crv);

CagdSrfStruct *CnvrtPower2BezierSrf(CagdSrfStruct *Srf);
CagdSrfStruct *CnvrtBezier2PowerSrf(CagdSrfStruct *Srf);
CagdSrfStruct *CnvrtBezier2BsplineSrf(CagdSrfStruct *Srf);
CagdSrfStruct *CnvrtBspline2BezierSrf(CagdSrfStruct *Srf);

CagdCrvStruct *CnvrtPeriodic2FloatCrv(CagdCrvStruct *Crv);
CagdSrfStruct *CnvrtPeriodic2FloatSrf(CagdSrfStruct *Srf);
CagdCrvStruct *CnvrtFloat2OpenCrv(CagdCrvStruct *Crv);
CagdSrfStruct *CnvrtFloat2OpenSrf(CagdSrfStruct *Srf);

CagdCrvStruct *CnvrtPolyline2LinBsplineCrv(CagdPolylineStruct *Poly);

/******************************************************************************
* Routines to handle adaptive forward differencing basis functions.	      *
******************************************************************************/
void AfdCnvrtCubicBzrToAfd(CagdRType Coef[4]);
void AfdApplyLn(CagdRType Coef[4], int n);
void AfdApplyEStep(CagdRType Coef[4]);
void AfdComputePolyline(CagdRType Coef[4],
			CagdRType *Poly,
			int Log2Step,
			CagdBType NonAdaptive);
void AfdBzrCrvEvalToPolyline(CagdCrvStruct *Crv,
			     int FineNess,
			     CagdRType *Points[]);

/******************************************************************************
* Error handling.							      *
******************************************************************************/
void CagdFatalError(CagdFatalErrorType ErrID);
char *CagdDescribeError(CagdFatalErrorType ErrID);

#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

extern int _CagdGlblLineCount;	     /* Used to locate errors in input file. */

#endif /* CAGD_LIB_H */
