From 256f01284fae7954e9a726bb47a2a01937bdb817 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 8 Aug 2012 10:31:19 +0000
Subject: [PATCH] fix pyramids

---
 Geo/GRegion.cpp      | 51 ++++++++++++-------------------
 Geo/GRegion.h        |  8 ++---
 Geo/OCCRegion.cpp    | 13 ++++----
 Geo/gmshRegion.cpp   |  3 +-
 Mesh/meshGRegion.cpp | 73 +++++++++++++++++++++-----------------------
 tutorial/t5.geo      | 18 +++++------
 6 files changed, 75 insertions(+), 91 deletions(-)

diff --git a/Geo/GRegion.cpp b/Geo/GRegion.cpp
index 0709934519..ba668a3a2e 100644
--- a/Geo/GRegion.cpp
+++ b/Geo/GRegion.cpp
@@ -31,17 +31,6 @@ GRegion::~GRegion()
   deleteMesh();
 }
 
-void GRegion::set(const std::list<GFace*> f) { 
-  for (std::list<GFace*>::iterator it =  l_faces.begin(); it !=  l_faces.end() ; ++it){
-    (*it)->delRegion(this);
-  }
-  l_faces = f; 
-  for (std::list<GFace*>::iterator it =  l_faces.begin(); it !=  l_faces.end() ; ++it){
-    (*it)->addRegion(this);
-  }
-}
-
-
 void GRegion::deleteMesh()
 {
   for(unsigned int i = 0; i < mesh_vertices.size(); i++) delete mesh_vertices[i];
@@ -62,7 +51,7 @@ void GRegion::deleteMesh()
 }
 
 unsigned int GRegion::getNumMeshElements()
-{ 
+{
   return tetrahedra.size() + hexahedra.size() + prisms.size() + pyramids.size() +
     polyhedra.size();
 }
@@ -108,19 +97,19 @@ MElement *const *GRegion::getStartElementType(int type) const
 }
 
 MElement *GRegion::getMeshElement(unsigned int index)
-{ 
+{
   if(index < tetrahedra.size())
     return tetrahedra[index];
   else if(index < tetrahedra.size() + hexahedra.size())
     return hexahedra[index - tetrahedra.size()];
   else if(index < tetrahedra.size() + hexahedra.size() + prisms.size())
     return prisms[index - tetrahedra.size() - hexahedra.size()];
-  else if(index < tetrahedra.size() + hexahedra.size() + prisms.size() + 
+  else if(index < tetrahedra.size() + hexahedra.size() + prisms.size() +
           pyramids.size())
     return pyramids[index - tetrahedra.size() - hexahedra.size() - prisms.size()];
-  else if(index < tetrahedra.size() + hexahedra.size() + prisms.size() + 
+  else if(index < tetrahedra.size() + hexahedra.size() + prisms.size() +
           pyramids.size() + polyhedra.size())
-    return polyhedra[index - tetrahedra.size() - hexahedra.size() - prisms.size() - 
+    return polyhedra[index - tetrahedra.size() - hexahedra.size() - prisms.size() -
                      pyramids.size()];
   return 0;
 }
@@ -152,7 +141,7 @@ SOrientedBoundingBox GRegion::getOBB()
   if (!_obb) {
     std::vector<SPoint3> vertices;
     std::list<GFace*> b_faces = faces();
-    for (std::list<GFace*>::iterator b_face = b_faces.begin(); 
+    for (std::list<GFace*>::iterator b_face = b_faces.begin();
          b_face != b_faces.end(); b_face++) {
       if((*b_face)->getNumMeshVertices() > 0) {
         int N = (*b_face)->getNumMeshVertices();
@@ -177,17 +166,17 @@ SOrientedBoundingBox GRegion::getOBB()
           vertices.push_back(pt1);
           vertices.push_back(pt2);
         }
-      } 
+      }
       else if ((*b_face)->buildSTLTriangulation()) {
         for (unsigned int i = 0; i < (*b_face)->stl_vertices.size(); i++){
           GPoint p = (*b_face)->point((*b_face)->stl_vertices[i]);
           vertices.push_back(SPoint3(p.x(), p.y(), p.z()));
-        } 
+        }
       }
       else {
         int N = 10;
         std::list<GEdge*> b_edges = (*b_face)->edges();
-        for (std::list<GEdge*>::iterator b_edge = b_edges.begin(); 
+        for (std::list<GEdge*>::iterator b_edge = b_edges.begin();
              b_edge != b_edges.end(); b_edge++) {
           Range<double> tr = (*b_edge)->parBounds(0);
           for (int j = 0; j < N; j++) {
@@ -196,7 +185,7 @@ SOrientedBoundingBox GRegion::getOBB()
             SPoint3 pt(p.x(), p.y(), p.z());
             vertices.push_back(pt);
           }
-        }       
+        }
       }
     }
     _obb = SOrientedBoundingBox::buildOBB(vertices);
@@ -312,7 +301,7 @@ void GRegion::replaceFaces (std::list<GFace*> &new_faces)
   std::list<int> newdirs;
   for ( ; it != l_faces.end(); ++it, ++it2, ++it3){
     (*it)->delRegion(this);
-    (*it2)->addRegion(this);        
+    (*it2)->addRegion(this);
     // if ((*it2)->getBeginVertex() == (*it)->getBeginVertex())
       newdirs.push_back(*it3);
     // else
@@ -332,13 +321,13 @@ double GRegion::computeSolidProperties (std::vector<double> cg,
   double volumez = 0;
   double surface = 0;
   cg[0] = cg[1] = cg[2] = 0.0;
-  for ( ; it != l_faces.end(); ++it,++itdir){    
+  for ( ; it != l_faces.end(); ++it,++itdir){
     //printf("face %d dir %d %d elements\n",(*it)->tag(),*itdir,(int)(*it)->triangles.size());
     for (unsigned int i = 0; i < (*it)->triangles.size(); ++i){
       MTriangle *e = (*it)->triangles[i];
       int npt;
       IntPt *pts;
-      e->getIntegrationPoints (2*(e->getPolynomialOrder()-1)+3, &npt, &pts);      
+      e->getIntegrationPoints (2*(e->getPolynomialOrder()-1)+3, &npt, &pts);
       for (int j=0;j<npt;j++){
 	SPoint3 pt;
 	// compute x,y,z of the integration point
@@ -370,19 +359,19 @@ double GRegion::computeSolidProperties (std::vector<double> cg,
 
   it = l_faces.begin();
   itdir =  l_dirs.begin();
-  inertia[0] =   
-    inertia[1] = 
-    inertia[2] = 
-    inertia[3] = 
-    inertia[4] = 
+  inertia[0] =
+    inertia[1] =
+    inertia[2] =
+    inertia[3] =
+    inertia[4] =
     inertia[5] = 0.0;
 
-  for ( ; it != l_faces.end(); ++it,++itdir){    
+  for ( ; it != l_faces.end(); ++it,++itdir){
     for (unsigned int i = 0; i < (*it)->getNumMeshElements(); ++i){
       MElement *e = (*it)->getMeshElement(i);
       int npt;
       IntPt *pts;
-      e->getIntegrationPoints (2*(e->getPolynomialOrder()-1)+3, &npt, &pts);      
+      e->getIntegrationPoints (2*(e->getPolynomialOrder()-1)+3, &npt, &pts);
       for (int j = 0; j < npt; j++){
 	SPoint3 pt;
 	// compute x,y,z of the integration point
diff --git a/Geo/GRegion.h b/Geo/GRegion.h
index e6a6733ee6..7f87c3a3fe 100644
--- a/Geo/GRegion.h
+++ b/Geo/GRegion.h
@@ -26,8 +26,8 @@ class GRegion : public GEntity {
  protected:
   std::list<GFace*> l_faces;
   std::list<int> l_dirs;
-  GRegionCompound *compound; // this model ede belongs to a compound 
-  
+  GRegionCompound *compound; // this model ede belongs to a compound
+
   // replace faces (for gluing) for specific modelers, we have to
   // re-create internal data ...
   virtual void replaceFacesInternal (std::list<GFace*> &) {}
@@ -48,7 +48,7 @@ class GRegion : public GEntity {
   // get/set faces that bound the region
   virtual std::list<GFace*> faces() const{ return l_faces; }
   virtual std::list<int> faceOrientations() const{ return l_dirs; }
-  void set(const std::list<GFace*> f);
+  inline void set(const std::list<GFace*> f) { l_faces = f; }
 
   // edges that bound the region
   virtual std::list<GEdge*> edges() const;
@@ -91,7 +91,7 @@ class GRegion : public GEntity {
 
   // reset the mesh attributes to default values
   virtual void resetMeshAttributes();
-  
+
   // compound
   void setCompound(GRegionCompound *grc) { compound = grc; }
   GRegionCompound *getCompound() const { return compound; }
diff --git a/Geo/OCCRegion.cpp b/Geo/OCCRegion.cpp
index 9d65e62005..e341df9d35 100644
--- a/Geo/OCCRegion.cpp
+++ b/Geo/OCCRegion.cpp
@@ -26,7 +26,7 @@ void OCCRegion::setup()
   for(exp2.Init(s, TopAbs_SHELL); exp2.More(); exp2.Next()){
     TopoDS_Shape shell = exp2.Current();
     Msg::Debug("OCC Region %d - New Shell",tag());
-    for(exp3.Init(shell, TopAbs_FACE); exp3.More(); exp3.Next()){         
+    for(exp3.Init(shell, TopAbs_FACE); exp3.More(); exp3.Next()){
       TopoDS_Face face = TopoDS::Face(exp3.Current());
       GFace *f = getOCCFaceByNativePtr(model(),face);
       if(f){
@@ -35,7 +35,7 @@ void OCCRegion::setup()
       }
       else
         Msg::Error("Unknown face in region %d", tag());
-    }      
+    }
   }
   Msg::Debug("OCC Region %d with %d faces", tag(), l_faces.size());
 }
@@ -45,7 +45,6 @@ GEntity::GeomType OCCRegion::geomType() const
   return Unknown;
 }
 
-
 bool FaceHaveDifferentOrientations(const TopoDS_Face& aFR,
 				   const TopoDS_Face& aF)
 {
@@ -82,19 +81,19 @@ void OCCRegion::replaceFacesInternal(std::list<GFace*> &new_faces)
 	if (occF){
 	  TopoDS_Face oldf = occF->getTopoDS_Face();
 	  if (oldf.IsSame(_face)){
-	    _face_replacement = *((TopoDS_Face*)(*it2)->getNativePtr());		  
+	    _face_replacement = *((TopoDS_Face*)(*it2)->getNativePtr());
 	  }
 	  else {
 	    oldf = occF->getTopoDS_FaceOld();
 	    if (oldf.IsSame(_face)){
-	      _face_replacement = *((TopoDS_Face*)(*it2)->getNativePtr());		  
+	      _face_replacement = *((TopoDS_Face*)(*it2)->getNativePtr());
 	    }
 	  }
 	}
       }
       if (_face_replacement.IsNull()){
 	Msg::Error("cannot find an face for gluing a region");
-      }      
+      }
 
       if (_face_replacement.IsSame(_face)) {
 	aBB.Add(_shell_replacement, _face);
@@ -104,7 +103,7 @@ void OCCRegion::replaceFacesInternal(std::list<GFace*> &new_faces)
           _face_replacement.Reverse();
 	aBB.Add(_shell_replacement, _face_replacement);
       }
-    }    
+    }
     aBB.Add(_s_replacement, _shell_replacement);
   }
   s = _s_replacement;
diff --git a/Geo/gmshRegion.cpp b/Geo/gmshRegion.cpp
index 5e0c9889a1..8ce695cebb 100644
--- a/Geo/gmshRegion.cpp
+++ b/Geo/gmshRegion.cpp
@@ -21,6 +21,7 @@ gmshRegion::gmshRegion(GModel *m, ::Volume *volume)
     if(f){
       l_faces.push_back(f);
       l_dirs.push_back(ori);
+      f->addRegion(this);
     }
     else
       Msg::Error("Unknown surface %d", s->Num);
@@ -32,11 +33,11 @@ gmshRegion::gmshRegion(GModel *m, ::Volume *volume)
     if(f){
       l_faces.push_back(f);
       l_dirs.push_back(sign(is));
+      f->addRegion(this);
     }
     else
       Msg::Error("Unknown surface %d", is);
   }
-
   resetMeshAttributes();
 }
 
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index c75fe74f47..09e5c7295f 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -76,11 +76,10 @@ class splitQuadRecovery {
 	allFaces.erase(*itf1);
 	allFaces.erase(*itf2);
 	allFaces.erase(*itf3);
-	printf("some pyramids should be created %d regions\n",(*it)->numRegions());
+	// printf("some pyramids should be created %d regions\n", (*it)->numRegions());
 	for (int iReg = 0; iReg < (*it)->numRegions(); iReg++){
-	   printf("one pyramid is created\n");
 	  if (iReg == 1) {
-            Msg::Error("cannot build pyramids on non manifold faces ...");
+            Msg::Error("Cannot build pyramids on non manifold faces");
             v = new MVertex(v->x(), v->y(), v->z(), (*it)->getRegion(iReg));
           }
 	  else
@@ -358,7 +357,7 @@ void getBoundingInfoAndSplitQuads(GRegion *gr,
   std::map<MFace, GEntity*, Less_Face>::iterator itx = allBoundingFaces_temp.begin();
   for (; itx != allBoundingFaces_temp.end();++itx){
     const MFace &f = itx->first;
-    // SPLIT that face into 4 triangular faces
+    // split the quad face into 4 triangular faces
     if (f.getNumVertices() == 4){
       sqr.setEmpty(false);
       MVertex *v0 = f.getVertex(0);
@@ -374,7 +373,6 @@ void getBoundingInfoAndSplitQuads(GRegion *gr,
       allBoundingFaces[MFace(v2,v3,newv)] = itx->second;
       allBoundingFaces[MFace(v3,v0,newv)] = itx->second;
       itx->second->mesh_vertices.push_back(newv);
-      // myGr->pyramids.push_back(new MPyramid(v0,v1,v2,v3,newv));
       allBoundingVertices.insert(v0);
       allBoundingVertices.insert(v1);
       allBoundingVertices.insert(v2);
@@ -390,26 +388,10 @@ void getBoundingInfoAndSplitQuads(GRegion *gr,
   }
 }
 
-void getAllBoundingVertices(GRegion *gr, std::set<MVertex*> &allBoundingVertices)
-{
-  std::list<GFace*> faces = gr->faces();
-  std::list<GFace*>::iterator it = faces.begin();
-
-  while (it != faces.end()){
-    GFace *gf = (*it);
-    for(unsigned int i = 0; i < gf->triangles.size(); i++){
-      MTriangle *t = gf->triangles[i];
-      for(int k = 0; k < 3; k++)
-        if(allBoundingVertices.find(t->getVertex(k)) ==  allBoundingVertices.end())
-          allBoundingVertices.insert(t->getVertex(k));
-    }
-    ++it;
-  }
-}
-
 #if defined(HAVE_TETGEN)
 #include "tetgen.h"
-void buildTetgenStructure(GRegion *gr, tetgenio &in, std::vector<MVertex*> &numberedV,  splitQuadRecovery &sqr)
+void buildTetgenStructure(GRegion *gr, tetgenio &in, std::vector<MVertex*> &numberedV,
+                          splitQuadRecovery &sqr)
 {
   std::set<MVertex*> allBoundingVertices;
   std::map<MFace,GEntity*,Less_Face> allBoundingFaces;
@@ -479,10 +461,10 @@ void buildTetgenStructure(GRegion *gr, tetgenio &in, std::vector<MVertex*> &numb
 void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out,
                         std::vector<MVertex*> &numberedV)
 {
-  // improvement has to be done here : tetgen splits some of the
-  // existing edges of the mesh. If those edges are classified on some
-  // model faces, new points SHOULD be classified on the model face
-  // and get the right set of parametric coordinates.
+  // improvement has to be done here : tetgen splits some of the existing edges
+  // of the mesh. If those edges are classified on some model faces, new points
+  // SHOULD be classified on the model face and get the right set of parametric
+  // coordinates.
 
   for(int i = numberedV.size(); i < out.numberofpoints; i++){
     MVertex *v = new MVertex(out.pointlist[i * 3 + 0],
@@ -520,9 +502,8 @@ void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out,
 
   bool needParam = (CTX::instance()->mesh.order > 1 &&
                     CTX::instance()->mesh.secondOrderExperimental);
-  // re-create the triangular meshes FIXME: this can lead to hanging
-  // nodes for non manifold geometries (single surface connected to
-  // volume)
+  // re-create the triangular meshes FIXME: this can lead to hanging nodes for
+  // non manifold geometries (single surface connected to volume)
   for(int i = 0; i < out.numberoftrifaces; i++){
     if (out.trifacemarkerlist[i] > 0) {
       MVertex *v[3];
@@ -580,9 +561,9 @@ void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out,
 		       v[j]));
 	  MVertex *v1b;
 	  if(needParam){
-	    // parametric coordinates should be set for the vertex !
-	    // (this is not 100 % safe yet, so we reserve that operation
-	    // for high order meshes)
+	    // parametric coordinates should be set for the vertex !  (this is
+	    // not 100 % safe yet, so we reserve that operation for high order
+	    // meshes)
 	    GPoint gp = gf->closestPoint(SPoint3(v[j]->x(), v[j]->y(), v[j]->z()), guess);
 	    if(gp.g()){
 	      v1b = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, gp.u(), gp.v());
@@ -650,8 +631,6 @@ void _relocateVertex(MVertex *ver,
   }
 }
 
-
-
 void MeshDelaunayVolume(std::vector<GRegion*> &regions)
 {
   if(regions.empty()) return;
@@ -686,8 +665,6 @@ void MeshDelaunayVolume(std::vector<GRegion*> &regions)
     std::vector<MVertex*> numberedV;
     char opts[128];
     buildTetgenStructure(gr, in, numberedV, sqr);
-    // JFR REMOVED THE -q OPTION BECAUSE MESH SIZES AT VERTICES WERE WRONG ...
-    // COULD BE FIXED IF NEEDED
     if(CTX::instance()->mesh.algo3d == ALGO_3D_FRONTAL_DEL ||
        CTX::instance()->mesh.algo3d == ALGO_3D_FRONTAL_HEX ||
        CTX::instance()->mesh.algo3d == ALGO_3D_MMG3D ||
@@ -695,8 +672,9 @@ void MeshDelaunayVolume(std::vector<GRegion*> &regions)
        CTX::instance()->mesh.algo2d == ALGO_2D_BAMG){
       sprintf(opts, "-pY%c",  (Msg::GetVerbosity() < 3) ? 'Q':
 	      (Msg::GetVerbosity() > 6) ? 'V': '\0');
+      // removed -q because mesh sizes at vertices were wrong...
       // sprintf(opts, "-q1.5pY%c",  (Msg::GetVerbosity() < 3) ? 'Q':
-      // 	      (Msg::GetVerbosity() > 6) ? 'V': '\0');
+      // 	 (Msg::GetVerbosity() > 6) ? 'V': '\0');
     }
     else {
       sprintf(opts, "-Ype%c",  (Msg::GetVerbosity() < 3) ? 'Q':
@@ -751,7 +729,7 @@ void MeshDelaunayVolume(std::vector<GRegion*> &regions)
   // restore the initial set of faces
   gr->set(faces);
 
-  //EMI VORONOI FOR CENRTERLINE
+  // EMI Voronoi for centerlines
   if (Msg::GetVerbosity() == 20) {
     std::set<SPoint3> candidates;
     printVoronoi(gr, candidates);
@@ -796,6 +774,23 @@ namespace nglib {
 }
 using namespace nglib;
 
+static void getAllBoundingVertices(GRegion *gr, std::set<MVertex*> &allBoundingVertices)
+{
+  std::list<GFace*> faces = gr->faces();
+  std::list<GFace*>::iterator it = faces.begin();
+
+  while (it != faces.end()){
+    GFace *gf = (*it);
+    for(unsigned int i = 0; i < gf->triangles.size(); i++){
+      MTriangle *t = gf->triangles[i];
+      for(int k = 0; k < 3; k++)
+        if(allBoundingVertices.find(t->getVertex(k)) ==  allBoundingVertices.end())
+          allBoundingVertices.insert(t->getVertex(k));
+    }
+    ++it;
+  }
+}
+
 Ng_Mesh *buildNetgenStructure(GRegion *gr, bool importVolumeMesh,
                               std::vector<MVertex*> &numberedV)
 {
diff --git a/tutorial/t5.geo b/tutorial/t5.geo
index 635b159908..d10f08ae06 100644
--- a/tutorial/t5.geo
+++ b/tutorial/t5.geo
@@ -1,7 +1,7 @@
-/********************************************************************* 
+/*********************************************************************
  *
  *  Gmsh tutorial 5
- * 
+ *
  *  Characteristic lengths, arrays of variables, functions, loops
  *
  *********************************************************************/
@@ -33,7 +33,7 @@ lcar3 = .055;
 // truncated cube:
 
 Point(1) = {0.5,0.5,0.5,lcar2}; Point(2) = {0.5,0.5,0,lcar1};
-Point(3) = {0,0.5,0.5,lcar1};   Point(4) = {0,0,0.5,lcar1}; 
+Point(3) = {0,0.5,0.5,lcar1};   Point(4) = {0,0,0.5,lcar1};
 Point(5) = {0.5,0,0.5,lcar1};   Point(6) = {0.5,0,0,lcar1};
 Point(7) = {0,0.5,0,lcar1};     Point(8) = {0,1,0,lcar1};
 Point(9) = {1,1,0,lcar1};       Point(10) = {0,0,1,lcar1};
@@ -61,7 +61,7 @@ Line Loop(38) = {-14,-13,-12,19};    Plane Surface(39) = {38};
 // Instead of using included files, we now use a user-defined function
 // in order to carve some holes in the cube:
 
-Function CheeseHole 
+Function CheeseHole
 
   // In the following commands we use the reserved variable name
   // `newp', which automatically selects a new point number. This
@@ -102,11 +102,11 @@ Function CheeseHole
   // for later reference (we will need these to define the final
   // volume):
 
-  theloops[t] = newreg ; 
+  theloops[t] = newreg ;
 
   Surface Loop(theloops[t]) = {l8+1,l5+1,l1+1,l2+1,l3+1,l7+1,l6+1,l4+1};
 
-  thehole = newreg ; 
+  thehole = newreg ;
   Volume(thehole) = theloops[t] ;
 
 Return
@@ -117,8 +117,8 @@ x = 0 ; y = 0.75 ; z = 0 ; r = 0.09 ;
 
 For t In {1:5}
 
-  x += 0.166 ; 
-  z += 0.166 ; 
+  x += 0.166 ;
+  z += 0.166 ;
 
   // We call the `CheeseHole' function:
 
@@ -127,7 +127,7 @@ For t In {1:5}
   // We define a physical volume for each hole:
 
   Physical Volume (t) = thehole ;
- 
+
   // We also print some variables on the terminal (note that, since
   // all variables are treated internally as floating point numbers,
   // the format string should only contain valid floating point format
-- 
GitLab