From da1194ac61d099bb9faaa786d8d53aa2b6435c72 Mon Sep 17 00:00:00 2001
From: Emilie Marchandise <emilie.marchandise@uclouvain.be>
Date: Wed, 29 Feb 2012 12:45:40 +0000
Subject: [PATCH] Centerline with closeVolume action

---
 Geo/GModelFactory.cpp    | 120 +++++++++++++++++++++++++--------------
 Geo/GModelIO_Geo.cpp     |   2 +
 Mesh/CenterlineField.cpp | 101 ++++++++++++++++----------------
 Mesh/CenterlineField.h   |   7 ++-
 Mesh/meshGEdge.cpp       |   3 +-
 benchmarks/2d/square.geo |   6 +-
 6 files changed, 141 insertions(+), 98 deletions(-)

diff --git a/Geo/GModelFactory.cpp b/Geo/GModelFactory.cpp
index 4780eb6743..22903d89d5 100644
--- a/Geo/GModelFactory.cpp
+++ b/Geo/GModelFactory.cpp
@@ -26,7 +26,7 @@ GVertex *GeoFactory::addVertex(GModel *gm, double x, double y, double z, double
   if(lc == 0.) lc = MAX_LC; // no mesh size given at the point
   Vertex *p;
   p = Create_Vertex(num, x, y, z, lc, 1.0);
-  Tree_Add(GModel::current()->getGEOInternals()->Points, &p);
+  Tree_Add(gm->getGEOInternals()->Points, &p);
   p->Typ = MSH_POINT;
   p->Num = num;
 
@@ -47,7 +47,7 @@ GEdge *GeoFactory::addLine(GModel *gm, GVertex *start, GVertex *end)
 
   Curve *c = Create_Curve(num, MSH_SEGM_LINE, 1, iList, NULL,
 			  -1, -1, 0., 1.);
-  Tree_Add(GModel::current()->getGEOInternals()->Curves, &c);
+  Tree_Add(gm->getGEOInternals()->Curves, &c);
   CreateReversedCurve(c);
   List_Delete(iList);
   c->Typ = MSH_SEGM_LINE;
@@ -61,49 +61,83 @@ GEdge *GeoFactory::addLine(GModel *gm, GVertex *start, GVertex *end)
 
 GFace *GeoFactory::addPlanarFace(GModel *gm, std::vector< std::vector<GEdge *> > edges)
 {
-  //create line loops
-  std::vector<EdgeLoop *> vecLoops;
+  
+   //create line loops
   int nLoops = edges.size();
+  std::vector<EdgeLoop *> vecLoops;
   for (int i=0; i< nLoops; i++){
-    int numl = gm->getMaxElementaryNumber(1) + i;
-    while (FindEdgeLoop(numl)){
-      numl++;
-      if (!FindEdgeLoop(numl)) break;
-    }
-    int nl=(int)edges[i].size();
-    List_T *iListl = List_Create(nl, nl, sizeof(int));
-    for(int j = 0; j < nl; j++){
-      int numEdge = edges[i][j]->tag();
-      List_Add(iListl, &numEdge);
-    }
-    int type=ENT_LINE;
-
-    select_contour(type, edges[i][0]->tag(), iListl);
+    int ne=(int)edges[i].size();
+    List_T *temp = List_Create(ne, ne, sizeof(int));
+    for(int j = 0; j < ne; j++){
+      GEdge *ge = edges[i][j];
+      int numEdge = ge->tag();
+      //create curve
+      Curve *c = FindCurve(numEdge);
+      if(!c){
+	GVertex *gvb = ge->getBeginVertex();
+	GVertex *gve = ge->getEndVertex();
+	Vertex *vertb = FindPoint((int)fabs(gvb->tag()));
+	Vertex *verte = FindPoint((int)fabs(gve->tag()));
+	if (!vertb){
+	  vertb = Create_Vertex(gvb->tag(), gvb->x(), gvb->y(), gvb->z(),
+				gvb->prescribedMeshSizeAtVertex(), 1.0);
+	  Tree_Add(gm->getGEOInternals()->Points, &vertb);
+	 }
+	if (!verte){
+	  verte = Create_Vertex(gve->tag(), gve->x(), gve->y(), gve->z(),
+				gve->prescribedMeshSizeAtVertex(), 1.0);
+	  Tree_Add(gm->getGEOInternals()->Points, &verte);
+	}
+
+	List_T *temp = List_Create(2, 2, sizeof(int));
+	List_Add(temp, &vertb);
+	List_Add(temp, &verte);
+
+	if (ge->geomType() == GEntity::Line){
+	  printf("creating line \n");
+	  c = Create_Curve(numEdge, MSH_SEGM_LINE, 1, temp, NULL, -1, -1, 0., 1.);
+	}
+	else if (ge->geomType() == GEntity::DiscreteCurve){
+	  printf("creating discrete line \n");
+	  c = Create_Curve(numEdge, MSH_SEGM_DISCRETE, 1, NULL, NULL, -1, -1, 0., 1.);
+	}
+	else {
+	  printf("type not implemented \n"); exit(1);
+	}
+	c->Control_Points = List_Create(2, 1, sizeof(Vertex *));
+	List_Add(c->Control_Points, &vertb);
+	List_Add(c->Control_Points, &verte);
+	c->beg = vertb;
+	c->end = verte;
+	End_Curve(c);
+
+	Tree_Add(gm->getGEOInternals()->Curves, &c);
+	CreateReversedCurve(c);
+	List_Delete(temp);
+      }
+       List_Add(temp, &numEdge);
+    }  
 
-    sortEdgesInLoop(numl, iListl);
-    EdgeLoop *l = Create_EdgeLoop(numl, iListl);
+    int num  = gm->getMaxElementaryNumber(2)+1+i;
+    if(FindEdgeLoop(num)) num++; 
+    sortEdgesInLoop(num, temp);
+    EdgeLoop *l = Create_EdgeLoop(num, temp);
     vecLoops.push_back(l);
-    Tree_Add(GModel::current()->getGEOInternals()->EdgeLoops, &l);
-    l->Num = numl;
-
-
-    List_Delete(iListl);
-  }
-
-  //create plane surfaces
-  int numf = gm->getMaxElementaryNumber(2) + 1;
+    Tree_Add(gm->getGEOInternals()->EdgeLoops, &l);
+    List_Delete(temp);  
+  } 
+ 
+  int numf  = gm->getMaxElementaryNumber(2)+1;
   Surface *s = Create_Surface(numf, MSH_SURF_PLAN);
-  List_T *iList = List_Create(nLoops, nLoops, sizeof(int));
-  for (unsigned int i=0; i< vecLoops.size(); i++){
+  List_T *temp = List_Create(nLoops, nLoops, sizeof(int));
+  for (unsigned int i=0; i< nLoops; i++){
     int numl = vecLoops[i]->Num;
-    List_Add(iList, &numl);
+    List_Add(temp, &numl);
   }
-  setSurfaceGeneratrices(s, iList);
+  setSurfaceGeneratrices(s, temp);
+  List_Delete(temp);
   End_Surface(s);
-  Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
-  s->Typ= MSH_SURF_PLAN;
-  s->Num = numf;
-  List_Delete(iList);
+  Tree_Add(gm->getGEOInternals()->Surfaces, &s);
 
   //gmsh surface
   GFace *gf = new gmshFace(gm,s);
@@ -131,7 +165,7 @@ GRegion* GeoFactory::addVolume (GModel *gm, std::vector<std::vector<GFace *> > f
     }
     SurfaceLoop *l = Create_SurfaceLoop(numfl, iListl);
     vecLoops.push_back(l);
-    Tree_Add(GModel::current()->getGEOInternals()->SurfaceLoops, &l);
+    Tree_Add(gm->getGEOInternals()->SurfaceLoops, &l);
     List_Delete(iListl);
   }
 
@@ -145,7 +179,7 @@ GRegion* GeoFactory::addVolume (GModel *gm, std::vector<std::vector<GFace *> > f
   }
   setVolumeSurfaces(v, iList);
   List_Delete(iList);
-  Tree_Add(GModel::current()->getGEOInternals()->Volumes, &v);
+  Tree_Add(gm->getGEOInternals()->Volumes, &v);
   v->Typ = MSH_VOLUME;
   v->Num = numv;
 
@@ -169,7 +203,7 @@ GEdge* GeoFactory::addCircleArc(GModel *gm,GVertex *begin, GVertex *center, GVer
 
   Curve *c = Create_Curve(num, MSH_SEGM_CIRC, 1, iList, NULL,
 			  -1, -1, 0., 1.);
-  Tree_Add(GModel::current()->getGEOInternals()->Curves, &c);
+  Tree_Add(gm->getGEOInternals()->Curves, &c);
   CreateReversedCurve(c);
   List_Delete(iList);
   c->Typ = MSH_SEGM_CIRC;
@@ -200,12 +234,12 @@ std::vector<GFace *> GeoFactory::addRuledFaces(GModel *gm,
       List_Add(iListl, &numEdge);
     }
     int type=ENT_LINE;
-    if(select_contour(type, edges[0][0]->tag(), iListl))
+    if(select_contour(type, edges[i][0]->tag(), iListl))
     {
         sortEdgesInLoop(numl, iListl);
         EdgeLoop *l = Create_EdgeLoop(numl, iListl);
         vecLoops.push_back(l);
-        Tree_Add(GModel::current()->getGEOInternals()->EdgeLoops, &l);
+        Tree_Add(gm->getGEOInternals()->EdgeLoops, &l);
         l->Num = numl;
     }
 
@@ -222,7 +256,7 @@ std::vector<GFace *> GeoFactory::addRuledFaces(GModel *gm,
   }
   setSurfaceGeneratrices(s, iList);
   End_Surface(s);
-  Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
+  Tree_Add(gm->getGEOInternals()->Surfaces, &s);
   s->Typ= MSH_SURF_TRIC;
   s->Num = numf;
   List_Delete(iList);
diff --git a/Geo/GModelIO_Geo.cpp b/Geo/GModelIO_Geo.cpp
index a0f921a258..49b21febce 100644
--- a/Geo/GModelIO_Geo.cpp
+++ b/Geo/GModelIO_Geo.cpp
@@ -118,6 +118,7 @@ int GModel::exportDiscreteGEOInternals()
 
 int GModel::importGEOInternals()
 {
+
   if(Tree_Nbr(_geo_internals->Points)) {
     List_T *points = Tree2List(_geo_internals->Points);
     for(int i = 0; i < List_Nbr(points); i++){
@@ -163,6 +164,7 @@ int GModel::importGEOInternals()
         if(!c->Visible) e->setVisibility(0);
         if(c->Color.type) e->setColor(c->Color.mesh);
         if(c->degenerated) {
+	  printf("setting edge too small c-degenerated \n");
           e->setTooSmall(true);
         }
       }
diff --git a/Mesh/CenterlineField.cpp b/Mesh/CenterlineField.cpp
index d3c827efea..6ee94d46bc 100644
--- a/Mesh/CenterlineField.cpp
+++ b/Mesh/CenterlineField.cpp
@@ -329,6 +329,7 @@ Centerline::Centerline(std::string fileName): kdtree(0), nodes(0){
 
   update_needed = false;
   is_cut = false;
+  is_closed = false;
 
 }
 Centerline::Centerline(): kdtree(0), nodes(0){
@@ -342,8 +343,10 @@ Centerline::Centerline(): kdtree(0), nodes(0){
 
   options["FileName"] = new FieldOptionString (fileName, "File name for the centerlines", &update_needed);
   options["nbPoints"] = new FieldOptionInt(nbPoints, "Number of mesh elements in a circle");
+  callbacks["closeVolume"] = new FieldCallbackGeneric<Centerline>(this, &Centerline::closeVolume, "Create In/Outlet planar faces \n");
   callbacks["cutMesh"] = new FieldCallbackGeneric<Centerline>(this, &Centerline::cutMesh, "Cut the initial mesh in different mesh partitions using the centerlines \n");
   is_cut = false;
+  is_closed = false;
 
 }
 
@@ -490,7 +493,7 @@ void Centerline::createBranches(int maxN){
       edges.push_back(newBranch) ;
     }
   }
-  printf("in/outlets =%d branches =%d \n", (int)color_edges.size(), (int)edges.size());
+  printf("in/outlets =%d branches =%d \n", (int)color_edges.size()+1, (int)edges.size());
   
   //create children
   for(unsigned int i = 0; i < edges.size(); ++i) {
@@ -504,7 +507,7 @@ void Centerline::createBranches(int maxN){
   }
 
   //compute radius
-  distanceToLines();
+  distanceToSurface();
   computeRadii();
 
   printSplit();
@@ -524,10 +527,10 @@ void Centerline::createBranches(int maxN){
 
 }
 
-void Centerline::distanceToLines(){
-  Msg::Info("Centerline: computing distance to lines ");
+void Centerline::distanceToSurface(){
+  Msg::Info("Centerline: computing distance to surface mesh ");
 
-  //SOLUTION 1: REVERSE ANN TREE (SURFACE POINTS IN TREE)
+  //COMPUTE WITH REVERSE ANN TREE (SURFACE POINTS IN TREE)
   ANNkd_tree *kdtreeR; 
   ANNpointArray nodesR;
   ANNidxArray indexR = new ANNidx[1];
@@ -562,47 +565,6 @@ void Centerline::distanceToLines(){
   annDeallocPts(nodesR);
   delete[]indexR;
   delete[]distR;
-  
-  // //SOLUTION 2: DISTANCE TO LINES (QUITE SLOW)
-  // std::vector<SPoint3> pts;
-  // std::set<SPoint3> pts_set;
-  // std::vector<double> distances;
-  // std::vector<double> distancesE;
-  // std::vector<SPoint3> closePts;
-
-  // for(unsigned int i = 0; i < surfaces.size(); i++){ 
-  //   for(int j = 0; j < surfaces[i]->getNumMeshElements(); j++){ 
-  //     MElement *e = surfaces[i]->getMeshElement(j);
-  //     for (int k = 0; k < e->getNumVertices(); k++){
-  // 	MVertex *v = e->getVertex(k);
-  // 	pts_set.insert(SPoint3(v->x(), v->y(),v->z()));
-  //     }
-  //   }
-  // }
-  // std::set<SPoint3>::iterator its =  pts_set.begin();
-  // for (; its != pts_set.end(); its++){
-  //   pts.push_back(*its);
-  // } 
-  // if (pts.size() == 0) {Msg::Error("Centerline needs a GModel with a surface \n"); exit(1);}
- 
-  // for(unsigned int i = 0; i < lines.size(); i++){
-  //   std::vector<double> iDistances;
-  //   std::vector<SPoint3> iClosePts;
-  //   std::vector<double> iDistancesE;
-  //   MLine *l = lines[i];
-  //   MVertex *v1 = l->getVertex(0);
-  //   MVertex *v2 = l->getVertex(1);
-  //   SPoint3 p1(v1->x(), v1->y(), v1->z());
-  //   SPoint3 p2(v2->x(), v2->y(), v2->z());
-  //   signedDistancesPointsLine(iDistances, iClosePts, pts, p1,p2);
-
-  //   double minRad = std::abs(iDistances[0]);
-  //   for (unsigned int kk = 1; kk< pts.size(); kk++) {
-  //     if (std::abs(iDistances[kk]) < minRad)
-  // 	minRad = std::abs(iDistances[kk]);
-  //   }
-  //   radiusl.insert(std::make_pair(lines[i], minRad)); 
-  // }
      
 }
 void Centerline::computeRadii(){
@@ -774,6 +736,7 @@ void Centerline::cleanMesh(){
     mySplitMesh->mesh_vertices.push_back(*it);
   mySplitMesh->meshStatistics.status = GFace::DONE; 
   current->createTopologyFromMesh();
+
   
 }
 void Centerline::createFaces(){
@@ -830,6 +793,42 @@ void Centerline::createFaces(){
 
 }
 
+void Centerline::createInOutFaces(){
+
+  //identify the boundary edges by looping over all discreteFaces
+  std::vector<GEdge*> boundEdges;
+  int nbFaces = current->getMaxElementaryNumber(2);
+  for (int i= 0; i< nbFaces; i++){
+    GFace *gf = current->getFaceByTag(i+1);
+    std::list<GEdge*> l_edges = gf->edges();
+    for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){
+      std::vector<GEdge*>::iterator ite = std::find(boundEdges.begin(), boundEdges.end(), *it);
+      if (ite != boundEdges.end()) boundEdges.erase(ite);
+      else boundEdges.push_back(*it);
+    }
+  }
+  printf("boundEdges size =%d \n", boundEdges.size());
+
+  //create the inlet and outlet planar face
+  current->setFactory("Gmsh");
+  for (int i = 0; i<  boundEdges.size(); i++){
+    std::vector<std::vector<GEdge *> > myEdges;
+    std::vector<GEdge *> myEdge;
+    myEdge.push_back(boundEdges[i]);
+    myEdges.push_back(myEdge);
+    GFace *newFace = current->addPlanarFace(myEdges); 
+  }  
+
+}
+
+void Centerline::closeVolume(){
+
+  is_closed = true;
+  //printf("calling closed volume \n");
+  //exit(1);
+
+}
+
 void Centerline::cutMesh(){
   
   is_cut = true;
@@ -861,11 +860,11 @@ void Centerline::cutMesh(){
   for(unsigned int i = 0; i < edges.size(); i++){
     std::vector<MLine*> lines = edges[i].lines;
     double L = edges[i].length;
-    double R = 0.5*(edges[i].minRad+edges[i].maxRad);
+    double R = edges[i].minRad; //0.5*(edges[i].minRad+edges[i].maxRad);
     double AR = L/R;
-    printf("*** branch =%d \n", i, AR);
+    printf("*** branch =%d AR=%g \n", i, AR);
     if( AR > 4.5){
-      int nbSplit = (int)ceil(AR/4.0);
+      int nbSplit = (int)ceil(AR/3.0);
       double li  = L/nbSplit;
       double lc = 0.0;
       for (int j= 0; j < lines.size(); j++){
@@ -898,6 +897,8 @@ void Centerline::cutMesh(){
   //create discreteFaces
   createFaces();
   current->createTopologyFromFaces(discFaces);
+  current->exportDiscreteGEOInternals();
+  if (is_closed) createInOutFaces();
 
   //write
   Msg::Info("Writing splitted mesh 'myPARTS.msh'");
@@ -966,7 +967,7 @@ void Centerline::cutByDisk(SVector3 &PT, SVector3 &NORM, double &maxRad){
       break;
     }
     else {
-      if (step ==19) {printf("no closed cut %d \n", (int)newCut.size()); };
+      if (step == 9) {printf("no closed cut %d \n", (int)newCut.size()); };
       step++;
       // // triangles = newTris;
       // // theCut.insert(newCut.begin(),newCut.end());
diff --git a/Mesh/CenterlineField.h b/Mesh/CenterlineField.h
index cac7103cea..73b1947f3c 100644
--- a/Mesh/CenterlineField.h
+++ b/Mesh/CenterlineField.h
@@ -64,6 +64,7 @@ class Centerline : public Field{
   double recombine;
   int NF, NV, NE;
   bool is_cut;
+  bool is_closed;
 
   //all (unique) lines of centerlines
   std::vector<MLine*> lines;
@@ -131,17 +132,21 @@ class Centerline : public Field{
   void computeRadii();
 
   //Computes for each MLine the minRadius
-  void distanceToLines();
+  void distanceToSurface();
 
   // Cut the mesh in different parts of small aspect ratio
   void cutMesh();
 
+  //Create In and Outlet Planar Faces
+  void closeVolume();
+
   // Cut the tubular structure with a disk
   // perpendicular to the tubular structure
   void cutByDisk(SVector3 &pt, SVector3 &dir, double &maxRad);
 
   //create discrete faces
   void createFaces();
+  void createInOutFaces();
   void createSplitCompounds();
 
   //Print for debugging
diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp
index 57df16408b..35b22c060b 100644
--- a/Mesh/meshGEdge.cpp
+++ b/Mesh/meshGEdge.cpp
@@ -344,8 +344,9 @@ void meshGEdge::operator() (GEdge *ge)
   ge->setLength(length);
   Points.clear();
 
-  if(length < CTX::instance()->mesh.toleranceEdgeLength)
+  if(length < CTX::instance()->mesh.toleranceEdgeLength){
     ge->setTooSmall(true);
+  }
 
   // Integrate detJ/lc du
   double a;
diff --git a/benchmarks/2d/square.geo b/benchmarks/2d/square.geo
index 366bae5b86..75d3f2c59a 100644
--- a/benchmarks/2d/square.geo
+++ b/benchmarks/2d/square.geo
@@ -25,10 +25,10 @@ Plane Surface(10) = {5};
 
 //----------------------
 
-Compound Line(10)={1,2,3,4};
-Compound Surface(100)={10};
+//Compound Line(10)={1,2,3,4};
+//Compound Surface(100)={10};
 
-Line {1,2,3,4} In Surface{100};
+//Line {1,2,3,4} In Surface{100};
 
 //Physical Surface(100)={10};
 //Physical Line(200)={1,2,3,4};
-- 
GitLab