From 66d1a3768040759d19a842d6e36ce97b84f33e14 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 19 Aug 2016 07:39:59 +0000
Subject: [PATCH] merged support for TOCHNOG files, contributed by Fernando
 Lorenzo

---
 Common/CreateFile.cpp  |  7 +++++++
 Common/GmshDefines.h   |  3 ++-
 Fltk/graphicWindow.cpp |  4 ++++
 Geo/CMakeLists.txt     |  2 +-
 Geo/GModel.h           |  4 ++++
 Geo/MElement.cpp       | 13 +++++++++++++
 Geo/MElement.h         |  5 +++++
 Geo/MHexahedron.h      |  2 ++
 Geo/MLine.h            |  2 ++
 Geo/MQuadrangle.h      |  2 ++
 Geo/MTetrahedron.h     |  2 ++
 Geo/MTriangle.h        |  2 ++
 Geo/MVertex.cpp        | 19 +++++++++++++++++++
 Geo/MVertex.h          |  1 +
 doc/CREDITS.txt        |  5 +++--
 15 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index 4a50810cce..53b73e5bd0 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -40,6 +40,7 @@ int GetFileFormatFromExtension(const std::string &ext)
   else if(ext == ".opt")  return FORMAT_OPT;
   else if(ext == ".unv")  return FORMAT_UNV;
   else if(ext == ".vtk")  return FORMAT_VTK;
+  else if(ext == ".dat")  return FORMAT_TOCHNOG;
   else if(ext == ".txt")  return FORMAT_TXT;
   else if(ext == ".stl")  return FORMAT_STL;
   else if(ext == ".cgns") return FORMAT_CGNS;
@@ -99,6 +100,7 @@ std::string GetDefaultFileName(int format)
   case FORMAT_OPT:  name += ".opt"; break;
   case FORMAT_UNV:  name += ".unv"; break;
   case FORMAT_VTK:  name += ".vtk"; break;
+  case FORMAT_TOCHNOG: name += ".dat"; break;
   case FORMAT_STL:  name += ".stl"; break;
   case FORMAT_CGNS: name += ".cgns"; break;
   case FORMAT_MED:  name += ".med"; break;
@@ -296,6 +298,11 @@ void CreateOutputFile(const std::string &fileName, int format,
        CTX::instance()->mesh.scalingFactor);
     break;
 
+  case FORMAT_TOCHNOG:
+    GModel::current()->writeTOCHNOG
+      (name, CTX::instance()->mesh.saveAll, CTX::instance()->mesh.scalingFactor);
+    break;
+
   case FORMAT_VTK:
     GModel::current()->writeVTK
       (name, CTX::instance()->mesh.binary, CTX::instance()->mesh.saveAll,
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index 2abd8dd9a4..7f3a1829ee 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -52,7 +52,8 @@
 #define FORMAT_MPEG_PREVIEW 43
 #define FORMAT_PGF   44
 #define FORMAT_PVTU  45
-#define FORMAT_X3D  46
+#define FORMAT_X3D   46
+#define FORMAT_TOCHNOG 47
 
 // Element types
 #define TYPE_PNT     1
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index 1c99e27db1..93091df7c5 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -276,6 +276,8 @@ static int _save_unv(const char *name){ return unvinpFileDialog
     (name, "UNV Options", FORMAT_UNV); }
 static int _save_vtk(const char *name){ return genericMeshFileDialog
     (name, "VTK Options", FORMAT_VTK, true, false); }
+static int _save_tochnog(const char *name){ return genericMeshFileDialog
+    (name, "Tochnog Options", FORMAT_TOCHNOG, true, false); }
 static int _save_diff(const char *name){ return genericMeshFileDialog
     (name, "Diffpack Options", FORMAT_DIFF, true, false); }
 static int _save_inp(const char *name){ return unvinpFileDialog
@@ -348,6 +350,7 @@ static int _save_auto(const char *name)
   case FORMAT_CGNS : return _save_cgns(name);
   case FORMAT_UNV  : return _save_unv(name);
   case FORMAT_VTK  : return _save_vtk(name);
+  case FORMAT_TOCHNOG: return _save_tochnog(name);
   case FORMAT_MED  : return _save_med(name);
   case FORMAT_RMED : return _save_view_med(name);
   case FORMAT_MESH : return _save_mesh(name);
@@ -414,6 +417,7 @@ static void file_save_as_cb(Fl_Widget *w, void *data)
     {"Mesh - STL Surface" TT "*.stl", _save_stl},
     {"Mesh - VRML Surface" TT "*.wrl", _save_vrml},
     {"Mesh - VTK" TT "*.vtk", _save_vtk},
+    {"Mesh - Tochnog" TT "*.dat", _save_tochnog},
     {"Mesh - PLY2 Surface" TT "*.ply2", _save_ply2},
     {"Mesh - SU2" TT "*.su2", _save_su2},
     {"Post-processing - Gmsh POS" TT "*.pos", _save_view_pos},
diff --git a/Geo/CMakeLists.txt b/Geo/CMakeLists.txt
index 1c7bd3b40b..ecfd656e58 100644
--- a/Geo/CMakeLists.txt
+++ b/Geo/CMakeLists.txt
@@ -23,7 +23,7 @@ set(SRC
   GModel.cpp
     GModelVertexArrays.cpp
     GModelFactory.cpp
-    GModelIO_GEO.cpp GModelIO_ACIS.cpp GModelIO_OCC.cpp 
+    GModelIO_GEO.cpp GModelIO_ACIS.cpp GModelIO_OCC.cpp GModelIO_TOCHNOG.cpp
       GModelIO_Fourier.cpp OCC_Connect.cpp
     GModelIO_MSH.cpp GModelIO_MSH2.cpp GModelIO_VTK.cpp GModelIO_POS.cpp 
       GModelIO_CGNS.cpp GModelIO_MED.cpp GModelIO_MESH.cpp GModelIO_STL.cpp 
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 6e1de7891f..78de5e1bbc 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -702,6 +702,10 @@ class GModel
                bool saveAll=false, double scalingFactor=1.0,
                bool bigEndian=false);
 
+  // Tochnog format
+  int writeTOCHNOG(const std::string &name,  bool saveGroupsOfNodes=false,
+                   bool saveAll=false, double scalingFactor=1.0);
+
   // DIFFPACK format
   int readDIFF(const std::string &name);
   int writeDIFF(const std::string &name, bool binary=false,
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 12b8bbd453..24cb8009a1 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1321,6 +1321,19 @@ void MElement::writeVRML(FILE *fp)
   fprintf(fp, "-1,\n");
 }
 
+void MElement::writeTOCHNOG(FILE *fp, int num)
+{
+  const char *str = getStringForTOCHNOG();
+  if(!str) return;
+
+  int n = getNumVertices();
+  fprintf(fp, "element %d %s ", num, str);
+  for(int i = 0; i < n; i++) {
+    fprintf(fp, " %d", getVertexTOCHNOG(i)->getIndex());
+  }
+  fprintf(fp, "\n");
+}
+
 void MElement::writeVTK(FILE *fp, bool binary, bool bigEndian)
 {
   if(!getTypeForVTK()) return;
diff --git a/Geo/MElement.h b/Geo/MElement.h
index cdf005092a..abf4c161a3 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -109,6 +109,9 @@ class MElement
   // get the vertex using the VTK ordering
   virtual MVertex *getVertexVTK(int num){ return getVertex(num); }
 
+  // get the vertex using the Tochnog ordering
+  virtual MVertex *getVertexTOCHNOG(int num){ return getVertex(num); }
+
   // get the vertex using the Nastran BDF ordering
   virtual MVertex *getVertexBDF(int num){ return getVertex(num); }
 
@@ -380,6 +383,7 @@ class MElement
   virtual void writePLY2(FILE *fp);
   virtual void writeUNV(FILE *fp, int num=0, int elementary=1, int physical=1);
   virtual void writeVTK(FILE *fp, bool binary=false, bool bigEndian=false);
+  virtual void writeTOCHNOG(FILE *fp, int num);
   virtual void writeMESH(FILE *fp, int elementTagType=1, int elementary=1,
                          int physical=0);
   virtual void writeIR3(FILE *fp, int elementTagType, int num, int elementary,
@@ -396,6 +400,7 @@ class MElement
   virtual int getTypeForMSH() const { return 0; }
   virtual int getTypeForUNV() const { return 0; }
   virtual int getTypeForVTK() const { return 0; }
+  virtual const char *getStringForTOCHNOG() const { return 0; }
   virtual const char *getStringForPOS() const { return 0; }
   virtual const char *getStringForBDF() const { return 0; }
   virtual const char *getStringForDIFF() const { return 0; }
diff --git a/Geo/MHexahedron.h b/Geo/MHexahedron.h
index 7a5fbca9b2..c410956441 100644
--- a/Geo/MHexahedron.h
+++ b/Geo/MHexahedron.h
@@ -119,6 +119,7 @@ class MHexahedron : public MElement {
   virtual const char *getStringForBDF() const { return "CHEXA"; }
   virtual const char *getStringForDIFF() const { return "ElmB8n3D"; }
   virtual const char *getStringForINP() const { return "C3D8"; }
+   virtual const char *getStringForTOCHNOG() const { return "-hex8"; }
   virtual void reverse()
   {
     MVertex *tmp;
@@ -425,6 +426,7 @@ class MHexahedron27 : public MHexahedron {
   virtual const char *getStringForPOS() const { return "SH2"; }
   virtual const char *getStringForDIFF() const { return "ElmB27n3D"; }
   virtual const char *getStringForINP() const { return "C3D27"; }
+  virtual const char *getStringForTOCHNOG() const { return "-hex27"; }
   virtual void reverse()
   {
     MVertex *tmp;
diff --git a/Geo/MLine.h b/Geo/MLine.h
index 5df4415e15..0e26cab51e 100644
--- a/Geo/MLine.h
+++ b/Geo/MLine.h
@@ -70,6 +70,7 @@ class MLine : public MElement {
   virtual const char *getStringForPOS() const { return "SL"; }
   virtual const char *getStringForBDF() const { return "CBAR"; }
   virtual const char *getStringForINP() const { return "T3D2"/*"C1D2"*/; }
+  virtual const char *getStringForTOCHNOG() const { return "-bar2"; }
   virtual void reverse()
   {
     MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
@@ -145,6 +146,7 @@ class MLine3 : public MLine {
   virtual int getTypeForVTK() const { return 21; }
   virtual const char *getStringForPOS() const { return "SL2"; }
   virtual const char *getStringForINP() const { return "T3D3"/*"C1D3"*/; }
+  virtual const char *getStringForTOCHNOG() const { return "-bar3"; }
   virtual void getNode(int num, double &u, double &v, double &w) const
   {
     num < 2 ? MLine::getNode(num, u, v, w) : MElement::getNode(num, u, v, w);
diff --git a/Geo/MQuadrangle.h b/Geo/MQuadrangle.h
index 1b8839ed57..f81b261147 100644
--- a/Geo/MQuadrangle.h
+++ b/Geo/MQuadrangle.h
@@ -117,6 +117,7 @@ class MQuadrangle : public MElement {
   virtual const char *getStringForBDF() const { return "CQUAD4"; }
   virtual const char *getStringForDIFF() const { return "ElmB4n2D"; }
   virtual const char *getStringForINP() const { return "CPS4"/*"C2D4"*/; }
+  virtual const char *getStringForTOCHNOG() const { return "-quad4"; }
   virtual void getNode(int num, double &u, double &v, double &w) const
   {
     w = 0.;
@@ -328,6 +329,7 @@ class MQuadrangle9 : public MQuadrangle {
   virtual int getTypeForVTK() const { return 28; }
   virtual const char *getStringForPOS() const { return "SQ2"; }
   virtual const char *getStringForDIFF() const { return "ElmB9n2D"; }
+  virtual const char *getStringForTOCHNOG() const { return "-quad9"; }
   virtual void reverse()
   {
     MVertex *tmp;
diff --git a/Geo/MTetrahedron.h b/Geo/MTetrahedron.h
index 0456dc3959..ec41b1a8cf 100644
--- a/Geo/MTetrahedron.h
+++ b/Geo/MTetrahedron.h
@@ -106,6 +106,7 @@ class MTetrahedron : public MElement {
   virtual const char *getStringForBDF() const { return "CTETRA"; }
   virtual const char *getStringForDIFF() const { return "ElmT4n3D"; }
   virtual const char *getStringForINP() const { return "C3D4"; }
+  virtual const char *getStringForTOCHNOG() const { return "-tet4"; }
   virtual void reverse()
   {
     MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
@@ -277,6 +278,7 @@ class MTetrahedron10 : public MTetrahedron {
   virtual const char *getStringForBDF() const { return "CTETRA"; }
   virtual const char *getStringForDIFF() const { return "ElmT10n3D"; }
   virtual const char *getStringForINP() const { return "C3D10"; }
+  virtual const char *getStringForTOCHNOG() const { return "-tet10"; }
   virtual void reverse()
   {
     MVertex *tmp;
diff --git a/Geo/MTriangle.h b/Geo/MTriangle.h
index fe46e28e0a..d0318b44c7 100644
--- a/Geo/MTriangle.h
+++ b/Geo/MTriangle.h
@@ -120,6 +120,7 @@ class MTriangle : public MElement {
   virtual const char *getStringForBDF() const { return "CTRIA3"; }
   virtual const char *getStringForDIFF() const { return "ElmT3n2D"; }
   virtual const char *getStringForINP() const { return "CPS3"/*"STRI3"*//*"C2D3"*/; }
+  virtual const char *getStringForTOCHNOG() const { return "-tria3"; }
   virtual void reverse()
   {
     MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
@@ -231,6 +232,7 @@ class MTriangle6 : public MTriangle {
   virtual const char *getStringForBDF() const { return "CTRIA6"; }
   virtual const char *getStringForDIFF() const { return "ElmT6n2D"; }
   virtual const char *getStringForINP() const { return "CPS6"/*"STRI65"*//*"C2D6"*/; }
+  virtual const char *getStringForTOCHNOG() const { return "-tria6"; }
   virtual void reverse()
   {
     MVertex *tmp;
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index 21b41eed1d..dc71217037 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -242,6 +242,25 @@ void MVertex::writeVTK(FILE *fp, bool binary, double scalingFactor, bool bigEndi
   }
 }
 
+void MVertex::writeTOCHNOG(FILE *fp, int dim, double scalingFactor)
+{
+  if(_index < 0) return; // negative index vertices are never saved
+  if(dim == 2) {
+    fprintf(fp, "node %d %.16g %.16g\n", _index,
+            x() * scalingFactor, y() * scalingFactor);
+  }
+  else if (dim == 3) {
+    fprintf(fp, "node %d %.16g %.16g %.16g\n", _index,
+            x() * scalingFactor, y() * scalingFactor, z() * scalingFactor);
+  }
+  else if (dim == 1) {
+    fprintf(fp, "node %d %.16g\n", _index, x() * scalingFactor);
+  }
+  else {
+    fprintf(fp, "ERROR -- unsupported dimension: %d\n", dim);
+  }
+}
+
 void MVertex::writeMESH(FILE *fp, double scalingFactor)
 {
   if(_index < 0) return; // negative index vertices are never saved
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index 8445ff5481..2a2a0c6316 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -98,6 +98,7 @@ class MVertex{
   void writeUNV(FILE *fp, double scalingFactor=1.0);
   void writeVTK(FILE *fp, bool binary=false, double scalingFactor=1.0,
                 bool bigEndian=false);
+  void writeTOCHNOG(FILE *fp, int dim, double scalingFactor=1.0);
   void writeMESH(FILE *fp, double scalingFactor=1.0);
   void writeBDF(FILE *fp, int format=0, double scalingFactor=1.0);
   void writeINP(FILE *fp, double scalingFactor=1.0);
diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt
index 356229ae9d..faead36b35 100644
--- a/doc/CREDITS.txt
+++ b/doc/CREDITS.txt
@@ -24,8 +24,9 @@ Bechet (solver), Gilles Marckmann (camera and stero mode), Ashish Negi
 with pyramids), Amaury Johnen (Bezier), Benjamin Ruard (Java wrappers), Maxime
 Graulich (iOS/Android port), Francois Henrotte (onelab metamodels), Sebastian
 Eiser (PGF output), Alexis Salzman (compressed IO), Hang Si (TetGen/BR boundary
-recovery code). See comments in the sources for more information. If we forgot
-to list your contributions please send us an email!
+recovery code), Fernando Lorenzo (Tochnog support). See comments in the sources
+for more information. If we forgot to list your contributions please send us an
+email!
 
 The TetGen/BR code (Mesh/tetgenBR.{cpp,h}) is copyright (c) 2016 Hang Si, Weierstrass
 Institute for Applied Analysis and Stochatics.
-- 
GitLab