home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Module to handle PostScript output. *
- * *
- * Written by: Gershon Elber Ver 1.0, Apr. 1990 *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include "program.h"
- #include "genmat.h"
- #include "postscrp.h"
-
- static FILE *PSFile = NULL; /* Used to save PostScript text file. */
-
- static void ViewGeomObjectListPS(FileDescription **FD, int NumOfObjects,
- char **Objects);
- static ObjectStruct *SearchObjectPS(FileDescription **FD, char *Object);
- static void DrawAllObjectsPS(FileDescription **FD);
- static void VisitObjectTreePS(BinTree *PBinTree);
- static void ViewOneObjectPS(ObjectStruct *PObject);
- static void ViewOnePolygonPS(PolygonStruct *PPolygon);
- static void MyMoveToPS(float Coord[3]);
- static void MyDrawToPS(float Coord[3]);
-
- /*****************************************************************************
- * Routine to save the current view as PostScript text file. *
- *****************************************************************************/
- void SavePostScript(FileDescription **FD, int NumOfObjects, char **Objects)
- {
- int i, j;
- char *p, FileName[FILE_NAME_LEN];
- static char FileCount = '0';
- static char *PSHeader[] = {
- "%!",
- "%",
- "% Creator: Poly3d",
- "%",
- "",
- "gsave",
- "",
- "72 72 scale", /* First scale to inches, se we can speak in inches. */
- "4.0 5.0 translate", /* To Center of image area. */
- "3.5 3.5 scale", /* Make the universe -1..1 on both X and Y. */
- "",
- "/line {",
- " newpath",
- " moveto",
- " lineto",
- " stroke",
- "} def",
- "",
- "/setdashline {",
- " [0.012 0.024] 0 setdash",
- "} def",
- "",
- "/setfullline {",
- " [] 0 setdash",
- "} def",
- "",
- "0.006 setlinewidth", /* Set some default line attributes. */
- "1 setlinecap",
- "1 setlinejoin",
- "setfullline",
- "",
- NULL
- };
- static char *PSTrailer[] = {
- "",
- "showpage",
- "grestore",
- NULL
- };
-
- strcpy(FileName, GENERIC_PS_FILE);
- if ((p = strchr(FileName, '#')) != NULL) {
- *p = FileCount;
- if (FileCount++ == '9') FileCount = '0';
- }
- if ((PSFile = fopen(FileName, "wt")) == NULL) {
- GGTone(700, 200);
- return;
- }
-
- for (i=0; PSHeader[i] != NULL; i++)
- fprintf(PSFile, "%s\n", PSHeader[i]);
-
- ViewGeomObjectListPS(FD, NumOfObjects, Objects);
-
- for (i=0; PSTrailer[i] != NULL; i++)
- fprintf(PSFile, "%s\n", PSTrailer[i]);
-
- fclose(PSFile);
- }
-
- /*****************************************************************************
- * PS Routine to draw NumOfObjects given in Objects from FileDescription FD *
- * according to view matrix Mat. If NumOfObjects == 0 then all the objects *
- * are drawn. If NumEdges != 0 only the first NumEdges edges in each polygon *
- * are drawn. If InterFlag then INTERNAL edges (created by IRIT solid *
- * modeller) are also drawn. *
- *****************************************************************************/
- static void ViewGeomObjectListPS(FileDescription **FD, int NumOfObjects,
- char **Objects)
- {
- int i;
- ObjectStruct *PObject;
-
- if (NumOfObjects > 0) /* There was something on command line... */
- for (i=0; i<NumOfObjects; i++) {
- if ((PObject = SearchObjectPS(FD, *Objects)) == NULL)
- printf("Given Object %s not found in data files\n", *Objects);
- else ViewOneObjectPS(PObject);
- Objects++;
- }
- else {
- /* Draw all objects not in other object by scanning object trees. */
- DrawAllObjectsPS(FD); /* and drawing ones with Reference == 0. */
- }
- }
-
- /*****************************************************************************
- * Routine to search for an object in the File descriptions FD. Note that if *
- * an object exists more than once only the first will be returned. If none *
- * is found then NULL is returned, else a pointer to that object struct. *
- *****************************************************************************/
- static ObjectStruct *SearchObjectPS(FileDescription **FD, char *Object)
- {
- BinTree *PBinTree;
-
- while (*FD) {
- if ((PBinTree = GetBinTree(Object, (*FD++) -> ObjectPointer)) !=
- (BinTree *) NULL)
- return PBinTree -> Data.PObject;
- }
- return (ObjectStruct *) NULL;
- }
-
- /*****************************************************************************
- * Routine to draw all the objects not in other objects... *
- * by scanning all the object trees and drawing the objects with Reference==0 *
- * meaning nobody referred to them yet... *
- *****************************************************************************/
- static void DrawAllObjectsPS(FileDescription **FD)
- {
- while (*FD) VisitObjectTreePS((*FD++) -> ObjectPointer);
- }
-
- /*****************************************************************************
- * Routine to draw all the objects not in other objects... *
- * by scanning all the object in tree PBinTree and drawing the objects with *
- * Reference==0, meaning nobody referred to them yet... *
- *****************************************************************************/
- static void VisitObjectTreePS(BinTree *PBinTree)
- {
- if (PBinTree == (BinTree *) NULL) return;
-
- VisitObjectTreePS(PBinTree -> right);
-
- ViewOneObjectPS(PBinTree -> Data.PObject);
-
- VisitObjectTreePS(PBinTree -> left);
- }
-
- /*****************************************************************************
- * Routine to draw one object Object, using the Matrix transform Mat. *
- *****************************************************************************/
- static void ViewOneObjectPS(ObjectStruct *PObject)
- {
- PolygonStruct *PList = PObject -> PPolygon;
-
- while (PList) {
- ViewOnePolygonPS(PList);
- PList = PList -> Pnext;
- }
- }
-
- /*****************************************************************************
- * Routine to draw one polygon, using the Matrix transform Mat. *
- * Note this is the routine that makes the real drawing... *
- *****************************************************************************/
- static void ViewOnePolygonPS(PolygonStruct *PPolygon)
- {
- int i, Count, DrawNextEdge, NumOfVertices;
- float MappedNormal[3], PolyNormal[3];
- VertexStruct *PList = PPolygon -> PVertex;
-
- Count = NumEdges;
-
- if (PList == NULL) return;
-
- switch (PPolygon -> PolyType) {
- case POINTLIST:
- while (PList) {
- MyMoveToPS(PList -> Coord);
- MyDrawToPS(PList -> Coord);
- PList = PList -> Pnext;
- }
- break;
- case POLYLINE:
- MyMoveToPS(PList -> Coord);
- DrawNextEdge = !PList -> Internal;
- PList = PList -> Pnext;
-
- while (PList) {
- MyDrawToPS(PList -> Coord);
-
- PList = PList -> Pnext;
- }
- break;
- case POLYGON:
- if (DrawPNormalsFlag && PPolygon->HasPlane)
- {
- for (i=0; i<3; i++) PolyNormal[i] = PList -> Coord[i];
- NumOfVertices = 1;
- }
-
- MyMoveToPS(PList -> Coord);
- DrawNextEdge = !PList -> Internal;
- PList = PList -> Pnext;
-
- while (PList) {
- if (DrawNextEdge || InterFlag)
- MyDrawToPS(PList -> Coord);
- else MyMoveToPS(PList -> Coord);
-
- if (DrawVNormalsFlag && PList -> HasNormal) {
- for (i=0; i<3; i++) MappedNormal[i] =
- PList -> Coord[i] + PList -> Normal[i];
- i = ClosedObject;
- ClosedObject = FALSE;
- MyDrawToPS(MappedNormal);
- MyMoveToPS(PList -> Coord);
- ClosedObject = i;
- }
-
- if (DrawPNormalsFlag && PPolygon->HasPlane)
- {
- for (i=0; i<3; i++) PolyNormal[i] += PList -> Coord[i];
- NumOfVertices++;
- }
- /* If -e option specified #Edges to draw. */
- if (!(--Count)) return;
- DrawNextEdge = !PList -> Internal;
- PList = PList -> Pnext;
- }
-
- /* Close polygon by drawing a line to first vertex. */
- if (DrawNextEdge || InterFlag)
- MyDrawToPS(PPolygon -> PVertex -> Coord);
-
- if (DrawPNormalsFlag && PPolygon->HasPlane)
- {
- for (i=0; i<3; i++) PolyNormal[i] /= NumOfVertices;
- MyMoveToPS(PolyNormal);
- for (i=0; i<3; i++) PolyNormal[i] += PPolygon->Plane[i];
- i = ClosedObject;
- ClosedObject = FALSE;
- MyDrawToPS(PolyNormal);
- ClosedObject = i;
- }
- break;
- }
- }
-
- static double LastCoord[3]; /* Used to store last point we moved/draw to. */
-
- /*****************************************************************************
- * Routine to mave to 3D point given as Coord[3], using Mat transform. *
- *****************************************************************************/
- static void MyMoveToPS(float Coord[3])
- {
- MultVecby4by4(LastCoord, Coord, CrntViewMat); /* Set last point coord. */
- }
-
- /*****************************************************************************
- * Routine to draw to 3D point given as Coord[3], using Mat transform, from *
- * the last point we moved to. *
- *****************************************************************************/
- static void MyDrawToPS(float Coord[3])
- {
- static DashState = FALSE;
- double NewCoord[3], MiddleCoord[3], t;
-
- MultVecby4by4(NewCoord, Coord, CrntViewMat); /* Set last point coord. */
- if (ClosedObject && NewCoord[2] < LastCoord[2]) {
- GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double));
- return;
- }
-
- /* Implementation of simple depth cue - if line is >Z or <Z ... */
- if (LastCoord[2] <= 0.0 && NewCoord[2] <= 0.0) {
- if (GlblDepthCue && !DashState) {
- fprintf(PSFile, "setdashline\n");
- DashState = TRUE;
- }
- fprintf(PSFile, "%10.7lf %10.7lf ", LastCoord[0], LastCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
- }
- else
- if (LastCoord[2] >= 0.0 && NewCoord[2] >= 0.0 ||
- ABS(LastCoord[2] - NewCoord[2]) < EPSILON) {
- if (GlblDepthCue && DashState) {
- fprintf(PSFile, "setfullline\n");
- DashState = FALSE;
- }
- fprintf(PSFile, "%10.7lf %10.7lf ", LastCoord[0], LastCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
- }
- else { /* Line intersect Z = 0 plane. */
- t = LastCoord[2] / (LastCoord[2] - NewCoord[2]);
- MiddleCoord[0] = LastCoord[0] * (1.0 - t) + NewCoord[0] * t;
- MiddleCoord[1] = LastCoord[1] * (1.0 - t) + NewCoord[1] * t;
-
- if (GlblDepthCue && DashState) {
- fprintf(PSFile, "setfullline\n");
- DashState = FALSE;
- }
- if (LastCoord[2] > 0.0) {
- fprintf(PSFile, "%10.7lf %10.7lf ", LastCoord[0], LastCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", MiddleCoord[0], MiddleCoord[1]);
- }
- else {
- fprintf(PSFile, "%10.7lf %10.7lf ", MiddleCoord[0], MiddleCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
- }
-
- if (GlblDepthCue && !DashState) {
- fprintf(PSFile, "setdashline\n");
- DashState = TRUE;
- }
- if (LastCoord[2] < 0.0) {
- fprintf(PSFile, "%10.7lf %10.7lf ", LastCoord[0], LastCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", MiddleCoord[0], MiddleCoord[1]);
- }
- else {
- fprintf(PSFile, "%10.7lf %10.7lf ", MiddleCoord[0], MiddleCoord[1]);
- fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
- }
- }
-
- GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double)); /* Set current point. */
- }
-