/******************************************************************************
* Cagd_gen.c - General routines used by all modules of CAGD_lib.	      *
*******************************************************************************
* Written by Gershon Elber, Mar. 90.					      *
******************************************************************************/

#include <string.h>
#include "cagd_loc.h"

/* Control of the linear order surface convertion to polygon: */
CagdLin2PolyType
    _CagdLin2Poly = CAGD_ONE_POLY_PER_COLIN;

static void CagdTransform(CagdRType **Points, int Len, int MaxCoord,
	     CagdBType IsNotRational, CagdRType *Translate, CagdRType Scale);
static void CagdMatTransform(CagdRType **Points, int Len, int MaxCoord,
				  CagdBType IsNotRational, CagdMType Mat);

/******************************************************************************
* Allocate and reset all slots of a curve structure:			      *
******************************************************************************/
CagdCrvStruct *CagdCrvNew(CagdGeomType GType, CagdPointType PType, int Length)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(PType);
    CagdCrvStruct
	*NewCrv = (CagdCrvStruct *) IritMalloc(sizeof(CagdCrvStruct));

    NewCrv -> GType = GType;
    NewCrv -> PType = PType;
    NewCrv -> Length = Length;
    NewCrv -> Order = 0;
    NewCrv -> KnotVector = NULL;
    NewCrv -> Pnext = NULL;
    NewCrv -> Attr = NULL;
    NewCrv -> Points[0] = NULL;			    /* The rational element. */

    for (i = !CAGD_IS_RATIONAL_PT(PType); i <= MaxAxis; i++)
	NewCrv -> Points[i] = (CagdRType *) IritMalloc(sizeof(CagdRType) *
								 Length);

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

    return NewCrv;
}

/******************************************************************************
* Allocate and reset all slots of a surface structure:			      *
******************************************************************************/
CagdSrfStruct *CagdSrfNew(CagdGeomType GType, CagdPointType PType, int ULength,
								   int VLength)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(PType);
    CagdSrfStruct
	*NewSrf = (CagdSrfStruct *) IritMalloc(sizeof(CagdSrfStruct));

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

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

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

    return NewSrf;
}

/******************************************************************************
* Allocate and reset all slots of a polygon structure:			      *
******************************************************************************/
CagdPolygonStruct *CagdPolygonNew(void)
{
    CagdPolygonStruct
	*NewPoly = (CagdPolygonStruct *) IritMalloc(sizeof(CagdPolygonStruct));

    NewPoly -> Pnext = NULL;
    NewPoly -> Attr = NULL;

    return NewPoly;
}


/******************************************************************************
* Allocate and reset all slots of a polyline structure:			      *
******************************************************************************/
CagdPolylineStruct *CagdPolylineNew(int Length)
{
    CagdPolylineStruct
	*NewPoly = (CagdPolylineStruct *) IritMalloc(sizeof(CagdPolylineStruct));

    NewPoly -> Pnext = NULL;
    NewPoly -> Attr = NULL;
    NewPoly -> Polyline = (CagdPtStruct *) IritMalloc(sizeof(CagdPtStruct) *
								       Length);
    NewPoly -> Length = Length;

    return NewPoly;
}

/******************************************************************************
* Allocate and copy all slots of a curve structure:			      *
******************************************************************************/
CagdCrvStruct *CagdCrvCopy(CagdCrvStruct *Crv)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(Crv -> PType);
    CagdCrvStruct
	*NewCrv = (CagdCrvStruct *) IritMalloc(sizeof(CagdCrvStruct));

    NewCrv -> GType = Crv -> GType;
    NewCrv -> PType = Crv -> PType;
    NewCrv -> Length = Crv -> Length;
    NewCrv -> Order = Crv -> Order;
    if (Crv -> KnotVector != NULL)
	NewCrv -> KnotVector = BspKnotCopy(Crv -> KnotVector,
					   Crv -> Length + Crv -> Order);
    else
	NewCrv -> KnotVector = NULL;
    NewCrv -> Pnext = NULL;
    NewCrv -> Attr = NULL;
    NewCrv -> Points[0] = NULL;			    /* The rational element. */

    for (i = !CAGD_IS_RATIONAL_PT(Crv -> PType); i <= MaxAxis; i++) {
	NewCrv -> Points[i] = (CagdRType *) IritMalloc(sizeof(CagdRType) *
							       Crv -> Length);
	CAGD_GEN_COPY(NewCrv -> Points[i], Crv -> Points[i],
		      sizeof(CagdRType) * Crv -> Length);
    }

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

    return NewCrv;
}

/******************************************************************************
* Allocate and copy all slots of a surface structure:			      *
******************************************************************************/
CagdSrfStruct *CagdSrfCopy(CagdSrfStruct *Srf)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(Srf -> PType);
    CagdSrfStruct
	*NewSrf = (CagdSrfStruct *) IritMalloc(sizeof(CagdSrfStruct));

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

    for (i = !CAGD_IS_RATIONAL_PT(Srf -> PType); i <= MaxAxis; i++) {
	NewSrf -> Points[i] = (CagdRType *) IritMalloc(sizeof(CagdRType) *
					 Srf -> ULength * Srf -> VLength);
	CAGD_GEN_COPY(NewSrf -> Points[i], Srf -> Points[i],
		      sizeof(CagdRType) * Srf -> ULength * Srf -> VLength);
    }

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

    return NewSrf;
}

/******************************************************************************
* Allocate and copy all slots of a polygon structure:			      *
******************************************************************************/
CagdPolygonStruct *CagdPolygonCopy(CagdPolygonStruct *Poly)
{
    CagdPolygonStruct
	*NewPoly = (CagdPolygonStruct *) IritMalloc(sizeof(CagdPolygonStruct));

    CAGD_GEN_COPY(NewPoly, Poly, sizeof(CagdPolygonStruct));
    NewPoly -> Pnext = NULL;
    NewPoly -> Attr = NULL;

    return NewPoly;
}


/******************************************************************************
* Allocate and copy all slots of a polyline structure:			      *
******************************************************************************/
CagdPolylineStruct *CagdPolylineCopy(CagdPolylineStruct *Poly)
{
    CagdPolylineStruct
	*NewPoly = (CagdPolylineStruct *) IritMalloc(sizeof(CagdPolylineStruct));

    NewPoly -> Polyline = (CagdPtStruct *) IritMalloc(sizeof(CagdPtStruct) *
							Poly -> Length);
    CAGD_GEN_COPY(NewPoly -> Polyline, Poly -> Polyline,
					sizeof(CagdPtStruct) * Poly -> Length);
    NewPoly -> Pnext = NULL;
    NewPoly -> Attr = NULL;
    NewPoly -> Length = Poly -> Length;

    return NewPoly;
}

/******************************************************************************
* Deallocate and free all slots of a curve structure:			      *
******************************************************************************/
void CagdCrvFree(CagdCrvStruct *Crv)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(Crv -> PType);

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

    if (Crv -> KnotVector != NULL)
	IritFree((VoidPtr) Crv -> KnotVector);

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

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdCrvFreeList(CagdCrvStruct *CrvList)
{
    CagdCrvStruct *CrvTemp;

    while (CrvList) {
	CrvTemp = CrvList -> Pnext;
	CagdCrvFree(CrvList);
	CrvList = CrvTemp;
    }
}

/******************************************************************************
* Copy a curve structure list:						      *
******************************************************************************/
CagdCrvStruct *CagdCrvCopyList(CagdCrvStruct *CrvList)
{
    CagdCrvStruct *CrvTemp, *NewCrvList;

    if (CrvList == NULL)
	return NULL;
    CrvTemp = NewCrvList = CagdCrvCopy(CrvList);
    CrvList = CrvList -> Pnext;
    while (CrvList) {
	CrvTemp -> Pnext = CagdCrvCopy(CrvList);
	CrvTemp = CrvTemp -> Pnext;
	CrvList = CrvList -> Pnext;
    }
    return NewCrvList;
}

/******************************************************************************
* Deallocate and free all slots of a surface structure:			      *
******************************************************************************/
void CagdSrfFree(CagdSrfStruct *Srf)
{
    int i,
	MaxAxis = CAGD_NUM_OF_PT_COORD(Srf -> PType);

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

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

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

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdSrfFreeList(CagdSrfStruct *SrfList)
{
    CagdSrfStruct *SrfTemp;

    while (SrfList) {
	SrfTemp = SrfList -> Pnext;
	CagdSrfFree(SrfList);
	SrfList = SrfTemp;
    }
}

/******************************************************************************
* Copy a surface structure list:					      *
******************************************************************************/
CagdSrfStruct *CagdSrfCopyList(CagdSrfStruct *SrfList)
{
    CagdSrfStruct *SrfTemp, *NewSrfList;

    if (SrfList == NULL)
	return NULL;
    SrfTemp = NewSrfList = CagdSrfCopy(SrfList);
    SrfList = SrfList -> Pnext;
    while (SrfList) {
	SrfTemp -> Pnext = CagdSrfCopy(SrfList);
	SrfTemp = SrfTemp -> Pnext;
	SrfList = SrfList -> Pnext;
    }
    return NewSrfList;
}

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdPolylineFree(CagdPolylineStruct *Poly)
{
    IritFree((VoidPtr) Poly -> Polyline);
    AttrFreeAttributes(&Poly -> Attr);
    IritFree((VoidPtr) Poly);
}

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdPolylineFreeList(CagdPolylineStruct *PolyList)
{
    CagdPolylineStruct *PolyTemp;

    while (PolyList) {
	PolyTemp = PolyList -> Pnext;
	CagdPolylineFree(PolyList);
	PolyList = PolyTemp;
    }
}

/******************************************************************************
* Copy a polyline structure list:					      *
******************************************************************************/
CagdPolylineStruct *CagdPolylineCopyList(CagdPolylineStruct *PolyList)
{
    CagdPolylineStruct *PolyTemp, *NewPolyList;

    if (PolyList == NULL)
	return NULL;
    PolyTemp = NewPolyList = CagdPolylineCopy(PolyList);
    PolyList = PolyList -> Pnext;
    while (PolyList) {
	PolyTemp -> Pnext = CagdPolylineCopy(PolyList);
	PolyTemp = PolyTemp -> Pnext;
	PolyList = PolyList -> Pnext;
    }
    return NewPolyList;
}

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdPolygonFree(CagdPolygonStruct *Poly)
{
    AttrFreeAttributes(&Poly -> Attr);
    IritFree((VoidPtr) Poly);
}

/******************************************************************************
* Deallocate and free a curve structure list:				      *
******************************************************************************/
void CagdPolygonFreeList(CagdPolygonStruct *PolyList)
{
    CagdPolygonStruct *PolyTemp;

    while (PolyList) {
	PolyTemp = PolyList -> Pnext;
	CagdPolygonFree(PolyList);
	PolyList = PolyTemp;
    }
}

/******************************************************************************
* Copy a polygon structure list:					      *
******************************************************************************/
CagdPolygonStruct *CagdPolygonCopyList(CagdPolygonStruct *PolyList)
{
    CagdPolygonStruct *PolyTemp, *NewPolyList;

    if (PolyList == NULL)
	return NULL;
    PolyTemp = NewPolyList = CagdPolygonCopy(PolyList);
    PolyList = PolyList -> Pnext;
    while (PolyList) {
	PolyTemp -> Pnext = CagdPolygonCopy(PolyList);
	PolyTemp = PolyTemp -> Pnext;
	PolyList = PolyList -> Pnext;
    }
    return NewPolyList;
}

/******************************************************************************
* Deallocate and free a point structure list:				      *
******************************************************************************/
void CagdPtFreeList(CagdPtStruct *PtList)
{
    CagdPtStruct *PtTemp;

    while (PtList) {
	PtTemp = PtList -> Pnext;
	IritFree((VoidPtr) PtList);
	PtList = PtTemp;
    }
}

/******************************************************************************
* Deallocate and free a control point structure list:			      *
******************************************************************************/
void CagdCtlPtFreeList(CagdCtlPtStruct *CtlPtList)
{
    CagdCtlPtStruct *CtlPtTemp;

    while (CtlPtList) {
	CtlPtTemp = CtlPtList -> Pnext;
	IritFree((VoidPtr) CtlPtList);
	CtlPtList = CtlPtTemp;
    }
}

/******************************************************************************
* Deallocate and free a vector structure list:				      *
******************************************************************************/
void CagdVecFreeList(CagdVecStruct *VecList)
{
    CagdVecStruct *VecTemp;

    while (VecList) {
	VecTemp = VecList -> Pnext;
	IritFree((VoidPtr) VecList);
	VecList = VecTemp;
    }
}

/******************************************************************************
* Deallocate and free a plane point structure list:			      *
******************************************************************************/
void CagdPlaneFreeList(CagdPlaneStruct *PlaneList)
{
    CagdPlaneStruct *PlaneTemp;

    while (PlaneList) {
	PlaneTemp = PlaneList -> Pnext;
	IritFree((VoidPtr) PlaneList);
	PlaneList = PlaneTemp;
    }
}

/******************************************************************************
* Deallocate and free a bound box structure list:			      *
******************************************************************************/
void CagdBBoxFreeList(CagdBBoxStruct *BBoxList)
{
    CagdBBoxStruct *BBoxTemp;

    while (BBoxList) {
	BBoxTemp = BBoxList -> Pnext;

	IritFree((VoidPtr) BBoxList);
	BBoxList = BBoxTemp;
    }
}

/******************************************************************************
* Reverse a list of objects, in place.					      *
******************************************************************************/
VoidPtr CagdListReverse(VoidPtr List)
{
    CagdGenericStruct
	*OldHead = (CagdGenericStruct *) List,
	*NewHead = NULL;

    while (OldHead) {
	CagdGenericStruct
	    *TmpStruct = OldHead -> Pnext;

	OldHead -> Pnext = NewHead;
	NewHead = OldHead;

	OldHead = TmpStruct;
    }

    return (VoidPtr) NewHead;
}

/******************************************************************************
* Linear transform in place given Crv as specified by Translate and Scale.    *
******************************************************************************/
void CagdCrvTransform(CagdCrvStruct *Crv, CagdRType *Translate,
							     CagdRType Scale)
{
    switch (Crv -> GType) {
	case CAGD_CBEZIER_TYPE:
	case CAGD_CBSPLINE_TYPE:
    	    CagdTransform(Crv -> Points,
			  Crv -> Length,
    			  CAGD_NUM_OF_PT_COORD(Crv -> PType),
    			  !CAGD_IS_RATIONAL_CRV(Crv),
			  Translate,
			  Scale);

	    break;
	case CAGD_CPOWER_TYPE:
	    FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
	    break;
	default:
	    FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
	    break;
    }
}

/******************************************************************************
* Linear transform in place given Srf as specified by Translate and Scale.    *
******************************************************************************/
void CagdSrfTransform(CagdSrfStruct *Srf, CagdRType *Translate,
							     CagdRType Scale)
{
    switch (Srf -> GType) {
	case CAGD_SBEZIER_TYPE:
	case CAGD_SBSPLINE_TYPE:
	    CagdTransform(Srf -> Points,
	    		  Srf -> ULength * Srf -> VLength,
	                  CAGD_NUM_OF_PT_COORD(Srf -> PType),
			  !CAGD_IS_RATIONAL_SRF(Srf),
		          Translate,
        	          Scale);
	    break;
	case CAGD_SPOWER_TYPE:
	    FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
	    break;
	default:
	    FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
	    break;
    }
}

/******************************************************************************
* Linear transform in place given Data as specified by Translate and Scale.   *
******************************************************************************/
static void CagdTransform(CagdRType **Points, int Len, int MaxCoord,
	     CagdBType IsNotRational, CagdRType *Translate, CagdRType Scale)
{
    int i, j;

    if (IsNotRational)
	for (i = 1; i <= MaxCoord; i++)
	    for (j = 0; j < Len; j++)
		Points[i][j] = (Points[i][j] + Translate[i - 1]) * Scale;
    else
	for (i = 1; i <= MaxCoord; i++)
	    for (j = 0; j < Len; j++)
		Points[i][j] = (Points[i][j] +
				Translate[i - 1] * Points[W][j]) * Scale;
}

/******************************************************************************
* Linear transform in place the given Crv as specified by Mat.		      *
******************************************************************************/
void CagdCrvMatTransform(CagdCrvStruct *Crv, CagdMType Mat)
{
    switch (Crv -> GType) {
	case CAGD_CBEZIER_TYPE:
	case CAGD_CBSPLINE_TYPE:
	    CagdMatTransform(Crv -> Points,
    			     Crv -> Length,
                	     CAGD_NUM_OF_PT_COORD(Crv -> PType),
			     !CAGD_IS_RATIONAL_CRV(Crv),
		             Mat);
	    break;
	case CAGD_CPOWER_TYPE:
	    FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
	    break;
	default:
	    FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
	    break;
    }
}

/******************************************************************************
* Linear transform in place the given Srf as specified by Mat.		      *
******************************************************************************/
void CagdSrfMatTransform(CagdSrfStruct *Srf, CagdMType Mat)
{
    switch (Srf -> GType) {
	case CAGD_SBEZIER_TYPE:
	case CAGD_SBSPLINE_TYPE:
	    CagdMatTransform(Srf -> Points,
    			     Srf -> ULength * Srf -> VLength,
        	             CAGD_NUM_OF_PT_COORD(Srf -> PType),
			     !CAGD_IS_RATIONAL_SRF(Srf),
		             Mat);
	    break;
	case CAGD_SPOWER_TYPE:
	    FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
	    break;
	default:
	    FATAL_ERROR(CAGD_ERR_UNDEF_SRF);
	    break;
    }
}

/******************************************************************************
* Linear transform in place the given Data as specified by Mat.		      *
******************************************************************************/
static void CagdMatTransform(CagdRType **Points, int Len, int MaxCoord,
				  CagdBType IsNotRational, CagdMType Mat)
{
    int i, j;
    CagdRType P[4], Q[4];

    if (MaxCoord > 3)
	MaxCoord = 3;

    if (IsNotRational)
	for (i = 0; i < Len; i++) {
	    for (j = 1; j <= MaxCoord; j++)
		P[j - 1] = Points[j][i];

	    /* Zero unused coords. */
	    for (j = MaxCoord + 1; j < 3; i++)
		P[j - 1] = 0.0;

            MatMultVecby4by4(Q, P, Mat);

	    for (j = 1; j <= MaxCoord; j++)
		Points[j][i] = Q[j - 1];
        }
    else
	for (i = 0; i < Len; i++) {
	    for (j = 1; j <= MaxCoord; j++)
		P[j - 1] = Points[j][i];
	    P[3] = Points[W][i];

	    /* Zero unused coords. */
	    for (j = MaxCoord + 1; j < 3; i++)
		P[j - 1] = 0.0;

            MatMultWVecby4by4(Q, P, Mat);

	    for (j = 1; j <= MaxCoord; j++)
		Points[j][i] = Q[j - 1];
	    Points[W][i] = Q[3];
        }
}

/*****************************************************************************
* Routine to create one polygon given its vertices.			     *
*****************************************************************************/
CagdPolygonStruct *_CagdMakePolygon(CagdBType ComputeNormals,
				    CagdBType ComputeUV,
				    CagdPtStruct *Pt1,
				    CagdPtStruct *Pt2,
				    CagdPtStruct *Pt3,
				    CagdVecStruct *Nl1,
				    CagdVecStruct *Nl2,
				    CagdVecStruct *Nl3,
				    CagdUVStruct *UV1,
				    CagdUVStruct *UV2,
				    CagdUVStruct *UV3)
{
    CagdPolygonStruct
	*Poly = CagdPolygonNew();

    CAGD_COPY_POINT(Poly -> Polygon[0], *Pt1);
    CAGD_COPY_POINT(Poly -> Polygon[1], *Pt2);
    CAGD_COPY_POINT(Poly -> Polygon[2], *Pt3);

    if (ComputeNormals) {
	CAGD_COPY_VECTOR(Poly -> Normal[0], *Nl1);
	CAGD_COPY_VECTOR(Poly -> Normal[1], *Nl2);
	CAGD_COPY_VECTOR(Poly -> Normal[2], *Nl3);
    }
    else {
	CAGD_RESET_VECTOR(Poly -> Normal[0]);
	CAGD_RESET_VECTOR(Poly -> Normal[1]);
	CAGD_RESET_VECTOR(Poly -> Normal[2]);
    }

    if (ComputeUV) {
	CAGD_COPY_UVVAL(Poly -> UV[0], *UV1);
	CAGD_COPY_UVVAL(Poly -> UV[1], *UV2);
	CAGD_COPY_UVVAL(Poly -> UV[2], *UV3);
    }
    else {
	CAGD_RESET_UVVAL(Poly -> UV[0]);
	CAGD_RESET_UVVAL(Poly -> UV[1]);
	CAGD_RESET_UVVAL(Poly -> UV[2]);
    }

    return Poly;
}

/*****************************************************************************
* Set the way (co)linear surfaces are converted into polygons.		     *
*****************************************************************************/
void CagdSetLinear2Poly(CagdLin2PolyType Lin2Poly)
{
    _CagdLin2Poly = Lin2Poly;
}

