/******************************************************************************
* SBzrEval.c - Bezier surfaces handling routines - evaluation routines.	      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Mar. 90.					      *
******************************************************************************/

#include "cagd_loc.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Evaluates the given tensor product Bezier surface at a given point, by     M
* extracting an isoparamteric curve along u from the surface and evaluating  M
* the curve at parameter v.                                                  M
*									     M
*		u -->							     V
*     +----------------------+						     V
*     |P0		 Pi-1|						     V
*   V |Pi		P2i-1|	Parametric space orientation - control mesh. V
*    ||			     |						     V
*    v|Pn-i		 Pn-1|						     V
*     +----------------------+						     V
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       Surface to evaluate at the given (u, v) location.             M
*   u, v:      Location where to evaluate the surface.                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdRType *:  A vector holding all the coefficients of all components    M
*                 of curve Crv's point type. If for example the curve's      M
*                 point type is P2, the W, X, and Y will be saved in the     M
*                 first three locations of the returned vector. The first    M
*                 location (index 0) of the returned vector is reserved for  M
*                 the rational coefficient W and XYZ always starts at second M
*                 location of the returned vector (index 1).                 M
*                                                                            *
* SEE ALSO:                                                                  M
*   CagdSrfEval, BspSrfEvalAtParam, BspSrfEvalAtParam2, TrimSrfEval          M
*                                                                            *
* KEYWORDS:                                                                  M
*   BzrSrfEvalAtParam, evaluation, Bezier                                    M
*****************************************************************************/
CagdRType *BzrSrfEvalAtParam(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
{
    CagdRType *Pt;
    CagdCrvStruct
	*IsoCrv = BzrSrfCrvFromSrf(Srf, u, CAGD_CONST_U_DIR);

    Pt = BzrCrvEvalAtParam(IsoCrv, v);

    CagdCrvFree(IsoCrv);

    return Pt;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Extracts an isoparametric curve out of the given tensor product Bezier     M
* surface in direction Dir at the parameter value of t.                      M
*   Operations should prefer the CONST_U_DIR, in which the extraction is     M
* somewhat faster if that is possible.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To extract an isoparametric ocurve from.                      M
*   t:         Parameter value of extracted isoparametric curve.             M
*   dir:       Direction of the isocurve on the surface. Either U or V.      M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:  An isoparametric curve of Srf. This curve inherits the M
*		      order and continuity of surface Srf in direction Dir.  M
*                                                                            *
* SEE ALSO:                                                                  M
*   CagdCrvFromSrf, BspSrfCrvFromSrf, CagdCrvFromMesh, BzrSrfCrvFromMesh,    M
*   BspSrfCrvFromMesh					                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   BzrSrfCrvFromSrf, isoparametric curves, curve from surface               M
*****************************************************************************/
CagdCrvStruct *BzrSrfCrvFromSrf(CagdSrfStruct *Srf,
				CagdRType t,
				CagdSrfDirType Dir)
{
    CagdCrvStruct
	*Crv = NULL;
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
    int i, j, CrvOrder, VecLen,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
    CagdRType *CrvP, *SrfP;

    switch (Dir) {
	case CAGD_CONST_U_DIR:
	    Crv = BzrCrvNew(CrvOrder = Srf -> VLength, Srf -> PType);
	    VecLen = Srf -> ULength;

	    for (i = IsNotRational; i <= MaxCoord; i++) {
		CrvP = Crv -> Points[i];
		SrfP = Srf -> Points[i];
		for (j = 0; j < CrvOrder; j++) {
		    *CrvP++ = BzrCrvEvalVecAtParam(SrfP, CAGD_NEXT_U(Srf),
								VecLen, t);
		    SrfP += CAGD_NEXT_V(Srf);
		}
	    }
	    break;
	case CAGD_CONST_V_DIR:
	    Crv = BzrCrvNew(CrvOrder = Srf -> ULength, Srf -> PType);
	    VecLen = Srf -> VLength;

	    for (i = IsNotRational; i <= MaxCoord; i++) {
		CrvP = Crv -> Points[i];
		SrfP = Srf -> Points[i];
		for (j = 0; j < CrvOrder; j++) {
		    *CrvP++ = BzrCrvEvalVecAtParam(SrfP, CAGD_NEXT_V(Srf),
								VecLen, t);
		    SrfP += CAGD_NEXT_U(Srf);
		}
	    }
	    break;
	default:
	    CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
	    break;
    }
    return Crv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Extracts a curve from the mesh of a tensor product Bezier surface Srf in   M
* direction Dir at index Index.                                              M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:       To extract a curve from.  		                     M
*   Index:     Index along the mesh of Srf to extract the curve from.        M
*   Dir:       Direction of extracted curve. Either U or V.		     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:   A curve from Srf. This curve inherit the order and    M
*                      continuity of surface Srf in direction Dir. However,  M
*                      thiscurve is not on surface Srf, in general.          M
*                                                                            *
* SEE ALSO:                                                                  M
*   CagdCrvFromSrf, BzrSrfCrvFromSrf, BspSrfCrvFromSrf,                      M
*   CagdCrvFromMesh, BspSrfCrvFromMesh                                       M
*                                                                            *
* KEYWORDS:                                                                  M
*   BzrSrfCrvFromMesh, isoparametric curves, curve from mesh                 M
*****************************************************************************/
CagdCrvStruct *BzrSrfCrvFromMesh(CagdSrfStruct *Srf,
				 int Index,
				 CagdSrfDirType Dir)
{
    CagdCrvStruct
	*Crv = NULL;
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
    int i, j, CrvOrder,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
    CagdRType *CrvP, *SrfP;

    switch (Dir) {
	case CAGD_CONST_U_DIR:
	    if (Index + 1 > Srf -> ULength)
		CAGD_FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);

	    Crv = BzrCrvNew(CrvOrder = Srf -> VLength, Srf -> PType);

	    for (i = IsNotRational; i <= MaxCoord; i++) {
		CrvP = Crv -> Points[i];
		SrfP = Srf -> Points[i] + Index * CAGD_NEXT_U(Srf);
		for (j = 0; j < CrvOrder; j++) {
		    *CrvP++ = *SrfP;
		    SrfP += CAGD_NEXT_V(Srf);
		}
	    }
	    break;
	case CAGD_CONST_V_DIR:
	    if (Index + 1 > Srf -> VLength)
		CAGD_FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);

	    Crv = BzrCrvNew(CrvOrder = Srf -> ULength, Srf -> PType);

	    for (i = IsNotRational; i <= MaxCoord; i++) {
		CrvP = Crv -> Points[i];
		SrfP = Srf -> Points[i] + Index * CAGD_NEXT_V(Srf);
		for (j = 0; j < CrvOrder; j++) {
		    *CrvP++ = *SrfP;
		    SrfP += CAGD_NEXT_U(Srf);
		}
	    }
	    break;
	default:
	    CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
	    break;
    }
    return Crv;
}

