home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / DRAWFN3S.ZIP / SAVEFUNC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-06  |  16.8 KB  |  452 lines

  1. /*****************************************************************************
  2. *  Routines to save current surface function into a file.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                   Ver 0.2,    June 1988    *
  5. *                                         *
  6. * The following    file type are used in the output files:                 *
  7. * 1. file.fun holds real parametric function (x, y, z as function of u, v)   *
  8. *    and the transformation matrix (can    be used    with file.ply) respectively  *
  9. * 2. file.row holds row    samples    - gird in u, v space of 3d sampled data.     *
  10. * 3. file.ply holds polygonal data file    - vertices are defined and polygons  *
  11. *    are defined above them, as    a text file.                     *
  12. * Note the matrix transformation is saved with all 3 cases as '.mat' file.   *
  13. *****************************************************************************/
  14.  
  15. #include <stdio.h>
  16. #include <graphics.h>
  17. #include <string.h>
  18. #include <math.h>
  19. #include <dir.h>
  20. #include <dos.h>
  21. #include "Gif_Lib.h"
  22. #include "Expr2TrG.h"
  23. #include "GraphGnG.h"
  24. #include "GenMat.h"
  25. #include "Dir-Graf.h"
  26. #include "Program.h"
  27.  
  28. #define    MAX_SAMPLING    100 /* In output files - max sampling along an axis. */
  29.  
  30. static void SaveGifFile(void);
  31. static void SaveFunction(char SFunc[3][LINE_LEN_LONG],
  32.     double UMin, double UMax, double VMin, double VMax,
  33.     int NumOfIsoLines, int NumOfSamples, MatrixType TransMat);
  34. static void SaveRowSamples(ExprNode *PFunc[3],
  35.     double UMin, double UMax, double VMin, double VMax,
  36.     MatrixType TransMat);
  37. static void SaveGraphFile(ExprNode *PFunc[3],
  38.     double UMin, double UMax, double VMin, double VMax,
  39.     MatrixType TransMat);
  40. static void SaveMatFile(char *FileName, MatrixType TransMat);
  41. static void GenerateFuncSamples(ExprNode *PFunc[3], int i, int j,
  42.     int Usamples, int Vsamples,
  43.     double UMin, double UMax, double VMin, double VMax,
  44.     double OneSample[]);
  45. static void GenerateNormalSamples(ExprNode *PFuncDu[3], ExprNode *PFuncDv[3],
  46.                                  double Normal[3]);
  47.  
  48. /*****************************************************************************
  49. *   Main routine of the    SaveFunc module    - set the Menu and call    the         *
  50. * requested routines.                                 *
  51. *   Save the surface function in the same format explained in GetFunc module *
  52. * which    includes X(u, v), Y(u, v), Z(u, v), the domain (u, v range), number  *
  53. * of iso lines, number of samples per iso line, and transformation matrix.   *
  54. *   The    function and all its params is saved with extension '.fun', and    only *
  55. * the transformation  matrix is    saved in file with extension '.mat' .         *
  56. *****************************************************************************/
  57. void DoSaveFunc(ExprNode *PFunc[3], char SFunc[3][LINE_LEN_LONG],
  58.     double UMin, double UMax, double VMin, double VMax,
  59.     int NumOfIsoLines, int NumOfSamples, MatrixType TransMat)
  60. {
  61.     static struct MenuItem SaveFuncMenu[] = {          /* Save Data Menu. */
  62.     YELLOW,    "Save Function",
  63.     MAGENTA, "File <- F(u, v)",
  64.     MAGENTA, "Samples <- F(u, v)",
  65.     MAGENTA, "Polys <- F(u, v)",
  66.     MAGENTA, "GIF file",
  67.     MAGENTA, "",
  68.     MAGENTA, "List Files",
  69.     MAGENTA, "Change Dir",
  70.     MAGENTA, "",
  71.     CYAN,    "Help",
  72.     BLUE,    "Exit"
  73.     };
  74.  
  75.     GGMenuDraw(10, SaveFuncMenu, TRUE);                   /* Draw Menu. */
  76.     while (TRUE) {
  77.     switch (GGMenuPick()) {
  78.         case 1:              /* Save function: F(u, v) to file. */
  79.         SaveFunction(SFunc, UMin, UMax, VMin, VMax, NumOfIsoLines
  80.                     , NumOfSamples, TransMat);
  81.         break;
  82.         case 2:          /* Save F(u, v) as row square grid of samples. */
  83.         SaveRowSamples(PFunc, UMin, UMax, VMin, VMax, TransMat);
  84.         break;
  85.         case 3:        /* Save F(u, v) as polygonal text data file. */
  86.         SaveGraphFile(PFunc, UMin, UMax, VMin, VMax, TransMat);
  87.         break;
  88.         case 4:               /* Generate GIF file from screen. */
  89.         SaveGifFile();
  90.         break;
  91.         case 6:             /* Print current directory content. */
  92.         PrintDir(FILES_TO_DIR);
  93.         GGMenuDraw(10, SaveFuncMenu, TRUE);           /* Draw Menu. */
  94.         break;
  95.         case 7:                /* Change current directory. */
  96.         ChangeDir();
  97.         break;
  98.         case 9:                            /* Help. */
  99.         GGPrintHelpMenu("DrawFn3D.hlp", "SAVEFUNCTION");
  100.         GGMenuDraw(10, SaveFuncMenu, TRUE);           /* Draw Menu. */
  101.         break;
  102.         case 10:                            /* Exit. */
  103.         return;
  104.     }
  105.     }
  106. }
  107.  
  108. /*****************************************************************************
  109. * Routine to save the X(u, v), Y(u, v), Z(u, v) functions, (u, v) domain:    *
  110. * number of iso    line and samples per iso line in FileName with extension     *
  111. * '.fun' and the transformation    matrix in FileName with    ext. '.mat' .         *
  112. *****************************************************************************/
  113. static void SaveGifFile(void)
  114. {
  115.     char FileName[LINE_LEN], FileNameGif[LINE_LEN], *Pchar;
  116.  
  117.     /* See GetFunc module for GetLine function definition. */
  118.     FileName[0] = 0;
  119.     GetLine(stdin, TRUE, "Enter File Name:", FileName);
  120.     if (strlen(FileName) == 0) return;
  121.  
  122.     if (IS_DISK_FILE(FileName)) {
  123.     /* Make sure its disk file only: */
  124.     if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
  125.         *Pchar = NULL;         /* Make sure no file type is given. */
  126.     strcpy(FileNameGif, FileName);
  127.     strcat(FileNameGif, ".gif");
  128.     }
  129.     else strcpy(FileNameGif, FileName);
  130.  
  131.     if (DumpScreen(FileNameGif, GraphDriver, GGGraphMode) != 0) {
  132.     /* Something went wrong - let the user know about it. */
  133.     GGTone(400, 300);
  134.     GGTone(100, 300);
  135.     }
  136.     else GGTone(1000, 100);
  137. }
  138.  
  139. /*****************************************************************************
  140. * Routine to save the X(u, v), Y(u, v), Z(u, v) functions, (u, v) domain:    *
  141. * number of iso    line and samples per iso line in FileName with extension     *
  142. * '.fun' and the transformation    matrix in FileName with    ext. '.mat' .         *
  143. *****************************************************************************/
  144. static void SaveFunction(char SFunc[3][LINE_LEN_LONG],
  145.     double UMin, double UMax, double VMin, double VMax,
  146.     int NumOfIsoLines, int NumOfSamples, MatrixType TransMat)
  147. {
  148.     char FileName[LINE_LEN], FileNameFunc[LINE_LEN], *Pchar;
  149.     FILE *f;
  150.  
  151.     /* See GetFunc module for GetLine function definition. */
  152.     FileName[0] = 0;
  153.     GetLine(stdin, TRUE, "Enter File Name:", FileName);
  154.     if (strlen(FileName) == 0) return;
  155.  
  156.     if (IS_DISK_FILE(FileName)) {
  157.     /* Make sure its disk file only: */
  158.     if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
  159.         *Pchar = NULL;         /* Make sure no file type is given. */
  160.     strcpy(FileNameFunc, FileName);
  161.     strcat(FileNameFunc, ".fun");
  162.     }
  163.     else strcpy(FileNameFunc, FileName);
  164.  
  165.     if ((f = fopen(FileNameFunc, "wt")) == (FILE *) NULL) {
  166.     GGPutErrorMsg("Cannt open Func. file");
  167.     return;
  168.     }
  169.     /* Save surf. func., U, V domain, & Iso lines parameters: */
  170.     fprintf(f, "# Surface automatic generator,         Gershon Elber           Mar. 89\n");
  171.     fprintf(f, "%s\n%s\n%s\n", SFunc[0], SFunc[1], SFunc[2]);
  172.     fprintf(f, "%lf\n%lf\n%lf\n%lf\n", UMin, UMax, VMin, VMax);
  173.     fprintf(f, "%d\n%d\n", NumOfIsoLines, NumOfSamples);
  174.     fclose(f);                    /* Thats it for the '.fun' file. */
  175.  
  176.     SaveMatFile(FileName, TransMat);      /* Save the transformation matrix. */
  177. }
  178.  
  179. /*****************************************************************************
  180. *   Routine to save sampled points along the surface in    row format: first    *
  181. * line is number of samples along u & v    and follows are    u*v lines - each     *
  182. * holds    x y z of sampled point.    The order of sampling is: u blocks of fixed  *
  183. * u values, each for all needed    v values.                     *
  184. *****************************************************************************/
  185. static void SaveRowSamples(ExprNode *PFunc[3],
  186.     double UMin, double UMax, double VMin, double VMax,
  187.     MatrixType TransMat)
  188. {
  189.     int    i, j, Usamples, Vsamples;
  190.     char FileName[LINE_LEN], Line[LINE_LEN], Header[LINE_LEN], *Pchar;
  191.     double OneSample[3];
  192.     FILE *f;
  193.  
  194.     FileName[0] = 0;
  195.     GetLine(stdin, TRUE, "Enter File Name:", FileName);
  196.     if (strlen(FileName) == 0) return;
  197.  
  198.     if (IS_DISK_FILE(FileName)) {
  199.     /* Make sure its disk file only: */
  200.     if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
  201.         *Pchar = NULL;         /* Make sure no file type is given. */
  202.     strcat(FileName, ".row");
  203.     }
  204.  
  205.     if ((f = fopen(FileName, "wt")) == (FILE *) NULL) {
  206.     GGPutErrorMsg("Cannt create file");
  207.     return;
  208.     }
  209.  
  210.     sprintf(Header, "# U Samples [2..%d]:", MAX_SAMPLING);
  211.     Line[0] = 0;
  212.     do GetLine(stdin, TRUE, Header, Line);
  213.     while ((sscanf(Line, "%d", &Usamples) != 1) || (Usamples < 2) ||
  214.                        (Usamples > MAX_SAMPLING));
  215.  
  216.     sprintf(Header, "# V Samples [2..%d]:", MAX_SAMPLING);
  217.     Line[0] = 0;
  218.     do GetLine(stdin, TRUE, Header, Line);
  219.     while ((sscanf(Line, "%d", &Vsamples) != 1) || (Vsamples < 2) ||
  220.                        (Vsamples > MAX_SAMPLING));
  221.  
  222.     fprintf(f, "%d %d\n", Usamples, Vsamples);      /* Save number of samples. */
  223.     for    (i=0; i<Usamples; i++) {
  224.     for (j=0; j<Vsamples; j++) {
  225.         GenerateFuncSamples(PFunc, i, j, Usamples, Vsamples,
  226.                 UMin, UMax, VMin, VMax, OneSample);
  227.         fprintf(f, "%10lf %10lf %10lf\n",
  228.              OneSample[0], OneSample[1], OneSample[2]);
  229.     }
  230.     fprintf(f, "\n");        /* make extra line space between blocks. */
  231.     }
  232.  
  233.     fclose(f);                          /* Close the file. */
  234.  
  235.     SaveMatFile(FileName, TransMat);      /* Save the transformation matrix. */
  236. }
  237.  
  238. /*****************************************************************************
  239. *   Routine to save sampled points along the surface in    graphic    file format. *
  240. * This routine scans the surface in fixed u/v values and generates the file  *
  241. * using    triangolar polygons only.                         *
  242. *****************************************************************************/
  243. static void SaveGraphFile(ExprNode *PFunc[3],
  244.     double UMin, double UMax, double VMin, double VMax,
  245.     MatrixType TransMat)
  246. {
  247.     int    i, j, Usamples, Vsamples, PCount = 0, VCount = 0, SaveNormals,
  248.     Base1, Base2, Base3, Base4, UClosed, VClosed;
  249.     char FileName[LINE_LEN], Line[LINE_LEN], Header[LINE_LEN], *Pchar;
  250.     double OneSample[3], Normal[3];
  251.     ExprNode *PFuncDu[3], *PFuncDv[3];
  252.     FILE *f;
  253.  
  254.     FileName[0] = 0;
  255.     GetLine(stdin, TRUE, "Enter File Name:", FileName);
  256.     if (strlen(FileName) == 0) return;
  257.     if (IS_DISK_FILE(FileName)) {
  258.     /* Make sure its disk file only: */
  259.     if ((Pchar = strchr(FileName, '.')) != NULL && strlen(Pchar) < 4)
  260.         *Pchar = NULL;         /* Make sure no file type is given. */
  261.     strcat(FileName, ".ply");
  262.     }
  263.  
  264.     if ((f = fopen(FileName, "wt")) == NULL) {
  265.     GGPutErrorMsg("Cannt create file");
  266.     return;
  267.     }
  268.  
  269.     strcpy(Line, "n");
  270.     GetLine(stdin, TRUE, "Save normals:", Line);
  271.     SaveNormals = Line[0] == 'y' || Line[0] == 'Y';
  272.     if (SaveNormals) {
  273.     strcpy(Line, "n");
  274.     GetLine(stdin, TRUE, "Flip normal dir:", Line);
  275.     SaveNormals = (Line[0] == 'y' || Line[0] == 'Y') ? -1 : 1;
  276.  
  277.     for (i = 0; i < 3; i++) {
  278.         PFuncDu[i] = DerivTree(PFunc[i], PARAMETER_U);
  279.         PFuncDv[i] = DerivTree(PFunc[i], PARAMETER_V);
  280.     }
  281.     }
  282.  
  283.     sprintf(Header, "#USamples [2..%d]:", MAX_SAMPLING);
  284.     Line[0] = 0;
  285.     do GetLine(stdin, TRUE, Header, Line);
  286.     while ((sscanf(Line, "%d", &Usamples) != 1) || (Usamples < 2) ||
  287.                        (Usamples > MAX_SAMPLING));
  288.  
  289.     sprintf(Header, "#VSamples [2..%d]:", MAX_SAMPLING);
  290.     Line[0] = 0;
  291.     do GetLine(stdin, TRUE, Header, Line);
  292.     while ((sscanf(Line, "%d", &Vsamples) != 1) || (Vsamples < 2) ||
  293.                        (Vsamples > MAX_SAMPLING));
  294.  
  295.     if (Usamples > 2) {
  296.     Line[0] = 0;
  297.     do GetLine(stdin, TRUE, "Closed In U [Y/N]", Line);
  298.     while (!((Line[0] == 'Y') || (Line[0] == 'N') ||
  299.          (Line[0] == 'y') || (Line[0] == 'n')));
  300.     UClosed = ((Line[0] == 'Y') || (Line[0] == 'y'));
  301.     }
  302.     else UClosed = FALSE;
  303.  
  304.     if (Vsamples > 2) {
  305.     Line[0] = 0;
  306.     do GetLine(stdin, TRUE, "Closed In V [Y/N]", Line);
  307.     while (!((Line[0] == 'Y') || (Line[0] == 'N') ||
  308.          (Line[0] == 'y') || (Line[0] == 'n')));
  309.     VClosed = ((Line[0] == 'Y') || (Line[0] == 'y'));
  310.     }
  311.     else VClosed = FALSE;
  312.  
  313.     fprintf(f, "Surface automatic generator,          Gershon Elber           Feb. 88\n\n");
  314.  
  315.     if (UClosed) Usamples--;     /* If surface is closed than last == first. */
  316.     if (VClosed) Vsamples--;
  317.     for    (i=0; i<Usamples; i++)              /* Print all vertices at once: */
  318.     for (j=0; j<Vsamples; j++) {
  319.         GenerateFuncSamples(PFunc, i, j, Usamples, Vsamples,
  320.                 UMin, UMax, VMin, VMax, OneSample);
  321.         if (SaveNormals) {
  322.         /* Note we assume GenerateFuncSamples above set the correct  */
  323.         /* u/v parametric values, so no need to pass them again!     */
  324.         GenerateNormalSamples(PFuncDu, PFuncDv, Normal);
  325.         fprintf(f, "[VERTEX V%-4d [NORMAL %10lf %10lf %10lf] %10lf %10lf %10lf]\n",
  326.             VCount++,
  327.             Normal[0] * SaveNormals,
  328.             Normal[1] * SaveNormals,
  329.             Normal[2] * SaveNormals,
  330.             OneSample[0], OneSample[1], OneSample[2]);
  331.         }
  332.         else fprintf(f, "[VERTEX V%-4d %10lf %10lf %10lf]\n", VCount++,
  333.                 OneSample[0], OneSample[1], OneSample[2]);
  334.     }
  335.     if (UClosed) Usamples++;                       /* Recover... */
  336.     if (VClosed) Vsamples++;
  337.  
  338.     for    (i=0; i<Usamples-1; i++)      /* Now print all polygons (triangles): */
  339.     for (j=0; j<Vsamples-1;    j++) {
  340.         if (VClosed)          /* Calculate the two triangles points. */
  341.          Base1 = i*(Vsamples-1)+j;
  342.         else Base1 = i*Vsamples+j;
  343.         if ((VClosed) && (j    == Vsamples-2))
  344.          Base2 = Base1 - j;     /* Back to first row (same column). */
  345.         else Base2 = Base1 + 1;
  346.         if ((UClosed) && (i    == Usamples-2))
  347.          Base3 = j;         /* Back to first column (same row). */
  348.         else if (VClosed)
  349.               Base3 = Base1 + (Vsamples-1);
  350.          else Base3 = Base1 + Vsamples;
  351.         if ((VClosed) && (j    == Vsamples-2))
  352.          Base4 = Base3 - j;               /* Back to start. */
  353.         else Base4 = Base3 + 1;
  354.         /* The diagonal edge is allways the    last one (from last point */
  355.         /* to first    point in polygon point list) :              */
  356.         fprintf(f, "[POLYGON P%-4d V%-4d V%-4d V%-4d]\n", PCount++,
  357.                              Base2, Base1, Base3);
  358.         fprintf(f, "[POLYGON P%-4d V%-4d V%-4d V%-4d]\n", PCount++,
  359.                              Base3, Base4, Base2);
  360.     }
  361.  
  362.     fprintf(f, "[OBJECT surface");          /* Now save the object itself: */
  363.     for    (i=0; i<PCount;    i++) {
  364.     if (i %    12== 0)    fprintf(f, "\n    ");     /* Make lines not too long. */
  365.     fprintf(f, " P%-4d", i);
  366.     }
  367.     fprintf(f, "]\n");
  368.  
  369.     fclose(f);                          /* Close the file. */
  370.  
  371.     if (SaveNormals)
  372.     for (i = 0; i < 3; i++) {
  373.         FreeTree(PFuncDu[i]);
  374.         FreeTree(PFuncDv[i]);
  375.     }
  376.  
  377.     SaveMatFile(FileName, TransMat);      /* Save the transformation matrix. */
  378. }
  379.  
  380. /*****************************************************************************
  381. * Routine to save the trasnformation matrix if file name with extension .mat *
  382. *****************************************************************************/
  383. static void SaveMatFile(char *FileName, MatrixType TransMat)
  384. {
  385.     int i, j;
  386.     char FileNameMat[LINE_LEN], *Pchar;
  387.     FILE *f;
  388.  
  389.     if (strlen(FileName) == 0) return;
  390.     strcpy(FileNameMat, FileName);
  391.  
  392.     if (IS_DISK_FILE(FileName)) {
  393.     /* Make sure its disk file only: */
  394.     if ((Pchar = strchr(FileNameMat, '.')) != (char *) NULL)
  395.         *Pchar = NULL;         /* Make sure no file type is given. */
  396.     strcat(FileNameMat, ".mat");
  397.     }
  398.  
  399.     if ((f = fopen(FileNameMat, "wt")) == (FILE *) NULL) {
  400.     GGPutErrorMsg("Cannt open Mat. file");
  401.     return;
  402.     }
  403.     for    (i=0; i<4; i++)    {
  404.     for (j=0; j<4; j++) fprintf(f, "%12lf ", TransMat[i][j]);
  405.     fprintf(f, "\n");
  406.     }
  407.     fclose(f);                     /* That it for the '.mat' file. */
  408. }
  409.  
  410. /*****************************************************************************
  411. *   Routine to generate    one sample at location (i, j) of function. (i, j)    *
  412. * is the relative index    in UVsamples (integer).                     *
  413. *****************************************************************************/
  414. static void GenerateFuncSamples(ExprNode *PFunc[3], int i, int j,
  415.     int Usamples, int Vsamples,
  416.     double UMin, double UMax, double VMin, double VMax, double OneSample[])
  417. {
  418.     int    k;
  419.     double U, V;
  420.  
  421.     U =    (UMax -    UMin) *    (((double) i) /    (Usamples - 1))    + UMin;
  422.     V =    (VMax -    VMin) *    (((double) j) /    (Vsamples - 1))    + VMin;
  423.  
  424.     SetParamValue(V, PARAMETER_V);
  425.     SetParamValue(U, PARAMETER_U);
  426.  
  427.     for    (k=0; k<3; k++)    OneSample[k] = EvalTree(PFunc[k]);
  428. }
  429.  
  430. /*****************************************************************************
  431. *   Routine to generate    one sample at the current set u/v location.         *
  432. * of the normal, by evaluating the cross product of the parital derivatives. *
  433. *****************************************************************************/
  434. static void GenerateNormalSamples(ExprNode *PFuncDu[3], ExprNode *PFuncDv[3],
  435.                                  double Normal[3])
  436. {
  437.     int    k;
  438.     double Du[3], Dv[3], Len;
  439.  
  440.     for    (k=0; k<3; k++)    {
  441.     Du[k] = EvalTree(PFuncDu[k]);
  442.     Dv[k] = EvalTree(PFuncDv[k]);
  443.     }
  444.  
  445.     Normal[0] = Du[1] * Dv[2] - Du[2] * Dv[1];
  446.     Normal[1] = Du[2] * Dv[0] - Du[0] * Dv[2];
  447.     Normal[2] = Du[0] * Dv[1] - Du[1] * Dv[0];
  448.  
  449.     Len = sqrt(SQR(Normal[0]) + SQR(Normal[1]) + SQR(Normal[2]));
  450.     for    (k=0; k<3; k++)    Normal[k] /= Len;
  451. }
  452.