From f148a0fe10985d9f0b6e3803d9b2b8f1c0e250ea Mon Sep 17 00:00:00 2001
From: Gaetan Bricteux <gaetan.bricteux@uclouvain.be>
Date: Tue, 18 Jun 2013 08:48:38 +0000
Subject: [PATCH] makeSimplyConnected

---
 Geo/GModel.cpp      | 169 ++++++++++++++++++++++++--------------------
 Geo/MElementCut.cpp |  72 ++++++++++++-------
 2 files changed, 140 insertions(+), 101 deletions(-)

diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 63f4924cd9..b75edfc705 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -2304,42 +2304,52 @@ void makeSimplyConnected(std::map<int, std::vector<MElement*> > elements[10])
     for(unsigned int j = 0; j < elements[4][ri].size(); j++)
       allElements.push_back(elements[4][ri][j]);
     std::vector<std::vector<MElement*> > conRegions;
-    int nbRegions = connectedVolumes(allElements, conRegions);
-    printf("%d regions (%d)\n",nbRegions,ri);
-    for(int j = 0; j < nbRegions; j++){
+    int nbConRegions = connectedVolumes(allElements, conRegions);
+    for(int j = 0; j < nbConRegions; j++){
       if(conRegions[j].size() < 3){ //remove conRegions containing 1 or 2 elements
+        //find adjacent region
+        int r2 = ri;
+        if(regs.size() == 2)
+          r2 = (ri + 1) % 2;
+        else{
+          for(unsigned int k = 0; k < conRegions[j].size(); k++){
+            MElement *el = conRegions[j][k];
+            for(int l = 0; l < el->getNumFaces(); l++){
+              MFace mf = el->getFace(l);
+              std::multimap<MFace, MElement*, Less_Face>::iterator itl = f2e.lower_bound(mf);
+              for(; itl != f2e.upper_bound(mf); itl++){
+                if(itl->second != el) break;
+              }
+              MElement *el2 = itl->second;
+              bool sameRegion = false;
+              for(unsigned int m = 0; m < conRegions[j].size(); m++)
+                if(conRegions[j][m] == el2) {
+                  sameRegion = true; break;
+                }
+              if(sameRegion) continue;
+              for(unsigned int m = 0; m < regs.size(); m++){
+                int rm = regs[m];
+                if(rm == ri) continue;
+                for(unsigned int n = 0; n < elements[4][rm].size(); n++)
+                  if(elements[4][rm][n] == el2){
+                    r2 = rm;
+                    break;
+                  }
+                if(r2 != ri) break;
+              }
+              if(r2 != ri) break;
+            }
+            if(r2 != ri) break;
+          }
+          if(r2 == ri) Msg::Warning("Element not found for simply connected regions");
+        }
+
         for(unsigned int k = 0; k < conRegions[j].size(); k++){
           MElement *el = conRegions[j][k];
           unsigned int l = 0;
           for(; l < elements[4][ri].size(); l++)
             if(elements[4][ri][l] == el) break;
           elements[4][ri].erase(elements[4][ri].begin() + l);
-          //find adjacent region
-          int r2 = ri;
-          if(regs.size() == 2)
-            r2 = (ri + 1) % 2;
-          else{
-            MFace mf = el->getFace(0);
-            std::multimap<MFace, MElement*, Less_Face>::iterator itl = f2e.lower_bound(mf);
-            for(; itl != f2e.upper_bound(mf); itl++){
-              if(itl->second != el) break;
-            }
-            if(itl == f2e.upper_bound(mf)) printf("adjacent 3d element not found\n");
-            MElement *el2 = itl->second;
-            bool found = false;
-            for(unsigned int m = 0; m < regs.size(); m++){
-              int rm = regs[m];
-              if(rm == ri) continue;
-              for(unsigned int n = 0; n < elements[4][rm].size(); n++)
-                if(elements[4][rm][n] == el2){
-                  r2 = rm;
-                  found = true;
-                  break;
-                }
-              if(found) break;
-            }
-            if(r2 == ri) Msg::Warning("Element not found for simply connected regions");
-          }
           elements[4][r2].push_back(el);
         }
       }
@@ -2367,41 +2377,50 @@ void makeSimplyConnected(std::map<int, std::vector<MElement*> > elements[10])
       allElements.push_back(elements[2][fi][j]);
     std::vector<std::vector<MElement*> > conSurfaces;
     int nbSurfaces = connectedSurfaces(allElements, conSurfaces);
-    printf("%d consurfaces (reg=%d)\n",nbSurfaces,fi);
     for(int j = 0; j < nbSurfaces; j++){
       if(conSurfaces[j].size() < 3){ //remove conSurfaces containing 1 or 2 elements
+        //find adjacent surface
+        int f2 = fi;
+        if(faces.size() == 2)
+          f2 = (fi + 1) % 2;
+        else{
+          for(unsigned int k = 0; k < conSurfaces[j].size(); k++){
+            MElement *el = conSurfaces[j][k];
+            for(int l = 0; l < el->getNumEdges(); l++){
+              MEdge me = el->getEdge(l);
+              std::multimap<MEdge, MElement*, Less_Edge>::iterator itl = e2e.lower_bound(me);
+              for(; itl != e2e.upper_bound(me); itl++){
+                if(itl->second != el) break;
+              }
+              MElement *el2 = itl->second;
+              bool sameSurface = false;
+              for(unsigned int m = 0; m < conSurfaces[j].size(); m++)
+                if(conSurfaces[j][m] == el2) {
+                  sameSurface = true; break;
+                }
+              if(sameSurface) continue;
+              for(unsigned int m = 0; m < faces.size(); m++){
+                int fm = faces[m];
+                if(fm == fi) continue;
+                for(unsigned int n = 0; n < elements[2][fm].size(); n++)
+                  if(elements[2][fm][n] == el2){
+                    f2 = fm;
+                    break;
+                  }
+                if(f2 != fi) break;
+              }
+              if(f2 != fi) break;
+            }
+            if(f2 != fi) break;
+          }
+          if(f2 == fi) Msg::Warning("Element not found for simply connected surfaces");
+        }
         for(unsigned int k = 0; k < conSurfaces[j].size(); k++){
           MElement *el = conSurfaces[j][k];
           unsigned int l = 0;
           for(; l < elements[2][fi].size(); l++)
             if(elements[2][fi][l] == el) break;
           elements[2][fi].erase(elements[2][fi].begin() + l);
-          //find adjacent surface
-          int f2 = fi;
-          if(faces.size() == 2)
-            f2 = (fi + 1) % 2;
-          else{
-            MEdge me = el->getEdge(0);
-            std::multimap<MEdge, MElement*, Less_Edge>::iterator itl = e2e.lower_bound(me);
-            for(; itl != e2e.upper_bound(me); itl++){
-              if(itl->second != el) break;
-            }
-            if(itl == e2e.upper_bound(me)) printf("adjacent 2d element not found\n");
-            MElement *el2 = itl->second;
-            bool found = false;
-            for(unsigned int m = 0; m < faces.size(); m++){
-              int fm = faces[m];
-              if(fm == fi) continue;
-              for(unsigned int n = 0; n < elements[2][fm].size(); n++)
-                if(elements[2][fm][n] == el2){
-                  f2 = fm;
-                  found = true;
-                  break;
-                }
-              if(found) break;
-            }
-            if(f2 == fi) Msg::Warning("Element not found for simply connected surfaces");
-          }
           elements[2][f2].push_back(el);
         }
       }
@@ -2427,7 +2446,8 @@ GModel *GModel::buildCutGModel(gLevelset *ls, bool cutElem, bool saveTri)
 
   GModel *cutGM = buildCutMesh(this, ls, elements, vertexMap, physicals, cutElem);
 
-  makeSimplyConnected(elements);
+  if(!cutElem)
+    makeSimplyConnected(elements);
 
   for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
     cutGM->_storeElementsInEntities(elements[i]);
@@ -2670,15 +2690,15 @@ GRegion* GModel::addVolume (std::vector<std::vector<GFace *> > faces){
 
 GFace *GModel::add2Drect(double x0, double y0, double dx, double dy)
 {
-  if(_factory) 
-	return _factory->add2Drect(this, x0, y0, dx, dy);
+  if(_factory)
+    return _factory->add2Drect(this, x0, y0, dx, dy);
   return 0;
 }
 
 GFace *GModel::add2Dellips(double xc, double yc, double rx, double ry)
 {
-  if(_factory) 
-	return _factory->add2Dellips(this, xc, yc, rx, ry);
+  if(_factory)
+    return _factory->add2Dellips(this, xc, yc, rx, ry);
   return 0;
 }
 
@@ -2740,8 +2760,7 @@ GEntity *GModel::addBlock(std::vector<double> p1, std::vector<double> p2)
 
 GEntity *GModel::add3DBlock(std::vector<double> p1, double dx, double dy, double dz )
 {
-  if(_factory) 
-	return _factory->add3DBlock(this, p1, dx, dy, dz);
+  if(_factory) return _factory->add3DBlock(this, p1, dx, dy, dz);
   return 0;
 }
 
@@ -2775,32 +2794,32 @@ GModel *GModel::computeBooleanDifference(GModel *tool, int createNewModel)
 
 void GModel::salomeconnect()
 {
-  if(_factory) 
-	_factory->salomeconnect(this);
+  if(_factory) _factory->salomeconnect(this);
 }
 
 void GModel::occconnect()
 {
-  if(_factory)
-	_factory->occconnect(this);
+  if(_factory) _factory->occconnect(this);
 }
 
 void GModel::setPeriodicAllFaces(std::vector<double> FaceTranslationVector)
 {
-  if(_factory) 
-	_factory->setPeriodicAllFaces(this, FaceTranslationVector);
+  if(_factory) _factory->setPeriodicAllFaces(this, FaceTranslationVector);
 }
 
-void GModel::setPeriodicPairOfFaces(int numFaceMaster, std::vector<int> EdgeListMaster, int numFaceSlave, std::vector<int> EdgeListSlave)
+void GModel::setPeriodicPairOfFaces(int numFaceMaster, std::vector<int> EdgeListMaster,
+                                    int numFaceSlave, std::vector<int> EdgeListSlave)
 {
-  if(_factory) 
-	_factory->setPeriodicPairOfFaces(this, numFaceMaster, EdgeListMaster, numFaceSlave, EdgeListSlave);
+  if(_factory)
+    _factory->setPeriodicPairOfFaces(this, numFaceMaster, EdgeListMaster,
+                                     numFaceSlave, EdgeListSlave);
 }
 
-void GModel::setPhysicalNumToEntitiesInBox(int EntityType, int PhysicalGroupNumber, std::vector<double> p1, std::vector<double> p2)
+void GModel::setPhysicalNumToEntitiesInBox(int EntityType, int PhysicalGroupNumber,
+                                           std::vector<double> p1, std::vector<double> p2)
 {
-  if(_factory) 
-	_factory->setPhysicalNumToEntitiesInBox(this,EntityType,PhysicalGroupNumber,p1,p2);
+  if(_factory)
+    _factory->setPhysicalNumToEntitiesInBox(this, EntityType, PhysicalGroupNumber, p1, p2);
 }
 
 static void computeDuplicates(GModel *model,
diff --git a/Geo/MElementCut.cpp b/Geo/MElementCut.cpp
index 44a5808738..744646ee64 100644
--- a/Geo/MElementCut.cpp
+++ b/Geo/MElementCut.cpp
@@ -557,7 +557,8 @@ static int getElementaryTag(int lsTag, int elementary, std::map<int, int> &newEl
   }
   return elementary;
 }
-static void getPhysicalTag(int lsTag, const std::vector<int> &physicals, std::map<int, int> &newPhysTags)
+static void getPhysicalTag(int lsTag, const std::vector<int> &physicals,
+                           std::map<int, int> &newPhysTags)
 {
   for(unsigned int i = 0; i < physicals.size(); i++){
     int phys = physicals[i];
@@ -605,7 +606,7 @@ static void elementSplitMesh(MElement *e, std::vector<gLevelset *> &RPN,
   int gLsTag = RPN[RPN.size() - 1]->getTag();
 
   MElement *copy = e->copy(vertexMap, newParents, newDomains);
-  double eps = 0.0; //-1.e-6;
+  double eps = 1.e-6;
   bool splitElem = false;
  
   //split acording to center of gravity
@@ -766,7 +767,8 @@ static void elementSplitMesh(MElement *e, std::vector<gLevelset *> &RPN,
             if(f1 == f2) break;
           }
           if(i < 0){
-            MTriangle *tri = new MTriangle(f1.getVertex(0), f1.getVertex(1), f1.getVertex(2));
+            MTriangle *tri = new MTriangle(f1.getVertex(0), f1.getVertex(1),
+                                           f1.getVertex(2));
             elements[2][reg].push_back(tri);
           }
           else{
@@ -923,7 +925,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z(),
                     e->getVertex(5)->x(), e->getVertex(5)->y(), e->getVertex(5)->z());
         //T3.setPolynomialOrder(recur+1);
-        for(int i = 1; i < 4; i++) nodeLs[i] = &verticesLs(0, e->getVertex(i+2)->getIndex());
+        for(int i = 1; i < 4; i++)
+          nodeLs[i] = &verticesLs(0, e->getVertex(i+2)->getIndex());
         bool iC3 = T3.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, recur, nodeLs);
         isCut = iC1 || iC2 || iC3;
@@ -944,7 +947,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z());
         //T2.setPolynomialOrder(recur+1);
         nodeLs[0] = &verticesLs(0, e->getVertex(0)->getIndex());
-        for(int i = 1; i < 4; i++) nodeLs[i] = &verticesLs(0, e->getVertex(i+1)->getIndex());
+        for(int i = 1; i < 4; i++)
+          nodeLs[i] = &verticesLs(0, e->getVertex(i+1)->getIndex());
         bool iC2 = T2.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, recur, nodeLs);
         isCut = iC1 || iC2;
@@ -973,8 +977,10 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
           for(int j = 0; j < 4; j++){
             int numV = getElementVertexNum(tetras[i]->pt(j), e);
             if (numV == -1){
-              MVertex *newv = new MVertex(tetras[i]->x(j), tetras[i]->y(j), tetras[i]->z(j));
-              std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
+              MVertex *newv = new MVertex(tetras[i]->x(j), tetras[i]->y(j),
+                                          tetras[i]->z(j));
+              std::pair<newVerticesContainer::iterator, bool> it =
+                newVertices.insert(newv);
               mv[j] = *(it.first);
               if (!it.second) newv->deleteLast();
             }
@@ -1013,7 +1019,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
         }
         // check for border surfaces cut earlier along the polyhedra
         std::pair<std::multimap<MElement*, MElement*>::iterator,
-                  std::multimap<MElement*, MElement*>::iterator> itr = borders[1].equal_range(copy);
+                  std::multimap<MElement*, MElement*>::iterator> itr =
+          borders[1].equal_range(copy);
         std::vector<std::pair<MElement*, MElement*> > bords;
         for(std::multimap<MElement*, MElement*>::iterator it = itr.first;
             it != itr.second; it++) {
@@ -1060,7 +1067,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
         for(int j = 0; j < 3; j++){
           int numV = getElementVertexNum(triangles[i]->pt(j), e);
           if(numV == -1) {
-            MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j), triangles[i]->z(j));
+            MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j),
+                                        triangles[i]->z(j));
             std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
             mv[j] = *(it.first);
             if (!it.second) newv->deleteLast();
@@ -1082,7 +1090,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
         }
         else tri = new MTriangle(mv[0], mv[1], mv[2], ++numEle, ePart);
         int lsTag = triangles[i]->lsTag();
-        int cR = elements[2].count(lsTag) + elements[3].count(lsTag) + elements[8].count(lsTag);
+        int cR = elements[2].count(lsTag) + elements[3].count(lsTag) +
+                 elements[8].count(lsTag);
         int cP = 0;
         for(std::map<int, std::map<int, std::string> >::iterator it = physicals[2].begin();
             it != physicals[2].end(); it++)
@@ -1152,8 +1161,10 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
           for(int j = 0; j < 3; j++){
             int numV = getElementVertexNum(triangles[i]->pt(j), e);
             if(numV == -1) {
-              MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j), triangles[i]->z(j));
-              std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
+              MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j),
+                                          triangles[i]->z(j));
+              std::pair<newVerticesContainer::iterator, bool> it =
+                newVertices.insert(newv);
               mv[j] = *(it.first);
               if (!it.second) newv->deleteLast();
             }
@@ -1180,7 +1191,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
           int numV = getElementVertexNum(quads[i]->pt(j), e);
             if(numV == -1) {
               MVertex *newv = new MVertex(quads[i]->x(j), quads[i]->y(j), quads[i]->z(j));
-              std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
+              std::pair<newVerticesContainer::iterator, bool> it =
+                newVertices.insert(newv);
               mv[j] = *(it.first);
               if (!it.second) newv->deleteLast();
             }
@@ -1237,7 +1249,8 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
         }
         // check for border lines cut earlier along the polygons
         std::pair<std::multimap<MElement*, MElement*>::iterator,
-                  std::multimap<MElement*, MElement*>::iterator> itr = borders[0].equal_range(copy);
+                  std::multimap<MElement*, MElement*>::iterator> itr =
+          borders[0].equal_range(copy);
         std::vector<std::pair<MElement*, MElement*> > bords;
         for(std::multimap<MElement*, MElement*>::iterator it = itr.first;
             it != itr.second; ++it) {
@@ -1342,14 +1355,16 @@ static void elementCutMesh(MElement *e, std::vector<gLevelset *> &RPN,
             int numV = getElementVertexNum(lines[i]->pt(j), e);
             if(numV == -1) {
               MVertex *newv = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j));
-              std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
+              std::pair<newVerticesContainer::iterator, bool> it =
+                newVertices.insert(newv);
               mv[j] = *(it.first);
               if (!it.second) newv->deleteLast();
             }
             else {
               std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
               if(it == vertexMap.end()) {
-                mv[j] = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j), 0, numV);
+                mv[j] = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j),
+                                    0, numV);
                 vertexMap[numV] = mv[j];
               }
               else mv[j] = it->second;
@@ -1458,7 +1473,8 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
     }
   }
 
-  int numEle = gm->getNumMeshElements() + gm->getNumMeshParentElements(); //element number increment
+  //element number increment
+  int numEle = gm->getNumMeshElements() + gm->getNumMeshParentElements();
   for(unsigned int i = 0; i < gmEntities.size(); i++) {
     for(unsigned int j = 0; j < gmEntities[i]->getNumMeshElements(); j++) {
       MElement *e = gmEntities[i]->getMeshElement(j);
@@ -1488,9 +1504,9 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
       for(unsigned int j = 0; j < gmEntities[i]->getNumMeshElements(); j++) {
         MElement *e = gmEntities[i]->getMeshElement(j);
         e->setVolumePositive();
-        elementSplitMesh(e, RPN, verticesLs, gmEntities[i], gm, numEle, vertexMap, newParents,
-                         newDomains, elements, physicals, newElemTags, newPhysTags,
-                         borderElemTags, borderPhysTags);
+        elementSplitMesh(e, RPN, verticesLs, gmEntities[i], gm, numEle, vertexMap,
+                         newParents, newDomains, elements, physicals, newElemTags,
+                         newPhysTags, borderElemTags, borderPhysTags);
         cutGM->getMeshPartitions().insert(e->getPartition());
       }
     }
@@ -1499,7 +1515,8 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
 
   //CutMesh
   newVerticesContainer newVertices;
-  std::multimap<MElement*, MElement*> borders[2]; //multimap<domain,border>[polyg=0,polyh=1]
+  //multimap<domain,border>[polyg=0,polyh=1]
+  std::multimap<MElement*, MElement*> borders[2];
   DI_Point::Container cp;
   std::vector<DI_Line *> lines;
   std::vector<DI_Triangle *> triangles;
@@ -1516,9 +1533,10 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
     for(unsigned int j = 0; j < gmEntities[i]->getNumMeshElements(); j++) {
       MElement *e = gmEntities[i]->getMeshElement(j);
       e->setVolumePositive();
-      elementCutMesh(e, RPN, verticesLs, gmEntities[i], gm, numEle, vertexMap, newVertices, newParents,
-                     newDomains, borders, elements, physicals, newElemTags, newPhysTags,
-                     borderElemTags, borderPhysTags, cp, lines, triangles, quads, tetras, hexas);
+      elementCutMesh(e, RPN, verticesLs, gmEntities[i], gm, numEle, vertexMap,
+                     newVertices, newParents, newDomains, borders, elements, physicals,
+                     newElemTags, newPhysTags, borderElemTags, borderPhysTags, cp,
+                     lines, triangles, quads, tetras, hexas);
       cutGM->getMeshPartitions().insert(e->getPartition());
     }
 
@@ -1581,7 +1599,8 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
     for(unsigned int k = 0; k < quads.size(); k++) delete quads[k];
     for(unsigned int k = 0; k < tetras.size(); k++) delete tetras[k];
     for(unsigned int k = 0; k < hexas.size(); k++) delete hexas[k];
-    cp.clear(); lines.clear(); triangles.clear(); quads.clear(); tetras.clear(); hexas.clear();
+    cp.clear(); lines.clear(); triangles.clear(); quads.clear();
+    tetras.clear(); hexas.clear();
   }
 
 #if 0
@@ -1608,7 +1627,8 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
   printf("\n");
 #endif
 
-  for(newVerticesContainer::iterator it = newVertices.begin() ; it != newVertices.end(); ++it) {
+  for(newVerticesContainer::iterator it = newVertices.begin();
+      it != newVertices.end(); ++it){
     vertexMap[(*it)->getNum()] = *it;
   }
 
-- 
GitLab