home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / POLY3DS.ZIP / POSTSCRP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  11.1 KB  |  343 lines

  1. /*****************************************************************************
  2. * Module to handle PostScript output.                         *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 1.0, Apr. 1990   *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "program.h"
  10. #include "genmat.h"
  11. #include "postscrp.h"
  12.  
  13. static FILE *PSFile = NULL;           /* Used to save PostScript text file. */
  14.  
  15. static void ViewGeomObjectListPS(FileDescription **FD, int NumOfObjects,
  16.                                 char **Objects);
  17. static ObjectStruct *SearchObjectPS(FileDescription **FD, char *Object);
  18. static void DrawAllObjectsPS(FileDescription **FD);
  19. static void VisitObjectTreePS(BinTree *PBinTree);
  20. static void ViewOneObjectPS(ObjectStruct *PObject);
  21. static void ViewOnePolygonPS(PolygonStruct *PPolygon);
  22. static void MyMoveToPS(float Coord[3]);
  23. static void MyDrawToPS(float Coord[3]);
  24.  
  25. /*****************************************************************************
  26. * Routine to save the current view as PostScript text file.             *
  27. *****************************************************************************/
  28. void SavePostScript(FileDescription **FD, int NumOfObjects, char **Objects)
  29. {
  30.     int    i, j;
  31.     char *p, FileName[FILE_NAME_LEN];
  32.     static char FileCount = '0';
  33.     static char *PSHeader[] = {
  34.     "%!",
  35.     "%",
  36.     "% Creator: Poly3d",
  37.     "%",
  38.     "",
  39.     "gsave",
  40.     "",
  41.     "72 72 scale",    /* First scale to inches, se we can speak in inches. */
  42.     "4.0 5.0 translate",             /* To Center of image area. */
  43.     "3.5 3.5 scale",     /* Make the universe -1..1 on both X and Y. */
  44.     "",
  45.     "/line {",
  46.     "    newpath",
  47.     "    moveto",
  48.     "    lineto",
  49.     "    stroke",
  50.     "} def",
  51.     "",
  52.     "/setdashline {",
  53.     "    [0.012 0.024] 0 setdash",
  54.     "} def",
  55.     "",
  56.     "/setfullline {",
  57.     "    [] 0 setdash",
  58.     "} def",
  59.     "",
  60.     "0.006 setlinewidth",        /* Set some default line attributes. */
  61.     "1 setlinecap",
  62.     "1 setlinejoin",
  63.     "setfullline",
  64.     "",
  65.     NULL
  66.     };
  67.     static char *PSTrailer[] = {
  68.     "",
  69.     "showpage",
  70.     "grestore",
  71.     NULL
  72.     };
  73.  
  74.     strcpy(FileName, GENERIC_PS_FILE);
  75.     if ((p = strchr(FileName, '#')) != NULL) {
  76.     *p = FileCount;
  77.     if (FileCount++ == '9') FileCount = '0';
  78.     }
  79.     if ((PSFile = fopen(FileName, "wt")) == NULL) {
  80.     GGTone(700, 200);
  81.     return;
  82.     }
  83.  
  84.     for (i=0; PSHeader[i] != NULL; i++)
  85.     fprintf(PSFile, "%s\n", PSHeader[i]);
  86.  
  87.     ViewGeomObjectListPS(FD, NumOfObjects, Objects);
  88.  
  89.     for (i=0; PSTrailer[i] != NULL; i++)
  90.     fprintf(PSFile, "%s\n", PSTrailer[i]);
  91.  
  92.     fclose(PSFile);
  93. }
  94.  
  95. /*****************************************************************************
  96. * PS Routine to draw NumOfObjects given in Objects from FileDescription FD   *
  97. * according to view matrix Mat.    If NumOfObjects    == 0 then all the objects    *
  98. * are drawn. If NumEdges != 0 only the first NumEdges edges in each polygon  *
  99. * are drawn. If InterFlag then INTERNAL edges (created by IRIT solid         *
  100. * modeller) are also drawn.                             *
  101. *****************************************************************************/
  102. static void ViewGeomObjectListPS(FileDescription **FD, int NumOfObjects,
  103.                                 char **Objects)
  104. {
  105.     int    i;
  106.     ObjectStruct *PObject;
  107.  
  108.     if (NumOfObjects > 0)       /* There was something on command line... */
  109.     for (i=0; i<NumOfObjects; i++) {
  110.         if ((PObject = SearchObjectPS(FD, *Objects)) == NULL)
  111.         printf("Given Object %s not found in data files\n", *Objects);
  112.         else ViewOneObjectPS(PObject);
  113.         Objects++;
  114.     }
  115.     else {
  116.     /* Draw all objects not in other object by scanning object trees.    */
  117.     DrawAllObjectsPS(FD);        /* and drawing ones with Reference == 0. */
  118.     }
  119. }
  120.  
  121. /*****************************************************************************
  122. * Routine to search for    an object in the File descriptions FD. Note that if  *
  123. * an object exists more    than once only the first will be returned. If none   *
  124. * is found then    NULL is    returned, else a pointer to that object    struct.         *
  125. *****************************************************************************/
  126. static ObjectStruct *SearchObjectPS(FileDescription **FD, char *Object)
  127. {
  128.      BinTree *PBinTree;
  129.  
  130.      while (*FD) {
  131.       if ((PBinTree    = GetBinTree(Object, (*FD++) -> ObjectPointer)) !=
  132.                          (BinTree *) NULL)
  133.       return PBinTree -> Data.PObject;
  134.      }
  135.      return (ObjectStruct *) NULL;
  136. }
  137.  
  138. /*****************************************************************************
  139. * Routine to draw all the objects not in other objects...             *
  140. * by scanning all the object trees and drawing the objects with    Reference==0 *
  141. * meaning nobody referred to them yet...                     *
  142. *****************************************************************************/
  143. static void DrawAllObjectsPS(FileDescription **FD)
  144. {
  145.     while (*FD)    VisitObjectTreePS((*FD++) -> ObjectPointer);
  146. }
  147.  
  148. /*****************************************************************************
  149. * Routine to draw all the objects not in other objects...             *
  150. * by scanning all the object in    tree PBinTree and drawing the objects with   *
  151. * Reference==0,    meaning    nobody referred    to them    yet...                 *
  152. *****************************************************************************/
  153. static void VisitObjectTreePS(BinTree *PBinTree)
  154. {
  155.     if (PBinTree == (BinTree *)    NULL) return;
  156.  
  157.     VisitObjectTreePS(PBinTree -> right);
  158.  
  159.     ViewOneObjectPS(PBinTree -> Data.PObject);
  160.  
  161.     VisitObjectTreePS(PBinTree -> left);
  162. }
  163.  
  164. /*****************************************************************************
  165. * Routine to draw one object Object, using the Matrix transform    Mat.         *
  166. *****************************************************************************/
  167. static void ViewOneObjectPS(ObjectStruct *PObject)
  168. {
  169.     PolygonStruct *PList = PObject -> PPolygon;
  170.  
  171.     while (PList) {
  172.     ViewOnePolygonPS(PList);
  173.     PList =    PList -> Pnext;
  174.     }
  175. }
  176.  
  177. /*****************************************************************************
  178. * Routine to draw one polygon, using the Matrix    transform Mat.             *
  179. * Note this is the routine that    makes the real drawing...             *
  180. *****************************************************************************/
  181. static void ViewOnePolygonPS(PolygonStruct *PPolygon)
  182. {
  183.     int    i, Count, DrawNextEdge, NumOfVertices;
  184.     float MappedNormal[3], PolyNormal[3];
  185.     VertexStruct *PList = PPolygon -> PVertex;
  186.  
  187.     Count = NumEdges;
  188.  
  189.     if (PList == NULL) return;
  190.  
  191.     switch (PPolygon -> PolyType) {
  192.     case POINTLIST:
  193.         while (PList) {
  194.         MyMoveToPS(PList -> Coord);
  195.         MyDrawToPS(PList -> Coord);
  196.         PList = PList -> Pnext;
  197.         }
  198.         break;
  199.     case POLYLINE:
  200.         MyMoveToPS(PList -> Coord);
  201.         DrawNextEdge = !PList -> Internal;
  202.         PList = PList -> Pnext;
  203.  
  204.         while (PList) {
  205.         MyDrawToPS(PList -> Coord);
  206.  
  207.         PList = PList -> Pnext;
  208.         }
  209.         break;
  210.     case POLYGON:
  211.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  212.         {
  213.         for (i=0; i<3; i++) PolyNormal[i] = PList -> Coord[i];
  214.         NumOfVertices = 1;
  215.         }
  216.  
  217.         MyMoveToPS(PList -> Coord);
  218.         DrawNextEdge = !PList -> Internal;
  219.         PList = PList -> Pnext;
  220.  
  221.         while (PList) {
  222.         if (DrawNextEdge || InterFlag)
  223.             MyDrawToPS(PList -> Coord);
  224.         else MyMoveToPS(PList -> Coord);
  225.  
  226.         if (DrawVNormalsFlag && PList -> HasNormal) {
  227.             for (i=0; i<3; i++) MappedNormal[i] =
  228.                     PList -> Coord[i] + PList -> Normal[i];
  229.             i = ClosedObject;
  230.             ClosedObject = FALSE;
  231.             MyDrawToPS(MappedNormal);
  232.             MyMoveToPS(PList -> Coord);
  233.             ClosedObject = i;
  234.         }
  235.  
  236.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  237.         {
  238.             for (i=0; i<3; i++) PolyNormal[i] += PList -> Coord[i];
  239.             NumOfVertices++;
  240.         }
  241.         /* If -e option specified #Edges to draw. */
  242.         if (!(--Count)) return;
  243.         DrawNextEdge = !PList -> Internal;
  244.         PList = PList -> Pnext;
  245.         }
  246.  
  247.         /* Close polygon by drawing a line to first vertex. */
  248.         if (DrawNextEdge || InterFlag)
  249.         MyDrawToPS(PPolygon -> PVertex -> Coord);
  250.  
  251.         if (DrawPNormalsFlag && PPolygon->HasPlane)
  252.         {
  253.         for (i=0; i<3; i++) PolyNormal[i] /= NumOfVertices;
  254.         MyMoveToPS(PolyNormal);
  255.         for (i=0; i<3; i++) PolyNormal[i] += PPolygon->Plane[i];
  256.         i = ClosedObject;
  257.         ClosedObject = FALSE;
  258.         MyDrawToPS(PolyNormal);
  259.         ClosedObject = i;
  260.         }
  261.         break;
  262.     }
  263. }
  264.  
  265. static double LastCoord[3];    /* Used to store last point we moved/draw to. */
  266.  
  267. /*****************************************************************************
  268. * Routine to mave to 3D    point given as Coord[3], using Mat transform.         *
  269. *****************************************************************************/
  270. static void MyMoveToPS(float Coord[3])
  271. {
  272.     MultVecby4by4(LastCoord, Coord, CrntViewMat);   /* Set last point coord. */
  273. }
  274.  
  275. /*****************************************************************************
  276. * Routine to draw to 3D    point given as Coord[3], using Mat transform, from   *
  277. * the last point we moved to.                             *
  278. *****************************************************************************/
  279. static void MyDrawToPS(float Coord[3])
  280. {
  281.     static DashState = FALSE;
  282.     double NewCoord[3], MiddleCoord[3], t;
  283.  
  284.     MultVecby4by4(NewCoord, Coord, CrntViewMat);    /* Set last point coord. */
  285.     if (ClosedObject && NewCoord[2] < LastCoord[2]) {
  286.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double));
  287.     return;
  288.     }
  289.  
  290.     /* Implementation of simple depth cue - if line is >Z or <Z ... */
  291.     if (LastCoord[2] <= 0.0 && NewCoord[2] <= 0.0) {
  292.     if (GlblDepthCue && !DashState) {
  293.         fprintf(PSFile, "setdashline\n");
  294.         DashState = TRUE;
  295.     }
  296.     fprintf(PSFile, "%10.7lf %10.7lf  ", LastCoord[0], LastCoord[1]);
  297.     fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
  298.     }
  299.     else
  300.     if (LastCoord[2] >= 0.0 && NewCoord[2] >= 0.0 ||
  301.     ABS(LastCoord[2] - NewCoord[2]) < EPSILON) {
  302.     if (GlblDepthCue && DashState) {
  303.         fprintf(PSFile, "setfullline\n");
  304.         DashState = FALSE;
  305.     }
  306.     fprintf(PSFile, "%10.7lf %10.7lf  ", LastCoord[0], LastCoord[1]);
  307.     fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
  308.     }
  309.     else {                      /* Line intersect Z = 0 plane. */
  310.     t = LastCoord[2] / (LastCoord[2] - NewCoord[2]);
  311.     MiddleCoord[0] = LastCoord[0] * (1.0 - t) + NewCoord[0] * t;
  312.     MiddleCoord[1] = LastCoord[1] * (1.0 - t) + NewCoord[1] * t;
  313.  
  314.     if (GlblDepthCue && DashState) {
  315.         fprintf(PSFile, "setfullline\n");
  316.         DashState = FALSE;
  317.     }
  318.     if (LastCoord[2] > 0.0) {
  319.         fprintf(PSFile, "%10.7lf %10.7lf  ", LastCoord[0], LastCoord[1]);
  320.         fprintf(PSFile, "%10.7lf %10.7lf line\n", MiddleCoord[0], MiddleCoord[1]);
  321.     }
  322.     else {
  323.         fprintf(PSFile, "%10.7lf %10.7lf  ", MiddleCoord[0], MiddleCoord[1]);
  324.         fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
  325.     }
  326.  
  327.     if (GlblDepthCue && !DashState) {
  328.         fprintf(PSFile, "setdashline\n");
  329.         DashState = TRUE;
  330.     }
  331.     if (LastCoord[2] < 0.0) {
  332.         fprintf(PSFile, "%10.7lf %10.7lf  ", LastCoord[0], LastCoord[1]);
  333.         fprintf(PSFile, "%10.7lf %10.7lf line\n", MiddleCoord[0], MiddleCoord[1]);
  334.     }
  335.     else {
  336.         fprintf(PSFile, "%10.7lf %10.7lf  ", MiddleCoord[0], MiddleCoord[1]);
  337.         fprintf(PSFile, "%10.7lf %10.7lf line\n", NewCoord[0], NewCoord[1]);
  338.     }
  339.     }
  340.  
  341.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(double)); /* Set current point. */
  342. }
  343.