From 25fa0af7037a889e80b424cb35fa8d73f23b3c44 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 12 Nov 2008 09:24:33 +0000
Subject: [PATCH] readDIFF from Jacques Lechelle

---
 Fltk/Callbacks.cpp    |   5 +-
 Geo/GModel.h          |   1 +
 Geo/GModelIO_Mesh.cpp | 219 ++++++++++++++++++++++++++++++++++++++++++
 Geo/MElement.h        |   4 +-
 doc/VERSIONS.txt      |   5 +-
 5 files changed, 228 insertions(+), 6 deletions(-)

diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 58631e5eee..0c3fa60e15 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -595,6 +595,7 @@ static const char *input_formats =
   "BRep model" TT "*.brep" NN
 #endif
   "I-deas universal mesh" TT "*.unv" NN
+  "Diffpack 3D mesh" TT "*.diff" NN
   "VTK mesh" TT "*.vtk" NN
 #if defined(HAVE_MED)
   "MED file" TT "*.{med,mmed,rmed}" NN
@@ -651,7 +652,7 @@ int _save_geo(const char *name){ return geo_dialog(name); }
 int _save_cgns(const char *name){ return cgns_write_dialog(name); }
 int _save_unv(const char *name){ return unv_dialog(name); }
 int _save_vtk(const char *name){ return generic_mesh_dialog(name, "VTK Options", FORMAT_VTK, true); }
-int _save_diff(const char *name){ return generic_mesh_dialog(name, "DIFFPACK Options", FORMAT_DIFF, true); }
+int _save_diff(const char *name){ return generic_mesh_dialog(name, "Diffpack Options", FORMAT_DIFF, true); }
 int _save_med(const char *name){ return generic_mesh_dialog(name, "MED Options", FORMAT_MED, false); }
 int _save_mesh(const char *name){ return generic_mesh_dialog(name, "MESH Options", FORMAT_MESH, false); }
 int _save_bdf(const char *name){ return bdf_dialog(name); }
@@ -727,7 +728,7 @@ void file_save_as_cb(CALLBACK_ARGS)
     {"CGNS" TT "*.cgns", _save_cgns},
 #endif
     {"I-deas universal mesh" TT "*.unv", _save_unv},
-    {"DIFFPACK 3D mesh" TT "*.diff", _save_diff},
+    {"Diffpack 3D mesh" TT "*.diff", _save_diff},
     {"VTK mesh" TT "*.vtk", _save_vtk},
 #if defined(HAVE_MED)
     {"MED file" TT "*.med", _save_med},
diff --git a/Geo/GModel.h b/Geo/GModel.h
index dbee4f744b..35a167e50a 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -332,6 +332,7 @@ class GModel
 	       bool bigEndian=false);
 
   // DIFFPACK format
+  int readDIFF(const std::string &name);
   int writeDIFF(const std::string &name, bool binary=false,
                bool saveAll=false, double scalingFactor=1.0);
 };
diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp
index d375b23e80..a2a4f68e9d 100644
--- a/Geo/GModelIO_Mesh.cpp
+++ b/Geo/GModelIO_Mesh.cpp
@@ -2154,6 +2154,225 @@ int GModel::readVTK(const std::string &name, bool bigEndian)
   return 1;
 }
 
+int GModel::readDIFF(const std::string &name)
+{
+  FILE *fp = fopen(name.c_str(), "r");
+  if(!fp){
+    Msg::Error("Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+// FIXME: todo
+#if 0 
+  char str[256] = "XXX";
+  std::map<int, std::vector<MElement*> > elements[8];
+  std::map<int, std::map<int, std::string> > physicals[4];
+  std::map<int, MVertex*> vertexMap;
+  std::vector<MVertex*> vertexVector;
+ 
+  while(1) {
+
+    while(strstr(str, "Number of space dim. =") == NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    
+    int dim;
+    if(sscanf(str, "%*s %*s %*s %*s %*s %d", &dim) != 1) return 0;
+    Msg::Info("dimension %d", dim); 
+
+    int numElements;
+    if(!fgets(str, sizeof(str), fp) || feof(fp)) return 0;
+    while(strstr(str, "Number of elements   =") == NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    if(sscanf(str, "%*s %*s %*s %*s %d", &numElements) != 1) return 0;
+    Msg::Info("%d elements", numElements); 
+
+    int numVertices;
+    if(!fgets(str, sizeof(str), fp) || feof(fp)) return 0;
+    while(strstr(str, "Number of nodes      =") == NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    if(sscanf(str, "%*s %*s %*s %*s %d", &numVertices) != 1) return 0;
+    Msg::Info("%d vertices", numVertices); 
+
+    int numVerticesPerElement;
+    if(!fgets(str, sizeof(str), fp)||feof(fp)) return 0;
+    while(strstr(str, "Max number of nodes in an element:")==NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+      }
+    if(sscanf(str, "%*s %*s %*s %*s %*s %*s %*s %d", &numVerticesPerElement) != 1) return 0;
+    Msg::Info("numVerticesPerElement %d",numVerticesPerElement); 
+
+    bool several_subdomains;
+    if(!fgets(str, sizeof(str), fp) || feof(fp)) return 0;
+    while(strstr(str, "Only one subdomain el              :") == NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    if(!strncmp(&str[39], "dpFALSE", 6))
+      several_subdomains = true;
+    else
+      several_subdomains = false;
+    Msg::Info("several_subdomains %x", several_subdomains); 
+    
+    int nbi;
+    int* bi;
+    if(!fgets(str, sizeof(str), fp) || feof(fp)) return 0;
+    while(strstr(str, "Boundary indicators:") == NULL){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    if(sscanf(str, "%d %*s %*s", &nbi) != 1) return 0;
+    Msg::Info("nbi %d", nbi);
+    if(nbi != 0) 
+      bi = new int[nbi];
+    std::string format_read_bi = "%*d %*s %*s";
+    for(int i = 0; i < nbi; i++){
+      if(format_read_bi[format_read_bi.size()-1] == 'd') {
+        format_read_bi[format_read_bi.size()-1] = '*';
+        format_read_bi += "d %d";
+      }
+      else
+        format_read_bi += " %d";
+      if(sscanf(str, format_read_bi.c_str(), bi + i) != 1) return 0;
+      Msg::Info("bi[%d]=%d", i, bi[i]); 
+    }
+    
+    while(str[0] != '#'){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    vertexVector.clear();
+    vertexMap.clear();
+    int minVertex = numVertices + 1, maxVertex = -1;
+    int num;
+    int **elementary;
+    elementary = new int*[numVertices];
+
+    Msg::ResetProgressMeter();
+    for(int i = 0; i < numVertices; i++){
+      elementary[i] = new int[nbi + 1];
+      if(!fgets(str, sizeof(str), fp)) return 0;
+      double xyz[3];
+      if(sscanf(str, "%d ( %lf , %lf , %lf ) [%d]", &num, &xyz[0], &xyz[1], &xyz[2], 
+                &elementary[i][0]) != 5) return 0;
+      minVertex = std::min(minVertex, num);
+      maxVertex = std::max(maxVertex, num);
+      if(vertexMap.count(num))
+        Msg::Warning("Skipping duplicate vertex %d", num);
+      else
+        vertexMap[num] = new MVertex(xyz[0], xyz[1], xyz[2], 0, num);
+      if(numVertices > 100000) 
+        Msg::ProgressMeter(i + 1, numVertices, "Reading nodes");
+      // If the vertex numbering is dense, tranfer the map into a
+      // vector to speed up element creation
+      if((int)vertexMap.size() == numVertices && 
+         ((minVertex == 1 && maxVertex == numVertices) ||
+          (minVertex == 0 && maxVertex == numVertices - 1))){
+        Msg::Info("Vertex numbering is dense");
+        vertexVector.resize(vertexMap.size() + 1);
+        if(minVertex == 1) 
+          vertexVector[0] = 0;
+        else
+          vertexVector[numVertices] = 0;
+        std::map<int, MVertex*>::const_iterator it = vertexMap.begin();
+        for(; it != vertexMap.end(); ++it)
+          vertexVector[it->first] = it->second;
+        vertexMap.clear();
+      }
+      Msg::Info("%d ( %lf , %lf , %lf ) [%d]",i, xyz[0], xyz[1], xyz[2], elementary[i][0]);
+      std::string format_read_bi = "%*d ( %*lf , %*lf , %*lf ) [%*d]";
+      for(int j = 0; j < elementary[i][0]; j++){
+        if(format_read_bi[format_read_bi.size() - 1] == 'd') {
+          format_read_bi[format_read_bi.size() - 1] = '*';
+          format_read_bi += "d %d";
+        }
+        else
+          format_read_bi += " %d";
+        if(sscanf(str, format_read_bi.c_str(), &(elementary[i][j + 1])) != 1) return 0;
+        Msg::Info("elementary[%d][%d]=%d", i + 1, j + 1, elementary[i][j + 1]); 
+      }
+    }
+    while(str[0] != '#'){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+        break;
+    }
+    
+    int material[numElements];
+    int ElementsNodes[numElements][numVerticesPerElement];
+    Msg::ResetProgressMeter();
+    for(int i = 1; i <= numElements; i++){
+       if(!fgets(str, sizeof(str), fp)) return 0;
+       int num, type, physical = 0, partition = 0;
+       int indices[60];
+       if(numVerticesPerElement == 10){
+         if(sscanf(str, "%d %*s %d %d %d %d %d %d %d %d %d %d %d", &num, &material[i - 1],
+                   &ElementsNodes[i - 1][1], &ElementsNodes[i - 1][0],
+                   &ElementsNodes[i - 1][2], &ElementsNodes[i - 1][3],
+                   &ElementsNodes[i - 1][4], &ElementsNodes[i - 1][6],
+                   &ElementsNodes[i - 1][5], &ElementsNodes[i - 1][9],
+                   &ElementsNodes[i - 1][7], &ElementsNodes[i - 1][8]) != 12) return 0;
+         Msg::Info("%d %d %d %d %d %d %d %d %d %d %d %d", i, material[i - 1],
+                   ElementsNodes[i - 1][0], ElementsNodes[i - 1][1], ElementsNodes[i - 1][2],
+                   ElementsNodes[i - 1][3], ElementsNodes[i - 1][4], ElementsNodes[i - 1][5],
+                   ElementsNodes[i - 1][6], ElementsNodes[i - 1][7], ElementsNodes[i - 1][8],
+                   ElementsNodes[i - 1][9]);
+         type = MSH_TET_10;
+       }
+       else {
+         if(sscanf(str,"%d %*s %d %d %d %d %d", &num, &material[i - 1], 
+                   &ElementsNodes[i - 1][1], &ElementsNodes[i - 1][0], &ElementsNodes[i - 1][2],
+                   &ElementsNodes[i - 1][3]) != 6) return 0;
+         Msg::Info("%d %d %d %d %d %d", i, material[i - 1], ElementsNodes[i - 1][0],
+                   ElementsNodes[i - 1][1], ElementsNodes[i - 1][2], ElementsNodes[i - 1][3]);
+         type = MSH_TET_4;
+        }
+       for(int j=0;j<numVerticesPerElement;j++)
+         indices[j] = ElementsNodes[i - 1][j];
+       std::vector<MVertex*> vertices;
+       if(vertexVector.size()){
+         if(!getVertices(numVerticesPerElement, indices, vertexVector, vertices)) return 0;
+       }
+       else{
+         if(!getVertices(numVerticesPerElement, indices, vertexMap, vertices)) return 0;
+       }
+       createElementMSH(this, num, type, physical, elementary[i-1][1], partition, 
+                        vertices, elements, physicals); 
+       // trouble if elementary[i-1][0]>1 nodal post-processing needed ?
+       if(numElements > 100000) 
+         Msg::ProgressMeter(i + 1, numElements, "Reading elements");
+    }
+  }
+  
+  // store the elements in their associated elementary entity. If the
+  // entity does not exist, create a new (discrete) one.
+  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
+    _storeElementsInEntities(elements[i]);
+
+  // associate the correct geometrical entity with each mesh vertex
+  _associateEntityWithMeshVertices();
+
+  // store the vertices in their associated geometrical entity
+  if(vertexVector.size())
+    _storeVerticesInEntities(vertexVector);
+  else
+    _storeVerticesInEntities(vertexMap);
+
+  // store the physical tags
+  for(int i = 0; i < 4; i++)
+    storePhysicalTagsInEntities(this, i, physicals[i]);
+
+#endif
+
+  fclose(fp);
+  return 1;
+}
+
 int GModel::writeDIFF(const std::string &name, bool binary, bool saveAll,
                       double scalingFactor)
 {
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 51098ec8c2..bdf70b5c80 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -1033,7 +1033,7 @@ class MQuadrangle9 : public MQuadrangle {
   virtual int getNumVertices() const { return 9; }
   virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
   virtual int getNumEdgeVertices() const { return 4; }
-  virtual int getNumFaceVertices() const { return 6; }
+  virtual int getNumFaceVertices() const { return 1; }
   virtual int getNumEdgesRep(){ return 8; }
   virtual void getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
   { 
@@ -1450,7 +1450,7 @@ class MTetrahedronN : public MTetrahedron {
   virtual int getPolynomialOrder() const { return _order; }
   virtual int getNumVertices() const { return 4 + _vs.size(); }
   virtual MVertex *getVertex(int num){ return num < 4 ? _v[num] : _vs[num - 4]; }
-  virtual int getNumEdgeVertices() const { return 6*(_order - 1); }
+  virtual int getNumEdgeVertices() const { return 6 * (_order - 1); }
   virtual int getNumFaceVertices() const
   {
     return 4 * ((_order - 1) * (_order - 2)) / 2;
diff --git a/doc/VERSIONS.txt b/doc/VERSIONS.txt
index 6b20f26cbd..8d1db77ee4 100644
--- a/doc/VERSIONS.txt
+++ b/doc/VERSIONS.txt
@@ -1,11 +1,12 @@
-$Id: VERSIONS.txt,v 1.13 2008-11-08 09:45:47 geuzaine Exp $
+$Id: VERSIONS.txt,v 1.14 2008-11-12 09:24:33 geuzaine Exp $
 
 2.2.6 (?): better transfinite smoothing and automatic corner
 selection; 
 
 2.2.5 (Oct 25, 2008): Gmsh now requires FLTK 1.1.7 or above; various
 small improvements (STL and VTK mesh IO, Netgen upgrade, Visual C++
-support, Fields) and bug fixes (pyramid interpolation, Chaco crashes).
+support, Fields, Mesh.{Msh,Stl,...}Binary changed to Mesh.Bindary) and
+bug fixes (pyramid interpolation, Chaco crashes).
 
 2.2.4 (Aug 14, 2008): integrated Metis and Chaco mesh partitioners;
 variables can now be deleted in geo files; added support for point
-- 
GitLab