/******************************************************************************
* Triv_Wrt.c - Trivariate writing to files.				      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, Sep. 94.					      *
******************************************************************************/

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

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write trivariates to the given file.		     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in file f.                                        M
*   FileName:  File name where output should go to.                          M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVWriteToFile, files, write,trivariates                              M
*****************************************************************************/
int TrivTVWriteToFile(TrivTVStruct *TVs,
		      char *FileName,
		      int Indent,
		      char *Comment,
		      char **ErrStr)
{
    int RetVal = TRUE;
    TrivTVStruct *NextTV;

    for (; TVs != NULL && RetVal; TVs = TVs -> Pnext) {
	NextTV = TVs -> Pnext;      /* To make sure we dump one at a time. */
	TVs -> Pnext = NULL;

	switch (TVs -> GType) {
	    case TRIV_TVBEZIER_TYPE:
		RetVal = TrivBzrTVWriteToFile(TVs, FileName, Indent, Comment,
					      ErrStr);
		break;
	    case TRIV_TVBSPLINE_TYPE:
		RetVal = TrivBspTVWriteToFile(TVs, FileName, Indent, Comment,
					      ErrStr);
		break;
	    default:
		*ErrStr = "BSPLINE or BEZIER Token expected";
		return FALSE;
	}

	TVs -> Pnext = NextTV;
    }

    return RetVal;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write trivariates to the given file.		     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in stream.                                        M
*   Handler:   A handler to the open stream.				     M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVWriteToFile2, files, write, trivariates                            M
*****************************************************************************/
int TrivTVWriteToFile2(TrivTVStruct *TVs,
		       int Handler,
		       int Indent,
		       char *Comment,
		       char **ErrStr)
{
    int RetVal = TRUE;
    TrivTVStruct *NextTV;

    for (; TVs != NULL && RetVal; TVs = TVs -> Pnext) {
	NextTV = TVs -> Pnext;	     /* To make sure we dump one at a time. */
	TVs -> Pnext = NULL;

	switch (TVs -> GType) {
	    case TRIV_TVBEZIER_TYPE:
		RetVal = TrivBzrTVWriteToFile2(TVs, Handler, Indent, Comment,
					       ErrStr);
		break;
	    case TRIV_TVBSPLINE_TYPE:
		RetVal = TrivBspTVWriteToFile2(TVs, Handler, Indent, Comment,
					       ErrStr);
		break;
	    default:
		*ErrStr = "BSPLINE or BEZIER Token expected";
		return FALSE;
	}

	TVs -> Pnext = NextTV;
    }

    return RetVal;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write trivariate(s) to the given file.		     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in file f.                                        M
*   f:         File descriptor where output should go to.                    M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivTVWriteToFile3, files, write                                         M
*****************************************************************************/
int TrivTVWriteToFile3(TrivTVStruct *TVs,
		       FILE *f,
		       int Indent,
		       char *Comment,
		       char **ErrStr)
{
    int
	Handler = IritPrsrOpenStreamFromFile(f, FALSE, FALSE, FALSE),
	i = TrivTVWriteToFile2(TVs, Handler, Indent, Comment, ErrStr);

    IritPrsrCloseStream(Handler, TRUE);

    return i;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write Bezier trivariates to the given file.	     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in file.                                          M
*   FileName:  File name where output should go to.                          M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBzrTVWriteToFile, files, write,trivariates                           M
*****************************************************************************/
int TrivBzrTVWriteToFile(TrivTVStruct *TVs,
			 char *FileName,
			 int Indent,
			 char *Comment,
			 char **ErrStr)
{
    int i, Handler;
    FILE *f;

    if ((f = fopen(FileName, "w")) == NULL) {
	*ErrStr = "Fail to open file";
	return FALSE;
    }
    Handler = IritPrsrOpenStreamFromFile(f, FALSE,
					 IritPrsrSenseBinaryFile(FileName),
					 FALSE);

    i = TrivBzrTVWriteToFile2(TVs, Handler, Indent, Comment, ErrStr);

    IritPrsrCloseStream(Handler, TRUE);

    return i;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write Bezier trivariates to the given file.	     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in stream.                                        M
*   Handler:   A handler to the open stream.				     M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBzrTVWriteToFile2, files, write, trivariates                         M
*****************************************************************************/
int TrivBzrTVWriteToFile2(TrivTVStruct *TVs,
			  int Handler,
			  int Indent,
			  char *Comment,
			  char **ErrStr)
{
    int i, j, MaxCoord;

    if (Comment != NULL) {
	_IPFprintf(Handler, Indent, "#\n");
	_IPFprintf(Handler, Indent, "# cagd_lib - bezier TV(s) dump.\n");
	_IPFprintf(Handler, Indent, "#\n");
	_IPFprintf(Handler, Indent, "# %s\n", Comment);
	_IPFprintf(Handler, Indent, "#\n");
    }

    *ErrStr = NULL;

    while (TVs) {
	MaxCoord = CAGD_NUM_OF_PT_COORD(TVs -> PType);

	if (TVs -> GType != TRIV_TVBEZIER_TYPE) {
	    *ErrStr = "Given tri-variate(s) is (are) not BEZIER trivariate(s)";
	    break;
	}
	_IPFprintf(Handler, Indent, "[TRIVAR BEZIER %d %d %d %c%c\n",
		TVs -> ULength, TVs -> VLength, TVs -> WLength,
		CAGD_IS_RATIONAL_PT(TVs -> PType) ? 'P' : 'E',
		MaxCoord + '0');
	Indent += 4;

	for (i = 0;
	     i < TVs -> VLength * TVs -> ULength * TVs -> WLength;
	     i++) {
	    if (i && i % TVs -> ULength == 0)
		_IPFprintf(Handler, 0, "\n"); /* Put empty line between raws.*/
	    if (i && i % TVs -> UVPlane == 0)
		_IPFprintf(Handler, 0, "\n");   /* Put 2 lns between planes. */

	    _IPFprintf(Handler, Indent, "[");
	    if (CAGD_IS_RATIONAL_PT(TVs -> PType))
		_IPFprintf(Handler, 0, "%s ",
			   _IPReal2Str(TVs -> Points[0][i]));
	    for (j = 1; j <= MaxCoord; j++) {
		_IPFprintf(Handler, 0, "%s",
			   _IPReal2Str(TVs -> Points[j][i]));
		if (j < MaxCoord)
		    _IPFprintf(Handler, 0, " ");
	    }
	    _IPFprintf(Handler, 0, "]\n");
	}

	Indent -= 4;
	_IPFprintf(Handler, Indent, "]\n");

	TVs = TVs -> Pnext;
    }

    return *ErrStr == NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write Bspline trivariates to the given file.	     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in file f.                                        M
*   FileName:  File name where output should go to.                          M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBzrTVWriteToFile, files, write,trivariates                           M
*****************************************************************************/
int TrivBspTVWriteToFile(TrivTVStruct *TVs,
			 char *FileName,
			 int Indent,
			 char *Comment,
			 char **ErrStr)
{
    int i, Handler;
    FILE *f;

    if ((f = fopen(FileName, "w")) == NULL) {
	*ErrStr = "Fail to open file";
	return FALSE;
    }
    Handler = IritPrsrOpenStreamFromFile(f, FALSE,
					 IritPrsrSenseBinaryFile(FileName),
					 FALSE);

    i = TrivBspTVWriteToFile2(TVs, Handler, Indent, Comment, ErrStr);

    IritPrsrCloseStream(Handler, TRUE);

    return i;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generic routine to write Bspline trivariates to the given file.	     M
*   If Comment is NULL, no comment is printed, if "" only internal comment.  M
*                                                                            *
* PARAMETERS:                                                                M
*   TVs:       To be saved in stream.                                        M
*   Handler:   A handler to the open stream.				     M
*   Indent:    Column in which all printing starts at.                       M
*   Comment:   Optional comment to describe the geometry.                    M
*   ErrStr:    If failed, ErrStr will be set to describe the problem.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if succesful, FALSE otherwise.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   TrivBspTVWriteToFile2, files, write, trivariates                         M
*****************************************************************************/
int TrivBspTVWriteToFile2(TrivTVStruct *TVs,
			  int Handler,
			  int Indent,
			  char *Comment,
			  char **ErrStr)
{
    int i, j, Len, MaxCoord;
    CagdRType *KnotVector;

    if (Comment != NULL) {
	_IPFprintf(Handler, Indent, "#\n");
	_IPFprintf(Handler, Indent, "# cagd_lib - bspline TV(s) dump.\n");
	_IPFprintf(Handler, Indent, "#\n");
	_IPFprintf(Handler, Indent, "# %s\n", Comment);
	_IPFprintf(Handler, Indent, "#\n");
    }

    *ErrStr = NULL;

    while (TVs) {
	MaxCoord = CAGD_NUM_OF_PT_COORD(TVs -> PType);

	if (TVs -> GType != TRIV_TVBSPLINE_TYPE) {
	    *ErrStr = "Given tri-variate(s) is (are) not Bspline trivariate(s)";
	    break;
	}
	_IPFprintf(Handler, Indent, "[TRIVAR BSPLINE %d %d %d %d %d %d %c%c\n",
		TVs -> ULength, TVs -> VLength, TVs -> WLength,
		TVs -> UOrder, TVs -> VOrder, TVs -> WOrder,
		CAGD_IS_RATIONAL_PT(TVs -> PType) ? 'P' : 'E',
		MaxCoord + '0');
	Indent += 4;

	/* Put out the knot vectors: */
	for (i = 0; i < 3; i++) {
	    switch (i) {
		case 0:
		    KnotVector = TVs -> UKnotVector;
		    Len = TVs -> ULength + TVs -> UOrder;
		    break;
		case 1:
		    KnotVector = TVs -> VKnotVector;
		    Len = TVs -> VLength + TVs -> VOrder;
		    break;
		default:
		case 2:
		    KnotVector = TVs -> WKnotVector;
		    Len = TVs -> WLength + TVs -> WOrder;
		    break;
	    }

	    _IPFprintf(Handler, Indent, "[KV");
	    for (j = 0; j < Len; j++) {
		if (j && j % MAX_KNOTS_PER_LINE == 0) {
		    _IPFprintf(Handler, 0, "\n");
		    _IPFprintf(Handler, Indent + 4, "");
		}
		_IPFprintf(Handler, 0, " %s", _IPReal2Str(KnotVector[j]));
	    }
	    _IPFprintf(Handler, 0, "]\n");
	}

	/* Put out the control mesh. */
	for (i = 0;
	     i < TVs -> VLength * TVs -> ULength * TVs -> WLength;
	     i++) {
	    if (i && i % TVs -> ULength == 0)
		_IPFprintf(Handler, 0, "\n"); /* Put empty line between raws.*/
	    if (i && i % TVs -> UVPlane == 0)
		_IPFprintf(Handler, 0, "\n");   /* Put 2 lns between planes. */

	    _IPFprintf(Handler, Indent, "[");
	    if (CAGD_IS_RATIONAL_PT(TVs -> PType))
		_IPFprintf(Handler, 0, "%s ",
			   _IPReal2Str(TVs -> Points[0][i]));
	    for (j = 1; j <= MaxCoord; j++) {
		_IPFprintf(Handler, 0, "%s",
			   _IPReal2Str(TVs -> Points[j][i]));
		if (j < MaxCoord)
		    _IPFprintf(Handler, 0, " ");
	    }
	    _IPFprintf(Handler, 0, "]\n");
	}

	Indent -= 4;
	_IPFprintf(Handler, Indent, "]\n");

	TVs = TVs -> Pnext;
    }

    return *ErrStr == NULL;
}
