/******************************************************************************
* Triv_gen.c - General routines used by all modules of TRIV_lib.	      *
*******************************************************************************
* Written by Gershon Elber, sep. 94.					      *
******************************************************************************/

#include <string.h>
#include "triv_loc.h"
#include "geomat3d.h"
#include "miscattr.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates the memory required for a new trivariate.                        M
*                                                                            *
* PARAMETERS:                                                                M
*   GType:      Type of geometry the curve should be - Bspline, Bezier etc.  M
*   PType:      Type of control points (E2, P3, etc.).                       M
*   ULength:    Number of control points in the U direction.                 M
*   VLength:    Number of control points in the V direction.                 M
*   WLength:    Number of control points in the W direction.                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:    An uninitialized freeform trivariate.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVNew, trivariates, allocation                                       M
*****************************************************************************/
TrivTVStruct *TrivTVNew(TrivGeomType GType,
			CagdPointType PType,
			int ULength,
			int VLength,
			int WLength)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(PType);
    TrivTVStruct
	*NewTV = (TrivTVStruct *) IritMalloc(sizeof(TrivTVStruct));

    NewTV -> GType = GType;
    NewTV -> PType = PType;
    NewTV -> ULength = ULength;
    NewTV -> VLength = VLength;
    NewTV -> WLength = WLength;
    NewTV -> UVPlane = ULength * VLength;
    NewTV -> UOrder = 0;
    NewTV -> VOrder = 0;
    NewTV -> WOrder = 0;
    NewTV -> UKnotVector = NULL;
    NewTV -> VKnotVector = NULL;
    NewTV -> WKnotVector = NULL;
    NewTV -> Pnext = NULL;
    NewTV -> Attr = NULL;
    NewTV -> Points[0] = NULL;			    /* The rational element. */

    for (i = !CAGD_IS_RATIONAL_PT(PType); i <= MaxAxis; i++)
	NewTV -> Points[i] = (CagdRType *) IritMalloc(sizeof(CagdRType) *
						ULength * VLength * WLength);

    for (i = MaxAxis + 1; i <= CAGD_MAX_PT_COORD; i++)
	NewTV -> Points[i] = NULL;

    return NewTV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates the memory required for a new Bspline trivariate.                M
*                                                                            *
* PARAMETERS:                                                                M
*   ULength:    Number of control points in the U direction.                 M
*   VLength:    Number of control points in the V direction.                 M
*   WLength:    Number of control points in the W direction.                 M
*   UOrder:     Order of trivariate in the U direction.			     M
*   VOrder:     Order of trivariate in the V direction.			     M
*   WOrder:     Order of trivariate in the W direction.			     M
*   PType:      Type of control points (E2, P3, etc.).                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:    An uninitialized freeform trivariate Bspline.         M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBspNew, trivariates, allocation                                      M
*****************************************************************************/
TrivTVStruct *TrivBspTVNew(int ULength, 
			   int VLength,
			   int WLength,
			   int UOrder,
			   int VOrder,
			   int WOrder,
			   CagdPointType PType)
{
    TrivTVStruct *TV;

    if (ULength < UOrder || VLength < VOrder || WLength < WOrder) {
	TRIV_FATAL_ERROR(TRIV_ERR_WRONG_ORDER);
	return NULL;
    }

    TV = TrivTVNew(TRIV_TVBSPLINE_TYPE, PType, ULength, VLength, WLength);

    TV -> UKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
                                                           (UOrder + ULength));
    TV -> VKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
                                                           (VOrder + VLength));
    TV -> WKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
                                                           (WOrder + WLength));

    TV -> UOrder = UOrder;
    TV -> VOrder = VOrder;
    TV -> WOrder = WOrder;

    return TV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates the memory required for a new Bezier trivariate.                 M
*                                                                            *
* PARAMETERS:                                                                M
*   ULength:    Number of control points in the U direction.                 M
*   VLength:    Number of control points in the V direction.                 M
*   WLength:    Number of control points in the W direction.                 M
*   PType:      Type of control points (E2, P3, etc.).                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:    An uninitialized freeform trivariate Bezier.          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBzrNew, trivariates, allocation                                      M
*****************************************************************************/
TrivTVStruct *TrivBzrTVNew(int ULength,
			   int VLength,
			   int WLength,
			   CagdPointType PType)
{
    TrivTVStruct
	*TV = TrivTVNew(TRIV_TVBEZIER_TYPE, PType, ULength, VLength, WLength);

    TV -> UOrder = TV -> ULength = ULength;
    TV -> VOrder = TV -> VLength = VLength;
    TV -> WOrder = TV -> WLength = WLength;

    TV -> UKnotVector = TV -> VKnotVector = TV -> WKnotVector = NULL;

    return TV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and duplicates all slots of a trivariate structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TV:        Trivariate to duplicate                                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:    Duplicated trivariate.                                M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVCopy, trivariates                                                  M
*****************************************************************************/
TrivTVStruct *TrivTVCopy(TrivTVStruct *TV)
{
    int i, Len,
	MaxAxis = CAGD_NUM_OF_PT_COORD(TV -> PType);
    TrivTVStruct
	*NewTV = (TrivTVStruct *) IritMalloc(sizeof(TrivTVStruct));

    NewTV -> GType = TV -> GType;
    NewTV -> PType = TV -> PType;
    NewTV -> ULength = TV -> ULength;
    NewTV -> VLength = TV -> VLength;
    NewTV -> WLength = TV -> WLength;
    NewTV -> UVPlane = NewTV -> ULength * NewTV -> VLength;
    NewTV -> UOrder = TV -> UOrder;
    NewTV -> VOrder = TV -> VOrder;
    NewTV -> WOrder = TV -> WOrder;
    if (TV -> UKnotVector != NULL)
	NewTV -> UKnotVector = BspKnotCopy(TV -> UKnotVector,
					   TV -> ULength + TV -> UOrder);
    else
	NewTV -> UKnotVector = NULL;
    if (TV -> VKnotVector != NULL)
	NewTV -> VKnotVector = BspKnotCopy(TV -> VKnotVector,
					   TV -> VLength + TV -> VOrder);
    else
	NewTV -> VKnotVector = NULL;
    if (TV -> WKnotVector != NULL)
	NewTV -> WKnotVector = BspKnotCopy(TV -> WKnotVector,
					   TV -> WLength + TV -> WOrder);
    else
	NewTV -> WKnotVector = NULL;
    NewTV -> Pnext = NULL;
    NewTV -> Attr = NULL;
    NewTV -> Points[0] = NULL;			    /* The rational element. */

    Len = TV -> ULength * TV -> VLength * TV -> WLength;
    for (i = !TRIV_IS_RATIONAL_TV(TV); i <= MaxAxis; i++) {
	NewTV -> Points[i] = (CagdRType *) IritMalloc(sizeof(CagdRType) * Len);
	CAGD_GEN_COPY(NewTV -> Points[i], TV -> Points[i],
		      sizeof(CagdRType) * Len);
    }

    for (i = MaxAxis + 1; i <= CAGD_MAX_PT_COORD; i++)
	NewTV -> Points[i] = NULL;

    return NewTV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a list of trivariate structures.			 	     M
*                                                                            *
* PARAMETERS:                                                                M
*   TVList:    List of trivariates to duplicate.                             M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:  Duplicated list of trivariates.                         M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVCopyList, trivariates                                              M
*****************************************************************************/
TrivTVStruct *TrivTVCopyList(TrivTVStruct *TVList)
{
    TrivTVStruct *TVTemp, *NewTVList;

    if (TVList == NULL)
	return NULL;
    TVTemp = NewTVList = TrivTVCopy(TVList);
    TVList = TVList -> Pnext;
    while (TVList) {
	TVTemp -> Pnext = TrivTVCopy(TVList);
	TVTemp = TVTemp -> Pnext;
	TVList = TVList -> Pnext;
    }
    return NewTVList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates and frees all slots of a trivariate structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TV:         Trivariate to free.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVFree, trivariates                                                  M
*****************************************************************************/
void TrivTVFree(TrivTVStruct *TV)
{
    int i, MaxAxis;

    if (TV == NULL)
	return;

    MaxAxis = CAGD_NUM_OF_PT_COORD(TV -> PType);

    for (i = !TRIV_IS_RATIONAL_TV(TV); i <= MaxAxis; i++)
	IritFree((VoidPtr) TV -> Points[i]);

    if (TV -> UKnotVector != NULL)
	IritFree((VoidPtr) TV -> UKnotVector);
    if (TV -> VKnotVector != NULL)
	IritFree((VoidPtr) TV -> VKnotVector);
    if (TV -> WKnotVector != NULL)
	IritFree((VoidPtr) TV -> WKnotVector);

    AttrFreeAttributes(&TV -> Attr);
    IritFree((VoidPtr) TV);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates and frees a list of trivariate structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TVList:    Trivariate list to free.                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVFreeList, trivariates                                              M
*****************************************************************************/
void TrivTVFreeList(TrivTVStruct *TVList)
{
    TrivTVStruct *TVTemp;

    while (TVList) {
	TVTemp = TVList -> Pnext;
	TrivTVFree(TVList);
	TVList = TVTemp;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates the memory required for a new triangle.                          M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTriangleStruct *:  An uninitialized triangle.                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTriangleNew, allocation                                              M
*****************************************************************************/
TrivTriangleStruct *TrivTriangleNew(void)
{
    TrivTriangleStruct
	*NewTri = (TrivTriangleStruct *)
				IritMalloc(sizeof(TrivTriangleStruct));

    NewTri -> Pnext = NULL;
    NewTri -> Attr = NULL;

    return NewTri;    
}
/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and duplicates all slots of a triangle structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   TrivTriangleStruct *:  Triangle to duplicate.                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTriangleStruct *:  Duplicated triangle.                              M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTriangleCopy                                                         M
*****************************************************************************/
TrivTriangleStruct *TrivTriangleCopy(TrivTriangleStruct *Triangle)
{
    TrivTriangleStruct
	*NewTri = (TrivTriangleStruct *)
				IritMalloc(sizeof(TrivTriangleStruct));

    GEN_COPY(NewTri, Triangle, sizeof(TrivTriangleStruct));

    NewTri -> Pnext = NULL;
    NewTri -> Attr = NULL;

    return NewTri;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a list of triangle structures.			 	     M
*                                                                            *
* PARAMETERS:                                                                M
*   TriangleList:    List of triangle to duplicate.			     M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTriangleStruct *:  Duplicated list of triangle.                      M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTriangleCopyList	                                             M
*****************************************************************************/
TrivTriangleStruct *TrivTriangleCopyList(TrivTriangleStruct *TriangleList)
{
    TrivTriangleStruct *TriangleTemp, *NewTriangleList;

    if (TriangleList == NULL)
	return NULL;
    TriangleTemp = NewTriangleList = TrivTriangleCopy(TriangleList);
    TriangleList = TriangleList -> Pnext;
    while (TriangleList) {
	TriangleTemp -> Pnext = TrivTriangleCopy(TriangleList);
	TriangleTemp = TriangleTemp -> Pnext;
	TriangleList = TriangleList -> Pnext;
    }
    return NewTriangleList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates and frees all slots of a triangle structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Triangle:   Triangle to free.                                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTriangleFree                                                         M
*****************************************************************************/
void TrivTriangleFree(TrivTriangleStruct *Triangle)
{
    if (Triangle)
        return;

    AttrFreeAttributes(&Triangle -> Attr);
    IritFree((VoidPtr) Triangle);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates and frees a list of triangle structures.		             M
*                                                                            *
* PARAMETERS:                                                                M
*   TriangleList:    Triangle list to free.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTriangleFreeList		                                     M
*****************************************************************************/
void TrivTriangleFreeList(TrivTriangleStruct *TriangleList)
{
    TrivTriangleStruct *TriangleTemp;

    while (TriangleList) {
	TriangleTemp = TriangleList -> Pnext;
	TrivTriangleFree(TriangleList);
	TriangleList = TriangleTemp;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Linearly transforms, in place, given TV as specified by Translate and      M
* Scale.								     M
*                                                                            *
* PARAMETERS:                                                                M
*   TV:            Trivariate to transform.                                  M
*   Translate:     Translation factor.                                       M
*   Scale:         Scaling factor.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVTransform, trivariates                                             M
*****************************************************************************/
void TrivTVTransform(TrivTVStruct *TV, CagdRType *Translate, CagdRType Scale)
{
    switch (TV -> GType) {
	case TRIV_TVBEZIER_TYPE:
	case TRIV_TVBSPLINE_TYPE:
	    CagdTransform(TV -> Points,
	    		  TV -> ULength * TV -> VLength * TV -> WLength,
	                  CAGD_NUM_OF_PT_COORD(TV -> PType),
			  !TRIV_IS_RATIONAL_TV(TV),
		          Translate,
        	          Scale);
	    break;
	default:
	    TRIV_FATAL_ERROR(TRIV_ERR_UNDEF_GEOM);
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Transforms, in place, the given TV as specified by homogeneous matrix Mat. M
*                                                                            *
* PARAMETERS:                                                                M
*   TV:            Trivariate to transform.                                  M
*   Mat:           Homogeneous transformation to apply to TV.                M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVMatTransform, trivariates                                          M
*****************************************************************************/
void TrivTVMatTransform(TrivTVStruct *TV, CagdMType Mat)
{
    switch (TV -> GType) {
	case TRIV_TVBEZIER_TYPE:
	case TRIV_TVBSPLINE_TYPE:
	    CagdMatTransform(TV -> Points,
    			     TV -> ULength * TV -> VLength * TV -> WLength,
        	             CAGD_NUM_OF_PT_COORD(TV -> PType),
			     !TRIV_IS_RATIONAL_TV(TV),
		             Mat);
	    break;
	default:
	    TRIV_FATAL_ERROR(TRIV_ERR_UNDEF_GEOM);
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Converts a Bezier trivariate into a Bspline trivariate by adding two open  M
* end uniform knot vectors to it.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   TV:        A Bezier trivariate to convert to a Bspline TV.               M
*                                                                            *
* RETURN VALUE:                                                              M
*   TrivTVStruct *:  A Bspline trivariate representing the same geometry as  M
*                    the given Bezier TV.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivCnvrtBezier2BsplineTV, conversion, trivariate                        M
*****************************************************************************/
TrivTVStruct *TrivCnvrtBezier2BsplineTV(TrivTVStruct *TV)
{
    TrivTVStruct *BspTV;

    if (TV -> GType != TRIV_TVBEZIER_TYPE) {
        TRIV_FATAL_ERROR(TRIV_ERR_UNDEF_GEOM);
        return NULL;
    }

    BspTV = TrivTVCopy(TV);

    BspTV -> UOrder = BspTV -> ULength;
    BspTV -> VOrder = BspTV -> VLength;
    BspTV -> WOrder = BspTV -> WLength;
    BspTV -> UKnotVector = BspKnotUniformOpen(BspTV -> ULength,
					      BspTV -> UOrder, NULL);
    BspTV -> VKnotVector = BspKnotUniformOpen(BspTV -> VLength,
					      BspTV -> VOrder, NULL);
    BspTV -> WKnotVector = BspKnotUniformOpen(BspTV -> WLength,
					      BspTV -> WOrder, NULL);
    BspTV -> GType = TRIV_TVBSPLINE_TYPE;
    return BspTV;
}
