Metropoli BBS
VIEWER: dat2irit.c MODE: TEXT (ASCII)
/*****************************************************************************
* Filter to convert IRIT data files back to IRIT .irt files.		     *
*									     *
* Written by:  Gershon Elber				Ver 1.0, Sep 1991    *
*****************************************************************************/

#ifdef __MSDOS__
#include <dos.h>
#include <alloc.h>
#endif /* __MSDOS__ */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include "irit_sm.h"
#include "iritprsr.h"
#include "getarg.h"
#include "genmat.h"

#ifdef __MSDOS__
extern unsigned int _stklen = 32766;	     /* Increase default stack size. */
#endif /* __MSDOS__ */

#ifdef NO_CONCAT_STR
static char *VersionStr =
	"Dat2Irit		Version 3.0,		Gershon Elber,\n\
	 (C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
#else
static char *VersionStr = "Dat2Irit	" VERSION ",	Gershon Elber,	"
	__DATE__ ",   " __TIME__ "\n"
	"(C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
#endif /* NO_CONCAT_STR */

static char
    *CtrlStr = "dat2irit z%- DFiles!*s";

static IPObjectStruct *MainGetDataFiles(char **DataFileNames,
					int NumOfDataFiles);
static void DumpDataForIrit(IPObjectStruct *PObjects);
static void DumpOneObject(FILE *f, IPObjectStruct *PObject);
static void DumpOnePolygon(FILE *f, IPPolygonStruct *PPolygon, int PolyNum);
static void DumpOneSurface(FILE *f, char *Name, CagdSrfStruct *Srf);
static void DumpOneCurve(FILE *f, char *Name, CagdCrvStruct *Crv);
static void DumpCtlPt(FILE *f, CagdPointType PType, RealType **Points,
								int Index);
static void DumpKnotVector(FILE *f, RealType *KnotVector, int Length);

#ifdef __DEBUG_MALLOC__
static void AllocError(const char *Msg, VoidPtr *p);
#endif /* __DEBUG_MALLOC__ */
VoidPtr MyMalloc(unsigned size);
void MyFree(VoidPtr p);
void CagdFatalError(CagdFatalErrorType ErrID);
void MyExit(int ExitCode);

/*****************************************************************************
* Main routine - Read Parameter	line and do what you need...		     *
*****************************************************************************/
void main(int argc, char **argv)
{
    int Error,
	VerFlag = FALSE,
	NumFiles = 0;
    char
	**FileNames = NULL;
    IPObjectStruct *PObjects;

#ifdef __MSDOS__
    ctrlbrk((int (*)()) MyExit);		      /* Kill process if ^C. */
#endif /* __MSDOS__ */

    if ((Error = GAGetArgs (argc, argv, CtrlStr,
			    &VerFlag, &NumFiles, &FileNames)) != 0) {
	GAPrintErrMsg(Error);
	GAPrintHowTo(CtrlStr);
	MyExit(1);
    }

    if (VerFlag) {
	fprintf(stderr, "\n%s\n\n", VersionStr);
	GAPrintHowTo(CtrlStr);
	MyExit(0);
    }

    if (!NumFiles) {
	fprintf(stderr, "No data file names where given, exit.\n");
	GAPrintHowTo(CtrlStr);
	MyExit(1);
    }

    /* Get the data files: */
    IritPrsrPolyListCirc = FALSE;
    PObjects = MainGetDataFiles(FileNames, NumFiles);

    DumpDataForIrit(PObjects);

    MyExit(0);
}

/*****************************************************************************
* Main routine to read the data	description files:			     *
* Returns pointer to pointers on FileDescription structures (one per file).  *
*****************************************************************************/
static IPObjectStruct *MainGetDataFiles(char **DataFileNames,
					int NumOfDataFiles)
{
    int	i;
    FILE *f;
    IPObjectStruct *PObj, *PObjTail,
	*PObjHead = NULL;

    for	(i = 0; i < NumOfDataFiles; i++) {
#ifdef __MSDOS__
	if ((f = fopen(*DataFileNames, "rt")) == NULL) {   /* Open the file. */
#else
	if ((f = fopen(*DataFileNames, "r")) == NULL) {    /* Open the file. */
#endif /* __MSDOS__ */
	    fprintf(stderr, "Can't open data file %s\n", *DataFileNames);
	    MyExit(1);
	}

	if ((PObj = IritPrsrGetObjects(f)) != NULL) {  /* Get the data file. */
	    PObjTail = PObj;
	    while (PObjTail -> Pnext) PObjTail = PObjTail -> Pnext;
	    PObjTail -> Pnext = PObjHead;
	    PObjHead = PObj;
	}

	fclose(f);					  /* Close the file. */

	DataFileNames++;			  /* Skip to next file name. */
    }

    if (PObjHead == NULL) {
	fprintf(stderr, "No data found.\n");
	MyExit(1);
    }

    return PObjHead;
}

/*****************************************************************************
* Routine to handle all surfaces/curves. Simple chain them into a linear     *
* list and return it.							     *
*****************************************************************************/
IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
					IPObjectStruct *SrfObjs)
{
    if (CrvObjs == NULL)
	return SrfObjs;
    else if (SrfObjs == NULL)
	return CrvObjs;
    else {
	IPObjectStruct *PTmp = CrvObjs;

	while (PTmp -> Pnext) PTmp = PTmp -> Pnext;
	PTmp -> Pnext = SrfObjs;
	return CrvObjs;
    }
}

/*****************************************************************************
* Dumps the data for ray shade into stdout.				     *
*****************************************************************************/
static void DumpDataForIrit(IPObjectStruct *PObjects)
{
    int NameCount = 1;
    IPObjectStruct *PObj,
	*PObjHead = NULL;

    /* Reverse object list since it was loaded in reverse by iritprsr module.*/
    while (PObjects != NULL) {
	PObj = PObjects;
	PObjects = PObjects -> Pnext;
	PObj -> Pnext = PObjHead;
	PObjHead = PObj;
    }

    for (PObjects = PObjHead; PObjects != NULL; PObjects = PObjects -> Pnext)
	DumpOneObject(stdout, PObjects);

    printf("\n\ndat2irit = list(\n");
    for (PObjects = PObjHead; PObjects != NULL; PObjects = PObjects -> Pnext)
    if (PObjects -> Name == NULL || strlen(PObjects -> Name) == 0)
	printf("\tNoName%d%s\n",
	       NameCount++, PObjects -> Pnext == NULL ? "" : ",");
    else
	printf("\t%s%s\n",
	       PObjects -> Name, PObjects -> Pnext == NULL ? "" : ",");
    printf(");\n");

}

/*****************************************************************************
* Routine to dump one object PObject.					     *
*****************************************************************************/
static void DumpOneObject(FILE *f, IPObjectStruct *PObject)
{
    static int
	NameCount = 1;
    int i, j;
    char Name[LINE_LEN_LONG];
    CagdSrfStruct *Srf;
    CagdCrvStruct *Crv;
    IPPolygonStruct *Pl;

    if (PObject -> Name == NULL || strlen(PObject -> Name) == 0)
	sprintf(Name, "NoName%d", NameCount++);
    else
	strcpy(Name, PObject -> Name);

    switch (PObject -> Type) {
	case IP_OBJ_POLY:
	    for (Pl = PObject -> U.PPolygon, i = 1;
		 Pl != NULL;
		 Pl = Pl -> Pnext, i++)
		DumpOnePolygon(f, Pl, i);
	    fprintf(f, "%s = mergePoly( list( ", Name);
	    for (j = 1; j < i; j++) {
		if (j % 7 == 0) fprintf(f, "\n\t\t");
		fprintf(f, "POLY%d%s ", j, j == i - 1 ? "" : ",");
	    }
	    printf(") );\n\n");
	    break;
	case IP_OBJ_SURFACE:
	    for (Srf = PObject -> U.PSrfs; Srf != NULL; Srf = Srf -> Pnext)
		DumpOneSurface(stdout, Name, Srf);
	    break;
	case IP_OBJ_CURVE:
	    for (Crv = PObject -> U.PCrvs; Crv != NULL; Crv = Crv -> Pnext)
		DumpOneCurve(stdout, Name, Crv);
	    break;
    }
}

/*****************************************************************************
* Routine to dump one polygon.						     *
*****************************************************************************/
static void DumpOnePolygon(FILE *f, IPPolygonStruct *PPolygon, int PolyNum)
{
    int i,
	VCount = 1;
    IPVertexStruct
	*V = PPolygon -> PVertex,
	*VFirst = V;

    do {
	fprintf(f, "VRTX%d = vector( %lg, %lg, %lg );\n", VCount++,
		V -> Coord[0], V -> Coord[1], V -> Coord[2]);
	V = V -> Pnext;
    }
    while (V != VFirst && V != NULL);

    fprintf(f, "POLY%d = poly( list( ", PolyNum );
    for (i = 1; i < VCount; i++) {
	if (VCount % 9 == 0) fprintf(f, "\n\t\t");
	fprintf(f, "VRTX%d%s ", i, i == VCount - 1 ? "" : "," );
    }
    fprintf(f, ") );\n\n");
}

/*****************************************************************************
* Routine to dump one surface.						     *
*****************************************************************************/
static void DumpOneSurface(FILE *f, char *Name, CagdSrfStruct *Srf)
{
    int i, j, k;

    switch (Srf -> GType) {
	case CAGD_SBEZIER_TYPE:
	    fprintf(f, "%s = sbezier(\n", Name);
	    break;
	case CAGD_SBSPLINE_TYPE:
	    fprintf(f, "%s = sbspline( %d, %d, \n", Name,
		    Srf -> UOrder, Srf -> VOrder);
	    break;
	default:
	    fprintf(stderr, "Unsupported surface type ignored.\n");
	    return;
    }

    /* Print the control mesh: */
    for (i = k = 0; i < Srf -> VLength; i++) {
	for (j = 0; j < Srf -> ULength; j++) {
	    fprintf(f, "%s", i == 0 && j == 0 ? "\tlist( " : "\t      ");
	    fprintf(f, "%s", j == 0 ? "list( " : "      ");
	    DumpCtlPt(f, Srf -> PType, Srf -> Points, k++);
	    fprintf(f, "%s", j == Srf -> ULength - 1 ? " )" : ",\n" );
	}
	if (i < Srf -> VLength - 1) fprintf(f, ",\n");
    }

    switch (Srf -> GType) {
	case CAGD_SBEZIER_TYPE:
	    fprintf(f, " ) );\n");
	    break;
	case CAGD_SBSPLINE_TYPE:
	    fprintf(f, " ),\n\tlist( ");
	    DumpKnotVector(f, Srf -> UKnotVector,
			   Srf -> UOrder + Srf -> ULength);
	    fprintf(f, ",\n\t      ");
	    DumpKnotVector(f, Srf -> VKnotVector,
			   Srf -> VOrder + Srf -> VLength);
	    fprintf(f, " ) );\n");
	    break;
    }
}

/*****************************************************************************
* Routine to dump one curve.						     *
*****************************************************************************/
static void DumpOneCurve(FILE *f, char *Name, CagdCrvStruct *Crv)
{
    int i;

    switch (Crv -> GType) {
	case CAGD_CBEZIER_TYPE:
	    fprintf(f, "%s = cbezier(\n", Name);
	    break;
	case CAGD_CBSPLINE_TYPE:
	    fprintf(f, "%s = cbspline( %d,\n", Name, Crv -> Order);
	    break;
	default:
	    fprintf(stderr, "Unsupported curve type ignored.\n");
	    return;
    }

    /* Print the control polygon: */
    fprintf(f, "\tlist( ");
    for (i = 0; i < Crv -> Length; i++) {
	DumpCtlPt(f, Crv -> PType, Crv -> Points, i);
	if (i < Crv -> Length - 1) fprintf(f, ",\n\t      ");
    }

    switch (Crv -> GType) {
	case CAGD_CBEZIER_TYPE:
	    fprintf(f, " ) );\n");
	    break;
	case CAGD_CBSPLINE_TYPE:
	    fprintf(f, " ),\n\t ");
	    DumpKnotVector(f, Crv -> KnotVector, Crv -> Order + Crv -> Length);
	    fprintf(f, " );\n");
	    break;
    }
}

/*****************************************************************************
* Routine to dump one control point.					     *
*****************************************************************************/
static void DumpCtlPt(FILE *f, CagdPointType PType, RealType **Points,
								int Index)
{
    fprintf(f, "ctlpt( ");
    switch (PType) {
	case CAGD_PT_E2_TYPE:
	    fprintf(f, "E2, %lg, %lg",
		    Points[1][Index],
		    Points[2][Index]);
	    break;
	case CAGD_PT_P2_TYPE:
	    fprintf(f, "P2, %lg, %lg, %lg",
		    Points[0][Index],
		    Points[1][Index],
		    Points[2][Index]);
	    break;
	case CAGD_PT_E3_TYPE:
	    fprintf(f, "E3, %lg, %lg, %lg",
		    Points[1][Index],
		    Points[2][Index],
		    Points[3][Index]);
	    break;
	case CAGD_PT_P3_TYPE:
	    fprintf(f, "P3, %lg, %lg, %lg, %lg",
		    Points[0][Index],
		    Points[1][Index],
		    Points[2][Index],
		    Points[3][Index]);
	    break;
	default:
	    fprintf(stderr, "Unsupported control point type.\n");
	    MyExit(1);
    }
    fprintf(f, " )");
}

/*****************************************************************************
* Routine to dump one knot vector.					     *
*****************************************************************************/
static void DumpKnotVector(FILE *f, RealType *KnotVector, int Length)
{
    int i;

    fprintf(f, "list( ");
    for (i = 0; i < Length; i++)
	fprintf(f, "%lg%s ", KnotVector[i], i < Length -1 ? "," : "");
    fprintf(f, ")");
}

#ifdef __DEBUG_MALLOC__
/*****************************************************************************
* My Routine to	allocate dynamic memory. All program requests must call this *
* routine (no direct call to malloc). Dies if no memory.		     *
*****************************************************************************/
static void AllocError(const char *Msg, VoidPtr *p)
{
    fprintf(stderr, "%s, Ptr = %p\n", Msg, p);
    MyExit(3);
}
#endif /* __DEBUG_MALLOC__ */

/*****************************************************************************
* My Routine to	allocate dynamic memory. All program requests must call this *
* routine (no direct call to malloc). Dies if no memory.		     *
*****************************************************************************/
VoidPtr MyMalloc(unsigned size)
{
    static int Count = 0;
    VoidPtr p;

#ifdef __MSDOS__
    if (Count++ == 50) {
	Count = 0;
	fprintf(stderr, "Core left: %ldk   \r", coreleft() / 1024);
    }
#endif /* __MSDOS__ */

    if ((p = malloc(size)) != NULL) return p;

    fprintf(stderr, "Not enough memory, exit.\n");
    MyExit(2);

    return NULL;				    /* Make warnings silent. */
}

/*****************************************************************************
* My Routine to	free dynamic memory. All program requests must call this     *
* routine (no direct call to free).					     *
*****************************************************************************/
void MyFree(VoidPtr p)
{
#ifdef __DEBUG_MALLOC__
    switch (heapchecknode(p)) {
	case _HEAPCORRUPT:
	    AllocError("Heap is corrupted", p);
	    break;
	case _BADNODE:
	    AllocError("Attempt to free a bogus pointer", p);
	    break;
	case _FREEENTRY:
	    AllocError("Attempt to free an already freed pointer", p);
	    break;
	case _USEDENTRY:
	    break;
	default:
	    AllocError("Allocation error", p);
	    break;

    }
#endif /* __DEBUG_MALLOC__ */

    free(p);
}

/*****************************************************************************
* Trap Cagd_lib errors right here.					     *
*****************************************************************************/
void CagdFatalError(CagdFatalErrorType ErrID)
{
    char
	*ErrorMsg = CagdDescribeError(ErrID);

    fprintf(stderr, "CAGD_LIB: %s", ErrorMsg);

    exit(-1);
}

/*****************************************************************************
* MyExit routine. Note it might call to CloseGraph without calling	     *
* InitGraph(), or call MouseClose() without MouseInit() etc. and it is the   *
* responsibility of the individual modules to do nothing in these cases.     *
*****************************************************************************/
void MyExit(int ExitCode)
{
#ifdef __MSDOS__
    fprintf(stderr,
	    "\nIrit2Ray: Core left %ldk.\n", coreleft() / 1024);
#endif /* __MSDOS__ */

    exit(ExitCode);
}
[ RETURN TO DIRECTORY ]