home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Routines to save current surface function into a file. *
- * *
- * Written by: Gershon Elber Ver 0.2, June 1988 *
- * *
- * The following file type are used in the output files: *
- * 1. file.fun holds real parametric function (x, y, z as function of u, v) *
- * and the transformation matrix (can be used with file.ply) respectively *
- * 2. file.row holds row samples - gird in u, v space of 3d sampled data. *
- * 3. file.ply holds polygonal data file - vertices are defined and polygons *
- * are defined above them, as a text file. *
- * Note the matrix transformation is saved with all 3 cases as '.mat' file. *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <graphics.h>
- #include <string.h>
- #include <math.h>
- #include <dir.h>
- #include <dos.h>
- #include "Gif_Lib.h"
- #include "Expr2TrG.h"
- #include "GraphGnG.h"
- #include "GenMat.h"
- #include "Dir-Graf.h"
- #include "Program.h"
-
- #define MAX_SAMPLING 100 /* In output files - max sampling along an axis. */
-
- static void SaveGifFile(void);
- static void SaveFunction(char SFunc[3][LINE_LEN_LONG],
- double UMin, double UMax, double VMin, double VMax,
- int NumOfIsoLines, int NumOfSamples, MatrixType TransMat);
- static void SaveRowSamples(ExprNode *PFunc[3],
- double UMin, double UMax, double VMin, double VMax,
- MatrixType TransMat);
- static void SaveGraphFile(ExprNode *PFunc[3],
- double UMin, double UMax, double VMin, double VMax,
- MatrixType TransMat);
- static void SaveMatFile(char *FileName, MatrixType TransMat);
- static void GenerateFuncSamples(ExprNode *PFunc[3], int i, int j,
- int Usamples, int Vsamples,
- double UMin, double UMax, double VMin, double VMax,
- double OneSample[]);
- static void GenerateNormalSamples(ExprNode *PFuncDu[3], ExprNode *PFuncDv[3],
- double Normal[3]);
-
- /*****************************************************************************
- * Main routine of the SaveFunc module - set the Menu and call the *
- * requested routines. *
- * Save the surface function in the same format explained in GetFunc module *
- * which includes X(u, v), Y(u, v), Z(u, v), the domain (u, v range), number *
- * of iso lines, number of samples per iso line, and transformation matrix. *
- * The function and all its params is saved with extension '.fun', and only *
- * the transformation matrix is saved in file with extension '.mat' . *
- *****************************************************************************/
- void DoSaveFunc(ExprNode *PFunc[3], char SFunc[3][LINE_LEN_LONG],
- double UMin, double UMax, double VMin, double VMax,
- int NumOfIsoLines, int NumOfSamples, MatrixType TransMat)
- {
- static struct MenuItem SaveFuncMenu[] = { /* Save Data Menu. */
- YELLOW, "Save Function",
- MAGENTA, "File <- F(u, v)",
- MAGENTA, "Samples <- F(u, v)",
- MAGENTA, "Polys <- F(u, v)",
- MAGENTA, "GIF file",
- MAGENTA, "",
- MAGENTA, "List Files",
- MAGENTA, "Change Dir",
- MAGENTA, "",
- CYAN, "Help",
- BLUE, "Exit"
- };
-
- GGMenuDraw(10, SaveFuncMenu, TRUE); /* Draw Menu. */
- while (TRUE) {
- switch (GGMenuPick()) {
- case 1: /* Save function: F(u, v) to file. */
- SaveFunction(SFunc, UMin, UMax, VMin, VMax, NumOfIsoLines
- , NumOfSamples, TransMat);
- break;
- case 2: /* Save F(u, v) as row square grid of samples. */
- SaveRowSamples(PFunc, UMin, UMax, VMin, VMax, TransMat);
- break;
- case 3: /* Save F(u, v) as polygonal text data file. */
- SaveGraphFile(PFunc, UMin, UMax, VMin, VMax, TransMat);
- break;
- case 4: /* Generate GIF file from screen. */
- SaveGifFile();
- break;
- case 6: /* Print current directory content. */
- PrintDir(FILES_TO_DIR);
- GGMenuDraw(10, SaveFuncMenu, TRUE); /* Draw Menu. */
- break;
- case 7: /* Change current directory. */
- ChangeDir();
- break;
- case 9: /* Help. */
- GGPrintHelpMenu("DrawFn3D.hlp", "SAVEFUNCTION");
- GGMenuDraw(10, SaveFuncMenu, TRUE); /* Draw Menu. */
- break;
- case 10: /* Exit. */
- return;
- }
- }
- }
-
- /*****************************************************************************
- * Routine to save the X(u, v), Y(u, v), Z(u, v) functions, (u, v) domain: *
- * number of iso line and samples per iso line in FileName with extension *
- * '.fun' and the transformation matrix in FileName with ext. '.mat' . *
- *****************************************************************************/
- static void SaveGifFile(void)
- {
- char FileName[LINE_LEN], FileNameGif[LINE_LEN], *Pchar;
-
- /* See GetFunc module for GetLine function definition. */
- FileName[0] = 0;
- GetLine(stdin, TRUE, "Enter File Name:", FileName);
- if (strlen(FileName) == 0) return;
-
- if (IS_DISK_FILE(FileName)) {
- /* Make sure its disk file only: */
- if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
- *Pchar = NULL; /* Make sure no file type is given. */
- strcpy(FileNameGif, FileName);
- strcat(FileNameGif, ".gif");
- }
- else strcpy(FileNameGif, FileName);
-
- if (DumpScreen(FileNameGif, GraphDriver, GGGraphMode) != 0) {
- /* Something went wrong - let the user know about it. */
- GGTone(400, 300);
- GGTone(100, 300);
- }
- else GGTone(1000, 100);
- }
-
- /*****************************************************************************
- * Routine to save the X(u, v), Y(u, v), Z(u, v) functions, (u, v) domain: *
- * number of iso line and samples per iso line in FileName with extension *
- * '.fun' and the transformation matrix in FileName with ext. '.mat' . *
- *****************************************************************************/
- static void SaveFunction(char SFunc[3][LINE_LEN_LONG],
- double UMin, double UMax, double VMin, double VMax,
- int NumOfIsoLines, int NumOfSamples, MatrixType TransMat)
- {
- char FileName[LINE_LEN], FileNameFunc[LINE_LEN], *Pchar;
- FILE *f;
-
- /* See GetFunc module for GetLine function definition. */
- FileName[0] = 0;
- GetLine(stdin, TRUE, "Enter File Name:", FileName);
- if (strlen(FileName) == 0) return;
-
- if (IS_DISK_FILE(FileName)) {
- /* Make sure its disk file only: */
- if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
- *Pchar = NULL; /* Make sure no file type is given. */
- strcpy(FileNameFunc, FileName);
- strcat(FileNameFunc, ".fun");
- }
- else strcpy(FileNameFunc, FileName);
-
- if ((f = fopen(FileNameFunc, "wt")) == (FILE *) NULL) {
- GGPutErrorMsg("Cannt open Func. file");
- return;
- }
- /* Save surf. func., U, V domain, & Iso lines parameters: */
- fprintf(f, "# Surface automatic generator, Gershon Elber Mar. 89\n");
- fprintf(f, "%s\n%s\n%s\n", SFunc[0], SFunc[1], SFunc[2]);
- fprintf(f, "%lf\n%lf\n%lf\n%lf\n", UMin, UMax, VMin, VMax);
- fprintf(f, "%d\n%d\n", NumOfIsoLines, NumOfSamples);
- fclose(f); /* Thats it for the '.fun' file. */
-
- SaveMatFile(FileName, TransMat); /* Save the transformation matrix. */
- }
-
- /*****************************************************************************
- * Routine to save sampled points along the surface in row format: first *
- * line is number of samples along u & v and follows are u*v lines - each *
- * holds x y z of sampled point. The order of sampling is: u blocks of fixed *
- * u values, each for all needed v values. *
- *****************************************************************************/
- static void SaveRowSamples(ExprNode *PFunc[3],
- double UMin, double UMax, double VMin, double VMax,
- MatrixType TransMat)
- {
- int i, j, Usamples, Vsamples;
- char FileName[LINE_LEN], Line[LINE_LEN], Header[LINE_LEN], *Pchar;
- double OneSample[3];
- FILE *f;
-
- FileName[0] = 0;
- GetLine(stdin, TRUE, "Enter File Name:", FileName);
- if (strlen(FileName) == 0) return;
-
- if (IS_DISK_FILE(FileName)) {
- /* Make sure its disk file only: */
- if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
- *Pchar = NULL; /* Make sure no file type is given. */
- strcat(FileName, ".row");
- }
-
- if ((f = fopen(FileName, "wt")) == (FILE *) NULL) {
- GGPutErrorMsg("Cannt create file");
- return;
- }
-
- sprintf(Header, "# U Samples [2..%d]:", MAX_SAMPLING);
- Line[0] = 0;
- do GetLine(stdin, TRUE, Header, Line);
- while ((sscanf(Line, "%d", &Usamples) != 1) || (Usamples < 2) ||
- (Usamples > MAX_SAMPLING));
-
- sprintf(Header, "# V Samples [2..%d]:", MAX_SAMPLING);
- Line[0] = 0;
- do GetLine(stdin, TRUE, Header, Line);
- while ((sscanf(Line, "%d", &Vsamples) != 1) || (Vsamples < 2) ||
- (Vsamples > MAX_SAMPLING));
-
- fprintf(f, "%d %d\n", Usamples, Vsamples); /* Save number of samples. */
- for (i=0; i<Usamples; i++) {
- for (j=0; j<Vsamples; j++) {
- GenerateFuncSamples(PFunc, i, j, Usamples, Vsamples,
- UMin, UMax, VMin, VMax, OneSample);
- fprintf(f, "%10lf %10lf %10lf\n",
- OneSample[0], OneSample[1], OneSample[2]);
- }
- fprintf(f, "\n"); /* make extra line space between blocks. */
- }
-
- fclose(f); /* Close the file. */
-
- SaveMatFile(FileName, TransMat); /* Save the transformation matrix. */
- }
-
- /*****************************************************************************
- * Routine to save sampled points along the surface in graphic file format. *
- * This routine scans the surface in fixed u/v values and generates the file *
- * using triangolar polygons only. *
- *****************************************************************************/
- static void SaveGraphFile(ExprNode *PFunc[3],
- double UMin, double UMax, double VMin, double VMax,
- MatrixType TransMat)
- {
- int i, j, Usamples, Vsamples, PCount = 0, VCount = 0, SaveNormals,
- Base1, Base2, Base3, Base4, UClosed, VClosed;
- char FileName[LINE_LEN], Line[LINE_LEN], Header[LINE_LEN], *Pchar;
- double OneSample[3], Normal[3];
- ExprNode *PFuncDu[3], *PFuncDv[3];
- FILE *f;
-
- FileName[0] = 0;
- GetLine(stdin, TRUE, "Enter File Name:", FileName);
- if (strlen(FileName) == 0) return;
- if (IS_DISK_FILE(FileName)) {
- /* Make sure its disk file only: */
- if ((Pchar = strchr(FileName, '.')) != NULL && strlen(Pchar) < 4)
- *Pchar = NULL; /* Make sure no file type is given. */
- strcat(FileName, ".ply");
- }
-
- if ((f = fopen(FileName, "wt")) == NULL) {
- GGPutErrorMsg("Cannt create file");
- return;
- }
-
- strcpy(Line, "n");
- GetLine(stdin, TRUE, "Save normals:", Line);
- SaveNormals = Line[0] == 'y' || Line[0] == 'Y';
- if (SaveNormals) {
- strcpy(Line, "n");
- GetLine(stdin, TRUE, "Flip normal dir:", Line);
- SaveNormals = (Line[0] == 'y' || Line[0] == 'Y') ? -1 : 1;
-
- for (i = 0; i < 3; i++) {
- PFuncDu[i] = DerivTree(PFunc[i], PARAMETER_U);
- PFuncDv[i] = DerivTree(PFunc[i], PARAMETER_V);
- }
- }
-
- sprintf(Header, "#USamples [2..%d]:", MAX_SAMPLING);
- Line[0] = 0;
- do GetLine(stdin, TRUE, Header, Line);
- while ((sscanf(Line, "%d", &Usamples) != 1) || (Usamples < 2) ||
- (Usamples > MAX_SAMPLING));
-
- sprintf(Header, "#VSamples [2..%d]:", MAX_SAMPLING);
- Line[0] = 0;
- do GetLine(stdin, TRUE, Header, Line);
- while ((sscanf(Line, "%d", &Vsamples) != 1) || (Vsamples < 2) ||
- (Vsamples > MAX_SAMPLING));
-
- if (Usamples > 2) {
- Line[0] = 0;
- do GetLine(stdin, TRUE, "Closed In U [Y/N]", Line);
- while (!((Line[0] == 'Y') || (Line[0] == 'N') ||
- (Line[0] == 'y') || (Line[0] == 'n')));
- UClosed = ((Line[0] == 'Y') || (Line[0] == 'y'));
- }
- else UClosed = FALSE;
-
- if (Vsamples > 2) {
- Line[0] = 0;
- do GetLine(stdin, TRUE, "Closed In V [Y/N]", Line);
- while (!((Line[0] == 'Y') || (Line[0] == 'N') ||
- (Line[0] == 'y') || (Line[0] == 'n')));
- VClosed = ((Line[0] == 'Y') || (Line[0] == 'y'));
- }
- else VClosed = FALSE;
-
- fprintf(f, "Surface automatic generator, Gershon Elber Feb. 88\n\n");
-
- if (UClosed) Usamples--; /* If surface is closed than last == first. */
- if (VClosed) Vsamples--;
- for (i=0; i<Usamples; i++) /* Print all vertices at once: */
- for (j=0; j<Vsamples; j++) {
- GenerateFuncSamples(PFunc, i, j, Usamples, Vsamples,
- UMin, UMax, VMin, VMax, OneSample);
- if (SaveNormals) {
- /* Note we assume GenerateFuncSamples above set the correct */
- /* u/v parametric values, so no need to pass them again! */
- GenerateNormalSamples(PFuncDu, PFuncDv, Normal);
- fprintf(f, "[VERTEX V%-4d [NORMAL %10lf %10lf %10lf] %10lf %10lf %10lf]\n",
- VCount++,
- Normal[0] * SaveNormals,
- Normal[1] * SaveNormals,
- Normal[2] * SaveNormals,
- OneSample[0], OneSample[1], OneSample[2]);
- }
- else fprintf(f, "[VERTEX V%-4d %10lf %10lf %10lf]\n", VCount++,
- OneSample[0], OneSample[1], OneSample[2]);
- }
- if (UClosed) Usamples++; /* Recover... */
- if (VClosed) Vsamples++;
-
- for (i=0; i<Usamples-1; i++) /* Now print all polygons (triangles): */
- for (j=0; j<Vsamples-1; j++) {
- if (VClosed) /* Calculate the two triangles points. */
- Base1 = i*(Vsamples-1)+j;
- else Base1 = i*Vsamples+j;
- if ((VClosed) && (j == Vsamples-2))
- Base2 = Base1 - j; /* Back to first row (same column). */
- else Base2 = Base1 + 1;
- if ((UClosed) && (i == Usamples-2))
- Base3 = j; /* Back to first column (same row). */
- else if (VClosed)
- Base3 = Base1 + (Vsamples-1);
- else Base3 = Base1 + Vsamples;
- if ((VClosed) && (j == Vsamples-2))
- Base4 = Base3 - j; /* Back to start. */
- else Base4 = Base3 + 1;
- /* The diagonal edge is allways the last one (from last point */
- /* to first point in polygon point list) : */
- fprintf(f, "[POLYGON P%-4d V%-4d V%-4d V%-4d]\n", PCount++,
- Base2, Base1, Base3);
- fprintf(f, "[POLYGON P%-4d V%-4d V%-4d V%-4d]\n", PCount++,
- Base3, Base4, Base2);
- }
-
- fprintf(f, "[OBJECT surface"); /* Now save the object itself: */
- for (i=0; i<PCount; i++) {
- if (i % 12== 0) fprintf(f, "\n "); /* Make lines not too long. */
- fprintf(f, " P%-4d", i);
- }
- fprintf(f, "]\n");
-
- fclose(f); /* Close the file. */
-
- if (SaveNormals)
- for (i = 0; i < 3; i++) {
- FreeTree(PFuncDu[i]);
- FreeTree(PFuncDv[i]);
- }
-
- SaveMatFile(FileName, TransMat); /* Save the transformation matrix. */
- }
-
- /*****************************************************************************
- * Routine to save the trasnformation matrix if file name with extension .mat *
- *****************************************************************************/
- static void SaveMatFile(char *FileName, MatrixType TransMat)
- {
- int i, j;
- char FileNameMat[LINE_LEN], *Pchar;
- FILE *f;
-
- if (strlen(FileName) == 0) return;
- strcpy(FileNameMat, FileName);
-
- if (IS_DISK_FILE(FileName)) {
- /* Make sure its disk file only: */
- if ((Pchar = strchr(FileNameMat, '.')) != (char *) NULL)
- *Pchar = NULL; /* Make sure no file type is given. */
- strcat(FileNameMat, ".mat");
- }
-
- if ((f = fopen(FileNameMat, "wt")) == (FILE *) NULL) {
- GGPutErrorMsg("Cannt open Mat. file");
- return;
- }
- for (i=0; i<4; i++) {
- for (j=0; j<4; j++) fprintf(f, "%12lf ", TransMat[i][j]);
- fprintf(f, "\n");
- }
- fclose(f); /* That it for the '.mat' file. */
- }
-
- /*****************************************************************************
- * Routine to generate one sample at location (i, j) of function. (i, j) *
- * is the relative index in UVsamples (integer). *
- *****************************************************************************/
- static void GenerateFuncSamples(ExprNode *PFunc[3], int i, int j,
- int Usamples, int Vsamples,
- double UMin, double UMax, double VMin, double VMax, double OneSample[])
- {
- int k;
- double U, V;
-
- U = (UMax - UMin) * (((double) i) / (Usamples - 1)) + UMin;
- V = (VMax - VMin) * (((double) j) / (Vsamples - 1)) + VMin;
-
- SetParamValue(V, PARAMETER_V);
- SetParamValue(U, PARAMETER_U);
-
- for (k=0; k<3; k++) OneSample[k] = EvalTree(PFunc[k]);
- }
-
- /*****************************************************************************
- * Routine to generate one sample at the current set u/v location. *
- * of the normal, by evaluating the cross product of the parital derivatives. *
- *****************************************************************************/
- static void GenerateNormalSamples(ExprNode *PFuncDu[3], ExprNode *PFuncDv[3],
- double Normal[3])
- {
- int k;
- double Du[3], Dv[3], Len;
-
- for (k=0; k<3; k++) {
- Du[k] = EvalTree(PFuncDu[k]);
- Dv[k] = EvalTree(PFuncDv[k]);
- }
-
- Normal[0] = Du[1] * Dv[2] - Du[2] * Dv[1];
- Normal[1] = Du[2] * Dv[0] - Du[0] * Dv[2];
- Normal[2] = Du[0] * Dv[1] - Du[1] * Dv[0];
-
- Len = sqrt(SQR(Normal[0]) + SQR(Normal[1]) + SQR(Normal[2]));
- for (k=0; k<3; k++) Normal[k] /= Len;
- }