/*****************************************************************************
*   "Irit" - the 3d (not only polygonal) solid modeller.		     *
*									     *
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
*   Module to handle the objects list - fetch, insert, delete etc...	     *
*****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "primitiv.h"
#include "decimate.h"
#include "geomat3d.h"
#include "objects.h"
#include "freeform.h"

static int
    GlblDumpLvl = DEFAULT_DUMPLVL;

static void UpdateLoadedHierarchy(IPObjectStruct *PObj, IPObjectStruct *Root);
static int MatGenMatGeneric(IPObjectStruct *LstObjList, MatrixType Mat);

/*****************************************************************************
* DESCRIPTION:                                                               M
* Frees an Object - delete it from global active list and free all it memory M
* Assumes all references to this object are removed from this point on.      M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:       Object to free.                                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   FreeObject                                                               M
*****************************************************************************/
void FreeObject(IPObjectStruct *PObj)
{
    /* Force free the object. Since the reference count should be actually   */
    /* two (second for the parsing tree reference) we decrement it here.     */
    if (PObj -> Count == 2) {
	PObj -> Count = 1;
	DeleteObject(PObj, TRUE);
    }
    else {
	/* Reduce the reference count by two - one for the parsing tree      */
	/* this routine was called from and one for the fact this object     */
	/* reference count is to be deleted since this routine was called.   */
	DeleteObject(PObj, FALSE);
	PObj -> Count -= 2;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Delete object by its pointer - scans the object linear list.		     M
*   The deleted object is freed only if Free = TRUE.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:      Object to delete from global object list.                     M
*   Free:      Do we want to free it as well?                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   DeleteObject                                                             M
*****************************************************************************/
void DeleteObject(IPObjectStruct *PObj, int Free)
{
    IPObjectStruct
	*PObjScan = GlblObjList;

    if (GlblObjList == NULL)
	return;

    if (PObj == GlblObjList) {	   /* If it is the first one - special case. */
	GlblObjList = GlblObjList -> Pnext;
	if (Free)
	    IPFreeObject(PObj);
	return;
    }

    while (PObjScan -> Pnext) {
	if (PObj == PObjScan -> Pnext) {
	    /* Delete it from list. */
	    PObjScan -> Pnext = PObjScan -> Pnext -> Pnext;
	    if (Free)
		IPFreeObject(PObj);			     /* And free it. */
	    return;
	}
	PObjScan = PObjScan -> Pnext;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Inserts an object by its pointer - as first in object linear list.	     M
*    It is assumed the object is not in the object list already.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:     Object to insert to global list.                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   InsertObject                                                             M
*****************************************************************************/
void InsertObject(IPObjectStruct *PObj)
{
    PObj -> Count++;    /* Have one reference count from global object list. */
    PObj -> Pnext = GlblObjList;
    GlblObjList = PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Sets dumping level values for variables and expression's results.          M
*                                                                            *
* PARAMETERS:                                                                M
*   DumpLvl:  New dump level.				                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   SetDumpLevel                                                             M
*****************************************************************************/
void SetDumpLevel(int DumpLvl)
{
    GlblDumpLvl = DumpLvl;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Print some usefull info on the given object.			     	     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:      To print out.                                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PrintObject                                                              M
*****************************************************************************/
void PrintObject(IPObjectStruct *PObj)
{
    int Count = PObj -> Count;
    char Line[LINE_LEN_LONG],
	*Name = (int) strlen(PObj -> Name) > 0 ? PObj -> Name : "NONE";

    switch (PObj -> ObjType) {
	case IP_OBJ_UNDEF:
	    sprintf(Line, "%-10s (%d) - Undefined type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    break;
	case IP_OBJ_POLY:
	    sprintf(Line, "%-10s (%d) - Poly      type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 3)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_NUMERIC:
	    sprintf(Line, "%-10s (%d) - Numeric   type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_POINT:
	    sprintf(Line, "%-10s (%d) - Point     type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_VECTOR:
	    sprintf(Line, "%-10s (%d) - Vector    type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_PLANE:
	    sprintf(Line, "%-10s (%d) - Plane     type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_CTLPT:
	    sprintf(Line, "%-10s (%d) - CtlPt     type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_MATRIX:
	    sprintf(Line, "%-10s (%d) - Matrix    type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_INSTANCE:
	    sprintf(Line, "%-10s (%d) - Instance  type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_STRING:
	    sprintf(Line, "%-10s (%d) - String    type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 1)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_LIST_OBJ:
	    sprintf(Line, "%-10s (%d) - Object List type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 4)
		SaveObjectInFile(NULL, PObj);
	    break;
	case IP_OBJ_CURVE:
	    sprintf(Line, "%-10s (%d) - Curve     type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	case IP_OBJ_SURFACE:
	    sprintf(Line, "%-10s (%d) - Surface   type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	case IP_OBJ_TRIMSRF:
	    sprintf(Line, "%-10s (%d) - Trimmed Srf type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	case IP_OBJ_TRIVAR:
	    sprintf(Line, "%-10s (%d) - Trivariate type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	case IP_OBJ_MODEL:
	    sprintf(Line, "%-10s (%d) - Model type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	case IP_OBJ_TRISRF:
	    sprintf(Line, "%-10s (%d) - Triangular Surface type", Name, Count);
	    WndwInputWindowPutStr(Line);
	    if (GlblDumpLvl >= 2) {
		SaveObjectInFile(NULL, PObj);
	    }
	    break;
	default:
	    sprintf(Line, "%-10s (%d) - Obj type error, type = %d",
				Name, Count, PObj->ObjType);
	    WndwInputWindowPutStr(Line);
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Gets a string description of the object type.			     	     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:        Object to get a string description on.                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   char *:      A string describing PObj.                                   M
*                                                                            *
* KEYWORDS:                                                                  M
*   GetObjectTypeAsString                                                    M
*****************************************************************************/
char *GetObjectTypeAsString(IPObjectStruct *PObj)
{
    if (PObj == NULL)
	return "Unknown";

    switch (PObj -> ObjType) {
	case IP_OBJ_POLY:
	    return (IP_IS_POLYGON_OBJ(PObj) ? "Polygons"
				      : (IP_IS_POLYLINE_OBJ(PObj) ? "Polylines"
							          : "Points"));
	case IP_OBJ_NUMERIC:
	    return "Numeric";
	case IP_OBJ_POINT:
	    return "Point";
	case IP_OBJ_VECTOR:
	    return "Vector";
	case IP_OBJ_PLANE:
	    return "Plane";
	case IP_OBJ_CTLPT:
	    return "Control Point";
	case IP_OBJ_MATRIX:
	    return "Matrix";
	case IP_OBJ_INSTANCE:
	    return "Instance";
	case IP_OBJ_STRING:
	    return "String";
	case IP_OBJ_LIST_OBJ:
	    return "List Object";
	case IP_OBJ_CURVE:
	    return "Curve";
	case IP_OBJ_SURFACE:
	    return "Surface";
	case IP_OBJ_TRIMSRF:
	    return "TrimSrf";
	case IP_OBJ_TRIVAR:
	    return "Trivar";
	case IP_OBJ_MODEL:
	    return "Model";
	case IP_OBJ_TRISRF:
	    return "TriSrf";
	case IP_OBJ_UNDEF:
	default:
	    return "Undefined";
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Print some useful information on a list of objects.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:      List of objects to print out.                                 M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   PrintObjectList                                                          M
*****************************************************************************/
void PrintObjectList(IPObjectStruct *PObj)
{
    VerifyGlobalObjectList();

    WndwInputWindowPutStr("");

    while (PObj != NULL) {
	PrintObject(PObj);
	PObj = PObj -> Pnext;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Coerce an object to a new object.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   PObj:        Object to coerce.                                           M
*   RNewType:    New type for PObj.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   The newly coerced object.                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   CoerceObjectTo                                                           M
*****************************************************************************/
IPObjectStruct *CoerceObjectTo(IPObjectStruct *PObj, RealType *RNewType)
{
    int NewType = REAL_TO_INT(*RNewType);
    CagdCrvStruct *Crv;
    CagdSrfStruct *Srf;
    IPObjectStruct
	*NewObj = NULL;

    switch (NewType) {
	case KV_UNIFORM_PERIODIC:
	    WndwInputWindowPutStr("Conversion to periodic is not supported.");
	    return NULL;
	case KV_UNIFORM_FLOAT:
	    if (IP_IS_CRV_OBJ(PObj)) {
		if (CAGD_IS_PERIODIC_CRV(PObj -> U.Crvs)) {
		    NewObj =
		        GenCRVObject(CnvrtPeriodic2FloatCrv(PObj -> U.Crvs));
		}
		else if (CAGD_IS_BSPLINE_CRV(PObj -> U.Crvs) &&
			 !BspCrvHasOpenEC(PObj -> U.Crvs)) {
		    NewObj = GenCRVObject(CagdCrvCopy(PObj -> U.Crvs));
		}
		else {
		    WndwInputWindowPutStr("Conversion to float legal only from periodic.");
		    return NULL;
		}
	    }
	    else if (IP_IS_SRF_OBJ(PObj)) {
		if (CAGD_IS_PERIODIC_SRF(PObj -> U.Srfs)) {
		    Srf = CnvrtPeriodic2FloatSrf(PObj -> U.Srfs);
		    NewObj = GenSRFObject(Srf);
		}
		else if (CAGD_IS_BSPLINE_SRF(PObj -> U.Srfs) &&
			 !BspSrfHasOpenEC(PObj -> U.Srfs)) {
		    NewObj = GenSRFObject(CagdSrfCopy(PObj -> U.Srfs));
		}
		else {
		    WndwInputWindowPutStr("Conversion to float legal only from periodic.");
		    return NULL;
		}
	    }
	    break;
	case KV_UNIFORM_OPEN:
	    if (IP_IS_CRV_OBJ(PObj)) {
		if (CAGD_IS_BEZIER_CRV(PObj -> U.Crvs) ||
		    (CAGD_IS_BSPLINE_CRV(PObj -> U.Crvs) &&
		     BspCrvHasOpenEC(PObj -> U.Crvs))) {
		    NewObj = GenCRVObject(CagdCrvCopy(PObj -> U.Crvs));
		}
		else {
		    int NewCrv = FALSE;

		    Crv = PObj -> U.Crvs;
		    if (CAGD_IS_PERIODIC_CRV(Crv)) {
			Crv = CnvrtPeriodic2FloatCrv(Crv);
			NewCrv = TRUE;
		    }

		    NewObj = GenCRVObject(BspCrvOpenEnd(Crv));
		    if (NewCrv)
		        CagdCrvFree(Crv);
		}
	    }
	    else if (IP_IS_SRF_OBJ(PObj)) {
		if (CAGD_IS_BEZIER_SRF(PObj -> U.Srfs) ||
		    (CAGD_IS_BSPLINE_SRF(PObj -> U.Srfs) &&
		     BspSrfHasOpenEC(PObj -> U.Srfs))) {
		    NewObj = GenSRFObject(CagdSrfCopy(PObj -> U.Srfs));
		}
		else {
		    int NewSrf = FALSE;

		    Srf = PObj -> U.Srfs;
		    if (CAGD_IS_PERIODIC_SRF(Srf)) {
			Srf = CnvrtPeriodic2FloatSrf(Srf);
			NewSrf = TRUE;
		    }

		    NewObj = GenSRFObject(BspSrfOpenEnd(Srf));
		    if (NewSrf)
		        CagdSrfFree(Srf);
		}
	    }
	    break;
	default:
	    NewObj = IritPrsrCoerceObjectTo(PObj, NewType);
	    break;
    }

    if (NewObj == NULL)
	WndwInputWindowPutStr("Invalid coerction requested.");
    return NewObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Saves an object in a data file.				     	     M
*                                                                            *
* PARAMETERS:                                                                M
*   FileName:   Where to save PObj.                                          M
*   PObj:       Object to save in a file.                                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   SaveObjectInFile                                                         M
*****************************************************************************/
void SaveObjectInFile(char *FileName, IPObjectStruct *PObj)
{
    int Handler;
    char FullFileName[LINE_LEN_LONG];

    if (FileName != NULL) {
	strcpy(FullFileName, FileName);
	if (strstr(FullFileName, ".bdt") ||
	    strstr(FullFileName, ".BDT")) {
	    /* Binary data file is requested. */
	}
	else if (strstr(FullFileName, ".dat") == NULL &&
		 strstr(FullFileName, ".DAT") == NULL)
	    strcat(FullFileName, ".dat");

	if ((Handler = IritPrsrOpenDataFile(FullFileName,
					    FALSE, FALSE)) >= 0) {
	    IritPrsrPutObjectToHandler(Handler, PObj);
	    IritPrsrCloseStream(Handler, TRUE);
	}
	else {
	    sprintf(FullFileName, "Failed to open file \"%s\" for write.",
		    FileName);
	    WndwInputWindowPutStr(FullFileName);
	}
    }
    else {
	/* The output will go to WndwInputWindowPutStr2, not to stderr: */
	IritPrsrSetPrintFunc(WndwInputWindowPutStr2);
	IritPrsrPutObjectToFile(NULL, PObj);
	IritPrsrSetPrintFunc(NULL);
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Loads an object(s) from a data file.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   FileName:    Where to read object(s) from.                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:    Object(s) read from file FileName.                  M
*                                                                            *
* KEYWORDS:                                                                  M
*   LoadObjectFromFile                                                       M
*****************************************************************************/
IPObjectStruct *LoadObjectFromFile(char *FileName)
{
    int Handler;
    char FullFileName[LINE_LEN_LONG];

    if (FileName != NULL) {
	strcpy(FullFileName, FileName);
	if (strstr(FullFileName, ".bdt") == NULL &&
	    strstr(FullFileName, ".BDT") == NULL &&
	    strstr(FullFileName, ".dat") == NULL &&
	    strstr(FullFileName, ".DAT") == NULL &&
	    strstr(FullFileName, ".mat") == NULL &&
	    strstr(FullFileName, ".MAT") == NULL)
	    strcat(FullFileName, ".dat");

	if ((Handler = IritPrsrOpenDataFile(FullFileName, TRUE, FALSE)) >= 0) {
    	    IPObjectStruct
    	        *PObj = IritPrsrGetObjects(Handler);

	    IritPrsrCloseStream(Handler, TRUE);

	    if (PObj == NULL) {
		char *ErrorMsg;

		if (IritPrsrParseError(0, &ErrorMsg)) {
		    WndwInputWindowPutStr("Data file parsing error:");
		    WndwInputWindowPutStr(ErrorMsg);
		}
	    }
	    else
		UpdateLoadedHierarchy(PObj, PObj);

	    return PObj;
	}
    }

    sprintf(FullFileName, "Failed to open file \"%s\" for read.",
	    FileName);
    WndwInputWindowPutStr(FullFileName);
    return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Updates the hierarchy of loaded object.				     *
*                                                                            *
* PARAMETERS:                                                                *
*   PObj:     Current, local, top of hierarchy.                              *
*   Root:     Global, root, toop of hierarchy.                               *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
static void UpdateLoadedHierarchy(IPObjectStruct *PObj, IPObjectStruct *Root)
{
    if (PObj == NULL)
	return;

    if (IP_IS_OLST_OBJ(PObj)) {
	int i;
	IPObjectStruct *PObjTmp;

	for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
	    UpdateLoadedHierarchy(PObjTmp, Root);
    }

    if (PObj != Root && strlen(PObj -> Name) > 0) {
	IPObjectStruct *OldPObj;

	if ((OldPObj = GetObject(PObj -> Name)) != NULL)
	    DeleteObject(OldPObj, TRUE);
	InsertObject(PObj);
	PObj -> Count++;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Error handler for loading andsaving of files.                              M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrorMsg:   Returns description of error if found one.                   M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:        TRUE if error found, FALSE otherwise.                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   LoadSaveObjectParseError                                                 M
*****************************************************************************/
int LoadSaveObjectParseError(char **ErrorMsg)
{
    int RetVal = IritPrsrParseError(0, ErrorMsg);

    if (!RetVal) {
	*ErrorMsg = "";
	return FALSE;
    }
    else
	return TRUE;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to construct a matrix out of a list of four lists of four numbers. M
*                                                                            *
* PARAMETERS:                                                                M
*   LstObjList:   A list of four lists of four numbers.                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A matrix object.                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenMatObjectGeneric                                                      M
*****************************************************************************/
IPObjectStruct *GenMatObjectGeneric(IPObjectStruct *LstObjList)
{
    MatrixType Mat;

    /* Generate the transformation matrix */
    if (MatGenMatGeneric(LstObjList, Mat))
	return GenMATObject(Mat);
    else
	return NULL;
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Routine to generate a 4*4 matrix  by specifying all its 16 coefficients.   *
*                                                                            *
* PARAMETERS:                                                                *
*   LstObjList:   A list of four lists of four numbers.                      M
*   Mat:          Where to save the constructed matrix.                      *
*                                                                            *
* RETURN VALUE:                                                              *
*   int:          TRUE if successful, FALSE otherwise.                       *
*****************************************************************************/
static int MatGenMatGeneric(IPObjectStruct *LstObjList, MatrixType Mat)
{
    int i, j;
    IPObjectStruct *Row, *Col;

    MatGenUnitMat(Mat);                             /* Make it unit matrix, */

    if (!IP_IS_OLST_OBJ(LstObjList)) {
	WndwInputWindowPutStr("Matrix: Not object list object!");
	return FALSE;
    }

    for (i = 0; i < 4; i++) {
	if ((Row = ListObjectGet(LstObjList, i)) == NULL) {
	    WndwInputWindowPutStr("Matrix: Four rows expected, found less");
	    return FALSE;
	}
	if (!IP_IS_OLST_OBJ(Row)) {
	    WndwInputWindowPutStr("None list object found in list");
	    return FALSE;
	}

	for (j = 0; j < 4; j++) {
	    if ((Col = ListObjectGet(Row, j)) == NULL) {
		WndwInputWindowPutStr("Matrix: Four columns expected, found less.");
		return FALSE;
	    }

	    if (!IP_IS_NUM_OBJ(Col)) {
		WndwInputWindowPutStr("Numeric value expected.");
		return FALSE;
	    }

	    Mat[i][j] = Col -> U.R;
	}
    }
    return TRUE;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a BOX primitive for IRIT.                                        M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:          Low end corner of BOX.                                      M
*   WidthX:      Width of BOX (X axis).                                      M
*   WidthY:      Depth of BOX( Y axis).                                      M
*   WidthZ:      Height of BOX( Z axis).                                     M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A BOX primitive.                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenBOXObject                                                             M
*****************************************************************************/
IPObjectStruct *GenBOXObject(VectorType Pt,
			     RealType *WidthX,
			     RealType *WidthY,
			     RealType *WidthZ)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenBOXObject(Pt, *WidthX, *WidthY, *WidthZ)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to BOX primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a GBOX primitive for IRIT.                                       M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:                Low end corner of GBOX.				     M
*   Dir1, Dir2, Dir3:  Three independent directional vectors to define GBOX. M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A GBOX primitive.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenGBOXObject                                                            M
*****************************************************************************/
IPObjectStruct *GenGBOXObject(VectorType Pt,
			      VectorType Dir1,
			      VectorType Dir2,
			      VectorType Dir3)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenGBOXObject(Pt, Dir1, Dir2, Dir3)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to GBOX primitive\n");

    return PObj;

}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a CONE primitive for IRIT.                                       M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:         Center location of Base of CONE.                             M
*   Dir:        Direction and distance from Pt to apex of CONE.              M
*   R:          Radius of Base of the cone.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A CONE primitive.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenCONEObject                                                            M
*****************************************************************************/
IPObjectStruct *GenCONEObject(VectorType Pt, VectorType Dir, RealType *R)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenCONEObject(Pt, Dir, *R)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to CONE primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a CONE2 primitive for IRIT.                                      M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:      Center location of Base of CON2.                                M
*   Dir:     Direction and distance from Pt to center of other base of CON2. M
*   R1, R2:  Two base radii of the truncated CON2                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A CONE2 primitive.                                   M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenCONE2Object                                                           M
*****************************************************************************/
IPObjectStruct *GenCONE2Object(VectorType Pt,
			       VectorType Dir,
			       RealType *R1,
			       RealType *R2)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenCONE2Object(Pt, Dir, *R1, *R2)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to CONE2 primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a CYLINder primitive for IRIT.                                   M
*                                                                            *
* PARAMETERS:                                                                M
*   Pt:         Center location of Base of CYLINder.                         M
*   Dir:        Direction and distance from Pt to other base of cylinder.    M
*   R:          Radius of Base of the cylinder.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A CYLIN primitive.                                   M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenCYLINObject                                                           M
*****************************************************************************/
IPObjectStruct *GenCYLINObject(VectorType Pt, VectorType Dir, RealType *R)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenCYLINObject(Pt, Dir, *R)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to CYLIN primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a SPHERE primitive for IRIT.                                     M
*                                                                            *
* PARAMETERS:                                                                M
*   Center:   Center location of SPHERE.                                     M
*   R         Radius of sphere.                                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A SPHERE primitive.                                  M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenSPHEREObject                                                          M
*****************************************************************************/
IPObjectStruct *GenSPHEREObject(VectorType Center, RealType *R)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenSPHEREObject(Center, *R)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to SPHERE primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a TORUS primitive for IRIT.                                      M
*                                                                            *
* PARAMETERS:                                                                M
*   Center:  Center location of the TORUS primitive.                         M
*   Normal:  Normal to the major plane of the torus.                         M
*   Rmajor:  Major radius of torus.                                          M
*   Rminor:  Minor radius of torus.                                          M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A TOURS primitive.                                   M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenTORUSObject                                                           M
*****************************************************************************/
IPObjectStruct *GenTORUSObject(VectorType Center,
			       VectorType Normal,
			       RealType *Rmajor,
			       RealType *Rminor)
{
    IPObjectStruct *PObj;

    PrimSetResolution(GetResolution(TRUE));

    if ((PObj = PrimGenTORUSObject(Center, Normal, *Rmajor, *Rminor)) == NULL)
	WndwInputWindowPutStr("Invalid parameters to TORUS primitive\n");

    return PObj;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a POLYDISK primitive for IRIT.                                   M
*                                                                            *
* PARAMETERS:                                                                M
*   N:         Normal to the plane this disk included in.                    M
*   T:         A translation factor of the center of the disk.               M
*   R:         Radius of teh disk.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:  A POLYDISK primitive.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenPOLYDISKObject                                                        M
*****************************************************************************/
IPObjectStruct *GenPOLYDISKObject(VectorType N, VectorType T, RealType *R)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenPOLYDISKObject(N, T, *R);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a POLYGON primitive for IRIT.                                    M
*                                                                            *
* PARAMETERS:                                                                M
*   PObjList:     List of vertices/points to construct as a polygon/line.    M
*   RIsPolyline:   If TRUE, make a polyline, otherwise a polygon.            M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A POLYGON primitive.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenPOLYGONObject                                                         M
*****************************************************************************/
IPObjectStruct *GenPOLYGONObject(IPObjectStruct *PObjList,
				 RealType *RIsPolyline)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenPOLYGONObject(PObjList, REAL_PTR_TO_INT(RIsPolyline));
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Creates an object from a list of polys.                                    M
*                                                                            *
* PARAMETERS:                                                                M
*   PObjList:      List of polygonal objects.                                M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A single object containing all polygons in all       M
*                       provided objects, by a simple union.                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenObjectFromPolyList                                                    M
*****************************************************************************/
IPObjectStruct *GenObjectFromPolyList(IPObjectStruct *PObjList)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenObjectFromPolyList(PObjList);
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Not supported.                                                             *
*                                                                            *
* PARAMETERS:                                                                *
*   PObj:                                                                    *
*                                                                            *
* RETURN VALUE:                                                              *
*   IPObjectStruct *:                                                        *
*****************************************************************************/
IPObjectStruct *GenCROSSECObject(IPObjectStruct *PObj)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenCROSSECObject(PObj);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates a SURFREV primitive for IRIT.                                    M
*                                                                            *
* PARAMETERS:                                                                M
*   Cross:     To rotate around the Z axis forming a surface of revolution.  M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:   A SURFREV primitive.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenSURFREVObject                                                         M
*****************************************************************************/
IPObjectStruct *GenSURFREVObject(IPObjectStruct *Cross)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenSURFREVObject(Cross);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Generates an EXTRUDE primitive for IRIT.                                   M
*                                                                            *
* PARAMETERS:                                                                M
*   Cross:     To extrude in direction Dir.                                  M
*   Dir:       Direction and magnitude of extrusion.                         M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:    An EXTRUDE primitive.                               M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenEXTRUDEObject                                                         M
*****************************************************************************/
IPObjectStruct *GenEXTRUDEObject(IPObjectStruct *Cross, VectorType Dir)
{
    PrimSetResolution(GetResolution(TRUE));

    return PrimGenEXTRUDEObject(Cross, Dir);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Data reduces/Decimate a given polygonal model.                           M
*                                                                            *
* PARAMETERS:                                                                M
*   PPolyObj:      To data reduce/Decimate.                                  M
*   Dist:          Maximal accepable distance in error.                      M
*   RNumPasses:    Number of reduction passes.                               M
*   RDecimRatio:   Each vertex takes part in no more that # of reductions.   M
*   MinAspRatio:   Retriangulation with given aspect ratio.                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPObjectStruct *:  Decimated/Data reduced polygonal object.              M
*                                                                            *
* KEYWORDS:                                                                  M
*   GenDecimatedObject, data reduction, decimation                           M
*****************************************************************************/
IPObjectStruct *GenDecimatedObject(IPObjectStruct *PPolyObj,
				   RealType *Dist,
				   RealType *RNumPasses,
				   RealType *RDecimRatio,
				   RealType *MinAspRatio)
{
    DecimateObjSetDistParam(*Dist);
    DecimateObjSetPassNumParam(REAL_TO_INT(*RNumPasses));
    DecimateObjSetDcmRatioParam(REAL_TO_INT(*RDecimRatio));
    DecimateObjSetMinAspRatioParam(*MinAspRatio);

    return DecimateObject(PPolyObj);
}

