/******************************************************************************
* MVar_lib.h - header file for the multi variate library.		      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, May. 96.					      *
******************************************************************************/

#ifndef MVAR_LIB_H
#define MVAR_LIB_H

#include <stdio.h>
#include "irit_sm.h"
#include "miscattr.h"
#include "misc_lib.h"
#include "cagd_lib.h"
#include "symb_lib.h"

typedef enum {
    MVAR_ERR_DIR_NOT_VALID,
    MVAR_ERR_UNDEF_CRV,
    MVAR_ERR_UNDEF_SRF,
    MVAR_ERR_UNDEF_MVAR,
    MVAR_ERR_UNDEF_GEOM,
    MVAR_ERR_GEOM_NO_SUPPORT,
    MVAR_ERR_RATIONAL_NO_SUPPORT,
    MVAR_ERR_RATIONAL_EXPECTED,
    MVAR_ERR_WRONG_ORDER,
    MVAR_ERR_KNOT_NOT_ORDERED,
    MVAR_ERR_NUM_KNOT_MISMATCH,
    MVAR_ERR_INDEX_NOT_IN_MESH,
    MVAR_ERR_POWER_NO_SUPPORT,
    MVAR_ERR_WRONG_DOMAIN,
    MVAR_ERR_INCONS_DOMAIN,
    MVAR_ERR_SCALAR_PT_EXPECTED,
    MVAR_ERR_INVALID_AXIS,
    MVAR_ERR_NO_CLOSED_POLYGON,
    MVAR_ERR_TWO_INTERSECTIONS,
    MVAR_ERR_NO_MATCH_PAIR,
    MVAR_ERR_FAIL_READ_FILE,
    MVAR_ERR_INVALID_STROKE_TYPE,
    MVAR_ERR_READ_FAIL,
    MVAR_ERR_MVS_INCOMPATIBLE,
    MVAR_ERR_PT_OR_LEN_MISMATCH,
    MVAR_ERR_TOO_FEW_PARAMS,
    MVAR_ERR_TOO_MANY_PARAMS,
    MVAR_ERR_FAIL_CMPT,
    MVAR_ERR_NO_CROSS_PROD,
    MVAR_ERR_BEZIER_EXPECTED,
    MVAR_ERR_BSPLINE_EXPECTED,
    MVAR_ERR_SAME_GTYPE_EXPECTED,
    MVAR_ERR_ONE_OR_THREE_EXPECTED,
    MVAR_ERR_POWER_EXPECTED,
    MVAR_ERR_MSC_TOO_FEW_OBJ,
    MVAR_ERR_MSC_FAILED,
    MVAR_ERR_SCALAR_EXPECTED,
    MVAR_ERR_DIM_TOO_HIGH,
    MVAR_ERR_INVALID_MV,

    MVAR_ERR_UNDEFINE_ERR
} MvarFatalErrorType;

typedef enum {
    MVAR_UNDEF_TYPE = 1240,
    MVAR_BEZIER_TYPE,
    MVAR_BSPLINE_TYPE,
    MVAR_POWER_TYPE
} MvarGeomType;

typedef enum {
    MVAR_CNSTRNT_ZERO = 1320,
    MVAR_CNSTRNT_POSITIVE,
    MVAR_CNSTRNT_NEGATIVE
} MvarConstraintType;

typedef int MvarMVDirType;

#define MVAR_PREV_DIR(Dir) ((Dir) + 1)
#define MVAR_NEXT_DIR(Dir) ((Dir) - 1)

typedef struct MvarPtStruct {
    struct MvarPtStruct *Pnext;
    struct IPAttributeStruct *Attr;
    int Dim;				     /* Number of coordinates in Pt. */
    CagdRType *Pt;	       /* The coordinates of the multivariate point. */
} MvarPtStruct;

typedef struct MvarPolyStruct {			    /* A polyline structure. */
    struct MvarPolyStruct *Pnext;
    struct IPAttributeStruct *Attr;
    MvarPtStruct *Pl;
} MvarPolyStruct;

typedef struct MvarVecStruct {
    struct MvarVecStruct *Pnext;
    struct IPAttributeStruct *Attr;
    int Dim;				    /* Number of coordinates in Vec. */
    CagdRType *Vec;	      /* The coordinates of the multivariate vector. */
} MvarVecStruct;

typedef struct MvarPlaneStruct {
    struct MvarPlaneStruct *Pnext;
    struct IPAttributeStruct *Attr;
    int Dim;    /* Number of coordinates in Pln (one above space dimension). */
    CagdRType *Pln;	       /* The coordinates of the multivariate plane. */
} MvarPlaneStruct;

typedef struct MvarNormalConeStruct {        /* Normalized cone axis vector. */
    struct MvarNormalConeStruct *Pnext;
    struct IPAttributeStruct *Attr;
    MvarVecStruct *ConeAxis;
    CagdRType ConeAngleCosine;
} MvarNormalConeStruct;

typedef struct MvarMVStruct {
    struct MvarMVStruct *Pnext;
    struct IPAttributeStruct *Attr;
    MvarGeomType GType;
    CagdPointType PType;
    int Dim;		      /* Number of dimensions in this multi variate. */
    int *Lengths;               /* Dimensions of mesh size in multi-variate. */
    int *SubSpaces;	   /* SubSpaces[i] = Prod(i = 0, i-1) of Lengths[i]. */
    int *Orders;                  /* Orders of multi variate (Bspline only). */
    CagdBType *Periodic;            /* Periodicity - valid only for Bspline. */
    CagdRType *Points[CAGD_MAX_PT_SIZE];     /* Pointer on each axis vector. */
    CagdRType **KnotVectors;
    VoidPtr PAux;			        /* Auxiliary data structure. */
    VoidPtr PAux2;			        /* Auxiliary data structure. */
} MvarMVStruct;

typedef struct MvarMVGradientStruct {
    int Dim;
    CagdBType IsRational;
    MvarMVStruct *MV;			       /* The original multivariate. */
    MvarMVStruct *MVGrad;		    /* The gradient if not rational. */
    MvarMVStruct *MVRGrad[CAGD_MAX_PT_COORD + 1];  /* The grad. if rational. */
} MvarMVGradientStruct;

typedef enum {
    MVAR_SK2D_PRIM_POINT,
    MVAR_SK2D_PRIM_LINE,
    MVAR_SK2D_PRIM_ARC,
    MVAR_SK2D_PRIM_CRV
} MvarSkel2DPrimType;

typedef struct MvarSkel2DPrimPointStruct {
    CagdPType Pt;
} MvarSkel2DPrimPointStruct;

typedef struct MvarSkel2DPrimLineStruct {
    CagdPType Pt1, Pt2;
} MvarSkel2DPrimLineStruct;

typedef struct MvarSkel2DPrimArcStruct {
    CagdPType Center;
    RealType StartAngle, EndAngle, Radius;
} MvarSkel2DPrimArcStruct;

typedef struct MvarSkel2DPrimCrvStruct {
    CagdCrvStruct *Crv;
} MvarSkel2DPrimCrvStruct;

typedef struct MvarSkel2DPrimStruct {
    struct MvarSkel2DPrimStruct *Pnext;
    struct IPAttributeStruct *Attr;
    MvarSkel2DPrimType Type;
    union {
        MvarSkel2DPrimPointStruct Pt;
        MvarSkel2DPrimLineStruct Ln;
        MvarSkel2DPrimArcStruct Arc;
        MvarSkel2DPrimCrvStruct Crv;
    } U;
    int _Index;
    CagdCrvStruct *_CrvRep;
} MvarSkel2DPrimStruct;

typedef struct MvarSkel2DInter3PrimsStruct {
    struct MvarSkel2DInter3PrimsStruct *Pnext;
    struct IPAttributeStruct *Attr;
    CagdPType PosPrim1, PosPrim2, PosPrim3;
    CagdPType EquadistPoint;
} MvarSkel2DInter3PrimsStruct;

#define MVAR_MALLOC_STRUCT_ONCE     /* Faster allocation of MVAR structures. */

#define MVAR_IS_BEZIER_MV(MV)		((MV) -> GType == MVAR_BEZIER_TYPE)
#define MVAR_IS_POWER_MV(MV)		((MV) -> GType == MVAR_POWER_TYPE)
#define MVAR_IS_BSPLINE_MV(MV)		((MV) -> GType == MVAR_BSPLINE_TYPE)

#define MVAR_IS_RATIONAL_MV(MV)		CAGD_IS_RATIONAL_PT((MV) -> PType)
#define MVAR_NUM_OF_PT_COORD(MV)	CAGD_NUM_OF_PT_COORD((MV) -> PType)
#define MVAR_MAKE_PT_TYPE(IsRational, NumCoords) \
				    CAGD_MAKE_PT_TYPE(IsRational, NumCoords)

#define MVAR_CTL_MESH_LENGTH(MV)	((MV) -> SubSpaces[(MV) -> Dim])

/******************************************************************************
*  Provides easy access to multivariates up to dimension six.		      *
******************************************************************************/
#define MVAR_NEXT_U(MV)			(1)         /* == MV -> SubSpaces[0] */
#define MVAR_NEXT_V(MV)			((MV) -> SubSpaces[1])
#define MVAR_NEXT_W(MV)			((MV) -> SubSpaces[2])
#define MVAR_NEXT_FOURTH(MV)		((MV) -> SubSpaces[3])
#define MVAR_NEXT_FIFTH(MV)		((MV) -> SubSpaces[4])
#define MVAR_NEXT_SIXTH(MV)		((MV) -> SubSpaces[5])
#define MVAR_NEXT_DIM(MV, Dim)		((MV) -> SubSpaces[(Dim)])

#define MVAR_MESH_UV(MV, i, j)		((i) + \
					 ((MV) -> SubSpaces[1]) * (j))
#define MVAR_MESH_UVW(MV, i, j, k)	((i) + \
					 ((MV) -> SubSpaces[1]) * (j) + \
					 ((MV) -> SubSpaces[2]) * (k))
#define MVAR_MESH_UVW4(MV, i, j, k, l)  ((i) + \
					 ((MV) -> SubSpaces[1]) * (j) + \
					 ((MV) -> SubSpaces[2]) * (k) + \
					 ((MV) -> SubSpaces[3]) * (l))
#define MVAR_MESH_UVW45(MV, i, j, k, l, m) \
					((i) + \
					 ((MV) -> SubSpaces[1]) * (j) + \
					 ((MV) -> SubSpaces[2]) * (k) + \
					 ((MV) -> SubSpaces[3]) * (l) + \
					 ((MV) -> SubSpaces[4]) * (m))
#define MVAR_MESH_UVW456(MV, i, j, k, l, m, n) \
					((i) + \
					 ((MV) -> SubSpaces[1]) * (j) + \
					 ((MV) -> SubSpaces[2]) * (k) + \
					 ((MV) -> SubSpaces[3]) * (l) + \
					 ((MV) -> SubSpaces[4]) * (m) + \
					 ((MV) -> SubSpaces[5]) * (n))

/* If a mvarariate is periodic, the 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 MVAR_MVAR_UPT_LST_LEN(MV)	((MV) -> Lengths[0] + \
			 ((MV) -> Periodic[0] ? (MV) -> Orders[0] - 1 : 0))
#define MVAR_MVAR_VPT_LST_LEN(MV)	((MV) -> Lengths[1] + \
			 ((MV) -> Periodic[1] ? (MV) -> Orders[1] - 1 : 0))
#define MVAR_MVAR_WPT_LST_LEN(MV)	((MV) -> Lengths[2] + \
			 ((MV) -> Periodic[2] ? (MV) -> Orders[2] - 1 : 0))
#define MVAR_MVAR_FOURTH_PT_LST_LEN(MV)	((MV) -> Lengths[3] + \
			 ((MV) -> Periodic[3] ? (MV) -> Orders[3] - 1 : 0))
#define MVAR_MVAR_FIFTH_PT_LST_LEN(MV)	((MV) -> Lengths[4] + \
			 ((MV) -> Periodic[4] ? (MV) -> Orders[4] - 1 : 0))
#define MVAR_MVAR_SIXTH_PT_LST_LEN(MV)	((MV) -> Lengths[5] + \
			 ((MV) -> Periodic[5] ? (MV) -> Orders[5] - 1 : 0))
#define MVAR_MVAR_ITH_PT_LST_LEN(MV, i)	((MV) -> Lengths[i] + \
			 ((MV) -> Periodic[i] ? (MV) -> Orders[i] - 1 : 0))

#define MVAR_IS_UPERIODIC_MVAR(MV)	((MV) -> Periodic[0])
#define MVAR_IS_VPERIODIC_MVAR(MV)	((MV) -> Periodic[1])
#define MVAR_IS_WPERIODIC_MVAR(MV)	((MV) -> Periodic[2])
#define MVAR_IS_FOURTH_PERIODIC_MVAR(MV) ((MV) -> Periodic[3])
#define MVAR_IS_FIFTH_PERIODIC_MVAR(MV) ((MV) -> Periodic[4])
#define MVAR_IS_SIXTH_PERIODIC_MVAR(MV) ((MV) -> Periodic[5])
#define MVAR_IS_ITH_PERIODIC_MVAR(MV, i) ((MV) -> Periodic[i])

/* Ease the handling of the splitting of a multivariate to scalar fields. */
#define MVAR_CLEAR_SCALARS(MV) { \
	int ii; \
	for (ii = 0; ii < CAGD_MAX_PT_SIZE; ii++) \
	    (MV)[ii] = NULL; \
    } 
#define MVAR_FREE_SCALARS(MV) { \
        int ii; \
        if ((MV)[0] != NULL) \
	    MvarMVFree((MV)[0]); \
	for (ii = 1; ii <= CAGD_MAX_PT_COORD; ii++) { \
	    if ((MV)[ii] == NULL) \
	        break; \
	    MvarMVFree((MV)[ii]); \
	} \
    }
#define MVAR_SPLIT_SCALARS(MV, MVScalar) \
	    CAGD_GEN_COPY((MVScalar), MvarMVSplitScalar(MV), \
			  sizeof(MvarMVStruct *) * CAGD_MAX_PT_SIZE);

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

/******************************************************************************
* General routines of the Mvar library:					      *
******************************************************************************/
MvarMVStruct *MvarMVNew(int Dim,
			MvarGeomType GType,
			CagdPointType PType,
			int *Lengths);
MvarMVStruct *MvarBspMVNew(int Dim,
			   int *Lengths,
			   int *Orders,
			   CagdPointType PType);
MvarMVStruct *MvarBzrMVNew(int Dim, int *Lengths, CagdPointType PType);
MvarMVStruct *MvarPwrMVNew(int Dim, int *Lengths, CagdPointType PType);
MvarMVStruct *MvarMVCopy(MvarMVStruct *MV);
MvarMVStruct *MvarMVCopyList(MvarMVStruct *MVList);
void MvarMVFree(MvarMVStruct *MV);
void MvarMVFreeList(MvarMVStruct *MVList);

#ifdef DEBUG
#define MvarMVFree(MV)         { MvarMVFree(MV); MV = NULL; }
#define MvarMVFreeList(MVList) { MvarMVFreeList(MVList); MVList = NULL; }
#endif /* DEBUG */

MvarPtStruct *MvarPtNew(int Dim);
MvarPtStruct *MvarPtRealloc(MvarPtStruct *Pt, int NewDim);
MvarPtStruct *MvarPtCopy(MvarPtStruct *Pt);
MvarPtStruct *MvarPtCopyList(MvarPtStruct *PtList);
void MvarPtFree(MvarPtStruct *Pt);
void MvarPtFreeList(MvarPtStruct *PtList);

#ifdef DEBUG
#define MvarPtFree(Pt)         { MvarPtFree(Pt); Pt = NULL; }
#define MvarPtFreeList(PtList) { MvarPtFreeList(PtList); PtList = NULL; }
#endif /* DEBUG */

MvarPtStruct *MvarPolyReverseList(MvarPtStruct *Pts);

MvarPolyStruct *MvarPolyNew(MvarPtStruct *Pl);
MvarPolyStruct *MvarPolyCopy(MvarPolyStruct *Poly);
MvarPolyStruct *MvarPolyCopyList(MvarPolyStruct *PolyList);
void MvarPolyFree(MvarPolyStruct *Poly);
void MvarPolyFreeList(MvarPolyStruct *PolyList);

#ifdef DEBUG
#define MvarPolyFree(Poly)         { MvarPolyFree(Poly); Poly = NULL; }
#define MvarPolyFreeList(PolyList) { MvarPolyFreeList(PolyList); \
				     PolyList = NULL; }
#endif /* DEBUG */

MvarVecStruct *MvarVecNew(int Dim);
MvarVecStruct *MvarVecRealloc(MvarVecStruct *Vec, int NewDim);
MvarVecStruct *MvarVecCopy(MvarVecStruct *Vec);
MvarVecStruct *MvarVecCopyList(MvarVecStruct *VecList);
void MvarVecFree(MvarVecStruct *Vec);
void MvarVecFreeList(MvarVecStruct *VecList);
  void MvarVecAdd(MvarVecStruct *VRes, MvarVecStruct *V1, MvarVecStruct *V2);
CagdRType MvarVecDotProd(MvarVecStruct *V1, MvarVecStruct *V2);
CagdRType MvarVecSqrLength(MvarVecStruct *V);
CagdRType MvarVecLength(MvarVecStruct *V);
void MvarVecScale(MvarVecStruct *V, CagdRType ScaleFactor);
int MvarVecNormalize(MvarVecStruct *V);

#ifdef DEBUG
#define MvarVecFree(Vec)         { MvarVecFree(Vec); Vec = NULL; }
#define MvarVecFreeList(VecList) { MvarVecFreeList(VecList); VecList = NULL; }
#endif /* DEBUG */

MvarPlaneStruct *MvarPlaneNew(int Dim);
MvarPlaneStruct *MvarPlaneCopy(MvarPlaneStruct *Plane);
MvarPlaneStruct *MvarPlaneCopyList(MvarPlaneStruct *PlaneList);
void MvarPlaneFree(MvarPlaneStruct *Plane);
void MvarPlaneFreeList(MvarPlaneStruct *PlaneList);

#ifdef DEBUG
#define MvarPlaneFree(Plane)         { MvarPlaneFree(Plane); Plane = NULL; }
#define MvarPlaneFreeList(PlaneList) { MvarPlaneFreeList(PlaneList); \
				       PlaneList = NULL; }
#endif /* DEBUG */

MvarNormalConeStruct *MvarNormalConeNew(int Dim);
void MvarNormalConeFree(MvarNormalConeStruct *NormalCone);
void MvarNormalConeFreeList(MvarNormalConeStruct *NormalConeList);

#ifdef DEBUG
#define MvarConeFree(Cone)         { MvarConeFree(Cone); PCone = NULL; }
#endif /* DEBUG */

MvarPtStruct *MvarGetLastPt(MvarPtStruct *Pts);
int MvarPtCmpTwoPoints(MvarPtStruct *P1, MvarPtStruct *P2, CagdRType Eps);
CagdRType MvarPtDistTwoPoints(MvarPtStruct *P1, MvarPtStruct *P2);
CagdRType MvarPtDistSqrTwoPoints(MvarPtStruct *P1, MvarPtStruct *P2);
MvarPolyStruct *MvarPolyMergePolylines(MvarPolyStruct *Polys, RealType Eps);
MvarPolyStruct *MvarMatchPointListIntoPolylines(MvarPtStruct *PtsList,
						RealType MaxTol);

MvarMVStruct *MvarCnvrtBezier2BsplineMV(MvarMVStruct *MV);
MvarMVStruct *MvarCnvrtBspline2BezierMV(MvarMVStruct *MV);
MvarMVStruct *MvarCnvrtPower2BezierMV(MvarMVStruct *MV);
MvarMVStruct *MvarCnvrtBezier2PowerMV(MvarMVStruct *MV);

void MvarMVTransform(MvarMVStruct *MV, CagdRType *Translate, CagdRType Scale);
void MvarMVMatTransform(MvarMVStruct *MV, CagdMType Mat);

MvarMVStruct *MvarCoerceMVTo(MvarMVStruct *MV, CagdPointType PType);

void MvarMVDomain(MvarMVStruct *MV, CagdRType *Min, CagdRType *Max, int Axis);
CagdBType MvarParamInDomain(MvarMVStruct *MV,
			    CagdRType t,
			    MvarMVDirType Dir);
CagdBType MvarParamsInDomain(MvarMVStruct *MV, CagdRType *Params);

CagdRType *MvarMVEval(MvarMVStruct *MV, CagdRType *Params);
CagdRType *MvarMVEvalGradient2(MvarMVStruct *MV, CagdRType *Params);
MvarPlaneStruct *MvarMVEvalTanPlane(MvarMVStruct *MV, CagdRType *Params);

MvarMVStruct *MvarMVFromMV(MvarMVStruct *MV, CagdRType t, MvarMVDirType Dir);
MvarMVStruct *MvarMVFromMesh(MvarMVStruct *MV, int Index, MvarMVDirType Dir);
MvarMVStruct *MvarCrvToMV(CagdCrvStruct *Crv);
CagdCrvStruct *MvarMVToCrv(MvarMVStruct *MV);
MvarMVStruct *MvarSrfToMV(CagdSrfStruct *Srf);
CagdSrfStruct *MvarMVToSrf(MvarMVStruct *MV);
MvarMVStruct *MvarTVToMV(TrivTVStruct *TV);
TrivTVStruct *MvarMVToTV(MvarMVStruct *MV);

MvarMVStruct *MvarMVRegionFromMV(MvarMVStruct *MV,
				 CagdRType t1,
				 CagdRType t2,
				 MvarMVDirType Dir);
MvarMVStruct *MvarMVRefineAtParams(MvarMVStruct *MV,
				   MvarMVDirType Dir,
				   CagdBType Replace,
				   CagdRType *t,
				   int n);
MvarMVStruct *MvarBspMVKnotInsertNDiff(MvarMVStruct *MV,
				       MvarMVDirType Dir,
				       int Replace,
				       CagdRType *t,
				       int n);
MvarMVStruct *MvarMVDerive(MvarMVStruct *MV, MvarMVDirType Dir);
MvarMVStruct *MvarBzrMVDerive(MvarMVStruct *MV, MvarMVDirType Dir);
MvarMVStruct *MvarBspMVDerive(MvarMVStruct *MV, MvarMVDirType Dir);
MvarMVGradientStruct *MvarMVPrepGradient(MvarMVStruct *MV);
void MvarMVFreeGradient(MvarMVGradientStruct *MV);
CagdRType *MvarMVEvalGradient(MvarMVGradientStruct *MV, CagdRType *Params);
MvarMVStruct *MvarMVSubdivAtParam(MvarMVStruct *MV,
				  CagdRType t,
				  MvarMVDirType Dir);
MvarMVStruct *MvarBspMVSubdivAtParam(MvarMVStruct *MV,
				     CagdRType t,
				     MvarMVDirType Dir);
MvarMVStruct *MvarBzrMVSubdivAtParam(MvarMVStruct *MV,
				     CagdRType t,
				     MvarMVDirType Dir);
MvarMVStruct *MvarMVDegreeRaise(MvarMVStruct *MV, MvarMVDirType Dir);
MvarMVStruct *MvarMVDegreeRaiseN(MvarMVStruct *MV, int *NewOrders);
MvarMVStruct *MvarMVPwrDegreeRaise(MvarMVStruct *MV, int Dir, int IncOrder);
CagdBType MvarMakeMVsCompatible(MvarMVStruct **MV1,
				MvarMVStruct **MV2,
				CagdBType SameOrders,
				CagdBType SameKVs);
void MvarMVBBox(MvarMVStruct *MV, CagdBBoxStruct *BBox);
void MvarMVListBBox(MvarMVStruct *MVs, CagdBBoxStruct *BBox);
int MvarIncrementMeshIndices(MvarMVStruct *MV, int *Indices);
int MvarIncrementMeshIndices2(MvarMVStruct *MV, int *Indices, int *Index);
int MvarIncSkipMeshIndices(MvarMVStruct *MV, int *Indices, int Dir);
int MvarIncSkipMeshIndices2(MvarMVStruct *MV,
			    int *Indices,
			    int Dir,
			    int *Index);
int MvarIncBoundMeshIndices(MvarMVStruct *MV,
			    int *Indices,
			    int *LowerBound,
			    int *UpperBound);
int MvarIncBoundMeshIndices2(MvarMVStruct *MV,
			     int *Indices,
			     int *LowerBound,
			     int *UpperBound,
			     int *Index);
int MvarGetPointsMeshIndices(MvarMVStruct *MV, int *Indices);
int MvarMeshIndicesFromIndex(int Index, MvarMVStruct *MV, int *Indices);

MvarMVStruct *MvarEditSingleMVPt(MvarMVStruct *MV,
				 CagdCtlPtStruct *CtlPt,
				 int *Indices,
				 CagdBType Write);
CagdBType MvarMVsSame(MvarMVStruct *MV1, MvarMVStruct *MV2, CagdRType Eps);
MvarMVStruct *MvarPromoteMVToMV(MvarMVStruct *MV, int Axis);
MvarMVStruct *MvarPromoteMVToMV2(MvarMVStruct *MV, int NewDim, int StartAxis);
MvarMVStruct *MvarMVShiftAxes(MvarMVStruct *MV, int Axis);
MvarMVStruct *MvarMVReverse(MvarMVStruct *MV, int Axis1, int Axis2);
MvarMVStruct *MvarMergeMVMV(MvarMVStruct *MV1,
			    MvarMVStruct *MV2,
			    MvarMVDirType Dir,
			    CagdBType Discont);

CagdBType MvarBspMVIsOpenInDir(MvarMVStruct *MV, MvarMVDirType Dir);
CagdBType MvarBspMVIsOpen(MvarMVStruct *MV);
CagdBType MvarBspMVIsPeriodicInDir(MvarMVStruct *MV, MvarMVDirType Dir);
CagdBType MvarBspMVIsPeriodic(MvarMVStruct *MV);

void MvarDbg(void *Obj);

/******************************************************************************
* Symbolic computation over multivariates.				      *
******************************************************************************/
MvarMVStruct *MvarMVAdd(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVSub(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVMult(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVInvert(MvarMVStruct *MV);
MvarMVStruct *MvarMVScalarScale(MvarMVStruct *MV, CagdRType Scale);
MvarMVStruct *MvarMVMultScalar(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVDotProd(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVVecDotProd(MvarMVStruct *MV, CagdRType *Vec);
MvarMVStruct *MvarMVCrossProd(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarMVRtnlMult(MvarMVStruct *MV1X,
			     MvarMVStruct *MV1W,
			     MvarMVStruct *MV2X,
			     MvarMVStruct *MV2W,
			     CagdBType OperationAdd);
MvarMVStruct **MvarMVSplitScalar(MvarMVStruct *MV);
MvarMVStruct *MvarMVMergeScalar(MvarMVStruct **ScalarMVs);

int MvarBspMultInterpFlag(int BspMultUsingInter);

MvarMVStruct *MvarBzrMVMult(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarBspMVMult(MvarMVStruct *MV1, MvarMVStruct *MV2);

MvarMVStruct *MvarMVDeterminant2(MvarMVStruct *MV11,
				 MvarMVStruct *MV12,
				 MvarMVStruct *MV21,
				 MvarMVStruct *MV22);
MvarMVStruct *MvarMVDeterminant3(MvarMVStruct *MV11,
				 MvarMVStruct *MV12,
				 MvarMVStruct *MV13,
				 MvarMVStruct *MV21,
				 MvarMVStruct *MV22,
				 MvarMVStruct *MV23,
				 MvarMVStruct *MV31,
				 MvarMVStruct *MV32,
				 MvarMVStruct *MV33);
MvarMVStruct *MvarMVDeterminant4(MvarMVStruct *MV11,
				 MvarMVStruct *MV12,
				 MvarMVStruct *MV13,
				 MvarMVStruct *MV14,
				 MvarMVStruct *MV21,
				 MvarMVStruct *MV22,
				 MvarMVStruct *MV23,
				 MvarMVStruct *MV24,
				 MvarMVStruct *MV31,
				 MvarMVStruct *MV32,
				 MvarMVStruct *MV33,
				 MvarMVStruct *MV34,
				 MvarMVStruct *MV41,
				 MvarMVStruct *MV42,
				 MvarMVStruct *MV43,
				 MvarMVStruct *MV44);
MvarMVStruct *MvarMVDeterminant5(MvarMVStruct *MV11,
				 MvarMVStruct *MV12,
				 MvarMVStruct *MV13,
				 MvarMVStruct *MV14,
				 MvarMVStruct *MV15,
				 MvarMVStruct *MV21,
				 MvarMVStruct *MV22,
				 MvarMVStruct *MV23,
				 MvarMVStruct *MV24,
				 MvarMVStruct *MV25,
				 MvarMVStruct *MV31,
				 MvarMVStruct *MV32,
				 MvarMVStruct *MV33,
				 MvarMVStruct *MV34,
				 MvarMVStruct *MV35,
				 MvarMVStruct *MV41,
				 MvarMVStruct *MV42,
				 MvarMVStruct *MV43,
				 MvarMVStruct *MV44,
				 MvarMVStruct *MV45,
				 MvarMVStruct *MV51,
				 MvarMVStruct *MV52,
				 MvarMVStruct *MV53,
				 MvarMVStruct *MV54,
				 MvarMVStruct *MV55);
MvarPtStruct *MvarMVsZeros(MvarMVStruct **MVs,
			   MvarConstraintType *Constraints,
			   int NumOfMVs,
			   CagdRType SubdivTol,
			   CagdRType NumericTol);
int MvarMVsZerosNormalConeTest(int NormalConeTest);
CagdCtlPtStruct *MvarMVZeroOneSubdiv(MvarMVStruct *MV,
				     CagdRType NumericTolerance);
MvarNormalConeStruct *MVarMVNormalCone(MvarMVStruct *MV);
CagdBType MvarMVConesOverlap(MvarMVStruct **MVs, int NumOfZeroMVs);

/******************************************************************************
* Bisectors of multivariates.						      *
******************************************************************************/
MvarMVStruct *MvarMVsBisector(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarCrvSrfBisector(MvarMVStruct *MV1, MvarMVStruct *MV2);
MvarMVStruct *MvarSrfSrfBisector(MvarMVStruct *MV1, MvarMVStruct *MV2);
VoidPtr MvarCrvSrfBisectorApprox(MvarMVStruct *MV1,
				 MvarMVStruct *MV2,
				 int OutputType,
				 CagdRType SubdivTol,
				 CagdRType NumericTol);
VoidPtr MvarSrfSrfBisectorApprox(MvarMVStruct *MV1,
				 MvarMVStruct *MV2,
				 int OutputType,
				 CagdRType SubdivTol,
				 CagdRType NumericTol);

/******************************************************************************
* Voronoi cell computation						      *
******************************************************************************/
struct IPObjectStruct *MvarComputeVoronoiCell(CagdCrvStruct *Crv);
CagdCrvStruct *MvarBsctTrimCrvPt(CagdCrvStruct *Crv, 
				 CagdRType *Pt, 
				 CagdRType Alpha,
				 CagdCrvStruct *BaseCrv);

/******************************************************************************
* Bitangents/Tritangents.    						      *
******************************************************************************/
MvarPtStruct *MvarMVBiTangents(MvarMVStruct *MV1,
			       MvarMVStruct *MV2,
			       int Orientation,
			       CagdRType SubdivTol,
			       CagdRType NumericTol);
MvarPtStruct *MvarMVBiTangents2(MvarMVStruct *MV1,
				MvarMVStruct *MV2,
				CagdRType SubdivTol,
				CagdRType NumericTol);
MvarPtStruct *MvarMVTriTangents(MvarMVStruct *MV1,
				MvarMVStruct *MV2,
				MvarMVStruct *MV3,
				int Orientation,
				CagdRType SubdivTol,
				CagdRType NumericTol);

/******************************************************************************
 * Kernel and related analysis of curves.				      *
******************************************************************************/
MvarMVStruct *MVarCrvKernel(CagdCrvStruct *Crv);
MvarMVStruct *MVarCrvGammaKernel(CagdCrvStruct *Crv, CagdRType Gamma);
MvarMVStruct *MVarCrvGammaKernelSrf(CagdCrvStruct *Crv,
				    CagdRType ExtentScale,
				    CagdRType GammaMax);
struct IPObjectStruct *MVarCrvKernelSilhouette(CagdCrvStruct *Crv,
					       CagdRType Gamma,
					       CagdRType SubEps,
					       CagdRType NumEps);
struct IPObjectStruct *MVarCrvDiameter(CagdCrvStruct *Crv,
				       CagdRType SubEps,
				       CagdRType NumEps);

/******************************************************************************
* Distances between manifolds as multivariates.				      *
******************************************************************************/
CagdRType *MvarDistSrfPoint(CagdSrfStruct *Srf,
			    CagdPType Pt,
			    CagdBType MinDist,
			    CagdRType SubdivTol,
			    CagdRType NumericTol);
MvarPtStruct *MvarLclDistSrfPoint(CagdSrfStruct *Srf,
				  CagdPType Pt,
				  CagdRType SubdivTol,
				  CagdRType NumericTol);
CagdRType *MvarDistSrfLine(CagdSrfStruct *Srf,
			   CagdPType LnPt,
			   CagdVType LnDir,
			   CagdBType MinDist,
			   CagdRType SubdivTol,
			   CagdRType NumericTol);
MvarPtStruct *MvarLclDistSrfLine(CagdSrfStruct *Srf,
				 CagdPType LnPt,
				 CagdVType LnDir,
				 CagdRType SubdivTol,
				 CagdRType NumericTol);
MvarMVStruct *MvarMVDistCrvSrf(CagdCrvStruct *Crv1,
			       CagdSrfStruct *Srf2,
			       int DistType);
MvarMVStruct *MvarMVDistSrfSrf(CagdSrfStruct *Srf1,
			       CagdSrfStruct *Srf2,
			       int DistType);

/******************************************************************************
* Metamorphosis of multivariates.					      *
******************************************************************************/
MvarMVStruct *MvarTwoMVsMorphing(MvarMVStruct *MV1,
				 MvarMVStruct *MV2,
				 CagdRType Blend);

/******************************************************************************
* Light ray traps between n curves.					      *
******************************************************************************/
MvarPtStruct *MvarComputeRayTraps(CagdCrvStruct *Crvs,
				  CagdRType SubdivTol,
				  CagdRType NumerTol);

/******************************************************************************
* Surface/Check surface accessibility analysis.				      *
******************************************************************************/
MvarPtStruct *MvarSrfAccessibility(CagdSrfStruct *PosSrf,
				   CagdSrfStruct *OrientSrf,
				   CagdSrfStruct *CheckSrf,
				   CagdRType *AccessDir,
				   CagdRType SubdivTol,
				   CagdRType NumerTol);
MvarPtStruct *MvarSrfSilhInflections(CagdSrfStruct *Srf,
				     CagdVType ViewDir,
				     CagdRType SubdivTol,
				     CagdRType NumerTol);
MvarPtStruct *MvarSrfFlecnodalCrvs(CagdSrfStruct *Srf,
				   CagdRType SubdivTol,
				   CagdRType NumerTol);
MvarPtStruct *MvarSrfFlecnodalPts(CagdSrfStruct *Srf,
				  CagdRType SubdivTol,
				  CagdRType NumerTol);
MvarMVStruct *MVarProjNrmlPrmt2MVScl(CagdSrfStruct *Srf,
				     CagdSrfStruct *NrmlSrf,
				     MvarMVStruct *MVScl);

/******************************************************************************
* Freeform curvature analysis.						      *
******************************************************************************/
MvarPtStruct *MvarSrfRadialCurvature(CagdSrfStruct *Srf,
				     CagdVType ViewDir,
				     CagdRType SubdivTol,
				     CagdRType NumerTol);

/******************************************************************************
* Freeform topology analysis.						      *
******************************************************************************/
MvarPtStruct *MvarImplicitCrvExtreme(CagdSrfStruct *Srf,
				     CagdSrfDirType Dir,
				     CagdRType SubdivTol,
				     CagdRType NumerTol);

/******************************************************************************
* Routines to handle the computation of 2D skeletons and minimum spanning     *
* circles.								      *
******************************************************************************/
CagdRType MvarSkel2DSetEpsilon(CagdRType NewEps);
CagdRType MvarSkel2DSetFineNess(CagdRType NewFineNess);
CagdRType MvarSkel2DSetOuterExtent(CagdRType NewOutExtent);
MvarSkel2DInter3PrimsStruct *MvarSkel2DInter3Prims(MvarSkel2DPrimStruct *Prim1,
						  MvarSkel2DPrimStruct *Prim2,
						  MvarSkel2DPrimStruct *Prim3);
void MvarSkel2DInter3PrimsFree(MvarSkel2DInter3PrimsStruct *SK2DInt);
void MvarSkel2DInter3PrimsFreeList(MvarSkel2DInter3PrimsStruct *SK2DIntList);

int MvarMSCircOfTwoCurves(CagdCrvStruct *Crv1,
			  CagdCrvStruct *Crv2,
			  CagdRType Center[2],
			  CagdRType *Radius,
			  CagdRType SubdivTol,
			  CagdRType NumerTol);
int MvarMSCircOfThreeCurves(CagdCrvStruct *Crv1,
			    CagdCrvStruct *Crv2,
			    CagdCrvStruct *Crv3,
			    CagdRType Center[2],
			    CagdRType *Radius,
			    CagdRType SubdivTol,
			    CagdRType NumerTol);
int MVarIsCurveInsideCirc(CagdCrvStruct *Crv,
			  CagdRType Center[2],
			  CagdRType Radius,
			  CagdRType Tolerance);
int MvarMinSpanCirc(struct IPObjectStruct *Objs,
		    CagdRType *Center,
		    CagdRType *Radius,
		    CagdRType SubdivTol,
		    CagdRType NumerTol);

/******************************************************************************
* Routines to handle basis function conversions.			      *
******************************************************************************/
MvarMVStruct *MvarCnvrtPeriodic2FloatMV(MvarMVStruct *MV);
MvarMVStruct *MvarCnvrtFloat2OpenMV(MvarMVStruct *MV);

/******************************************************************************
* Error handling.							      *
******************************************************************************/
void MvarFatalError(MvarFatalErrorType ErrID);
char *MvarDescribeError(MvarFatalErrorType ErrID);

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

#endif /* MVAR_LIB_H */
