/******************************************************************************
* Cagd_gen.c - General routines used by all modules of CAGD_lib.	      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Mar. 90.					      *
******************************************************************************/

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

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new curve.	     	             M
*                                                                            *
* PARAMETERS:                                                                M
*   GType:      Type of geometry the curve should be - Bspline, Bezier etc.  M
*   PType:      Type of control points (E2, P3, etc.).                       M
*   Length:     Number of control points                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   An uninitialized freeform curve.                      M
*                                                                            *
* SEE ALSO:                                                                  M
*   BzrCrvNew, BspPeriodicCrvNew, bspCrvNew, CagdPeriodicCrvNew, TrimCrvNew  M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCrvNew, allocation                                                   M
*****************************************************************************/
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 -> Periodic = FALSE;
    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new, possibly periodic, curve.       M
*                                                                            *
* PARAMETERS:                                                                M
*   GType:      Type of geometry the curve should be - Bspline, Bezier etc.  M
*   PType:      Type of control points (E2, P3, etc.).                       M
*   Length:     Number of control points                                     M
*   Periodic:   Is this curve periodic?                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   An uninitialized freeform curve.                      M
*                                                                            *
* SEE ALSO:                                                                  M
*   BzrCrvNew, BspCrvNew, BspPeriodicCrvNew, CagdCrvNew, TrimCrvNew	     M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPeriodicCrvNew, allocation                                           M
*****************************************************************************/
CagdCrvStruct *CagdPeriodicCrvNew(CagdGeomType GType,
				  CagdPointType PType,
				  int Length,
				  CagdBType Periodic)
{
    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 -> Periodic = Periodic;
    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new surface.	     	             M
*                                                                            *
* PARAMETERS:                                                                M
*   GType:      Type of geometry the surface 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
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:   An uninitialized freeform surface.                    M
*                                                                            *
* SEE ALSO:                                                                  M
*   BzrSrfNew, BspPeriodicSrfNew, BspSrfNew, CagdPeriodicSrfNew, TrimSrfNew  M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdSrfNew, allocation                                                   M
*****************************************************************************/
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 -> UPeriodic = FALSE;
    NewSrf -> VPeriodic = FALSE;
    NewSrf -> Pnext = NULL;
    NewSrf -> Attr = NULL;
    NewSrf -> Points[0] = NULL;			    /* The rational element. */
    NewSrf -> PAux = NULL;

    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new, possibly periodic, surface.     M
*                                                                            *
* PARAMETERS:                                                                M
*   GType:      Type of geometry the surface 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
*   UPeriodic:  Is this surface periodic in the U direction?                 M
*   VPeriodic:  Is this surface periodic in the V direction?                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:   An uninitialized freeform surface.                    M
*                                                                            *
* SEE ALSO:                                                                  M
*   BzrSrfNew, BspSrfNew, BspPeriodicSrfNew, CagdSrfNew, TrimSrfNew	     M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPeriodicSrfNew, allocation                                           M
*****************************************************************************/
CagdSrfStruct *CagdPeriodicSrfNew(CagdGeomType GType,
				  CagdPointType PType,
				  int ULength,
				  int VLength,
				  CagdBType UPeriodic,
				  CagdBType VPeriodic)
{
    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 -> UPeriodic = UPeriodic;
    NewSrf -> VPeriodic = VPeriodic;
    NewSrf -> Pnext = NULL;
    NewSrf -> Attr = NULL;
    NewSrf -> Points[0] = NULL;			    /* The rational element. */
    NewSrf -> PAux = NULL;

    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of UV structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of UV array to allocate.                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  An array of UV structures of size Size.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdUVArrayNew, allocation                                               M
*****************************************************************************/
CagdUVStruct *CagdUVArrayNew(int Size)
{
    int i;
    CagdUVStruct
	*NewUV = (CagdUVStruct *) IritMalloc(Size * sizeof(CagdUVStruct));

    for (i = 0; i < Size; i++) {
	NewUV[i].Pnext = NULL;
	NewUV[i].Attr = NULL;
    }

    return NewUV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a UV structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A UV structure.				             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdUVNew, allocation                                                    M
*****************************************************************************/
CagdUVStruct *CagdUVNew(void)
{
    CagdUVStruct
	*NewUV = (CagdUVStruct *) IritMalloc(sizeof(CagdUVStruct));

    NewUV -> Pnext = NULL;
    NewUV -> Attr = NULL;

    return NewUV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of Pt structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of Pt array to allocate.                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPtStruct *:  An array of Pt structures of size Size.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPtArrayNew, allocation                                               M
*****************************************************************************/
CagdPtStruct *CagdPtArrayNew(int Size)
{
    int i;
    CagdPtStruct
	*NewPt = (CagdPtStruct *) IritMalloc(Size * sizeof(CagdPtStruct));

    for (i = 0; i < Size; i++) {
	NewPt[i].Pnext = NULL;
	NewPt[i].Attr = NULL;
    }

    return NewPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a Pt structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPtStruct *:  A Pt structure.				             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPtNew, allocation                                                    M
*****************************************************************************/
CagdPtStruct *CagdPtNew(void)
{
    CagdPtStruct
	*NewPt = (CagdPtStruct *) IritMalloc(sizeof(CagdPtStruct));

    NewPt -> Pnext = NULL;
    NewPt -> Attr = NULL;

    return NewPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of CtlPt structures.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of CtlPt array to allocate.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCtlPtStruct *:  An array of CtlPt structures of size Size.           M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCtlPtArrayNew, allocation                                            M
*****************************************************************************/
CagdCtlPtStruct *CagdCtlPtArrayNew(CagdPointType PtType, int Size)
{
    int i;
    CagdCtlPtStruct
	*NewCtlPt = (CagdCtlPtStruct *)
	    IritMalloc(Size * sizeof(CagdCtlPtStruct));

    for (i = 0; i < Size; i++) {
	NewCtlPt[i].Pnext = NULL;
	NewCtlPt[i].Attr = NULL;
	NewCtlPt[i].PtType = PtType;
    }

    return NewCtlPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a CtlPt structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A CtlPt structure.				             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCtlPtNew, allocation                                                 M
*****************************************************************************/
CagdCtlPtStruct *CagdCtlPtNew(CagdPointType PtType)
{
    CagdCtlPtStruct
	*NewCtlPt = (CagdCtlPtStruct *) IritMalloc(sizeof(CagdCtlPtStruct));

    NewCtlPt -> Pnext = NULL;
    NewCtlPt -> Attr = NULL;
    NewCtlPt -> PtType = PtType;

    return NewCtlPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of Vec structures.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of Vec array to allocate.                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdVecStruct *:  An array of Vec structures of size Size.               M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdVecArrayNew, allocation                                              M
*****************************************************************************/
CagdVecStruct *CagdVecArrayNew(int Size)
{
    int i;
    CagdVecStruct
	*NewVec = (CagdVecStruct *) IritMalloc(Size * sizeof(CagdVecStruct));

    for (i = 0; i < Size; i++) {
	NewVec[i].Pnext = NULL;
	NewVec[i].Attr = NULL;
    }

    return NewVec;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a Vec structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdVecStruct *:  A Vec structure.				             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdVecNew, allocation                                                   M
*****************************************************************************/
CagdVecStruct *CagdVecNew(void)
{
    CagdVecStruct
	*NewVec = (CagdVecStruct *) IritMalloc(sizeof(CagdVecStruct));

    NewVec -> Pnext = NULL;
    NewVec -> Attr = NULL;

    return NewVec;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of Plane structures.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of Plane array to allocate.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPlaneStruct *:  An array of Plane structures of size Size.           M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPlaneArrayNew, allocation                                            M
*****************************************************************************/
CagdPlaneStruct *CagdPlaneArrayNew(int Size)
{
    int i;
    CagdPlaneStruct
	*NewPlane = (CagdPlaneStruct *)
	    IritMalloc(Size * sizeof(CagdPlaneStruct));

    for (i = 0; i < Size; i++) {
	NewPlane[i].Pnext = NULL;
	NewPlane[i].Attr = NULL;
    }

    return NewPlane;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a Plane structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A Plane structure.				             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPlaneNew, allocation                                                 M
*****************************************************************************/
CagdPlaneStruct *CagdPlaneNew(void)
{
    CagdPlaneStruct
	*NewPlane = (CagdPlaneStruct *) IritMalloc(sizeof(CagdPlaneStruct));

    NewPlane -> Pnext = NULL;
    NewPlane -> Attr = NULL;

    return NewPlane;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of BBox structures.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of BBox array to allocate.                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdBBoxStruct *:  An array of BBox structures of size Size.             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdBBoxArrayNew, allocation                                             M
*****************************************************************************/
CagdBBoxStruct *CagdBBoxArrayNew(int Size)
{
    int i;
    CagdBBoxStruct
	*NewBBox = (CagdBBoxStruct *)
	    IritMalloc(Size * sizeof(CagdBBoxStruct));

    for (i = 0; i < Size; i++) {
	NewBBox[i].Pnext = NULL;
	NewBBox[i].Attr = NULL;
    }

    return NewBBox;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a BBox structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdBBoxStruct *:  A BBox structure.			             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdBBoxNew, allocation                                                  M
*****************************************************************************/
CagdBBoxStruct *CagdBBoxNew(void)
{
    CagdBBoxStruct
	*NewBBox = (CagdBBoxStruct *) IritMalloc(sizeof(CagdBBoxStruct));

    NewBBox -> Pnext = NULL;
    NewBBox -> Attr = NULL;

    return NewBBox;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of Polygon structures.          M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of Polygon array to allocate.                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolygonStruct *:  An array of Polygon structures of size Size.       M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolygonArrayNew, allocation                                          M
*****************************************************************************/
CagdPolygonStruct *CagdPolygonArrayNew(int Size)
{
    int i;
    CagdPolygonStruct
	*NewPoly = (CagdPolygonStruct *)
	    IritMalloc(Size * sizeof(CagdPolygonStruct));

    for (i = 0; i < Size; i++) {
	NewPoly[i].Pnext = NULL;
	NewPoly[i].Attr = NULL;
    }

    return NewPoly;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a Polygon structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolygonStruct *:  A Polygon structure.		                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolygonNew, allocation                                               M
*****************************************************************************/
CagdPolygonStruct *CagdPolygonNew(void)
{
    CagdPolygonStruct
	*NewPoly = (CagdPolygonStruct *) IritMalloc(sizeof(CagdPolygonStruct));

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

    return NewPoly;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of an array of Polyline structures.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Size:      Size of Polyline array to allocate.                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolylineStruct *:  An array of Polyline structures of size Size.     M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolylineArrayNew, allocation                                         M
*****************************************************************************/
CagdPolylineStruct *CagdPolylineArrayNew(int Length, int Size)
{
    int i;
    CagdPolylineStruct
	*NewPoly = (CagdPolylineStruct *)
	    IritMalloc(Size * sizeof(CagdPolylineStruct));

    for (i = 0; i < Size; i++) {
	NewPoly[i].Pnext = NULL;
	NewPoly[i].Attr = NULL;
	NewPoly[i].Polyline = (CagdPolylnStruct *)
	    IritMalloc(sizeof(CagdPolylnStruct) * Length);
	NewPoly[i].Length = Length;
    }

    return NewPoly;
}
/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and resets all slots of a Polyline structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolylineStruct *:  A Polyline structure.		             M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolylineNew, allocation                                              M
*****************************************************************************/
CagdPolylineStruct *CagdPolylineNew(int Length)
{
    CagdPolylineStruct
	*NewPoly = (CagdPolylineStruct *)
	    IritMalloc(sizeof(CagdPolylineStruct));

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

    return NewPoly;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a curve structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:       To be copied.                                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:  A duplicate of Crv.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCrvCopy, copy                                                        M
*****************************************************************************/
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;
    NewCrv -> Periodic = Crv -> Periodic;
    if (Crv -> KnotVector != NULL)
	NewCrv -> KnotVector = BspKnotCopy(Crv -> KnotVector,
				   Crv -> Length + Crv -> Order +
				   (Crv -> Periodic ? Crv -> Order - 1 : 0));
    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a surface structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To be copied.                                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:  A duplicate of Srf.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdSrfCopy, copy                                                        M
*****************************************************************************/
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;
    NewSrf -> UPeriodic = Srf -> UPeriodic;
    NewSrf -> VPeriodic = Srf -> VPeriodic;
    NewSrf -> PAux = NULL;

    if (Srf -> UKnotVector != NULL)
	NewSrf -> UKnotVector = BspKnotCopy(Srf -> UKnotVector,
				   Srf -> ULength + Srf -> UOrder +
				   (Srf -> UPeriodic ? Srf -> UOrder - 1 : 0));
    else
	NewSrf -> UKnotVector = NULL;
    if (Srf -> VKnotVector != NULL)
	NewSrf -> VKnotVector = BspKnotCopy(Srf -> VKnotVector,
				   Srf -> VLength + Srf -> VOrder +
				   (Srf -> VPeriodic ? Srf -> VOrder - 1 : 0));
    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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a UV structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   UV:       To be copied.                                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A duplicate of UV.                                      M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdUVCopy, copy                                                         M
*****************************************************************************/
CagdUVStruct *CagdUVCopy(CagdUVStruct *UV)
{
    CagdUVStruct
	*NewUV = (CagdUVStruct *) IritMalloc(sizeof(CagdUVStruct));

    CAGD_GEN_COPY(NewUV, UV, sizeof(CagdUVStruct));
    NewUV -> Pnext = NULL;
    NewUV -> Attr = AttrCopyAttributes(UV -> Attr);

    return NewUV;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a Pt structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:       To be copied.                                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPtStruct *:  A duplicate of Pt.                                      M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPtCopy, copy                                                         M
*****************************************************************************/
CagdPtStruct *CagdPtCopy(CagdPtStruct *Pt)
{
    CagdPtStruct
	*NewPt = (CagdPtStruct *) IritMalloc(sizeof(CagdPtStruct));

    CAGD_GEN_COPY(NewPt, Pt, sizeof(CagdPtStruct));
    NewPt -> Pnext = NULL;
    NewPt -> Attr = AttrCopyAttributes(Pt -> Attr);

    return NewPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a CtlPt structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   CtlPt:       To be copied.                                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A duplicate of CtlPt.                                   M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCtlPtCopy, copy                                                      M
*****************************************************************************/
CagdCtlPtStruct *CagdCtlPtCopy(CagdCtlPtStruct *CtlPt)
{
    CagdCtlPtStruct
	*NewCtlPt = (CagdCtlPtStruct *) IritMalloc(sizeof(CagdCtlPtStruct));

    CAGD_GEN_COPY(NewCtlPt, CtlPt, sizeof(CagdCtlPtStruct));
    NewCtlPt -> Pnext = NULL;
    NewCtlPt -> Attr = AttrCopyAttributes(CtlPt -> Attr);

    return NewCtlPt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a Vec structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Vec:       To be copied.                                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A duplicate of Vec.                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdVecCopy, copy                                                        M
*****************************************************************************/
CagdVecStruct *CagdVecCopy(CagdVecStruct *Vec)
{
    CagdVecStruct
	*NewVec = (CagdVecStruct *) IritMalloc(sizeof(CagdVecStruct));

    CAGD_GEN_COPY(NewVec, Vec, sizeof(CagdVecStruct));
    NewVec -> Pnext = NULL;
    NewVec -> Attr = AttrCopyAttributes(Vec -> Attr);

    return NewVec;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a Plane structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Plane:       To be copied.                                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPlaneStruct *:  A duplicate of Plane.                                M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPlaneCopy, copy                                                      M
*****************************************************************************/
CagdPlaneStruct *CagdPlaneCopy(CagdPlaneStruct *Plane)
{
    CagdPlaneStruct
	*NewPlane = (CagdPlaneStruct *) IritMalloc(sizeof(CagdPlaneStruct));

    CAGD_GEN_COPY(NewPlane, Plane, sizeof(CagdPlaneStruct));
    NewPlane -> Pnext = NULL;
    NewPlane -> Attr = AttrCopyAttributes(Plane -> Attr);

    return NewPlane;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a BBox structure.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   BBox:       To be copied.                                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdBBoxStruct *:  A duplicate of BBox.                                  M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdBBoxCopy, copy                                                       M
*****************************************************************************/
CagdBBoxStruct *CagdBBoxCopy(CagdBBoxStruct *BBox)
{
    CagdBBoxStruct
	*NewBBox = (CagdBBoxStruct *) IritMalloc(sizeof(CagdBBoxStruct));

    CAGD_GEN_COPY(NewBBox, BBox, sizeof(CagdBBoxStruct));
    NewBBox -> Pnext = NULL;
    NewBBox -> Attr = AttrCopyAttributes(BBox -> Attr);

    return NewBBox;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a Polygon structure.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Poly:       To be copied.                                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolygonStruct *:  A duplicate of Polygon.                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolygonCopy, copy                                                    M
*****************************************************************************/
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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies all slots of a Polyline structure.	             M
*                                                                            *
* PARAMETERS:                                                                M
*   Poly:       To be copied.                                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPolylineStruct *:  A duplicate of Polyline.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPolylineCopy, copy                                                   M
*****************************************************************************/
CagdPolylineStruct *CagdPolylineCopy(CagdPolylineStruct *Poly)
{
    CagdPolylineStruct
	*NewPoly = (CagdPolylineStruct *) IritMalloc(sizeof(CagdPolylineStruct));

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

    return NewPoly;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of curve structures.		             M
*                                                                            *
* PARAMETERS:                                                                M
*   CrvList:       To be copied.                                             M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:  A duplicated list of curves.                           M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCrvCopyList, copy                                                    M
*****************************************************************************/
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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of surface structures.		             M
*                                                                            *
* PARAMETERS:                                                                M
*   SrfList:       To be copied.                                             M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:  A duplicated list of surfaces.                         M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdSrfCopyList, copy                                                    M
*****************************************************************************/
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;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of UV structures.			             M
*                                                                            *
* PARAMETERS:                                                                M
*   UVList:       To be copied.                                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdUVStruct *:  A duplicated list of UV's.                              M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdUVCopyList, copy                                                     M
*****************************************************************************/
CagdUVStruct *CagdUVCopyList(CagdUVStruct *UVList)
{
    CagdUVStruct *UVTemp, *NewUVList;

    if (UVList == NULL)
	return NULL;
    UVTemp = NewUVList = CagdUVCopy(UVList);
    UVList = UVList -> Pnext;
    while (UVList) {
	UVTemp -> Pnext = CagdUVCopy(UVList);
	UVTemp = UVTemp -> Pnext;
	UVList = UVList -> Pnext;
    }
    return NewUVList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of point structures.		             M
*                                                                            *
* PARAMETERS:                                                                M
*   PtList:       To be copied.                                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdPtStruct *:  A duplicated list of points.                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdPtCopyList, copy                                                     M
*****************************************************************************/
CagdPtStruct *CagdPtCopyList(CagdPtStruct *PtList)
{
    CagdPtStruct *PtTemp, *NewPtList;

    if (PtList == NULL)
	return NULL;
    PtTemp = NewPtList = CagdPtCopy(PtList);
    PtList = PtList -> Pnext;
    while (PtList) {
	PtTemp -> Pnext = CagdPtCopy(PtList);
	PtTemp = PtTemp -> Pnext;
	PtList = PtList -> Pnext;
    }
    return NewPtList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Allocates and copies a list of CtlPt structures.		             M
*                                                                            *
* PARAMETERS:                                                                M
*   CtlPtList:       To be copied.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCtlPtStruct *:  A duplicated list of CtlPt's.                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdCtlPtCopyList, copy                                                  M
*****************************************************************************/
CagdCtlPtStruct *CagdCtlPtCopyList(CagdCtlPtStruct *CtlPtList)
{
    CagdCtlPtStruct *CtlPtTemp, *NewCtlPtList;

    if (CtlPtList == NULL)
	return NULL;
    CtlPtTemp = NewCtlPtList = CagdCtlPtCopy(CtlPtList);
    CtlPtList = CtlPtList -> Pnext;
    while (CtlPtList) {
	CtlPtTemp -> Pnext = CagdCtlPtCopy(CtlPtList);
	CtlPtTemp = CtlPtTemp -> Pnext;
	CtlPtList = CtlPtList -> Pnext;
    }
    return NewCtlPtList;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Returns TRUE if the curve is a closed loop.                              M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:       To test for a closed loop.                                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdBType:    TRUE if closed, FALSE otherwise.                           M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdIsClosedCrv                                                          M
*****************************************************************************/
CagdBType CagdIsClosedCrv(CagdCrvStruct *Crv)
{
    CagdPType P1, P2;

    if (CAGD_IS_BEZIER_CRV(Crv)) {
	CagdCoerceToE3(P1, Crv -> Points, 0, Crv -> PType);
	CagdCoerceToE3(P2, Crv -> Points, Crv -> Length - 1, Crv -> PType);
    }
    else if (CAGD_IS_BSPLINE_CRV(Crv)) {
	if (CAGD_IS_PERIODIC_CRV(Crv)) {
	    return TRUE;
	}
	else {
	    if (!BspCrvHasOpenEC(Crv)) {
		CagdCrvStruct
		    *TCrv = BspCrvOpenEnd(Crv);

		CagdCoerceToE3(P1, TCrv -> Points, 0, Crv -> PType);
		CagdCoerceToE3(P2, TCrv -> Points, Crv -> Length - 1,
			       Crv -> PType);

		CagdCrvFree(TCrv);
	    }
	    else {	
		CagdCoerceToE3(P1, Crv -> Points, 0, Crv -> PType);
		CagdCoerceToE3(P2, Crv -> Points, Crv -> Length - 1,
			       Crv -> PType);
	    }
	}
    }

    return PT_APX_EQ(P1, P2);
}
