/******************************************************************************
* Bsp-Gen.c - Bspline generic routines.					      *
*******************************************************************************
* Written by Gershon Elber, Aug. 90.					      *
******************************************************************************/

#include "cagd_loc.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new Bspline surface.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   ULength:      Number of control points in the U direction.               M
*   VLength:      Number of control points in the V direction.               M
*   UOrder:       The order of the surface in the U direction.               M
*   VOrder:       The order of the surface in the V direction.               M
*   PType:        Type of control points (E2, P3, etc.).                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:   An uninitialized freeform Bspline surface.            M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspSrfNew, allocation                                                    M
*****************************************************************************/
CagdSrfStruct *BspSrfNew(int ULength,
			 int VLength,
			 int UOrder,
			 int VOrder,
			 CagdPointType PType)
{
    CagdSrfStruct *Srf;

    if (ULength < UOrder || VLength < VOrder) {
	CAGD_FATAL_ERROR(CAGD_ERR_WRONG_ORDER);
	return NULL;
    }

    Srf = CagdSrfNew(CAGD_SBSPLINE_TYPE, PType, ULength, VLength);

    Srf -> UKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
							   (UOrder + ULength));
    Srf -> VKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
							   (VOrder + VLength));

    Srf -> UOrder = UOrder;
    Srf -> VOrder = VOrder;

    return Srf;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new, possibly periodic, Bspline      M
* surface.								     M
*                                                                            *
* PARAMETERS:                                                                M
*   ULength:      Number of control points in the U direction.               M
*   VLength:      Number of control points in the V direction.               M
*   UOrder:       The order of the surface in the U direction.               M
*   VOrder:       The order of the surface 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
*   PType:        Type of control points (E2, P3, etc.).                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:   An uninitialized freeform Bspline surface. If both    M
*                      UPeriodic and VPeriodic are FALSE, this function is   M
*                      identical to BspSrfNew.				     M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspPeriodicSrfNew, allocation                                            M
*****************************************************************************/
CagdSrfStruct *BspPeriodicSrfNew(int ULength,
				 int VLength,
				 int UOrder,
				 int VOrder,
				 CagdBType UPeriodic,
				 CagdBType VPeriodic,
				 CagdPointType PType)
{
    CagdSrfStruct *Srf;

    if (ULength < UOrder || VLength < VOrder) {
	CAGD_FATAL_ERROR(CAGD_ERR_WRONG_ORDER);
	return NULL;
    }

    Srf = CagdPeriodicSrfNew(CAGD_SBSPLINE_TYPE, PType, ULength, VLength,
			     UPeriodic, VPeriodic);

    Srf -> UKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
			   (UOrder + ULength + (UPeriodic ? UOrder - 1 : 0)));
    Srf -> VKnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
			   (VOrder + VLength + (VPeriodic ? VOrder - 1 : 0)));

    Srf -> UOrder = UOrder;
    Srf -> VOrder = VOrder;

    return Srf;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new Bspline curve.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   Length:     Number of control points                                     M
*   Order:      The order of the curve                                       M
*   PType:      Type of control points (E2, P3, etc.).                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   An uninitialized freeform Bspline curve.              M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspCrvNew, allocation                                                    M
*****************************************************************************/
CagdCrvStruct *BspCrvNew(int Length, int Order, CagdPointType PType)
{
    CagdCrvStruct *Crv;

    if (Length < Order) {
	CAGD_FATAL_ERROR(CAGD_ERR_WRONG_ORDER);
	return NULL;
    }

    Crv = CagdCrvNew(CAGD_CBSPLINE_TYPE, PType, Length);

    Crv -> KnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
							     (Order + Length));

    Crv -> Order = Order;

    return Crv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Allocates the memory required for a new, possibly periodic, Bspline      M
* curve.								     M
*                                                                            *
* PARAMETERS:                                                                M
*   Length:     Number of control points                                     M
*   Order:      The order of the curve                                       M
*   Periodic:   Is this curve periodic?                                      M
*   PType:      Type of control points (E2, P3, etc.).                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   An uninitialized freeform Bspline curve. If Periodic  M
*                      is FALSE, this function is identical to BspCrvNew.    M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspCrvNew, allocation                                                    M
*****************************************************************************/
CagdCrvStruct *BspPeriodicCrvNew(int Length,
				 int Order,
				 CagdBType Periodic,
				 CagdPointType PType)
{
    CagdCrvStruct *Crv;

    if (Length < Order) {
	CAGD_FATAL_ERROR(CAGD_ERR_WRONG_ORDER);
	return NULL;
    }

    Crv = CagdPeriodicCrvNew(CAGD_CBSPLINE_TYPE, PType, Length, Periodic);

    Crv -> KnotVector = (CagdRType *) IritMalloc(sizeof(CagdRType) *
				(Order + Length + (Periodic ? Order - 1 : 0)));

    Crv -> Order = Order;

    return Crv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Returns the parametric domain of a Bspline curve.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:       To get its parametric domain.                                 M
*   TMin:      Where to put the minimal domain's boundary.                   M
*   TMax:      Where to put the maximal domain's boundary.                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspCrvDomain, domain, parametric domain                                  M
*****************************************************************************/
void BspCrvDomain(CagdCrvStruct *Crv, CagdRType *TMin, CagdRType *TMax)
{
    int k = Crv -> Order,
	Len = CAGD_CRV_PT_LST_LEN(Crv);

    *TMin = Crv -> KnotVector[k - 1];
    *TMax = Crv -> KnotVector[Len];
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Returns the parametric domain of a Bspline surface.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To get its parametric domain.                                 M
*   UMin:      Where to put the minimal U domain's boundary.                 M
*   UMax:      Where to put the maximal U domain's boundary.                 M
*   VMin:      Where to put the minimal V domain's boundary.                 M
*   VMax:      Where to put the maximal V domain's boundary.                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspSrfDomain, domain, parametric domain                                  M
*****************************************************************************/
void BspSrfDomain(CagdSrfStruct *Srf,
		  CagdRType *UMin,
		  CagdRType *UMax,
		  CagdRType *VMin,
		  CagdRType *VMax)
{
    int UOrder = Srf -> UOrder,
	VOrder = Srf -> VOrder,
	ULen = CAGD_SRF_UPT_LST_LEN(Srf),
	VLen = CAGD_SRF_VPT_LST_LEN(Srf);

    *UMin = Srf -> UKnotVector[UOrder - 1];
    *UMax = Srf -> UKnotVector[ULen];
    *VMin = Srf -> VKnotVector[VOrder - 1];
    *VMax = Srf -> VKnotVector[VLen];
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Returns a curve with open end conditions, similar to given curve.	     M
*   Open end curve is computed by extracting a subregion from Crv that is    M
* the entire curve's parametric domain, by inserting multiple knots at the   M
* domain's boundary.                                                         M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:     To convert to a new curve with open end conditions.             M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *: Same curve as Crv but with open end conditions.         M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspCrvOpenEnd, open end conditions                                       M
*****************************************************************************/
CagdCrvStruct *BspCrvOpenEnd(CagdCrvStruct *Crv)
{
    int k = Crv -> Order,
	Len = Crv -> Length;
    CagdCrvStruct
	*OpenCrv = CagdCrvRegionFromCrv(Crv,
					Crv -> KnotVector[k - 1],
					Crv -> KnotVector[Len]);

    return OpenCrv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Returns a surface with open end conditions, similar to given surface.    M
*   Open end surface is computed by extracting a subregion from Srf that is  M
* the entire surface's parametric domain, by inserting multiple knots at the M
* domain's boundary.                                                         M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:     To convert to a new curve with open end conditions.             M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *: Same surface as Srf but with open end conditions.       M
*                                                                            *
* KEYWORDS:                                                                  M
*   BspSrfOpenEnd, open end conditions                                       M
*****************************************************************************/
CagdSrfStruct *BspSrfOpenEnd(CagdSrfStruct *Srf)
{
    int Uk = Srf -> UOrder,
	ULen = Srf -> ULength,
	Vk = Srf -> VOrder,
	VLen = Srf -> VLength;
    CagdSrfStruct
	*TSrf =
	    CagdSrfRegionFromSrf(Srf,
				 Srf -> UKnotVector[Uk - 1],
				 Srf -> UKnotVector[ULen],
				 CAGD_CONST_U_DIR),
	*OpenSrf =
	    CagdSrfRegionFromSrf(TSrf,
				 TSrf -> VKnotVector[Vk - 1],
				 TSrf -> VKnotVector[VLen],
				 CAGD_CONST_V_DIR);

    CagdSrfFree(TSrf);

    return OpenSrf;
}
