/******************************************************************************
* Trim_gen.c - generic routine to interface to different free from types.     *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, July. 90.					      *
******************************************************************************/

#include "trim_loc.h"

#define VEC_FIELD_TRIES	10
#define VEC_FIELD_START_STEP 1e-6

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates a trimming curve segment structure. Allows periodic and float    M
* end conditions - converts them to open end.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   UVCrv:     A UV curve. Must be an E2 curve.                              M
*   EucCrv:    Optional Euclidean curve. Must be an E3 curve.                M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvSegStruct *:   A trimming curve segment structure.                M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvSegNew, allocation                                                M
*****************************************************************************/
TrimCrvSegStruct *TrimCrvSegNew(CagdCrvStruct *UVCrv, CagdCrvStruct *EucCrv)
{
    TrimCrvSegStruct
	*TrimCrvSeg = (TrimCrvSegStruct *)
	    IritMalloc(sizeof(TrimCrvSegStruct));

    if (UVCrv != NULL && CAGD_IS_BSPLINE_CRV(UVCrv)) {
	if (!BspCrvHasOpenEC(UVCrv)) {   /* Must be open end trimming curve. */
	    CagdCrvStruct *TCrv;

	    if (CAGD_IS_PERIODIC_CRV(UVCrv)) {
		TCrv = CnvrtPeriodic2FloatCrv(UVCrv);
		CagdCrvFree(UVCrv);
		UVCrv = TCrv;
	    }
	    TCrv = CnvrtFloat2OpenCrv(UVCrv);
	    CagdCrvFree(UVCrv);
	    UVCrv = TCrv;
	}
    }
    if ((TrimCrvSeg -> UVCrv = UVCrv) != NULL)
	TrimCrvSeg -> UVCrv -> Pnext = NULL;

    if (EucCrv != NULL && CAGD_IS_BSPLINE_CRV(EucCrv)) {
	if (!BspCrvHasOpenEC(EucCrv)) {  /* Must be open end trimming curve. */
	    CagdCrvStruct *TCrv;

	    if (CAGD_IS_PERIODIC_CRV(EucCrv)) {
		TCrv = CnvrtPeriodic2FloatCrv(EucCrv);
		CagdCrvFree(EucCrv);
		EucCrv = TCrv;
	    }
	    TCrv = CnvrtFloat2OpenCrv(EucCrv);
	    CagdCrvFree(EucCrv);
	    EucCrv = TCrv;
	}
    }
    if ((TrimCrvSeg -> EucCrv = EucCrv) != NULL)
	TrimCrvSeg -> EucCrv -> Pnext = NULL;

    TrimCrvSeg -> Pnext = NULL;
    TrimCrvSeg -> Attr = NULL;

    return TrimCrvSeg;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a trimming curve segment structure.                             M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvSeg: A trimming curve segment to duplicate.			     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvSegStruct *:   A trimming curve segment structure.                M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvSegNew, allocation                                                M
*****************************************************************************/
TrimCrvSegStruct *TrimCrvSegCopy(TrimCrvSegStruct *TrimCrvSeg)
{
    TrimCrvSegStruct
	*NewTrimCrvSeg = (TrimCrvSegStruct *)
	    IritMalloc(sizeof(TrimCrvSegStruct));

    NewTrimCrvSeg -> UVCrv = CagdCrvCopy(TrimCrvSeg -> UVCrv);
    if (TrimCrvSeg -> EucCrv)
	NewTrimCrvSeg -> EucCrv = CagdCrvCopy(TrimCrvSeg -> EucCrv);
    else
	NewTrimCrvSeg -> EucCrv = NULL;
    NewTrimCrvSeg -> Pnext = NULL;
    NewTrimCrvSeg -> Attr = NULL;

    return NewTrimCrvSeg;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of trimming curve segment structures.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvSegList:   To be copied.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvSegStruct *:  A duplicated list of trimming curve segments.       M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvSegCopyList, copy                                                 M
*****************************************************************************/
TrimCrvSegStruct *TrimCrvSegCopyList(TrimCrvSegStruct *TrimCrvSegList)
{
    TrimCrvSegStruct *TrimCrvSegTemp, *NewTrimCrvSegList;

    if (TrimCrvSegList == NULL)
	return NULL;
    TrimCrvSegTemp = NewTrimCrvSegList = TrimCrvSegCopy(TrimCrvSegList);
    TrimCrvSegList = TrimCrvSegList -> Pnext;
    while (TrimCrvSegList) {
	TrimCrvSegTemp -> Pnext = TrimCrvSegCopy(TrimCrvSegList);
	TrimCrvSegTemp = TrimCrvSegTemp -> Pnext;
	TrimCrvSegList = TrimCrvSegList -> Pnext;
    }
    return NewTrimCrvSegList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a trimming curve segment structure.                            M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvSeg: A trimming curve segment to free.                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvSegFree, allocation                                               M
*****************************************************************************/
void TrimCrvSegFree(TrimCrvSegStruct *TrimCrvSeg)
{
    CagdCrvFree(TrimCrvSeg -> UVCrv);
    CagdCrvFree(TrimCrvSeg -> EucCrv);
    AttrFreeAttributes(&TrimCrvSeg -> Attr);
    IritFree((VoidPtr) TrimCrvSeg);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a list of trimming curve segment structures.                   M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvSegList: A list of trimming curve segments to free.               M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvSegFreeList, allocation                                           M
*****************************************************************************/
void TrimCrvSegFreeList(TrimCrvSegStruct *TrimCrvSegList)
{
    TrimCrvSegStruct *TrimCrvTemp;

    while (TrimCrvSegList) {
	TrimCrvTemp = TrimCrvSegList -> Pnext;
	TrimCrvSegFree(TrimCrvSegList);
	TrimCrvSegList = TrimCrvTemp;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates a trimming curve structure.                                      M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvSegList:    List of trimming curve segments forming the trimming  M
*                      curve.						     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvStruct *:   A trimmig curve.                                      M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvNew, allocation                                                   M
*****************************************************************************/
TrimCrvStruct *TrimCrvNew(TrimCrvSegStruct *TrimCrvSegList)
{
   TrimCrvStruct
	*TrimCrv = (TrimCrvStruct *)
	    IritMalloc(sizeof(TrimCrvStruct));

    TrimCrv -> TrimCrvSegList = TrimCrvSegList;
    TrimCrv -> Pnext = NULL;
    TrimCrv -> Attr = NULL;

    return TrimCrv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a trimming curve structure.	                             M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrv:   A trimming curve to duplicate.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvStruct *:   A trimming curve structure.		             M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvNew, allocation                                                   M
*****************************************************************************/
TrimCrvStruct *TrimCrvCopy(TrimCrvStruct *TrimCrv)
{
    TrimCrvStruct
	*NewTrimCrv = (TrimCrvStruct *)
	    IritMalloc(sizeof(TrimCrvStruct));

    NewTrimCrv -> TrimCrvSegList =
	TrimCrvSegCopyList(TrimCrv -> TrimCrvSegList);
    NewTrimCrv -> Pnext = NULL;
    NewTrimCrv -> Attr = NULL;

    return NewTrimCrv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of trimming curve structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvList:   To be copied.                                	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimCrvStruct *:  A duplicated list of trimming curves.		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvCopyList, copy                                                    M
*****************************************************************************/
TrimCrvStruct *TrimCrvCopyList(TrimCrvStruct *TrimCrvList)
{
    TrimCrvStruct *TrimCrvTemp, *NewTrimCrvList;

    if (TrimCrvList == NULL)
	return NULL;
    TrimCrvTemp = NewTrimCrvList = TrimCrvCopy(TrimCrvList);
    TrimCrvList = TrimCrvList -> Pnext;
    while (TrimCrvList) {
	TrimCrvTemp -> Pnext = TrimCrvCopy(TrimCrvList);
	TrimCrvTemp = TrimCrvTemp -> Pnext;
	TrimCrvList = TrimCrvList -> Pnext;
    }
    return NewTrimCrvList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a trimming curve structure.                                    M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrv: A trimming curve to free.                   	      	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvFree, allocation                                                  M
*****************************************************************************/
void TrimCrvFree(TrimCrvStruct *TrimCrv)
{
    TrimCrvSegFreeList(TrimCrv -> TrimCrvSegList);
    AttrFreeAttributes(&TrimCrv -> Attr);
    IritFree((VoidPtr) TrimCrv);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a list of trimming curve structures.	                     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimCrvList: A list of trimming curve to free.		             M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimCrvFreeList, allocation                     	                     M
*****************************************************************************/
void TrimCrvFreeList(TrimCrvStruct *TrimCrvList)
{
    TrimCrvStruct *TrimCrvTemp;

    while (TrimCrvList) {
	TrimCrvTemp = TrimCrvList -> Pnext;
	TrimCrvFree(TrimCrvList);
	TrimCrvList = TrimCrvTemp;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Constructor for a trimmed surface.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:             Surface to make into a trimmed surface.                 M
*   TrimCrvList:     A list of trimming curves.				     M
*   HasTopLvlTrim:   Do we have a top level outer most trimming curve?	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimSrfStruct *: The trimmed surface.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfNew, allocation,                                                  M
*****************************************************************************/
TrimSrfStruct *TrimSrfNew(CagdSrfStruct *Srf,
			  TrimCrvStruct *TrimCrvList,
			  CagdBType HasTopLvlTrim)
{
    CagdRType UMin, UMax, VMin, VMax;
    TrimSrfStruct
	*TrimSrf = (TrimSrfStruct *) IritMalloc(sizeof(TrimSrfStruct));

    CagdSrfDomain(Srf, &UMin, &UMax, &VMin, &VMax);

    TrimSrf -> Srf = Srf;
    TrimSrf -> Pnext = NULL;
    TrimSrf -> Attr = NULL;
    
    if (!HasTopLvlTrim) {
	CagdRType **Points;
	TrimCrvStruct *TrimCrv;
	CagdCrvStruct
	    *Crv = BspCrvNew(5, 2, CAGD_PT_E2_TYPE);

	BspKnotUniformOpen(5, 2, Crv -> KnotVector);
	Points = Crv -> Points;

	Points[1][0] = UMin;
	Points[2][0] = VMin;
	Points[1][1] = UMax;
	Points[2][1] = VMin;
	Points[1][2] = UMax;
	Points[2][2] = VMax;
	Points[1][3] = UMin;
	Points[2][3] = VMax;
	Points[1][4] = UMin;
	Points[2][4] = VMin;

	TrimCrv = TrimCrvNew(TrimCrvSegNew(Crv, NULL));

	TrimCrv -> Pnext = TrimCrvList;
	TrimSrf -> TrimCrvList = TrimCrv;
    }
    else
	TrimSrf -> TrimCrvList = TrimCrvList;

    return TrimSrf;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Constructor for a trimmed surface.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:             Surface to make into a trimmed surface.                 M
*   CagdCrvStruct:   A list of trimming curves, as regular curves.	     M
*   HasTopLvlTrim:   Do we have a top level outer most trimming curve?	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimSrfStruct *: The trimmed surface.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfNew2, allocation                                                  M
*****************************************************************************/
TrimSrfStruct *TrimSrfNew2(CagdSrfStruct *Srf,
			   CagdCrvStruct *TrimCrvList,
			   CagdBType HasTopLvlTrim)
{
    TrimCrvStruct
	*TrimCrvList2 = NULL;

    while (TrimCrvList) {
	CagdCrvStruct
	    *TrimCrvNext = TrimCrvList -> Pnext;
	TrimCrvStruct
	    *TrimCrv = TrimCrvNew(TrimCrvSegNew(TrimCrvList, NULL));

	TrimCrvList = TrimCrvNext;

	LIST_PUSH(TrimCrv, TrimCrvList2);
    }

    return TrimSrfNew(Srf, TrimCrvList2, HasTopLvlTrim);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a trimming surface structure.	                             M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrf:   A trimming surface to duplicate.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimSrfStruct *:   A trimming surface structure.		             M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfCopy, allocation                                                  M
*****************************************************************************/
TrimSrfStruct *TrimSrfCopy(TrimSrfStruct *TrimSrf)
{
    TrimSrfStruct
	*NewTrimSrf = (TrimSrfStruct *)
	    IritMalloc(sizeof(TrimSrfStruct));

    NewTrimSrf -> TrimCrvList =
	TrimCrvCopyList(TrimSrf -> TrimCrvList);
    NewTrimSrf -> Srf = CagdSrfCopy(TrimSrf -> Srf);
    NewTrimSrf -> Pnext = NULL;
    NewTrimSrf -> Attr = NULL;

    return NewTrimSrf;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of trimming surface structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrfList:   To be copied.                                	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrimSrfStruct *:  A duplicated list of trimming surfaces.		     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfCopyList, copy                                                    M
*****************************************************************************/
TrimSrfStruct *TrimSrfCopyList(TrimSrfStruct *TrimSrfList)
{
    TrimSrfStruct *TrimSrfTemp, *NewTrimSrfList;

    if (TrimSrfList == NULL)
	return NULL;
    TrimSrfTemp = NewTrimSrfList = TrimSrfCopy(TrimSrfList);
    TrimSrfList = TrimSrfList -> Pnext;
    while (TrimSrfList) {
	TrimSrfTemp -> Pnext = TrimSrfCopy(TrimSrfList);
	TrimSrfTemp = TrimSrfTemp -> Pnext;
	TrimSrfList = TrimSrfList -> Pnext;
    }
    return NewTrimSrfList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a trimmed surface structure.                                    M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrf: A trimmed surface to free.                   	      	     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfFree, allocation                                                  M
*****************************************************************************/
void TrimSrfFree(TrimSrfStruct *TrimSrf)
{
    TrimCrvFreeList(TrimSrf -> TrimCrvList);
    CagdSrfFree(TrimSrf -> Srf);
    AttrFreeAttributes(&TrimSrf -> Attr);
    IritFree((VoidPtr) TrimSrf);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a list of trimmed surface structures.	                     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrfList: A list of trimmed surface to free.		             M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfFreeList, allocation                     	                     M
*****************************************************************************/
void TrimSrfFreeList(TrimSrfStruct *TrimSrfList)
{
    TrimSrfStruct *TrimSrfTemp;

    while (TrimSrfList) {
	TrimSrfTemp = TrimSrfList -> Pnext;
	TrimSrfFree(TrimSrfList);
	TrimSrfList = TrimSrfTemp;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Linearly transforms, in place, given trimmed surface as specified by       M
* Translate and Scale.							     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrf:       Trimmed surface to transform.                             M
*   Translate:     Translation factor.                                       M
*   Scale:         Scaling factor.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfTransform		                                             M
*****************************************************************************/
void TrimSrfTransform(TrimSrfStruct *TrimSrf,
		      CagdRType *Translate,
		      CagdRType Scale)
{
    TrimCrvStruct
	*TrimCrvList = TrimSrf -> TrimCrvList;

    /* Transform the geometry. */
    CagdSrfTransform(TrimSrf -> Srf, Translate, Scale);

    /* And remove all Euclidean trimming curves. */
    for ( ; TrimCrvList != NULL; TrimCrvList = TrimCrvList -> Pnext) {
	TrimCrvSegStruct
	    *TrimCrvSegList = TrimCrvList -> TrimCrvSegList;

	for (;
	     TrimCrvSegList != NULL;
	     TrimCrvSegList = TrimCrvSegList -> Pnext) {
	    if (TrimCrvSegList -> EucCrv != NULL) {
		CagdCrvFree(TrimCrvSegList -> EucCrv);
		TrimCrvSegList -> EucCrv = NULL;
	    }
	}
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Transforms, in place, the given trimmed surface as specified by a	     M
* homogeneous matrix Mat.						     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrimSrf:       Trimmed surface to transform.                             M
*   Mat:           Homogeneous transformation to apply to trimmed surface.   M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrimSrfMatTransform, Trimmed surface                                     M
*****************************************************************************/
void TrimSrfMatTransform(TrimSrfStruct *TrimSrf, CagdMType Mat)
{
    TrimCrvStruct
	*TrimCrvList = TrimSrf -> TrimCrvList;

    /* Transform the geometry. */
    CagdSrfMatTransform(TrimSrf -> Srf, Mat);

    /* And remove all Euclidean trimming curves. */
    for ( ; TrimCrvList != NULL; TrimCrvList = TrimCrvList -> Pnext) {
	TrimCrvSegStruct
	    *TrimCrvSegList = TrimCrvList -> TrimCrvSegList;

	for (;
	     TrimCrvSegList != NULL;
	     TrimCrvSegList = TrimCrvSegList -> Pnext) {
	    if (TrimCrvSegList -> EucCrv != NULL) {
		CagdCrvFree(TrimCrvSegList -> EucCrv);
		TrimCrvSegList -> EucCrv = NULL;
	    }
	}
    }
}
