/******************************************************************************
* Bsp-Wrt.c - Bspline handling routines - write to file.		      *
*******************************************************************************
* Written by Gershon Elber, Aug. 90.					      *
******************************************************************************/

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

/******************************************************************************
* Writes a bspline curve(s) list into file. Returns TRUE if succesful, FALSE  *
* otherwise.								      *
* If Comment is NULL, no comment is printed, if "" only internal coment.      *
******************************************************************************/
int BspCrvWriteToFile(CagdCrvStruct *Crvs, char *FileName, int Indent,
						 char *Comment, char **ErrStr)
{
    int i;
    FILE *f;

    if ((f = fopen(FileName, "w")) == NULL) {
	*ErrStr = "Fail to open file";
	return FALSE;
    }
    i = BspCrvWriteToFile2(Crvs, f, Indent, Comment, ErrStr);

    fclose(f);

    return i;
}

/******************************************************************************
* Writes a bspline curve(s) list into file. Returns TRUE if succesful, FALSE  *
* otherwise. The file is not closed.					      *
* If Comment is NULL, no comment is printed, if "" only internal coment.      *
******************************************************************************/
int BspCrvWriteToFile2(CagdCrvStruct *Crvs, FILE *f, int Indent, char *Comment,
								char **ErrStr)
{
    int i, j, Len, MaxCoord;

    if (Comment != NULL) {
	_CagdFprintf(f, Indent, "#\n");
	_CagdFprintf(f, Indent, "# cagd_lib - bspline curve(s) dump.\n");
	_CagdFprintf(f, Indent, "#\n");
	_CagdFprintf(f, Indent, "# %s\n", Comment);
	_CagdFprintf(f, Indent, "#\n");
    }

    *ErrStr = NULL;

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

	if (Crvs -> GType != CAGD_CBSPLINE_TYPE) {
	    *ErrStr = "Given curve(s) is (are) not Bspline curve(s)";
	    break;
	}
	_CagdFprintf(f, Indent, "[CURVE BSPLINE %d %d %c%c\n",
		Crvs -> Length, Crvs -> Order,
		CAGD_IS_RATIONAL_PT(Crvs -> PType) ? 'P' : 'E',
		MaxCoord + '0');
	Indent += 4;

	/* Put out the knot vectors: */
	_CagdFprintf(f, Indent, "[KV");
	Len = Crvs -> Order + Crvs -> Length;
	for (i = 0; i < Len; i++) {
	    _CagdFprintf(f, 0, " %s", _CagdReal2Str(Crvs -> KnotVector[i]));
	    if (i && i % 8 == 0) {
		_CagdFprintf(f, 0, "\n");
		_CagdFprintf(f, Indent + 3, "");
	    }
	}
	_CagdFprintf(f, 0, "]\n");

	/* Put out the control polygon. */
	for (i = 0; i < Crvs -> Length; i++) {
	    _CagdFprintf(f, Indent, "[");
	    if (CAGD_IS_RATIONAL_PT(Crvs -> PType))
		_CagdFprintf(f, 0, "%s ", _CagdReal2Str(Crvs -> Points[0][i]));
	    for (j = 1; j <= MaxCoord; j++) {
		_CagdFprintf(f, 0, "%s", _CagdReal2Str(Crvs -> Points[j][i]));
		if (j < MaxCoord)
		    _CagdFprintf(f, 0, " ");
	    }
	    _CagdFprintf(f, 0, "]\n");
	}

	Indent -= 4;
	_CagdFprintf(f, Indent, "]\n\n");

	Crvs = Crvs -> Pnext;
    }

    return *ErrStr == NULL;
}

/******************************************************************************
* Writes a bspline curve(s) list into file. Returns TRUE if succesful, FALSE  *
* otherwise.								      *
******************************************************************************/
int BspSrfWriteToFile(CagdSrfStruct *Srfs, char *FileName, int Indent,
						 char *Comment,	char **ErrStr)
{
    int i;
    FILE *f;

    if ((f = fopen(FileName, "w")) == NULL) {
	*ErrStr = "Fail to open file";
	return FALSE;
    }
    i = BspSrfWriteToFile2(Srfs, f, Indent, Comment, ErrStr);

    fclose(f);

    return i;
}

/******************************************************************************
* Writes a bspline curve(s) list into file. Returns TRUE if succesful, FALSE  *
* otherwise. The file is not closed.					      *
******************************************************************************/
int BspSrfWriteToFile2(CagdSrfStruct *Srfs, FILE *f, int Indent, char *Comment,
								char **ErrStr)
{
    int i, j, Len, MaxCoord;
    CagdRType *KnotVector;

    if (Comment != NULL) {
	_CagdFprintf(f, Indent, "#\n");
	_CagdFprintf(f, Indent, "# cagd_lib - bspline Srf(s) dump.\n");
	_CagdFprintf(f, Indent, "#\n");
	_CagdFprintf(f, Indent, "# %s\n", Comment);
	_CagdFprintf(f, Indent, "#\n");
    }

    *ErrStr = NULL;

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

	if (Srfs -> GType != CAGD_SBSPLINE_TYPE) {
	    *ErrStr = "Given surface(s) is (are) not bspline surface(s)";
	    break;
	}
	_CagdFprintf(f, Indent, "[SURFACE BSPLINE %d %d %d %d %c%c\n",
		Srfs -> ULength, Srfs -> VLength,
		Srfs -> UOrder, Srfs -> VOrder,
		CAGD_IS_RATIONAL_PT(Srfs -> PType) ? 'P' : 'E',
		MaxCoord + '0');
	Indent += 4;

	/* Put out the knot vectors: */
	for (i = 0; i < 2; i++) {
	    if (i == 0) {
		KnotVector = Srfs -> UKnotVector;
		Len = Srfs -> ULength + Srfs -> UOrder;
	    }
	    else {
		KnotVector = Srfs -> VKnotVector;
		Len = Srfs -> VLength + Srfs -> VOrder;
	    }

	    _CagdFprintf(f, Indent, "[KV");
	    for (j = 0; j < Len; j++) {
		_CagdFprintf(f, 0, " %s", _CagdReal2Str(KnotVector[j]));
		if (j && j % 8 == 0) {
		    _CagdFprintf(f, 0, "\n\t\t");
		    _CagdFprintf(f, Indent + 3, "");
		}
	    }
	    _CagdFprintf(f, 0, "]\n");
	}

	/* Put out the control mesh. */
	for (i = 0; i < Srfs -> VLength * Srfs -> ULength; i++) {
	    if (i && i % Srfs -> ULength == 0)
		_CagdFprintf(f, 0, "\n");    /* Put empty lines between raws. */

	    _CagdFprintf(f, Indent, "[");
	    if (CAGD_IS_RATIONAL_PT(Srfs -> PType))
		_CagdFprintf(f, 0, "%s ", _CagdReal2Str(Srfs -> Points[0][i]));
	    for (j = 1; j <= MaxCoord; j++) {
		_CagdFprintf(f, 0, "%s", _CagdReal2Str(Srfs -> Points[j][i]));
		if (j < MaxCoord) _CagdFprintf(f, 0, " ");
	    }
	    _CagdFprintf(f, 0, "]\n");
	}

	Indent -= 4;
	_CagdFprintf(f, Indent, "]\n\n");

	Srfs = Srfs -> Pnext;
    }

    return *ErrStr == NULL;
}
