/******************************************************************************
* Trim_lib.h - header file for the TRIMmed surfaces library.		      *
* This header is also the interface header to the world.		      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Oct. 94.					      *
******************************************************************************/

#ifndef TRIM_LIB_H
#define TRIM_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 enum {
    TRIM_ERR_TRIM_CRV_E2 = 2000,
    TRIM_ERR_BZR_BSP_EXPECT,
    TRIM_ERR_DIR_NOT_CONST_UV,
    TRIM_ERR_ODD_NUM_OF_INTER,
    TRIM_ERR_TCRV_ORIENT,

    TRIM_ERR_UNDEFINE_ERR
} TrimFatalErrorType;

/******************************************************************************
* A trimmed surface can have trimming curves that either form a closed loop   *
* or start and end on the boundary of the surface. A trimming curve will be   *
* defined using a list of TrimCrvSegStruct, creating a closed loop or a       *
* curve that starts and ends in the boundary of the surface.		      *
*   Orientation of TrimCrvSegStruct should be such that the trimming curve    *
* tangent direction crossed with the surface normal points into the inside.   *
*   EucCrv can be either NULL where the Euclidean location must the be        *
* computed on the fly from parametric information or, if exist, must be       *
* used to prevent from black holes with adjacent surfaces.		      *
*   The trimming curves have no order what so ever.			      *
*   An outmost loop will always be present even if the entire four boundary   *
* curves are untrimmed.						 	      *
******************************************************************************/
typedef struct TrimCrvSegStruct {
    struct TrimCrvSegStruct *Pnext;
    IPAttributeStruct *Attr;
    CagdCrvStruct *UVCrv;    /* Trimming crv segment in srf's param. domain. */
    CagdCrvStruct *EucCrv;       /* Trimming curve as an E3 Euclidean curve. */
} TrimCrvSegStruct;

typedef struct TrimCrvStruct {
    struct TrimCrvStruct *Pnext;
    IPAttributeStruct *Attr;
    TrimCrvSegStruct *TrimCrvSegList;    /* List of trimming curve segments. */
} TrimCrvStruct;

typedef struct TrimSrfStruct {
    struct TrimSrfStruct *Pnext;
    IPAttributeStruct *Attr;
    int Tags;
    CagdSrfStruct *Srf;			  /* Surface trimmed by TrimCrvList. */
    TrimCrvStruct *TrimCrvList;		         /* List of trimming curves. */
} TrimSrfStruct;

/* Subdivision of trimmed surfaces may result in only one surface returned   */
/* as the other is completely trimmed away. This macros should be used to    */
/* define and identify the two parts.					     */
#define TRIM_IS_FIRST_SRF(Srf)		(((Srf) -> Tags & 0x01) == 0)
#define TRIM_IS_SECOND_SRF(Srf)		(((Srf) -> Tags & 0x01) == 1)
#define TRIM_SET_FIRST_SRF(Srf)		((Srf) -> Tags &= ~0x01)
#define TRIM_SET_SECOND_SRF(Srf)	((Srf) -> Tags |= 0x01)

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

TrimCrvSegStruct *TrimCrvSegNew(CagdCrvStruct *UVCrv, CagdCrvStruct *EucCrv);
TrimCrvSegStruct *TrimCrvSegCopy(TrimCrvSegStruct *TrimCrvSeg);
TrimCrvSegStruct *TrimCrvSegCopyList(TrimCrvSegStruct *TrimCrvSegList);
void TrimCrvSegFree(TrimCrvSegStruct *TrimCrvSeg);
void TrimCrvSegFreeList(TrimCrvSegStruct *TrimCrvSegList);

TrimCrvStruct *TrimCrvNew(TrimCrvSegStruct *TrimCrvSegList);
TrimCrvStruct *TrimCrvCopy(TrimCrvStruct *TrimCrv);
TrimCrvStruct *TrimCrvCopyList(TrimCrvStruct *TrimCrvList);
void TrimCrvFree(TrimCrvStruct *TrimCrv);
void TrimCrvFreeList(TrimCrvStruct *TrimCrvList);

TrimSrfStruct *TrimSrfNew(CagdSrfStruct *Srf,
			  TrimCrvStruct *TrimCrvList,
			  CagdBType HasTopLvlTrim);
TrimSrfStruct *TrimSrfNew2(CagdSrfStruct *Srf,
			   CagdCrvStruct *TrimCrvList,
			   CagdBType HasTopLvlTrim);
TrimSrfStruct *TrimSrfCopy(TrimSrfStruct *TrimSrf);
TrimSrfStruct *TrimSrfCopyList(TrimSrfStruct *TrimSrfList);
void TrimSrfFree(TrimSrfStruct *TrimSrf);
void TrimSrfFreeList(TrimSrfStruct *TrimSrfList);
void TrimSrfTransform(TrimSrfStruct *TrimSrf,
		      CagdRType *Translate,
		      CagdRType Scale);
void TrimSrfMatTransform(TrimSrfStruct *TrimSrf, CagdMType Mat);
CagdCrvStruct *TrimGetTrimmingCurves(TrimSrfStruct *TrimSrf,
				     CagdBType ParamSpace,
				     CagdBType EvalEuclid);
CagdPolylineStruct *TrimCrvs2Polylines(TrimSrfStruct *TrimSrf,
				       CagdBType ParamSpace,
				       int SamplesPerCurve,
				       int Optimal);
CagdCrvStruct *TrimEvalTrimCrvToEuclid(TrimSrfStruct *TrimSrf,
				       CagdCrvStruct *UVCrv);
int TrimSetEuclidComposedFromUV(int EuclidComposedFromUV);

TrimSrfStruct *TrimSrfDegreeRaise(TrimSrfStruct *TrimSrf, CagdSrfDirType Dir);
TrimSrfStruct *TrimSrfSubdivAtParam(TrimSrfStruct *TrimSrf,
				    CagdRType t,
				    CagdSrfDirType Dir);
TrimSrfStruct *TrimSrfRegionFromTrimSrf(TrimSrfStruct *TrimSrf,
					CagdRType t1,
					CagdRType t2,
					CagdSrfDirType Dir);
TrimSrfStruct *TrimSrfRefineAtParams(TrimSrfStruct *Srf,
				     CagdSrfDirType Dir,
				     CagdBType Replace,
				     CagdRType *t,
				     int n);
TrimSrfStruct *TrimSrfReverse(TrimSrfStruct *TrimSrf);
TrimSrfStruct *TrimSrfReverse2(TrimSrfStruct *TrimSrf);

void TrimSrfDomain(TrimSrfStruct *TrimSrf,
		   CagdRType *UMin,
		   CagdRType *UMax,
		   CagdRType *VMin,
		   CagdRType *VMax);
CagdRType *TrimSrfEval(TrimSrfStruct *TrimSrf, CagdRType u, CagdRType v);

CagdCrvStruct *TrimSrf2Curves(TrimSrfStruct *TrimSrf, int NumOfIsocurves[2]);
CagdPolylineStruct *TrimSrf2Polylines(TrimSrfStruct *TrimSrf,
				      int NumOfIsocurves[2],
				      int SamplesPerCurve,
				      int Optimal);
CagdPolygonStruct *TrimSrf2Polygons(TrimSrfStruct *TrimSrf,
				    int FineNess,
				    CagdBType ComputeNormals,
				    CagdBType ComputeUV);
int TrimSetTrimCrvLinearApprox(int UVSamplesPerCurve,
			       int UVSamplesOptimal);

char *TrimDescribeError(TrimFatalErrorType ErrorNum);
void TrimFatalError(TrimFatalErrorType ErrID);
void TrimDbg(void *Obj);

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

#endif /* TRIM_LIB_H */
