/******************************************************************************
* Cagd_lib.h - header file for the CAGD library.			      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Mar. 90.					      *
******************************************************************************/

#ifndef CAGD_LIB_H
#define CAGD_LIB_H

#include <stdio.h>
#include "irit_sm.h"
#include "miscattr.h"
#include "misc_lib.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_W_ZERO,
    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_ONLY_1D_TO_3D,
    CAGD_ERR_ONLY_2D,
    CAGD_ERR_DOMAIN_TOO_SMALL,
    CAGD_ERR_PERIODIC_EXPECTED,
    CAGD_ERR_PERIODIC_NO_SUPPORT,
    CAGD_ERR_OPEN_EC_EXPECTED,
    CAGD_ERR_POLYGON_EXPECTED,
    CAGD_ERR_POLYSTRIP_EXPECTED,
    CAGD_ERR_SWEEP_AXIS_TOO_COMPLEX,
    CAGD_ERR_INVALID_CONIC_COEF,
    CAGD_ERR_HYPERBOLA_NO_SUPPORT,
    CAGD_ERR_WRONG_DERIV_ORDER,
    CAGD_ERR_NO_TOL_TEST_FUNC,
    CAGD_ERR_NO_KV_FOUND,
    CAGD_ERR_WRONG_SIZE,
    CAGD_ERR_INVALID_CRV,
    CAGD_ERR_INVALID_SRF,

    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,
    CAGD_PT_E6_TYPE,
    CAGD_PT_P6_TYPE,
    CAGD_PT_E7_TYPE,
    CAGD_PT_P7_TYPE,
    CAGD_PT_E8_TYPE,
    CAGD_PT_P8_TYPE,
    CAGD_PT_E9_TYPE,
    CAGD_PT_P9_TYPE,
    CAGD_PT_MAX
} CagdPointType;

typedef enum {
    CAGD_POLY_APPROX_ERR_CENTER = 1,
    CAGD_POLY_APPROX_ERR_SAMPLES_MAX,
    CAGD_POLY_APPROX_ERR_SAMPLES_AVG
} CagdPolyErrEstimateType;

typedef enum {
    CAGD_END_COND_GENERAL = 0,
    CAGD_END_COND_OPEN = 1,
    CAGD_END_COND_FLOAT,
    CAGD_END_COND_PERIODIC
} CagdEndConditionType;

typedef enum {
    CAGD_PRIM_CAPS_NONE = 0,
    CAGD_PRIM_CAPS_BOTTOM = 1,
    CAGD_PRIM_CAPS_TOP = 2,
    CAGD_PRIM_CAPS_BOTH = 3
} CagdPrimCapsType;

typedef enum {
    CAGD_CONST_X_SYMMETRY = 1,
    CAGD_CONST_Y_SYMMETRY = 2,
    CAGD_CONST_Z_SYMMETRY = 4,
    CAGD_CONST_C_SYMMETRY = 32,
    CAGD_CONST_X_AREA = 64,
    CAGD_CONST_Y_AREA = 128
} CagdConstraintType;

typedef enum {
    CAGD_GEOM_CONST,
    CAGD_GEOM_LINEAR,
    CAGD_GEOM_CIRCULAR,
    CAGD_GEOM_CONIC_SEC,
    CAGD_GEOM_PLANAR,
    CAGD_GEOM_SPHERICAL,
    CAGD_GEOM_TORUS,
    CAGD_GEOM_CYLINDRICAL,
    CAGD_GEOM_CONICAL,
    CAGD_GEOM_SRF_OF_REV,
    CAGD_GEOM_BILINEAR,
    CAGD_GEOM_BOOL_SUM,
    CAGD_GEOM_EXTRUSION,
    CAGD_GEOM_RULED_SRF,
    CAGD_GEOM_DEVELOP_SRF,
    CAGD_GEOM_SWEEP_SRF
} CagdIsGeometryType;

#define CAGD_MALLOC_STRUCT_ONCE     /* Faster allocation of CAGD structures. */

#define CAGD_IS_RATIONAL_PT(PType)  ((int) ((PType) & 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		10     /* Rational P9 has 10 coords. */
#define CAGD_MAX_PT_COORD		9		       /* Without w. */

#define CAGD_MAX_E_POINT		CAGD_PT_E9_TYPE
#define CAGD_MAX_P_POINT		CAGD_PT_P9_TYPE

#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.					     */
#ifdef CAGD_LARGE_BEZIER_CACHE
#define CAGD_MAX_BEZIER_CACHE_ORDER	99    /* See cbzr_tbl.c in cagd_lib. */
#else
#define CAGD_MAX_BEZIER_CACHE_ORDER	28    /* See cbzr_tbl.c in cagd_lib. */
#endif
#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] = IRIT_INFNTY; \
    BBox -> Max[0] = BBox -> Max[1] = BBox -> Max[2] = -IRIT_INFNTY; }

#define CAGD_DEL_GEOM_TYPE(Obj) \
			    AttrFreeOneAttribute(&(Obj) -> Attr, "GeomType")
#define CAGD_SET_GEOM_TYPE(Obj, Geom) \
			    AttrSetIntAttrib(&(Obj) -> Attr, "GeomType", Geom)
#define CAGD_PROPAGATE_ATTR(NewObj, Obj) { \
		  IP_ATTR_FREE_ATTRS((NewObj) -> Attr); \
                  if ((Obj) -> Attr != NULL) { \
		      (NewObj) -> Attr = AttrCopyAttributes((Obj) -> Attr); } }

#define CAGD2PLY_MAX_SUBDIV_INDEX 512    /* Inc. this 2^n for finer subdivs. */

#define CAGD_QUERY_VALUE	-1030603010

#define CAGD_MAX_DOMAIN_EPS	(IRIT_UEPS * 10)
#define CAGD_VALIDATE_MIN_MAX_DOMAIN(t, TMin, TMax) { \
    if (t >= TMax - MAX(t * CAGD_MAX_DOMAIN_EPS, CAGD_MAX_DOMAIN_EPS)) \
	t -= MAX(t * CAGD_MAX_DOMAIN_EPS, CAGD_MAX_DOMAIN_EPS); \
    if (t < TMin) \
	t = TMin; }

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,
    CAGD_BOTH_DIR
} CagdSrfDirType;

typedef enum {
    CAGD_NO_BNDRY = 1400,
    CAGD_U_MIN_BNDRY,
    CAGD_U_MAX_BNDRY,
    CAGD_V_MIN_BNDRY,
    CAGD_V_MAX_BNDRY
} CagdSrfBndryType;

#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_GENERAL_PARAM = 1500,
    CAGD_UNIFORM_PARAM,
    CAGD_CENTRIPETAL_PARAM,
    CAGD_CHORD_LEN_PARAM,
    CAGD_NIELSON_FOLEY_PARAM
} CagdParametrizationType;

typedef enum {
    CAGD_POLYGON_TYPE_TRIANGLE,
    CAGD_POLYGON_TYPE_RECTANGLE,
    CAGD_POLYGON_TYPE_POLYSTRIP
} CagdPolygonType;

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 CagdSrfPtStruct {
    struct CagdSrfPtStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdUVType Uv;
    CagdPType Pt;
    CagdVType Nrml;
} CagdSrfPtStruct;

typedef struct CagdSrfAdapRectStruct {
    struct CagdSrfAdapRectStruct *Pnext;
    int UIndexBase;
    int UIndexSize;
    int VIndexBase;
    int VIndexSize;
    VoidPtr AuxSrfData;
    CagdRType Err;
} CagdSrfAdapRectStruct;

typedef struct CagdCtlPtStruct {
    struct CagdCtlPtStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdRType Coords[CAGD_MAX_PT_SIZE];
    CagdPointType PtType;
    int align8;
} 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;

    VoidPtr PAux;                         /* Used internally - do not touch. */
} CagdSrfStruct;

typedef struct CagdPolygonStruct {
    struct CagdPolygonStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPolygonType PolyType;
    union {
	struct {
	    CagdPType Pt;	 /* Polygon is either triangle or rectangle. */
	    CagdVType Nrml;
	    CagdUVType UV;
	} Polygon[4];
	struct {
	    /* Polygonal strip can have arbitrary # of polygons. */
	    CagdPType FirstPt[2];	      /* Base line - the first edge. */
	    CagdVType FirstNrml[2];
	    CagdUVType FirstUV[2];
	    CagdPType *StripPt;		       /* Arrays of size NumOfPolys. */
	    CagdVType *StripNrml;
	    CagdUVType *StripUV;
	    int NumOfPolys;
	} PolyStrip;
    } U;
} 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 BspKnotAlphaCoeffStruct {
    int Order, Length, RefLength, Periodic;   /* Dimensions of alpha matrix. */
    CagdRType *Matrix;
    CagdRType *MatrixTransp;
    CagdRType **Rows;		     /* A column of pointers to Matrix rows. */
    CagdRType **RowsTransp;	     /* A row of pointers to Matrix columns. */
    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. */
    CagdRType *_CacheKVT;	    /* To compare input/output kvs in cache. */
    CagdRType *_CacheKVt;
} BspKnotAlphaCoeffStruct;

typedef void (*CagdPrintfFuncType)(char *Line);
typedef int (*CagdCompFuncType)(VoidPtr P1, VoidPtr P2);
typedef CagdCrvStruct *(*CagdCrvFuncType)(CagdCrvStruct *Crv, CagdRType R);
typedef CagdRType (*CagdMatchNormFuncType) (CagdVType T1,
					    CagdVType T2,
					    CagdVType P1,
					    CagdVType P2);
typedef CagdRType (*CagdSrfErrorFuncType)(CagdSrfStruct *Srf);
typedef int (*CagdSrfAdapAuxDataFuncType)(CagdSrfStruct *Srf,
					  VoidPtr AuxSrfData,
					  CagdRType t,
					  CagdSrfDirType Dir,
					  CagdSrfStruct *Srf1,
					  VoidPtr *AuxSrf1Data,
					  CagdSrfStruct *Srf2,
					  VoidPtr *AuxSrf2Data);
typedef CagdPolygonStruct *(*CagdSrfAdapPolyGenFuncType)(CagdSrfStruct *Srf,
						  CagdSrfPtStruct *SrfPtList,
						  CagdSrfAdapRectStruct *Rect);

typedef CagdPolygonStruct *(*CagdSrfMakeTriFuncType)(CagdBType ComputeNormals,
						     CagdBType ComputeUV,
						     CagdRType *Pt1,
						     CagdRType *Pt2,
						     CagdRType *Pt3,
						     CagdRType *Nl1,
						     CagdRType *Nl2,
						     CagdRType *Nl3,
						     CagdRType *UV1,
						     CagdRType *UV2,
						     CagdRType *UV3,
						     CagdBType *GenPoly);
typedef CagdPolygonStruct *(*CagdSrfMakeRectFuncType)(CagdBType ComputeNormals,
						      CagdBType ComputeUV,
						      CagdRType *Pt1,
						      CagdRType *Pt2,
						      CagdRType *Pt3,
						      CagdRType *Pt4,
						      CagdRType *Nl1,
						      CagdRType *Nl2,
						      CagdRType *Nl3,
						      CagdRType *Nl4,
						      CagdRType *UV1,
						      CagdRType *UV2,
						      CagdRType *UV3,
						      CagdRType *UV4,
						      CagdBType *GenPoly);
typedef CagdRType (*CagdPlgErrorFuncType)(CagdPType P1,
					  CagdPType P2,
					  CagdPType P3);

#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/vectors 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_SQR_LEN_VECTOR(V)		(SQR((V).Vec[0]) + \
					     SQR((V).Vec[1]) + \
					     SQR((V).Vec[2]))
#define CAGD_LEN_VECTOR(V)		sqrt(CAGD_SQR_LEN_VECTOR(V))
#define CAGD_NORMALIZE_VECTOR(V)	{ CagdRType __t = CAGD_LEN_VECTOR(V); \
					  _IRIT_PT_NORMALIZE_MSG_ZERO(__t) \
					  { \
					      __t = 1.0 / __t; \
					      CAGD_MULT_VECTOR((V), __t); \
					  } \
				        }


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

#define CAGD_PT_ON_BNDRY(u, v, UMin, UMax, VMin, VMax, Eps) \
	(APX_EQ_EPS(u, UMin, Eps) || APX_EQ_EPS(u, UMax, Eps) || \
	 APX_EQ_EPS(v, VMin, Eps) || APX_EQ_EPS(v, VMax, Eps))

/******************************************************************************
* 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 IRIT_DOUBLE
#define CAGD_DOMAIN_IRIT_EPS 1e-13
#else
#define CAGD_DOMAIN_IRIT_EPS 1e-5
#endif /* IRIT_DOUBLE */

#define CAGD_DOMAIN_T_VERIFY(t, TMin, TMax) \
    { \
	if (t < TMin) \
	    t += CAGD_DOMAIN_IRIT_EPS; \
	if (t > TMax) \
	    t -= CAGD_DOMAIN_IRIT_EPS; \
	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_LOOP_BLEND_NOT_PERIODIC_OLD(A, IMin, IMax, OrigPts, RefPts) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType \
	**_Rows = A -> Rows; \
 \
    ZAP_MEM(RefPts, sizeof(CagdRType) * (IMax - IMin)); \
 \
    for (_i = IMin; _i < IMax; _i++) { \
	if (*_ColLength++ == 1) \
	    *RefPts++ = OrigPts[*_ColIndex++]; \
	else { \
	    int _Len = _ColLength[-1], \
	        _Idx = *_ColIndex++ + --_Len; \
	    CagdRType \
		*_Pts = &OrigPts[_Idx]; \
 \
	    for ( ; _Len-- >= 0; _Idx--) { \
		*RefPts += *_Pts-- * _Rows[_Idx][_i]; \
	    } \
 \
	    RefPts++; \
	} \
    } \
}

#define CAGD_ALPHA_LOOP_BLEND_PERIODIC_OLD(A, IMin, IMax, OrigPts, OrigLen, RefPts) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType \
	**_Rows = A -> Rows; \
 \
    ZAP_MEM(RefPts, sizeof(CagdRType) * (IMax - IMin)); \
 \
    for (_i = IMin; _i < IMax; _i++) { \
	if (*_ColLength++ == 1) { \
	    int _Idx = *_ColIndex++; \
	    *RefPts++ = OrigPts[_Idx >= OrigLen ? _Idx - OrigLen \
			                        : _Idx]; \
	} \
	else { \
	    int _Len = _ColLength[-1], \
	        _Idx = *_ColIndex++ + --_Len; \
	    CagdRType \
		*_Pts = &OrigPts[_Idx]; \
 \
	    for ( ; _Len-- >= 0; _Idx--) { \
		*RefPts += *_Pts-- * _Rows[_Idx >= OrigLen ? _Idx - OrigLen \
			                                   : _Idx][_i]; \
	    } \
 \
	    RefPts++; \
	} \
    } \
}

#define CAGD_ALPHA_LOOP_BLEND_STEP_OLD(A, IMin, IMax, OrigPts, OrigPtsStep, \
				   OrigLen, RefPts, RefPtsStep) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType \
	**_Rows = A -> Rows; \
 \
    for (_i = IMin; _i < IMax; _i++) { \
	if (*_ColLength++ == 1) { \
	    *RefPts = OrigPts[*_ColIndex++ * OrigPtsStep]; \
	} \
	else { \
	    int _Len = _ColLength[-1], \
	        _Idx = *_ColIndex++ + --_Len; \
	    CagdRType \
		*_Pts = &OrigPts[_Idx * OrigPtsStep]; \
 \
	    for (*RefPts = 0.0; _Len-- >= 0; _Idx--, _Pts -= OrigPtsStep) { \
		*RefPts += *_Pts * _Rows[_Idx][_i]; \
	    } \
	} \
	RefPts += RefPtsStep; \
    } \
}

#define CAGD_ALPHA_LOOP_BLEND_NOT_PERIODIC(A, IMin, IMax, OrigPts, RefPts) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType *_p, *_r; \
  \
    ZAP_MEM(RefPts, sizeof(CagdRType) * (IMax - IMin)); \
  \
    for (_i = IMin; _i < IMax; _i++) { \
	switch (*_ColLength++) { \
 	    case 1: \
		*RefPts++ = OrigPts[*_ColIndex++]; \
		break; \
 	    case 2: \
		_p = &OrigPts[*_ColIndex]; \
		_r = &A -> RowsTransp[_i][*_ColIndex++]; \
		*RefPts++ = _p[0] * _r[0] + \
		            _p[1] * _r[1]; \
		break; \
 	    case 3: \
		_p = &OrigPts[*_ColIndex]; \
		_r = &A -> RowsTransp[_i][*_ColIndex++]; \
		*RefPts++ = _p[0] * _r[0] + \
		            _p[1] * _r[1] + \
		            _p[2] * _r[2]; \
		break; \
 	    case 4: \
		_p = &OrigPts[*_ColIndex]; \
		_r = &A -> RowsTransp[_i][*_ColIndex++]; \
		*RefPts++ = _p[0] * _r[0] + \
		            _p[1] * _r[1] + \
		            _p[2] * _r[2] + \
		            _p[3] * _r[3]; \
		break; \
	    default: \
		{ \
		    int _Len = _ColLength[-1]; \
 \
		    _p = &OrigPts[*_ColIndex]; \
		    _r = &A -> RowsTransp[_i][*_ColIndex++]; \
 \
		    for (*RefPts = 0.0; _Len-- > 0; ) { \
			*RefPts += *_p++ * *_r++; \
		    } \
 \
		    RefPts++; \
	        } \
		break; \
	} \
    } \
}

#define CAGD_ALPHA_LOOP_BLEND_PERIODIC(A, IMin, IMax, OrigPts, OrigLen, RefPts) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType *_p, *_r; \
 \
    for (_i = IMin; _i < IMax; _i++) { \
        int _Len = *_ColLength++, \
	    _Idx = *_ColIndex++; \
 \
	if (_Idx + _Len <= OrigLen) { \
	    switch (_Len) { \
 	        case 1: \
		    *RefPts++ = OrigPts[_Idx]; \
		    break; \
 	        case 2: \
		    _p = &OrigPts[_Idx]; \
		    _r = &A -> RowsTransp[_i][_Idx]; \
		    *RefPts++ = _p[0] * _r[0] + \
		                _p[1] * _r[1]; \
		    break; \
 	        case 3: \
		    _p = &OrigPts[_Idx]; \
		    _r = &A -> RowsTransp[_i][_Idx]; \
		    *RefPts++ = _p[0] * _r[0] + \
		                _p[1] * _r[1] + \
		                _p[2] * _r[2]; \
		    break; \
 	        case 4: \
		    _p = &OrigPts[_Idx]; \
		    _r = &A -> RowsTransp[_i][_Idx]; \
		    *RefPts++ = _p[0] * _r[0] + \
		                _p[1] * _r[1] + \
		                _p[2] * _r[2] + \
		                _p[3] * _r[3]; \
		    break; \
	        default: \
	  	    { \
		        if (_Len == 1) { \
			    *RefPts++ = OrigPts[_Idx]; \
			} \
			else { \
			    _p = &OrigPts[_Idx]; \
			    _r = &A -> RowsTransp[_i][_Idx]; \
 \
			    for (*RefPts = 0.0 ; _Len-- > 0; ) { \
				*RefPts += *_p++ * *_r++; \
			    } \
 \
			    RefPts++; \
			} \
		    } \
	    } \
	} \
	else { \
	    if (_Len == 1) { \
		*RefPts++ = OrigPts[_Idx >= OrigLen ? _Idx - OrigLen : _Idx]; \
	    } \
	    else { \
		_p = &OrigPts[_Idx]; \
		_r = A -> RowsTransp[_i]; \
 \
		for (*RefPts = 0.0 ; _Len-- > 0; _Idx++) { \
		    *RefPts += *_p++ * _r[_Idx >= OrigLen ? _Idx - OrigLen : \
			                                    _Idx]; \
		} \
 \
		RefPts++; \
	    } \
	} \
    } \
}

#define CAGD_ALPHA_LOOP_BLEND_STEP(A, IMin, IMax, OrigPts, OrigPtsStep, \
				   OrigLen, RefPts, RefPtsStep) \
{ \
    int _i, \
	*_ColLength = &A -> ColLength[IMin], \
	*_ColIndex = &A -> ColIndex[IMin]; \
    CagdRType \
	**_Rows = A -> Rows; \
 \
    for (_i = IMin; _i < IMax; _i++) { \
	if (*_ColLength++ == 1) { \
	    *RefPts = OrigPts[*_ColIndex++ * OrigPtsStep]; \
	} \
	else { \
	    int _Len = _ColLength[-1], \
	        _Idx = *_ColIndex++ + --_Len; \
	    CagdRType \
		*_Pts = &OrigPts[_Idx * OrigPtsStep]; \
 \
	    for (*RefPts = 0.0; _Len-- >= 0; _Idx--, _Pts -= OrigPtsStep) { \
		*RefPts += *_Pts * _Rows[_Idx][_i]; \
	    } \
	} \
	RefPts += RefPtsStep; \
    } \
}

/******************************************************************************
* A fast macro to evaluate a point out of a control points' mesh/vector.      *
******************************************************************************/

#define BSP_CRV_EVAL_VEC_AT_PARAM(Res, Pts, Inc, Order, Len, \
				  t, BasisFuncs, IndexFirst) \
    { \
	int _i, \
	    _IFirst = IndexFirst; \
	CagdRType \
            *_B = BasisFuncs; \
 \
	*Res = 0.0; \
	if (Inc == 1) { \
	    for (_i = 0; _i < Order; _i++) { \
		*Res += *_B++ * Pts[_IFirst]; \
		if (++_IFirst >= Len) \
		    _IFirst -= Len; \
	    } \
        } \
	else { \
	    int _IFirstInc = _IFirst; \
 \
	    _IFirstInc *= Inc; \
	    for (_i = 0; _i < Order; _i++) { \
		*Res += *_B++ * Pts[_IFirstInc]; \
	        _IFirstInc += Inc; \
	        if (++_IFirst >= Len) { \
	            _IFirst -= Len; \
		    _IFirstInc -= Len * Inc; \
	        } \
	    } \
        } \
    }

/******************************************************************************
* 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"

extern GLOBAL_DATA CagdBType _CagdSrfMakeOnlyTri;
extern GLOBAL_DATA CagdSrfMakeTriFuncType _CagdSrfMakeTriFunc;
extern GLOBAL_DATA CagdSrfMakeRectFuncType _CagdSrfMakeRectFunc;

/******************************************************************************
* 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 global variable of the Cagd library:				      *
******************************************************************************/
extern GLOBAL_DATA CagdRType CagdIChooseKTable[CAGD_MAX_BEZIER_CACHE_ORDER + 1]
		                  [CAGD_MAX_BEZIER_CACHE_ORDER + 1];

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

CagdUVStruct *CagdUVNew(void);
CagdPtStruct *CagdPtNew(void);
CagdSrfPtStruct *CagdSrfPtNew(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(int Len);
CagdPolygonStruct *CagdPolygonStripNew(int Len);
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);
CagdSrfPtStruct *CagdSrfPtCopy(CagdSrfPtStruct *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);
CagdSrfPtStruct *CagdSrfPtCopyList(CagdSrfPtStruct *SrfPtList);
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 CagdSrfPtFree(CagdSrfPtStruct *SrfPt);
void CagdSrfPtFreeList(CagdSrfPtStruct *SrfPtList);
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 CagdPolygonFree(CagdPolygonStruct *Poly);
void CagdPolygonFreeList(CagdPolygonStruct *PolyList);

#ifdef DEBUG
#define CagdCrvFree(Crv)         { CagdCrvFree(Crv); Crv = NULL; }
#define CagdCrvFreeList(CrvList) { CagdCrvFreeList(CrvList); CrvList = NULL; }
#define CagdSrfFree(Srf)         { CagdSrfFree(Srf); Srf = NULL; }
#define CagdSrfFreeList(SrfList) { CagdSrfFreeList(SrfList); SrfList = NULL; }
#define CagdUVFree(UV)           { CagdUVFree(UV); UV = NULL; }
#define CagdUVFreeList(UVList)   { CagdUVFreeList(UVList); UVList = NULL; }
#define CagdUVArrayFree(UVArray, \
			Size)    { CagdUVArrayFree(UVArray, Size); \
				   UVArray = NULL; }
#define CagdPtFree(Pt)           { CagdPtFree(Pt); Pt = NULL; }
#define CagdPtFreeList(PtList)   { CagdPtFreeList(PtList); PtList = NULL; }
#define CagdSrfPtFree(SrfPt)     { CagdSrfPtFree(SrfPt); SrfPt = NULL; }
#define CagdSrfPtFreeList(SrfPtList) { CagdSrfPtFreeList(SrfPtList); \
				       SrfPtList = NULL; }
#define CagdPtArrayFree(PtArray, \
			Size)    { CagdPtArrayFree(PtArray, Size); \
				   PtArray = NULL; }
#define CagdCtlPtFree(CtlPt)     { CagdCtlPtFree(CtlPt); CtlPt = NULL; }
#define CagdCtlPtFreeList(CtlPtList) { CagdCtlPtFreeList(CtlPtList); \
				       CtlPtList = NULL; }
#define CagdCtlPtArrayFree(CtlPtArray, \
			   Size) { CagdCtlPtArrayFree(CtlPtArray, Size); \
				   CtlPtArray = NULL; }
#define CagdVecFree(Vec)         { CagdVecFree(Vec); Vec = NULL; }
#define CagdVecFreeList(VecList) { CagdVecFreeList(VecList); VecList = NULL; }
#define CagdVecArrayFree(VecArray, \
			 Size)   { CagdVecArrayFree(VecArray, Size); \
				   VecArray = NULL; }
#define CagdPlaneFree(Plane)     { CagdPlaneFree(Plane); Plane = NULL; }
#define CagdPlaneFreeList(PlaneList) { CagdPlaneFreeList(PlaneList); \
				       PlaneList = NULL; }
#define CagdPlaneArrayFree(PlaneArray, \
			   Size) { CagdPlaneArrayFree(PlaneArray, Size); \
				   PlaneArray = NULL; }
#define CagdBBoxFree(BBox)       { CagdBBoxFree(BBox); BBox = NULL; }
#define CagdBBoxFreeList(BBoxList) { CagdBBoxFreeList(BBoxList); \
				     BBoxList = NULL; }
#define CagdBBoxArrayFree(BBoxArray, \
			  Size) { CagdBBoxArrayFree(BBoxArray, Size); \
				  BBoxArray = NULL; }
#define CagdPolylineFree(Poly)   { CagdPolylineFree(Poly); Poly = NULL; }
#define CagdPolylineFreeList(PolyList) { CagdPolylineFreeList(PolyList); \
					 PolyList = NULL; }
#define CagdPolylineArrayFree(PolyArray, \
			      Size) { CagdPolylineArrayFree(PolyArray, Size); \
				      PolyArray = NULL; }
#define CagdPolygonFree(Poly)    { CagdPolygonFree(Poly); Poly = NULL; }
#define CagdPolygonFreeList(PolyList) { CagdPolygonFreeList(PolyList); \
					PolyList = NULL; }
#define CagdPolygonArrayFree(PolyArray, \
			     Size) { CagdPolygonArrayFree(PolyArray, Size); \
				     PolyArray = NULL; }
#endif /* DEBUG */

VoidPtr CagdListInsert(VoidPtr List,
		       VoidPtr NewElement,
		       CagdCompFuncType CompFunc,
		       CagdBType InsertEqual);
int CagdListLength(VoidPtr List);
VoidPtr CagdListAppend(VoidPtr List1, VoidPtr List2);
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);
VoidPtr CagdStructOnceCoercePointsTo(CagdRType *OldPoints[],
				     VoidPtr OldStruct,
				     int OldStructLen,
				     int ExtraMem,
				     int PtsLen,
				     CagdPointType OldPType,
				     CagdPointType NewPType);
CagdRType CagdDistTwoCtlPt(CagdRType *Pt1[CAGD_MAX_PT_SIZE],
			   int Index1,
			   CagdRType *Pt2[CAGD_MAX_PT_SIZE],
			   int Index2,
			   CagdPointType PType);
CagdBType CagdCtlMeshsSame(CagdRType *Mesh1[],
			   CagdRType *Mesh2[],
			   int Len,
			   CagdRType Eps);
CagdBType CagdCtlMeshsSameUptoRigidScl2D(CagdRType *Mesh1[],
					 CagdRType *Mesh2[],
					 int Len,
					 PointType Trans,
					 CagdRType *Rot,
					 CagdRType *Scl,
					 CagdRType Eps);
CagdCrvStruct *CagdCoerceCrvTo(CagdCrvStruct *Crv, CagdPointType PType);
CagdSrfStruct *CagdCoerceSrfTo(CagdSrfStruct *Srf, CagdPointType PType);
CagdPointType CagdMergePointType(CagdPointType PType1, CagdPointType PType2);
void CagdDbg(void *Obj);
void CagdSetLinear2Poly(CagdLin2PolyType Lin2Poly);
CagdBType CagdTightBBox(CagdBType TightBBox);
CagdBType CagdIgnoreNonPosWeightBBox(CagdBType IgnoreNonPosWeightBBox);
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 CagdScale(CagdRType **Points, int Len, int MaxCoord, CagdRType *Scale);
void CagdMatTransform(CagdRType **Points,
		      int Len,
		      int MaxCoord,
		      CagdBType IsNotRational,
		      CagdMType Mat);
CagdBType CagdPointsHasPoles(CagdRType **Points, int Len);
CagdBType CagdAllWeightsNegative(CagdRType **Points,
				 CagdPointType PType,
				 int Len,
				 CagdBType Flip);
CagdBType CagdAllWeightsSame(CagdRType **Points, int Len);
CagdPlgErrorFuncType CagdPolygonSetErrFunc(CagdPlgErrorFuncType Func);
CagdSrfMakeTriFuncType CagdSrfSetMakeTriFunc(CagdSrfMakeTriFuncType Func);
CagdSrfMakeRectFuncType CagdSrfSetMakeRectFunc(CagdSrfMakeRectFuncType Func);
CagdBType CagdSrfSetMakeOnlyTri(CagdBType OnlyTri);
CagdPolygonStruct *CagdMakeTriangle(CagdBType ComputeNormals,
				    CagdBType ComputeUV,
				    CagdRType *Pt1,
				    CagdRType *Pt2,
				    CagdRType *Pt3,
				    CagdRType *Nl1,
				    CagdRType *Nl2,
				    CagdRType *Nl3,
				    CagdRType *UV1,
				    CagdRType *UV2,
				    CagdRType *UV3,
				    CagdBType *GenPoly);
CagdPolygonStruct *CagdMakeRectangle(CagdBType ComputeNormals,
				     CagdBType ComputeUV,
				     CagdRType *Pt1,
				     CagdRType *Pt2,
				     CagdRType *Pt3,
				     CagdRType *Pt4,
				     CagdRType *Nl1,
				     CagdRType *Nl2,
				     CagdRType *Nl3,
				     CagdRType *Nl4,
				     CagdRType *UV1,
				     CagdRType *UV2,
				     CagdRType *UV3,
				     CagdRType *UV4,
				     CagdBType *GenPoly);
CagdRType CagdBlossomEval(CagdRType *Pts,
			  int PtsStep,
			  int Order,
			  CagdRType *Knots,
			  int KnotsLen,
			  CagdRType *BlsmVals,
			  int BlsmLen);
CagdPolylineStruct *CagdPtPolyline2E3Polyline(
					CagdRType *Polyline[CAGD_MAX_PT_SIZE],
					int n,
					int MaxCoord,
					int IsRational);
CagdPtStruct *CagdPtsSortAxis(CagdPtStruct *PtList, int Axis);

/******************************************************************************
* Matrix/Vector/Plane/Transformation routines:				      *
******************************************************************************/
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);
CagdCrvStruct *CagdCrvMatTransform(CagdCrvStruct *Crv, CagdMType Mat);
CagdSrfStruct *CagdSrfMatTransform(CagdSrfStruct *Srf, CagdMType Mat);
void CagdCrvScale(CagdCrvStruct *Crv, CagdRType *Scale);
void CagdCrvTransform(CagdCrvStruct *Crv,
		      CagdRType *Translate,
		      CagdRType Scale);
void CagdSrfScale(CagdSrfStruct *Srf, CagdRType *Scale);
void CagdSrfTransform(CagdSrfStruct *Srf,
		      CagdRType *Translate,
		      CagdRType Scale);
CagdCrvStruct *CagdCrvUnitMaxCoef(CagdCrvStruct *Crv);
CagdSrfStruct *CagdSrfUnitMaxCoef(CagdSrfStruct *Srf);
CagdCrvStruct *CagdCrvRotateToXY(CagdCrvStruct *Crv);
int CagdCrvRotateToXYMat(CagdCrvStruct *Crv, MatrixType Mat);

/******************************************************************************
* Routines to handle curves generically.				      *
******************************************************************************/
CagdRType *CagdCrvNodes(CagdCrvStruct *Crv);
CagdRType CagdEstimateCrvCollinearity(CagdCrvStruct *Crv);
void CagdCrvDomain(CagdCrvStruct *Crv, CagdRType *TMin, CagdRType *TMax);
CagdCrvStruct *CagdCrvSetDomain(CagdCrvStruct *Crv,
				CagdRType TMin,
				CagdRType TMax);
CagdRType *CagdCrvEval(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *CagdCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvDeriveScalar(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvIntegrate(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvMoebiusTransform(CagdCrvStruct *Crv, CagdRType c);
CagdCrvStruct *CagdCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *CagdCrvSubdivAtParams(CagdCrvStruct *Crv,
				     CagdPtStruct *Pts,
				     CagdRType Eps);
CagdCrvStruct *CagdCrvRegionFromCrv(CagdCrvStruct *Crv,
				    CagdRType t1,
				    CagdRType t2);
CagdCrvStruct *CagdCrvRefineAtParams(CagdCrvStruct *Crv,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
CagdVecStruct *CagdCrvTangent(CagdCrvStruct *Crv,
			      CagdRType t,
			      CagdBType Normalize);
CagdVecStruct *CagdCrvBiNormal(CagdCrvStruct *Crv,
			       CagdRType t,
			       CagdBType Normalize);
CagdVecStruct *CagdCrvNormal(CagdCrvStruct *Crv,
			     CagdRType t,
			     CagdBType Normalize);
CagdVecStruct *CagdCrvNormalXY(CagdCrvStruct *Crv,
			       CagdRType t,
			       CagdBType Normalize);
CagdPolylineStruct *CagdCrv2Polyline(CagdCrvStruct *Crv,
				     int SamplesPerCurve,
				     CagdBType OptiLin);
CagdCrvStruct *CagdCrvReverse(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *CagdCrvDegreeReduce(CagdCrvStruct *Crv);
CagdCrvStruct *CagdCrvCreateArc(CagdPtStruct *Center,
				CagdRType Radius,
				CagdRType StartAngle,
				CagdRType EndAngle);
CagdCrvStruct *CagdCreateConicCurve(CagdRType A,
				    CagdRType B,
				    CagdRType C,
				    CagdRType D,
				    CagdRType E,
				    CagdRType F,
				    CagdRType ZLevel);
CagdCrvStruct *CagdCreateConicCurve2(CagdRType A,
				     CagdRType B,
				     CagdRType C,
				     CagdRType D,
				     CagdRType E,
				     CagdRType F,
				     CagdRType ZLevel,
				     CagdRType *PStartXY,
				     CagdRType *PEndXY);
int CagdEllipse3Points(CagdPType Pt1,
		       CagdPType Pt2,
		       CagdPType Pt3,
		       CagdRType *A,
		       CagdRType *B,
		       CagdRType *C,
		       CagdRType *D,
		       CagdRType *E,
		       CagdRType *F);
int CagdEllipseOffset(CagdRType *A,
		      CagdRType *B,
		      CagdRType *C,
		      CagdRType *D,
		      CagdRType *E,
		      CagdRType *F,
		      CagdRType Offset);
int CagdConicMatTransform(CagdRType *A,
			  CagdRType *B,
			  CagdRType *C,
			  CagdRType *D,
			  CagdRType *E,
			  CagdRType *F,
			  CagdMType Mat);
int CagdQuadricMatTransform(CagdRType *A,
			    CagdRType *B,
			    CagdRType *C,
			    CagdRType *D,
			    CagdRType *E,
			    CagdRType *F,
			    CagdRType *G,
			    CagdRType *H,
			    CagdRType *I,
			    CagdRType *J,
			    CagdMType Mat);
int CagdConic2Quadric(CagdRType *A,
		      CagdRType *B,
		      CagdRType *C,
		      CagdRType *D,
		      CagdRType *E,
		      CagdRType *F,
		      CagdRType *G,
		      CagdRType *H,
		      CagdRType *I,
		      CagdRType *J);
CagdSrfStruct *CagdCreateQuadricSrf(CagdRType A,
				    CagdRType B,
				    CagdRType C,
				    CagdRType D,
				    CagdRType E,
				    CagdRType F,
				    CagdRType G,
				    CagdRType H,
				    CagdRType I,
				    CagdRType J);
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);
CagdRType CagdCrvArcLenPoly(CagdCrvStruct *Crv);
CagdCrvStruct *CagdLimitCrvArcLen(CagdCrvStruct *Crv, CagdRType MaxLen);
CagdPolylineStruct *CagdCrv2CtrlPoly(CagdCrvStruct *Crv);
CagdCrvStruct *CagdEditSingleCrvPt(CagdCrvStruct *Crv,
				   CagdCtlPtStruct *CtlPt,
				   int Index,
				   CagdBType Write);
CagdCrvStruct *CagdCrvDeletePoint(CagdCrvStruct *Crv, int Index);
CagdCrvStruct *CagdCrvInsertPoint(CagdCrvStruct *Crv, int Index, CagdPType Pt);
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[],
			  BspKnotAlphaCoeffStruct *A,
			  CagdBType OptiLin);
void CagdCrvFirstMoments(CagdCrvStruct *Crv,
			 int n,
			 CagdPType Pt,
			 CagdVType Dir);
CagdCrvStruct *CagdCubicHermiteCrv(CagdPType Pt1,
				   CagdPType Pt2,
				   CagdVType Dir1,
				   CagdVType Dir2);
CagdRType CagdMatchDistNorm(CagdVType T1,
			    CagdVType T2,
			    CagdVType P1,
			    CagdVType P2);
CagdRType CagdMatchRuledNorm(CagdVType T1,
			     CagdVType T2,
			     CagdVType P1,
			     CagdVType P2);
CagdRType CagdMatchBisectorNorm(CagdVType T1,
				CagdVType T2,
				CagdVType P1,
				CagdVType P2);
CagdRType CagdMatchMorphNorm(CagdVType T1,
			     CagdVType T2,
			     CagdVType P1,
			     CagdVType P2);

void CagdMatchingFixVector(int *OldVec, CagdRType *NewVec, int Len);
void CagdMatchingFixCrv(CagdCrvStruct *Crv);
void CagdMatchingPolyTransform(CagdRType **Poly,
			       int Len,
			       CagdRType NewBegin,
			       CagdRType NewEnd);
void CagdMatchingVectorTransform(CagdRType *Vec,
				 CagdRType NewBegin,
				 CagdRType NewEnd,
				 int Len);
CagdCrvStruct *CagdMatchingTwoCurves(CagdCrvStruct *Crv1,
				     CagdCrvStruct *Crv2,
				     int Reduce,
				     int SampleSet,
				     int ReparamOrder,
				     int RotateFlag,
				     int AllowNegativeNorm,
				     int ReturnReparamFunc,
				     CagdMatchNormFuncType MatchNormFunc);
int CagdCrvTwoCrvsOrient(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2, int n);
CagdBType CagdIsClosedCrv(CagdCrvStruct *Crv);
CagdBType CagdIsZeroLenCrv(CagdCrvStruct *Crv, CagdRType Eps);
CagdBType CagdCrvTanAngularSpan(CagdCrvStruct *Crv,
				CagdVType ConeDir,
				CagdRType *AngularSpan);
CagdPtStruct *CagdCrvCrvInter(CagdCrvStruct *Crv1,
			      CagdCrvStruct *Crv2,
			      CagdRType Eps);
CagdCrvStruct *CagdCrvCrvInterArrangment(CagdCrvStruct *Crvs,
					 CagdBType SplitCrvs,
					 CagdRType Eps);
CagdBType CagdCrvsSame(CagdCrvStruct *Crv1,
		       CagdCrvStruct *Crv2,
		       CagdRType Eps);
CagdBType CagdCrvsSameUptoRigidScl2D(CagdCrvStruct *Crv1,
				     CagdCrvStruct *Crv2,
				     PointType Trans,
				     CagdRType *Rot,
				     CagdRType *Scl,
				     CagdRType Eps);
CagdCtlPtStruct *CagdCrvBlossomEval(CagdCrvStruct *Crv,
				    CagdRType *BlsmVals,
				    int BlsmLen);
CagdCrvStruct *CagdCrvBlossomDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *CagdCrvBlossomDegreeRaise(CagdCrvStruct *Crv);

/******************************************************************************
* 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);
CagdSrfStruct *CagdSrfSetDomain(CagdSrfStruct *Srf,
				CagdRType UMin,
				CagdRType UMax,
				CagdRType VMin,
				CagdRType VMax);
CagdRType *CagdSrfEval(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
void CagdSrfEstimateCurveness(CagdSrfStruct *Srf,
			      CagdRType *UCurveness,
			      CagdRType *VCurveness);
CagdPolygonStruct *CagdSrf2Polygons(CagdSrfStruct *Srf,
				    int FineNess,
				    CagdBType ComputeNormals,
				    CagdBType FourPerFlat,
				    CagdBType ComputeUV);
CagdPolygonStruct *CagdSrf2PolygonsN(CagdSrfStruct *Srf,
				     int Nu,
				     int Nv,
				     CagdBType ComputeNormals,
				     CagdBType FourPerFlat,
				     CagdBType ComputeUV);
CagdSrfErrorFuncType CagdSrf2PolyAdapSetErrFunc(CagdSrfErrorFuncType Func);
CagdSrfAdapAuxDataFuncType
	      CagdSrf2PolyAdapSetAuxDataFunc(CagdSrfAdapAuxDataFuncType Func);
CagdSrfAdapPolyGenFuncType
	      CagdSrf2PolyAdapSetPolyGenFunc(CagdSrfAdapPolyGenFuncType Func);
CagdRType CagdSrfAdap2PolyDefErrFunc(CagdSrfStruct *Srf);
CagdRType CagdSrfIsCoplanarCtlMesh(CagdSrfStruct *Srf);
CagdRType CagdSrfIsLinearBndryCtlMesh(CagdSrfStruct *Srf);
CagdPolygonStruct *CagdSrfAdap2Polygons(CagdSrfStruct *Srf,
					CagdRType Tolerance,
					CagdBType ComputeNormals,
					CagdBType FourPerFlat,
					CagdBType ComputeUV,
					VoidPtr AuxSrfData,
					VoidPtr SrfPtEvalCache);
CagdPolygonStruct *CagdSrf2PolygonsGenPolys(CagdSrfStruct *Srf,
					    CagdBType FourPerFlat,
					    CagdRType *PtWeights,
					    CagdPtStruct *PtMesh,
					    CagdVecStruct *PtNrml,
					    CagdUVStruct *UVMesh,
					    int FineNessU,
					    int FineNessV);
CagdPolygonStruct *CagdSrfAdapRectPolyGen(CagdSrfStruct *Srf,
					  CagdSrfPtStruct *SrfPtList,
					  CagdSrfAdapRectStruct *Rect);
int CagdSrf2PolygonStrip(int PolygonStrip);
int CagdSrf2PolygonFast(int PolygonFast);
int CagdSrf2PolygonMergeCoplanar(int MergeCoplanarPolys);
int Cagd2PolyClipPolysAtPoles(int ClipPolysAtPoles);
CagdPolylineStruct *CagdSrf2Polylines(CagdSrfStruct *Srf,
				      int NumOfIsocurves[2],
				      int SamplesPerCurve);
CagdCrvStruct *CagdSrf2Curves(CagdSrfStruct *Srf, int NumOfIsocurves[2]);
void CagdEvaluateSurfaceVecField(CagdVType Vec,
				 CagdSrfStruct *VecFieldSrf,
				 CagdRType U,
				 CagdRType V);
CagdSrfStruct *CagdSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfDeriveScalar(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfIntegrate(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfMoebiusTransform(CagdSrfStruct *Srf,
				       CagdRType c,
				       CagdSrfDirType Dir);
CagdCrvStruct *CagdCrvFromSrf(CagdSrfStruct *Srf,
			      CagdRType t,
			      CagdSrfDirType Dir);
CagdCrvStruct *CagdCrvFromMesh(CagdSrfStruct *Srf,
			       int Index,
			       CagdSrfDirType Dir);
CagdCrvStruct **CagdBndryCrvsFromSrf(CagdSrfStruct *Srf);
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,
			      CagdBType Normalize);
CagdVecStruct *CagdSrfNormal(CagdSrfStruct *Srf,
			     CagdRType u,
			     CagdRType v,
			     CagdBType Normalize);
CagdUVType *CagdSrfUVDirOrthoE3(CagdSrfStruct *Srf,
				CagdUVType *UV,
				CagdUVType *UVDir);
CagdSrfStruct *CagdSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *CagdSrfDegreeRaiseN(CagdSrfStruct *Srf,
				   int NewUOrder,
				   int NewVOrder);
CagdSrfStruct *CagdSrfReverse(CagdSrfStruct *Srf);
CagdSrfStruct *CagdSrfReverseDir(CagdSrfStruct *Srf, CagdSrfDirType Dir);
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);
CagdRType CagdSrfAvgArgLenMesh(CagdSrfStruct *Srf,
			       CagdRType *AvgULen,
			       CagdRType *AvgVLen);
CagdSrfStruct *CagdExtrudeSrf(CagdCrvStruct *Crv, CagdVecStruct *Vec);
CagdSrfStruct *CagdSurfaceRev(CagdCrvStruct *Crv);
CagdSrfStruct *CagdSurfaceRevAxis(CagdCrvStruct *Crv, CagdVType Axis);
CagdSrfStruct *CagdSurfaceRev2(CagdCrvStruct *Crv,
			       CagdRType StartAngle,
			       CagdRType EndAngle);
CagdSrfStruct *CagdSurfaceRev2Axis(CagdCrvStruct *Crv,
				   CagdRType StartAngle,
				   CagdRType EndAngle,
				   CagdVType Axis);
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,
			       CagdEndConditionType OtherEC);
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);
CagdRType CagdPolyApproxMaxErr(CagdSrfStruct *Srf, CagdPolygonStruct *Polys);
CagdRType *CagdPolyApproxErrs(CagdSrfStruct *Srf, CagdPolygonStruct *Polys);
int CagdPolyApproxErrEstimate(CagdPolyErrEstimateType Method, int Samples);
CagdSrfStruct *CagdCubicHermiteSrf(CagdCrvStruct *Pos1Crv,
				   CagdCrvStruct *Pos2Crv,
				   CagdCrvStruct *Dir1Crv,
				   CagdCrvStruct *Dir2Crv);
CagdBType CagdIsClosedSrf(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdBType CagdIsZeroLenSrfBndry(CagdSrfStruct *Srf,
				CagdSrfBndryType Bdnry,
				CagdRType Eps);
CagdBType CagdSrfsSame(CagdSrfStruct *Srf1,
		       CagdSrfStruct *Srf2,
		       CagdRType Eps);
CagdCrvStruct *CagdCrvUpdateLength(CagdCrvStruct *Crv, int NewLength);
CagdSrfStruct *CagdSrfUpdateLength(CagdSrfStruct *Srf,
				   int NewLength,
				   CagdSrfDirType Dir);
CagdBType CagdSrfsSameUptoRigidScl2D(CagdSrfStruct *Srf1,
				     CagdSrfStruct *Srf2,
				     PointType Trans,
				     CagdRType *Rot,
				     CagdRType *Scl,
				     CagdRType Eps);
void CagdSrfEffiNrmlPrelude(CagdSrfStruct *Srf);
CagdVecStruct *CagdSrfEffiNrmlEval(CagdRType u,
				   CagdRType v,
				   CagdBType Normalize);
void CagdSrfEffiNrmlPostlude(void);
CagdSrfStruct *CagdSrfBlossomDegreeRaiseN(CagdSrfStruct *Srf,
					  int NewUOrder,
					  int NewVOrder);
CagdSrfStruct *CagdSrfBlossomDegreeRaise(CagdSrfStruct *Srf,
					 CagdSrfDirType Dir);

/******************************************************************************
* Routines to handle Power basis curves.				      *
******************************************************************************/
CagdCrvStruct *PwrCrvNew(int Length, CagdPointType PType);
CagdRType *PwrCrvEvalAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *PwrCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *PwrCrvDeriveScalar(CagdCrvStruct *Crv);
CagdCrvStruct *PwrCrvIntegrate(CagdCrvStruct *Crv);
CagdCrvStruct *PwrCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *PwrCrvDegreeRaise(CagdCrvStruct *Crv);

/******************************************************************************
* Routines to handle Power basis surfaces.				      *
******************************************************************************/
CagdSrfStruct *PwrSrfNew(int ULength, int VLength, CagdPointType PType);
CagdSrfStruct *PwrSrfDegreeRaiseN(CagdSrfStruct *Srf,
				  int NewUOrder,
				  int NewVOrder);
CagdSrfStruct *PwrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);

/******************************************************************************
* Routines to handle Bezier curves.					      *
******************************************************************************/
CagdCrvStruct *BzrCrvNew(int Length, CagdPointType PType);
CagdRType BzrCrvEvalBasisFunc(int i, int k, CagdRType t);
CagdRType *BzrCrvEvalBasisFuncs(int k, CagdRType t);
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);
void BzrCrvSubdivCtlPoly(CagdRType **Points,
			 CagdRType **LPoints,
			 CagdRType **RPoints,
			 int Length,
			 CagdPointType PType,
			 CagdRType t);
void BzrCrvSubdivCtlPolyStep(CagdRType **Points,
			     CagdRType **LPoints,
			     CagdRType **RPoints,
			     int Length,
			     CagdPointType PType,
			     CagdRType t,
			     int Step);
CagdCrvStruct *BzrCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BzrCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *BzrCrvDegreeReduce(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvDeriveScalar(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvIntegrate(CagdCrvStruct *Crv);
CagdCrvStruct *BzrCrvMoebiusTransform(CagdCrvStruct *Crv, CagdRType c);
CagdVecStruct *BzrCrvTangent(CagdCrvStruct *Crv,
			     CagdRType t,
			     CagdBType Normalize);
CagdVecStruct *BzrCrvBiNormal(CagdCrvStruct *Crv,
			      CagdRType t,
			      CagdBType Normalize);
CagdVecStruct *BzrCrvNormal(CagdCrvStruct *Crv,
			    CagdRType t,
			    CagdBType Normalize);
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);
void BzrSrfSubdivCtlMesh(CagdRType **Points,
			 CagdRType **LPoints,
			 CagdRType **RPoints,
			 int ULength,
			 int VLength,
			 CagdPointType PType,
			 CagdRType t,
			 CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfSubdivAtParam(CagdSrfStruct *Srf,
				   CagdRType t,
				   CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfDegreeRaiseN(CagdSrfStruct *Srf,
				  int NewUOrder,
				  int NewVOrder);
CagdSrfStruct *BzrSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfDeriveScalar(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfIntegrate(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BzrSrfMoebiusTransform(CagdSrfStruct *Srf,
				      CagdRType c,
				      CagdSrfDirType Dir);
CagdVecStruct *BzrSrfTangent(CagdSrfStruct *Srf,
			     CagdRType u,
			     CagdRType v,
			     CagdSrfDirType Dir,
			     CagdBType Normalize);
CagdVecStruct *BzrSrfNormal(CagdSrfStruct *Srf,
			    CagdRType u,
			    CagdRType v,
			    CagdBType Normalize);
CagdVecStruct *BzrSrfMeshNormals(CagdSrfStruct *Srf,
				 int UFineNess,
				 int VFineNess);
int BzrSrf2PolygonsSamples(CagdSrfStruct *Srf,
			   int FineNess,
			   CagdBType ComputeNormals,
			   CagdBType ComputeUV,
			   CagdRType **PtWeights,
			   CagdPtStruct **PtMesh,
			   CagdVecStruct **PtNrml,
			   CagdUVStruct **UVMesh,
			   int *FineNessU,
			   int *FineNessV);
int BzrSrf2PolygonsSamplesNuNv(CagdSrfStruct *Srf,
			       int Nu,
			       int Nv,
			       CagdBType ComputeNormals,
			       CagdBType ComputeUV,
			       CagdRType **PtWeights,
			       CagdPtStruct **PtMesh,
			       CagdVecStruct **PtNrml,
			       CagdUVStruct **UVMesh);
CagdPolygonStruct *BzrSrf2Polygons(CagdSrfStruct *Srf,
				   int FineNess,
				   CagdBType ComputeNormals,
				   CagdBType FourPerFlat,
				   CagdBType ComputeUV);
CagdPolygonStruct *BzrSrf2PolygonsN(CagdSrfStruct *Srf,
				    int Nu,
				    int Nv,
				    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 *BspKnotDiscontUniformOpen(int Len, int Order, CagdRType *KnotVector);
CagdEndConditionType BspIsKnotUniform(int Len,
				      int Order,
				      CagdRType *KnotVector);
CagdEndConditionType BspIsKnotDiscontUniform(int Len,
					     int Order,
					     CagdRType *KnotVector);
CagdRType *BspKnotDegreeRaisedKV(CagdRType *KV,
				 int Len,
				 int Order,
				 int NewOrder,
				 int *NewLen);
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 *BspKnotDoubleKnots(CagdRType *KnotVector, int *Len, int Order);
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 BspKnotScale(CagdRType *KnotVector, int Len, CagdRType Scale);
void BspKnotAffineTrans(CagdRType *KnotVector,
			int Len,
			CagdRType Translate,
			CagdRType Scale);
void BspKnotAffineTrans2(CagdRType *KnotVector,
			 int Len,
			 CagdRType MinVal,
			 CagdRType MaxVal);
void BspKnotAffineTrans3(CagdRType *KnotVector,
			 int Order,
			 int Len,
			 CagdRType MinVal,
			 CagdRType MaxVal);
void BspKnotAffineTransOrder(CagdRType *KnotVector,
			     int Order,
			     int Len,
			     CagdRType Translate,
			     CagdRType Scale);
void BspKnotAffineTransOrder2(CagdRType *KnotVector,
			      int Order,
			      int Len,
			      CagdRType MinVal,
			      CagdRType MaxVal);
CagdRType *BspKnotCopy(CagdRType *DstKV, CagdRType *SrcKV, int Len);
BspKnotAlphaCoeffStruct *BspKnotEvalAlphaCoef(int k,
					      CagdRType *KVT,
					      int LengthKVT,
					      CagdRType *KVt,
					      int LengthKVt,
					      int Periodic);
BspKnotAlphaCoeffStruct *BspKnotEvalAlphaCoefMerge(int k,
						   CagdRType *KVT,
						   int LengthKVT,
						   CagdRType *NewKV,
						   int LengthNewKV,
						   int Periodic);
BspKnotAlphaCoeffStruct *BspKnotCopyAlphaCoef(BspKnotAlphaCoeffStruct *A);
void BspKnotFreeAlphaCoef(BspKnotAlphaCoeffStruct *A);
void BspKnotAlphaLoopBlendNotPeriodic(BspKnotAlphaCoeffStruct *A,
				      int IMin,
				      int IMax,
				      CagdRType *OrigPts,
				      CagdRType *RefPts);
void BspKnotAlphaLoopBlendPeriodic(BspKnotAlphaCoeffStruct *A,
				   int IMin,
				   int IMax,
				   CagdRType *OrigPts,
				   int OrigLen,  
				   CagdRType *RefPts);
void BspKnotAlphaLoopBlendStep(BspKnotAlphaCoeffStruct *A,
			       int IMin,
			       int IMax,
			       CagdRType *OrigPts,
			       int OrigPtsStep,
			       int OrigLen,  
			       CagdRType *RefPts,
			       int RefPtsStep);
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 BspKnotC0Discont(CagdRType *KnotVector,
			   int Order,
			   int Length,
			   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);
int BspKnotMakeRobustKV(CagdRType *KV, int Len);
CagdBType BspKnotVectorsSame(CagdRType *KV1,
			     CagdRType *KV2,
			     int Len,
			     CagdRType Eps);
void BspKnotVerifyPeriodicKV(CagdRType *KV, int Order, int Len);
int BspKnotVerifyKVValidity(CagdRType *KV, int Order, int Len, CagdRType Tol);

/******************************************************************************
* 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,
				CagdBType Periodic,
				CagdRType t,
				int *IndexFirst);
int BspCrvCoxDeBoorIndexFirst(CagdRType *KnotVector,
			      int Order,
			      int Len,
			      CagdRType t);
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 *BspCrvCreateApproxSpiral(CagdRType NumOfLoops,
					CagdRType Pitch,
					int Sampling,
					int CtlPtsPerLoop);
CagdCrvStruct *BspCrvKnotInsert(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BspCrvKnotInsertNSame(CagdCrvStruct *Crv, CagdRType t, int n);
CagdCrvStruct *BspCrvKnotInsertNDiff(CagdCrvStruct *Crv,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
void BspCrvSubdivCtlPoly(CagdCrvStruct *Crv,
			 CagdRType **LPoints,
			 CagdRType **RPoints,
			 int LLength,
			 int RLength,
			 CagdRType t,
			 BspKnotAlphaCoeffStruct *A,
			 int Mult);
CagdCrvStruct *BspCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t);
CagdCrvStruct *BspCrvOpenEnd(CagdCrvStruct *Crv);
CagdBType BspCrvKnotC0Discont(CagdCrvStruct *Crv, CagdRType *t);
CagdBType BspCrvKnotC1Discont(CagdCrvStruct *Crv, CagdRType *t);
CagdBType BspCrvMeshC1Continuous(CagdCrvStruct *Crv, int Idx);
CagdCrvStruct *BspCrvDegreeRaise(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder);
CagdCrvStruct *BspCrvDerive(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvDeriveScalar(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvIntegrate(CagdCrvStruct *Crv);
CagdCrvStruct *BspCrvMoebiusTransform(CagdCrvStruct *Crv, CagdRType c);
CagdVecStruct *BspCrvTangent(CagdCrvStruct *Crv,
			     CagdRType t,
			     CagdBType Normalize);
CagdVecStruct *BspCrvBiNormal(CagdCrvStruct *Crv,
			      CagdRType t,
			      CagdBType Normalize);
CagdVecStruct *BspCrvNormal(CagdCrvStruct *Crv,
			    CagdRType t,
			    CagdBType Normalize);
CagdPolylineStruct *BspCrv2Polyline(CagdCrvStruct *Crv,
				    int SamplesPerCurve,
				    BspKnotAlphaCoeffStruct *A,
				    CagdBType OptiLin);
CagdCrvStruct *BspCrvInterpPts(CagdPtStruct *PtList,
			       int Order,
			       int CrvSize,
			       CagdParametrizationType ParamType,
			       CagdBType Periodic);
CagdCrvStruct *BspCrvInterpPts2(CagdCtlPtStruct *PtList,
				int Order,
				int CrvSize,
				CagdParametrizationType ParamType,
				CagdBType Periodic);
void BspCrvInterpBuildKVs(CagdCtlPtStruct *PtList,
			  int Order,
			  int CrvSize,
			  CagdParametrizationType ParamType,
			  CagdBType Periodic,
			  CagdRType **RetPtKnots,
			  CagdRType **RetKV);
CagdCrvStruct *BspCrvInterpolate(CagdCtlPtStruct *PtList,
				 int NumPts,
				 CagdRType *Params,
				 CagdRType *KV,
				 int Length,
				 int Order,
				 CagdBType Periodic);
CagdCrvStruct *BspCrvFitLstSqr(CagdCrvStruct *Crv,
			       int Order,
			       int Size, 
			       CagdParametrizationType ParamType,
			       CagdRType *Err);
CagdRType *BspPtSamplesToKV(CagdRType *PtsSamples,
			    int NumPts,
			    int CrvOrder,
			    int CrvLength);
CagdRType BspCrvInterpPtsError(CagdCrvStruct *Crv,
			       CagdPtStruct *PtList,
			       CagdParametrizationType ParamType,
			       CagdBType Periodic);
CagdCrvStruct *BspMakeReparamCurve(CagdPtStruct *PtsList,
				   int Order,
				   int DegOfFreedom);
CagdRType CagdLineFitToPts(CagdPtStruct *PtList,
			   CagdPType LineDir,
			   CagdVType LinePos);
void BspReparameterizeCrv(CagdCrvStruct *Crv,
			  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);
CagdRType *BspSrfEvalAtParam2(CagdSrfStruct *Srf, CagdRType u, CagdRType v);
CagdCrvStruct *BspSrfCrvFromSrf(CagdSrfStruct *Srf,
				CagdRType t,
				CagdSrfDirType Dir);
CagdCrvStruct *BspSrfC1DiscontCrvs(CagdSrfStruct *Srf);
CagdBType BspSrfIsC1DiscontAt(CagdSrfStruct *Srf,
			      CagdSrfDirType Dir,
			      CagdRType t);
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);
CagdBType BspSrfKnotC0Discont(CagdSrfStruct *Srf,
			      CagdSrfDirType Dir,
			      CagdRType *t);
CagdBType BspSrfKnotC1Discont(CagdSrfStruct *Srf,
			      CagdSrfDirType Dir,
			      CagdRType *t);
CagdBType BspSrfMeshC1Continuous(CagdSrfStruct *Srf,
				 CagdSrfDirType Dir,
				 int Idx);
CagdSrfStruct *BspSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BspSrfDegreeRaiseN(CagdSrfStruct *Srf,
				  int NewUOrder,
				  int NewVOrder);
CagdSrfStruct *BspSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BspSrfDeriveScalar(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BspSrfIntegrate(CagdSrfStruct *Srf, CagdSrfDirType Dir);
CagdSrfStruct *BspSrfMoebiusTransform(CagdSrfStruct *Srf,
				      CagdRType c,
				      CagdSrfDirType Dir);
CagdVecStruct *BspSrfTangent(CagdSrfStruct *Srf,
			     CagdRType u,
			     CagdRType v,
			     CagdSrfDirType Dir,
			     CagdBType Normalize);
CagdVecStruct *BspSrfNormal(CagdSrfStruct *Srf,
			    CagdRType u,
			    CagdRType v,
			    CagdBType Normalize);
CagdVecStruct *BspSrfMeshNormals(CagdSrfStruct *Srf,
				 int UFineNess,
				 int VFineNess);
CagdSrfErrorFuncType BspSrf2PolygonSetErrFunc(CagdSrfErrorFuncType Func);
CagdPolygonStruct *BspSrf2Polygons(CagdSrfStruct *Srf,
				   int FineNess,
				   CagdBType ComputeNormals,
				   CagdBType FourPerFlat,
				   CagdBType ComputeUV);
CagdPolygonStruct *BspSrf2PolygonsN(CagdSrfStruct *Srf,
				    int Nu,
				    int Nv,
				    CagdBType ComputeNormals,
				    CagdBType FourPerFlat,
				    CagdBType ComputeUV);
int BspSrf2PolygonsSamplesNuNv(CagdSrfStruct *Srf,
			       int Nu,
			       int Nv,
			       CagdBType ComputeNormals,
			       CagdBType ComputeUV,
			       CagdRType **PtWeights,
			       CagdPtStruct **PtMesh,
			       CagdVecStruct **PtNrml,
			       CagdUVStruct **UVMesh);
int BspC1Srf2PolygonsSamples(CagdSrfStruct *Srf,
			     int FineNess,
			     CagdBType ComputeNormals,
			     CagdBType ComputeUV,
			     CagdRType **PtWeights,
			     CagdPtStruct **PtMesh,
			     CagdVecStruct **PtNrml,
			     CagdUVStruct **UVMesh,
			     int *FineNessU,
			     int *FineNessV);
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);
CagdSrfStruct *BspSrfFitLstSqr(CagdSrfStruct *Srf,
			       int UOrder,
			       int VOrder,
			       int USize,
			       int VSize, 
			       CagdParametrizationType ParamType,
			       CagdRType *Err);
CagdSrfStruct *BspSrfInterpScatPts(CagdCtlPtStruct *PtList,
				   int UOrder,
				   int VOrder,
				   int USize,
				   int VSize,
				   CagdRType *UKV,
				   CagdRType *VKV);
CagdSrfStruct *BspSrfInterpScatPts2(CagdCtlPtStruct *PtList,
				    int UOrder,
				    int VOrder,
				    int USize,
				    int VSize,
				    CagdRType *UKV,
				    CagdRType *VKV,
				    CagdRType *MatrixCondition);
void BspReparameterizeSrf(CagdSrfStruct *Srf,
			  CagdSrfDirType Dir,
			  CagdParametrizationType ParamType);

/******************************************************************************
* Routines to construct primitive objects.				      *
******************************************************************************/
CagdSrfStruct *CagdPrimPlaneSrf(CagdRType MinX,
				CagdRType MinY,
				CagdRType MaxX,
				CagdRType MaxY,
				CagdRType ZLevel);
CagdSrfStruct *CagdPrimPlaneSrfOrderLen(CagdRType MinX,
					CagdRType MinY,
					CagdRType MaxX,
					CagdRType MaxY,
					CagdRType ZLevel,
					int Order,
					int Len);
CagdSrfStruct *CagdPrimSphereSrf(CagdVType Center,
				 CagdRType Radius,
				 CagdBType Rational);
CagdSrfStruct *CagdPrimTorusSrf(CagdVType Center,
				CagdRType MajorRadius,
				CagdRType MinorRadius,
				CagdBType Rational);
CagdSrfStruct *CagdPrimCone2Srf(CagdVType Center,
				CagdRType MajorRadius,
				CagdRType MinorRadius,
				CagdRType Height,
				CagdBType Rational,
				CagdPrimCapsType Caps);
CagdSrfStruct *CagdPrimConeSrf(CagdVType Center,
			       CagdRType Radius,
			       CagdRType Height,
			       CagdBType Rational,
			       CagdPrimCapsType Caps);
CagdSrfStruct *CagdPrimCylinderSrf(CagdVType Center,
				   CagdRType Radius,
				   CagdRType Height,
				   CagdBType Rational,
				   CagdPrimCapsType Caps);

/******************************************************************************
* 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);
CagdCrvStruct *CnvrtFloat2OpenCrv(CagdCrvStruct *Crv);
CagdCrvStruct *CnvrtBsp2OpenCrv(CagdCrvStruct *Crv);
CagdSrfStruct *CnvrtPeriodic2FloatSrf(CagdSrfStruct *Srf);
CagdSrfStruct *CnvrtFloat2OpenSrf(CagdSrfStruct *Srf);
CagdSrfStruct *CnvrtBsp2OpenSrf(CagdSrfStruct *Srf);

CagdCtlPtStruct *CnvrtCrvToCtlPts(CagdCrvStruct *Crv);

CagdCrvStruct *CnvrtPolyline2LinBsplineCrv(CagdPolylineStruct *Poly);
CagdPolylineStruct *CnvrtLinBsplineCrv2Polyline(CagdCrvStruct *Crv);

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

/******************************************************************************
* Routines to handle Bezier clipping based ray tracing.			      *
******************************************************************************/
CagdBType CagdRayTraceBzrSrf(CagdPType StPt,
                             CagdVType Dir,
                             CagdSrfStruct *BzrSrf,
                             CagdUVStruct **IntrPrm,
                             CagdPtStruct **IntrPt);

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

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

#endif /* CAGD_LIB_H */
