/******************************************************************************
* Triv_lib.h - header file for the TRIV library.			      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* Written by Gershon Elber, Sep. 94.					      *
******************************************************************************/

#ifndef TRIV_LIB_H
#define TRIV_LIB_H

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

typedef CagdRType TrivPType[4];
typedef CagdRType TrivVType[4];
typedef CagdRType TrivUVWType[3];
typedef CagdRType TrivPlaneType[5];

typedef enum {
    TRIV_ERR_DIR_NOT_VALID,
    TRIV_ERR_UNDEF_CRV,
    TRIV_ERR_UNDEF_SRF,
    TRIV_ERR_UNDEF_TRIVAR,
    TRIV_ERR_UNDEF_GEOM,
    TRIV_ERR_RATIONAL_NO_SUPPORT,
    TRIV_ERR_WRONG_ORDER,
    TRIV_ERR_KNOT_NOT_ORDERED,
    TRIV_ERR_NUM_KNOT_MISMATCH,
    TRIV_ERR_INDEX_NOT_IN_MESH,
    TRIV_ERR_POWER_NO_SUPPORT,
    TRIV_ERR_WRONG_DOMAIN,
    TRIV_ERR_DIR_NOT_CONST_UVW,
    TRIV_ERR_SCALAR_PT_EXPECTED,
    TRIV_ERR_NO_CLOSED_POLYGON,
    TRIV_ERR_TWO_INTERSECTIONS,
    TRIV_ERR_NO_MATCH_PAIR,
    TRIV_ERR_2_OR_4_INTERS,
    TRIV_ERR_FAIL_FIND_PT,

    TRIV_ERR_UNDEFINE_ERR
} TrivFatalErrorType;

typedef enum {
    TRIV_UNDEF_TYPE = 1220,
    TRIV_TVBEZIER_TYPE,
    TRIV_TVBSPLINE_TYPE
} TrivGeomType;

typedef enum {
    TRIV_NO_DIR = CAGD_NO_DIR,
    TRIV_CONST_U_DIR = CAGD_CONST_U_DIR,
    TRIV_CONST_V_DIR = CAGD_CONST_V_DIR,
    TRIV_CONST_W_DIR,
    TRIV_END_DIR
} TrivTVDirType;
#define TRIV_PREV_DIR(Dir) (((int) Dir) + 1 > ((int) TRIV_CONST_W_DIR) ? \
			TRIV_CONST_U_DIR : (TrivTVDirType) ((int) Dir) + 1)
#define TRIV_NEXT_DIR(Dir) (((int) Dir) - 1 < ((int) TRIV_CONST_U_DIR) ? \
			TRIV_CONST_W_DIR : (TrivTVDirType) ((int) Dir) - 1)

typedef struct TrivTriangleStruct {
    struct TrivTriangleStruct *Pnext;
    struct IPAttributeStruct *Attr;
    struct {
	CagdPType Pt;
	CagdVType Nrml;
	TrivUVWType UVW;
    } T[3];
} TrivTriangleStruct;

typedef struct TrivTVStruct {
    struct TrivTVStruct *Pnext;
    struct IPAttributeStruct *Attr;
    TrivGeomType GType;
    CagdPointType PType;
    int ULength, VLength, WLength;/* Mesh size in tri-variate tensor product.*/
    int UVPlane;	  /* Should equal ULength * VLength for fast access. */
    int UOrder, VOrder, WOrder;       /* Order in trivariate (Bspline only). */
    CagdBType UPeriodic, VPeriodic, WPeriodic;    /* Valid only for Bspline. */
    CagdRType *Points[CAGD_MAX_PT_SIZE];     /* Pointer on each axis vector. */
    CagdRType *UKnotVector, *VKnotVector, *WKnotVector;
} TrivTVStruct;

#define TRIV_IS_BEZIER_TV(TV)		(TV -> GType == TRIV_TVBEZIER_TYPE)
#define TRIV_IS_BSPLINE_TV(TV)		(TV -> GType == TRIV_TVBSPLINE_TYPE)

#define TRIV_IS_RATIONAL_TV(TV)		CAGD_IS_RATIONAL_PT(TV -> PType)

/******************************************************************************
*           +-----------------------+					      *
*       W  /                       /|					      *
*      /  /                       / |					      *
*     /  /	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|  /	    Once a full UV plane is complete  *
*	|			| /	W is incremented by 1.		      *
*	|Pn-i		    Pn-1|/          To encapsulate it, NEXTU/V/W are  *
*	+-----------------------+	defined below.			      *
******************************************************************************/
#define TRIV_NEXT_U(TV)			(1)
#define TRIV_NEXT_V(TV)			(TV -> ULength)
#define TRIV_NEXT_W(TV)			(TV -> UVPlane)
#define TRIV_MESH_UVW(TV, i, j, k)	((i) + (TV -> ULength) * (j) + (TV -> UVPlane) * (k))

/* If a trivariate 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 TRIV_TV_UPT_LST_LEN(TV)	((TV) -> ULength + \
				 ((TV) -> UPeriodic ? (TV) -> UOrder - 1 : 0))
#define TRIV_TV_VPT_LST_LEN(TV)	((TV) -> VLength + \
				 ((TV) -> VPeriodic ? (TV) -> VOrder - 1 : 0))
#define TRIV_TV_WPT_LST_LEN(TV)	((TV) -> WLength + \
				 ((TV) -> WPeriodic ? (TV) -> WOrder - 1 : 0))
#define TRIV_IS_UPERIODIC_TV(TV)	((TV) -> UPeriodic)
#define TRIV_IS_VPERIODIC_TV(TV)	((TV) -> VPeriodic)
#define TRIV_IS_WPERIODIC_TV(TV)	((TV) -> WPeriodic)
#define TRIV_IS_PERIODIC_TV(TV)	(CAGD_IS_UPERIODIC_TV(TV) || \
				 CAGD_IS_VPERIODIC_TV(TV) || \
				 CAGD_IS_WPERIODIC_TV(TV))

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

/******************************************************************************
* General routines of the Triv library:					      *
******************************************************************************/
TrivTVStruct *TrivTVNew(TrivGeomType GType,
			CagdPointType PType,
			int ULength,
			int VLength,
			int WLength);
TrivTVStruct *TrivBspTVNew(int ULength,
			   int VLength,
			   int WLength,
			   int UOrder,
			   int VOrder,
			   int WOrder,
			   CagdPointType PType);
TrivTVStruct *TrivBzrTVNew(int ULength,
			   int VLength,
			   int WLength,
			   CagdPointType PType);
TrivTVStruct *TrivTVCopy(TrivTVStruct *TV);
TrivTVStruct *TrivTVCopyList(TrivTVStruct *TVList);
void TrivTVFree(TrivTVStruct *TV);
void TrivTVFreeList(TrivTVStruct *TVList);

TrivTriangleStruct *TrivTriangleNew(void);
TrivTriangleStruct *TrivTriangleCopy(TrivTriangleStruct *Triangle);
TrivTriangleStruct *TrivTriangleCopyList(TrivTriangleStruct *TriangleList);
void TrivTriangleFree(TrivTriangleStruct *Triangle);
void TrivTriangleFreeList(TrivTriangleStruct *TriangleList);

TrivTVStruct *TrivCnvrtBezier2BsplineTV(TrivTVStruct *TV);

void TrivTVTransform(TrivTVStruct *TV, CagdRType *Translate, CagdRType Scale);
void TrivTVMatTransform(TrivTVStruct *TV, CagdMType Mat);

TrivTVStruct *TrivCoerceTVTo(TrivTVStruct *TV, CagdPointType PType);

void TrivTVDomain(TrivTVStruct *TV,
		  CagdRType *UMin,
		  CagdRType *UMax,
		  CagdRType *VMin,
		  CagdRType *VMax,
		  CagdRType *WMin,
		  CagdRType *WMax);
CagdBType TrivParamInDomain(TrivTVStruct *TV,
			    CagdRType t,
			    TrivTVDirType Dir);
CagdBType TrivParamsInDomain(TrivTVStruct *TV,
			     CagdRType u,
			     CagdRType v,
			     CagdRType w);

CagdRType *TrivTVEval(TrivTVStruct *TV,
		      CagdRType u,
		      CagdRType v,
		      CagdRType w);
CagdRType *TrivTVEval2(TrivTVStruct *TV,
		       CagdRType u,
		       CagdRType v,
		       CagdRType w);
CagdSrfStruct *TrivSrfFromTV(TrivTVStruct *TV,
			     CagdRType t,
			     TrivTVDirType Dir);
CagdSrfStruct *TrivSrfFromMesh(TrivTVStruct *TV,
			       int Index,
			       TrivTVDirType Dir);
void TrivSrfToMesh(CagdSrfStruct *Srf,
		   int Index,
		   TrivTVDirType Dir,
		   TrivTVStruct *TV);
TrivTVStruct *TrivTVRegionFromTV(TrivTVStruct *TV,
				 CagdRType t1,
				 CagdRType t2,
				 TrivTVDirType Dir);
TrivTVStruct *TrivTVRefineAtParams(TrivTVStruct *TV,
				   TrivTVDirType Dir,
				   CagdBType Replace,
				   CagdRType *t,
				   int n);
TrivTVStruct *TrivBspTVKnotInsertNDiff(TrivTVStruct *TV,
				       TrivTVDirType Dir,
				       int Replace,
				       CagdRType *t,
				       int n);
TrivTVStruct *TrivTVDerive(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivBzrTVDerive(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivBspTVDerive(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivTVDerive(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivTVSubdivAtParam(TrivTVStruct *TV,
				  CagdRType t,
				  TrivTVDirType Dir);
TrivTVStruct *TrivTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivBspTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir);
TrivTVStruct *TrivBzrTVDegreeRaise(TrivTVStruct *TV, TrivTVDirType Dir);
CagdBType TrivMakeTVsCompatible(TrivTVStruct **TV1,
				TrivTVStruct **TV2,
				CagdBType SameUOrder,
				CagdBType SameVOrder,
				CagdBType SameWOrder,
				CagdBType SameUKV,
				CagdBType SameVKV,
				CagdBType SameWKV);
void TrivTVBBox(TrivTVStruct *Trivar, CagdBBoxStruct *BBox);
void TrivTVListBBox(TrivTVStruct *TVs, CagdBBoxStruct *BBox);
CagdPolylineStruct *TrivTV2CtrlMesh(TrivTVStruct *Trivar);
TrivTVStruct *TrivInterpTrivar(TrivTVStruct *TV);
TrivTVStruct *TrivTVFromSrfs(CagdSrfStruct *SrfList, int OtherOrder);

void TrivDbg(void *Obj);

/******************************************************************************
* Error handling.							      *
******************************************************************************/
void TrivFatalError(TrivFatalErrorType ErrID);
char *TrivDescribeError(TrivFatalErrorType ErrID);

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

#endif /* TRIV_LIB_H */
