From 9349b73c1926acd4316bb6dc9aeb0aa1e4af4a2d Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Mon, 28 Feb 2005 23:57:59 +0000
Subject: [PATCH] Merged patch from Matt Gundry <mjgundry@faa-engineers.com> to
 support the structured Plot3d mesh format.

---
 Common/CommandLine.cpp  |   8 +-
 Fltk/Callbacks.cpp      |   9 +-
 Graphics/CreateFile.cpp |   4 +-
 Mesh/Mesh.h             |   1 +
 Mesh/Print_Mesh.cpp     | 214 +++++++++++++++++++++++++++++++++++++++-
 TODO                    |  11 ++-
 doc/CREDITS             |  15 +--
 7 files changed, 249 insertions(+), 13 deletions(-)

diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 42bdcb78bc..a645c8fba3 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -1,4 +1,4 @@
-// $Id: CommandLine.cpp,v 1.54 2005-01-01 19:35:27 geuzaine Exp $
+// $Id: CommandLine.cpp,v 1.55 2005-02-28 23:57:59 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -72,7 +72,7 @@ void Print_Usage(char *name){
   Msg(DIRECT, "  -1, -2, -3            Perform batch 1D, 2D and 3D mesh generation");
   Msg(DIRECT, "  -saveall              Save all elements (discard physical group definitions)");
   Msg(DIRECT, "  -o file               Specify mesh output file name");
-  Msg(DIRECT, "  -format string        Set output mesh format (msh, unv, gref)");
+  Msg(DIRECT, "  -format string        Set output mesh format (msh, unv, gref, p3d)");
   Msg(DIRECT, "  -algo string          Select mesh algorithm (iso, tri, aniso, netgen)");
   Msg(DIRECT, "  -smooth int           Set number of mesh smoothing steps");
   Msg(DIRECT, "  -optimize             Optimize quality of tetrahedral elements");
@@ -396,6 +396,10 @@ void Get_Options(int argc, char *argv[], int *nbfiles)
                   !strcmp(argv[i], "GREF") || !strcmp(argv[i], "Gref")) {
             CTX.mesh.format = FORMAT_GREF;
           }
+          else if(!strcmp(argv[i], "p3d") ||
+                  !strcmp(argv[i], "P3D") || !strcmp(argv[i], "Plot3D")) {
+            CTX.mesh.format = FORMAT_P3D;
+          }
           else {
             fprintf(stderr, ERROR_STR "Unknown mesh format\n");
             exit(1);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index b70aed53e2..eae0f74839 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.336 2005-02-20 06:36:52 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.337 2005-02-28 23:57:59 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -404,6 +404,12 @@ int _save_unv(char *name)
   return 1;
 }
 
+int _save_p3d(char *name)
+{
+  CreateOutputFile(name, CTX.mesh.format = FORMAT_P3D);
+  return 1;
+}
+
 int _save_vrml(char *name)
 {
   CreateOutputFile(name, CTX.mesh.format = FORMAT_VRML);
@@ -503,6 +509,7 @@ void file_save_as_cb(CALLBACK_ARGS)
     {"Gmsh characteristic length field (*.pos)", _save_lc},
     {"GREF mesh (*.gref)", _save_gref},
     {"I-DEAS universal mesh (*.unv)", _save_unv},
+    {"PLOT3D formatted ASCII mgrid (*.p3d)", _save_p3d},
     {"VRML surface mesh (*.wrl)", _save_vrml},
     {"STL triangulation (*.stl)", _save_stl},
     {"GIF (*.gif)", _save_gif},
diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp
index 1d5f79f03c..3bc042142a 100644
--- a/Graphics/CreateFile.cpp
+++ b/Graphics/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.66 2005-01-08 20:15:12 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.67 2005-02-28 23:57:59 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -78,6 +78,7 @@ void CreateOutputFile(char *name, int format)
     else if(!strcmp(ext, ".opt"))  CreateOutputFile(name, FORMAT_OPT);
     else if(!strcmp(ext, ".msh"))  CreateOutputFile(name, FORMAT_MSH);
     else if(!strcmp(ext, ".unv"))  CreateOutputFile(name, FORMAT_UNV);
+    else if(!strcmp(ext, ".p3d"))  CreateOutputFile(name, FORMAT_P3D);
     else if(!strcmp(ext, ".dmg"))  CreateOutputFile(name, FORMAT_DMG);
     else if(!strcmp(ext, ".stl"))  CreateOutputFile(name, FORMAT_STL);
     else if(!strcmp(ext, ".pos"))  CreateOutputFile(name, FORMAT_LC);
@@ -111,6 +112,7 @@ void CreateOutputFile(char *name, int format)
 
   case FORMAT_MSH:
   case FORMAT_UNV:
+  case FORMAT_P3D:
   case FORMAT_DMG:
   case FORMAT_STL:
   case FORMAT_GREF:
diff --git a/Mesh/Mesh.h b/Mesh/Mesh.h
index d2c1790a75..7676ba9d4b 100644
--- a/Mesh/Mesh.h
+++ b/Mesh/Mesh.h
@@ -58,6 +58,7 @@
 #define FORMAT_PDFTEX        25
 #define FORMAT_LC            26
 #define FORMAT_STL           27
+#define FORMAT_P3D           28
 
 #define CONV_VALUE    0.8
 
diff --git a/Mesh/Print_Mesh.cpp b/Mesh/Print_Mesh.cpp
index 36cf126b3d..9c9f46097d 100644
--- a/Mesh/Print_Mesh.cpp
+++ b/Mesh/Print_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Print_Mesh.cpp,v 1.59 2005-02-04 16:06:10 geuzaine Exp $
+// $Id: Print_Mesh.cpp,v 1.60 2005-02-28 23:57:59 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -1604,6 +1604,216 @@ void Print_Mesh_DMG(Mesh *m, FILE *fp)
   // write the volumes (2 b continued...)
 }
 
+// Write mesh in Plot3D format, ASCII structured, multi-zone
+// FIXME: still need to implement this for extruded grids
+
+static FILE *P3DFILE;
+
+int _p3d_cmp_entities(const void *a, const void *b)
+{
+  Element **e1 = (Element **) a;
+  Element **e2 = (Element **) b;
+
+  return (*e1)->iEnt - (*e2)->iEnt;
+}
+
+
+int _p3d_cmp_surf_num(const void *a, const void *b)
+{
+  Surface **e1 = (Surface **) a;
+  Surface **e2 = (Surface **) b;
+
+  return (*e1)->Num - (*e2)->Num;
+}
+
+int _p3d_cmp_vol_num(const void *a, const void *b)
+{
+  Volume **e1 = (Volume **) a;
+  Volume **e2 = (Volume **) b;
+
+  return (*e1)->Num - (*e2)->Num;
+}
+
+void _p3d_print_quads(List_T *ListQuads, int Nu, int Nv)
+{
+  int i = 0, j = 0, c = 1, curQuad = 0;
+  double coord;
+  Quadrangle *pQ;
+
+  for (c = 0; c < 3; c++) {
+    for (j = 0; j < (Nu - 1); j++) {
+      for (i = 0; i < (Nv - 1); i++) {
+        curQuad = i + (j * (Nv - 1));
+        List_Read(ListQuads, curQuad, &pQ);
+        coord = (c==0) ? pQ->V[0]->Pos.X : ((c==1) ? pQ->V[0]->Pos.Y : pQ->V[0]->Pos.Z);
+        fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+      }
+      coord = (c==0) ? pQ->V[3]->Pos.X : ((c==1) ? pQ->V[3]->Pos.Y : pQ->V[3]->Pos.Z);
+      fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+    } j--;
+    for (i = 0; i < (Nv - 1); i++) {
+      curQuad = i + (j * (Nv - 1));
+      List_Read(ListQuads, curQuad, &pQ);
+      coord = (c==0) ? pQ->V[1]->Pos.X : ((c==1) ? pQ->V[1]->Pos.Y : pQ->V[1]->Pos.Z);
+      fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+    }
+    coord = (c==0) ? pQ->V[2]->Pos.X : ((c==1) ? pQ->V[2]->Pos.Y : pQ->V[2]->Pos.Z);
+    fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+  }
+}
+
+void _p3d_print_hex(List_T *ListHex, int Nu, int Nv, int Nw)
+{
+  int i = 0, j = 0, k = 0, c = 0, curHex = 0;
+  double coord;
+  Hexahedron *pH;
+
+  
+  for (c = 0; c < 3; c++) {
+    for (k = 0; k < (Nu - 1); k++) {
+      for (j = 0; j < (Nv - 1); j++) {
+        for (i = 0; i < (Nw - 1); i++) {
+          curHex = i + (j * (Nw - 1)) + (k * (Nw - 1) * (Nv - 1));
+          List_Read(ListHex, curHex, &pH);
+          coord = (c==0) ? pH->V[0]->Pos.X : ((c==1) ? pH->V[0]->Pos.Y : pH->V[0]->Pos.Z);
+          fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+        }
+       coord = (c==0) ? pH->V[4]->Pos.X : ((c==1) ? pH->V[4]->Pos.Y : pH->V[4]->Pos.Z);
+       fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+      } j--;
+      for (i = 0; i < (Nw - 1); i++) {
+        curHex = i + (j * (Nw - 1)) + (k * (Nw - 1) * (Nv - 1));
+        List_Read(ListHex, curHex, &pH);
+        coord = (c==0) ? pH->V[3]->Pos.X : ((c==1) ? pH->V[3]->Pos.Y : pH->V[3]->Pos.Z);
+        fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+      }
+      coord = (c==0) ? pH->V[7]->Pos.X : ((c==1) ? pH->V[7]->Pos.Y : pH->V[7]->Pos.Z);
+      fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+    } k--;
+    for (j = 0; j < (Nv - 1); j++) {
+      for (i = 0; i < (Nw - 1); i++) {
+        curHex = i + (j * (Nw - 1)) + (k * (Nw - 1) * (Nv - 1));
+        List_Read(ListHex, curHex, &pH);
+        coord = (c==0) ? pH->V[1]->Pos.X : ((c==1) ? pH->V[1]->Pos.Y : pH->V[1]->Pos.Z);
+        fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+      }
+      coord = (c==0) ? pH->V[5]->Pos.X : ((c==1) ? pH->V[5]->Pos.Y : pH->V[5]->Pos.Z);
+      fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+    } j--;
+    for (i = 0; i < (Nw - 1); i++) {
+      curHex = i + (j * (Nw - 1)) + (k * (Nw - 1) * (Nv - 1));
+      List_Read(ListHex, curHex, &pH);
+      coord = (c==0) ? pH->V[2]->Pos.X : ((c==1) ? pH->V[2]->Pos.Y : pH->V[2]->Pos.Z);
+      fprintf(P3DFILE, "%g ", coord * CTX.mesh.scaling_factor);
+    }
+    coord = (c==0) ? pH->V[6]->Pos.X : ((c==1) ? pH->V[6]->Pos.Y : pH->V[6]->Pos.Z);
+    fprintf(P3DFILE, "%g\n", coord * CTX.mesh.scaling_factor);
+  }
+}
+
+void _p3d_print_all_elements(Mesh *M)
+{
+  int i, Nv, Nu, ElemCnt = 0;
+  Volume *pV;
+  Surface *pS;
+  List_T *ListQuads;
+  List_T *ListHex;
+
+  List_T *ListSurfaces = Tree2List(M->Surfaces);
+  List_T *ListVolumes = Tree2List(M->Volumes);
+
+  List_T *ListStructSurf = List_Create(1,1,sizeof(Surface *));
+  List_T *ListStructVol = List_Create(1,1,sizeof(Volume *));
+
+  List_Sort(ListSurfaces, _p3d_cmp_surf_num);
+  List_Sort(ListVolumes, _p3d_cmp_vol_num);
+
+  for(i = 0; i < List_Nbr(ListSurfaces); i++) {
+    List_Read(ListSurfaces, i, &pS);
+    if (pS->Nu &&
+        pS->Nv &&
+        (Tree_Nbr(pS->Quadrangles) == (pS->Nu - 1) * (pS->Nv - 1))){
+        ElemCnt++;
+        List_Add(ListStructSurf, &pS);
+    }
+  }
+
+  for(i = 0; i < List_Nbr(ListVolumes); i++) {
+    List_Read(ListVolumes, i, &pV);
+    List_Read(pV->Surfaces, 0, &pS);
+    Nu = pS->Nu;
+    Nv = pS->Nv;
+    List_Read(pV->Surfaces, 1, &pS);
+    if (Nu &&
+        Nv &&
+        pS->Nv &&
+        (Tree_Nbr(pV->Hexahedra) == (Nu - 1) * (Nv - 1) * (pS->Nv - 1))){
+        ElemCnt++;
+        List_Add(ListStructVol, &pV);
+    }
+  }
+
+  fprintf(P3DFILE, "%d\n", ElemCnt);
+
+  for(i = 0; i < List_Nbr(ListStructSurf); i++) {
+    List_Read(ListStructSurf, i, &pS);
+    fprintf(P3DFILE, "%d %d 1\n", pS->Nv, pS->Nu);
+  }
+
+  for(i = 0; i < List_Nbr(ListStructVol); i++) {
+    List_Read(ListStructVol, i, &pV);
+    List_Read(pV->Surfaces, 0, &pS);
+    Nu = pS->Nu;
+    Nv = pS->Nv;
+    List_Read(pV->Surfaces, 1, &pS);
+    fprintf(P3DFILE, "%d %d %d\n", pS->Nv, Nv, Nu);
+  }
+
+  for(i = 0; i < List_Nbr(ListStructSurf); i++) {
+    List_Read(ListStructSurf, i, &pS);
+    ListQuads = Tree2List(pS->Quadrangles);
+    List_Sort(ListQuads, _p3d_cmp_entities);
+    _p3d_print_quads(ListQuads, pS->Nu, pS->Nv);
+    List_Delete(ListQuads);
+  }
+
+  for(i = 0; i < List_Nbr(ListStructVol); i++) {
+    List_Read(ListStructVol, i, &pV);
+    List_Read(pV->Surfaces, 0, &pS);
+    Nu = pS->Nu;
+    Nv = pS->Nv;
+    List_Read(pV->Surfaces, 1, &pS);
+    ListHex = Tree2List(pV->Hexahedra);
+    List_Sort(ListHex, _p3d_cmp_entities);
+    _p3d_print_hex(ListHex, Nu, Nv, pS->Nv);
+    List_Delete(ListHex);
+  }
+
+  List_Delete(ListSurfaces);
+  List_Delete(ListVolumes);
+  List_Delete(ListStructSurf);
+  List_Delete(ListStructVol);
+}
+
+void _p3d_print_elements(Mesh *M)
+{
+  // FIXME: to do
+}
+
+void Print_Mesh_P3D(Mesh *M, FILE *fp)
+{
+  P3DFILE = fp;
+
+  if(!List_Nbr(M->PhysicalGroups) || CTX.mesh.save_all) {
+    Msg(INFO, "Saving all elements (discarding physical groups)");
+    _p3d_print_all_elements(M);
+  }
+  else{
+    Msg(WARNING, "No Plot3d format of physicals yet, saving all elements!");
+    //_p3d_print_elements(M);
+    _p3d_print_all_elements(M);
+  }
+}
 
 // Public Print_Mesh routine
 
@@ -1627,6 +1837,7 @@ void Print_Mesh(Mesh *M, char *c, int Type)
   case FORMAT_GREF: strcpy(ext, ".Gref"); break;
   case FORMAT_DMG:  strcpy(ext, ".dmg"); break;
   case FORMAT_STL:  strcpy(ext, ".stl"); break;
+  case FORMAT_P3D:  strcpy(ext, ".p3d"); break;
   default:
     Msg(GERROR, "Unknown mesh file format %d", Type);
     return;
@@ -1650,6 +1861,7 @@ void Print_Mesh(Mesh *M, char *c, int Type)
   case FORMAT_GREF: Print_Mesh_GREF(M, fp); break;
   case FORMAT_DMG:  Print_Mesh_DMG(M, fp); break;
   case FORMAT_STL:  Print_Mesh_STL(M, fp); break;
+  case FORMAT_P3D:  Print_Mesh_P3D(M, fp); break;
   default:
     break;
   }
diff --git a/TODO b/TODO
index 2b2a916718..45151248ed 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,13 @@
-$Id: TODO,v 1.85 2005-02-26 04:53:12 geuzaine Exp $
+$Id: TODO,v 1.86 2005-02-28 23:57:59 geuzaine Exp $
+
+********************************************************************
+
+add a mode to pick a mesh element with the mouse (a la medit)
+
+********************************************************************
+
+add option to cutmesh to cap the mesh instead of displaying "whole"
+elements
 
 ********************************************************************
 
diff --git a/doc/CREDITS b/doc/CREDITS
index 2d0e3aea84..1f46d7780b 100644
--- a/doc/CREDITS
+++ b/doc/CREDITS
@@ -1,4 +1,4 @@
-$Id: CREDITS,v 1.26 2005-02-04 16:06:10 geuzaine Exp $
+$Id: CREDITS,v 1.27 2005-02-28 23:57:59 geuzaine Exp $
 
              Gmsh is copyright (C) 1997-2005
 
@@ -19,8 +19,9 @@ univ.u-3mrs.fr> for new colormaps; Patrick Dular <patrick.dular at
 ulg.ac.be> for transfinite mesh bug fixes; Laurent Stainier
 <l.stainier at ulg.ac.be> for the eigenvalue solvers and for help with
 the MacOS port and the tensor display code; Pierre Badel <badel at
-freesurf.fr> for help with the GSL integration; and Marc Ume <Marc.Ume
-at digitalgraphics.be> for the original list code.
+freesurf.fr> for help with the GSL integration; Marc Ume <Marc.Ume at
+digitalgraphics.be> for the original list code; Matt Gundry
+<mjgundry at faa-engineers.com> for the Plot3d mesh format.
 
 The AVL tree code (DataStr/avl.*) and the YUV image code
 (Graphics/gl2yuv.*) are copyright (C) 1988-1993, 1995 The Regents of
@@ -94,7 +95,7 @@ at debian.org>, Sebastien.Clerc <Sebastien.Clerc at space.alcatel.fr>,
 Jose Miguel Pasini <jmp84 at cornell.edu>, Philippe Lussou <plussou at
 necs.fr>, Jacques Kools <JKools at veeco.com>, Bayram Yenikaya
 <yenikaya at math.umn.edu>, Peter Hornby <p.hornby at arrc.csiro.au>,
-Krishna Mohan Gundu <gkmohan at gmail.com>, Christopher Stott
-<C.Stott@surrey.ac.uk>, Timmy Schumacher
-<Tim.Schumacher@colorado.edu>, Carl Osterwisch <osterwischc@asme.org>,
-Bruno Frackowiak <bruno.frackowiak@onecert.fr>.
+Krishna Mohan Gundu <gkmohan at gmail.com>, Christopher Stott <C.Stott
+at surrey.ac.uk>, Timmy Schumacher <Tim.Schumacher at colorado.edu>,
+Carl Osterwisch <osterwischc at asme.org>, Bruno Frackowiak
+<bruno.frackowiak at onecert.fr>.
-- 
GitLab