From d95bf7f8f1ff2b5f5d584dfc40f65fa835235d0c Mon Sep 17 00:00:00 2001
From: Pierre-Alexandre Beaufort <pierre-alexandre.beaufort@uclouvain.be>
Date: Tue, 19 Jul 2016 13:51:35 +0000
Subject: [PATCH] (likely) robust filler of holes

---
 Geo/discreteDiskFace.cpp |  37 ++---
 Geo/discreteDiskFace.h   |  34 ++++-
 Geo/discreteFace.cpp     | 300 ++++++++++++++++++++++++++++++++++++++-
 Geo/discreteFace.h       |   7 +
 4 files changed, 352 insertions(+), 26 deletions(-)

diff --git a/Geo/discreteDiskFace.cpp b/Geo/discreteDiskFace.cpp
index 8bc019a514..4c28872ce9 100644
--- a/Geo/discreteDiskFace.cpp
+++ b/Geo/discreteDiskFace.cpp
@@ -274,6 +274,7 @@ discreteDiskFace::discreteDiskFace(int id, GFace *gf, triangulation* diskTriangu
         
   }// end loop over triangles
   geoTriangulation = new triangulation(id,discrete_triangles,gf);
+  geoTriangulation->fillingHoles = diskTriangulation->fillingHoles;
   allNodes = geoTriangulation->vert;
   _totLength = geoTriangulation->bord.rbegin()->first;
   _U0 = geoTriangulation->bord.rbegin()->second;
@@ -281,6 +282,7 @@ discreteDiskFace::discreteDiskFace(int id, GFace *gf, triangulation* diskTriangu
   parametrize(false);
   buildOct(CAD);
   
+  
   if (!checkOrientationUV()){
     Msg::Info("discreteDiskFace:: parametrization is not one-to-one; fixing "
               "the discrete system.");
@@ -312,21 +314,21 @@ void discreteDiskFace::buildOct(std::vector<GFace*> *CAD) const
   oct = Octree_Create(maxElePerBucket, origin, ssize, discreteDiskFaceBB,
 		      discreteDiskFaceCentroid, discreteDiskFaceInEle);
 
-  _ddft = new discreteDiskFaceTriangle[discrete_triangles.size()];
-
-  //  if (CAD) printf("------------->  %ld %ld\n",CAD->size(),discrete_triangles.size());
-
+  _ddft = new discreteDiskFaceTriangle[discrete_triangles.size()-geoTriangulation->fillingHoles.size()];
+  int c = 0;
   for(unsigned int i = 0; i < discrete_triangles.size(); ++i){
-    MElement *t = discrete_triangles[i];
-    discreteDiskFaceTriangle* my_ddft = &_ddft[i];
-    my_ddft->p.resize(_N);
-    for(int io=0; io<_N; io++)
-      my_ddft->p[io] = coordinates[t->getVertex(io)];
+    if(geoTriangulation->fillingHoles.find(i)==geoTriangulation->fillingHoles.end()){
+      MElement *t = discrete_triangles[i];
+      discreteDiskFaceTriangle* my_ddft = &_ddft[c++];
+      my_ddft->p.resize(_N);
+      for(int io=0; io<_N; io++)
+	my_ddft->p[io] = coordinates[t->getVertex(io)];
 
-    my_ddft->gf = CAD ? (*CAD)[i] : _parent;
-    my_ddft->tri = t;
+      my_ddft->gf = CAD ? (*CAD)[i] : _parent;
+      my_ddft->tri = t;
 
-    Octree_Insert(my_ddft, oct);
+      Octree_Insert(my_ddft, oct);
+    }
   }
   Octree_Arrange(oct);
 }
@@ -460,7 +462,7 @@ bool discreteDiskFace::checkOrientationUV()
     double p3[2] = {ct->p[2].x(), ct->p[2].y()};
     initial = robustPredicates::orient2d(p1, p2, p3);
     unsigned int i=1;
-    for (; i<discrete_triangles.size(); i++){
+    for (; i<discrete_triangles.size()-geoTriangulation->fillingHoles.size(); i++){
       ct = &_ddft[i];
       p1[0] = ct->p[0].x(); p1[1] = ct->p[0].y();
       p2[0] = ct->p[1].x(); p2[1] = ct->p[1].y();
@@ -478,7 +480,7 @@ bool discreteDiskFace::checkOrientationUV()
     double min, max;
     std::vector<MVertex*> localVertices;
     localVertices.resize(_N);
-    for(unsigned int i=0; i<discrete_triangles.size(); i++){
+    for(unsigned int i=0; i<discrete_triangles.size()-geoTriangulation->fillingHoles.size(); i++){
       ct = &_ddft[i];
       for(int j=0; j<_N; j++)
 	localVertices[j] = new MVertex(ct->p[j].x(),ct->p[j].y(),0.);
@@ -689,7 +691,7 @@ void discreteDiskFace::putOnView(bool Xu, bool Ux)
       fprintf(UVy,"View \"y(U)\"{\n");
       fprintf(UVz,"View \"z(U)\"{\n");
     }
-    for (unsigned int i=0; i<discrete_triangles.size(); i++){
+    for (unsigned int i=0; i<discrete_triangles.size()-geoTriangulation->fillingHoles.size(); i++){
       discreteDiskFaceTriangle* my_ddft = &_ddft[i];
       if (_order == 1){
 	if(Xu){
@@ -787,7 +789,7 @@ GPoint discreteDiskFace::intersectionWithCircle(const SVector3 &n1, const SVecto
 {
   SVector3 n = crossprod(n1,n2);
   n.normalize();
-  for (int i=-1;i<(int)discrete_triangles.size();i++){
+  for (int i=-1;i<(int)(discrete_triangles.size()-geoTriangulation->fillingHoles.size());i++){
     discreteDiskFaceTriangle *ct = NULL;
     double U,V;
     if (i == -1) getTriangleUV(uv[0],uv[1], &ct, U,V);
@@ -938,6 +940,7 @@ static MEdge getEdge (MElement *t, MVertex *v){
     if (t->getVertex(i) == v) return t->getEdge((i+1)%3);
 }
 
+/* warning
 static double computeDistanceLinePoint (MVertex *v1, MVertex *v2, MVertex *v){
 
   SVector3 U  = v2->point() - v1->point(); 
@@ -947,7 +950,7 @@ static double computeDistanceLinePoint (MVertex *v1, MVertex *v2, MVertex *v){
   return xx.norm() / U.norm();
 
 }
-
+*/
 static double computeDistance (MVertex *v1, double d1, MVertex *v2, double d2, MVertex *v){
 
 
diff --git a/Geo/discreteDiskFace.h b/Geo/discreteDiskFace.h
index c8fc29dc31..d5e3949045 100644
--- a/Geo/discreteDiskFace.h
+++ b/Geo/discreteDiskFace.h
@@ -23,6 +23,20 @@
 #include "PView.h"
 #include "robustPredicates.h"
 
+inline double tri3Darea(MVertex* mv0, MVertex* mv1, MVertex* mv2)
+{
+
+  SVector3 v1(mv1->x()-mv0->x(),mv1->y()-mv0->y(),mv1->z()-mv0->z());
+  SVector3 v2(mv2->x()-mv0->x(),mv2->y()-mv0->y(),mv2->z()-mv0->z());
+  
+  SVector3 n(v1.y()*v2.z()-v2.y()*v1.z(),v2.x()*v1.z()-v1.x()*v2.z(),v1.x()*v2.y()-v2.x()*v1.y());
+
+  
+  return .5*n.norm();
+
+}
+
+
 inline int nodeLocalNum(MElement* e, MVertex* v)
 {
   for(int i=0; i<e->getNumVertices(); i++)
@@ -39,6 +53,15 @@ inline int edgeLocalNum(MElement* e, MEdge ed)
   return -1;
 }
 
+inline MEdge maxEdge(MElement* e)
+{
+  MEdge maxEd = e->getEdge(0);
+  for(int i=0; i<e->getNumEdges(); i++)
+    if (maxEd.length() < e->getEdge(i).length())
+      maxEd = e->getEdge(i);
+  return maxEd;
+}
+
 class ANNkd_tree;
 class Octree;
 class GRbf;
@@ -48,22 +71,23 @@ class triangulation {
  public:
 
   // attributes
+  int idNum; // number of identification, for hashing purposes
+  std::vector<MElement*> tri;// trianglse
+  GFace* gf;
+
   double maxD;
   double area;
   bool seamPoint;
-  std::vector<MElement*> tri;// triangles
   std::set<MVertex*> vert;// nodes
   // edge to 1 or 2 triangle(s), their num into the vector of MElement*
   std::map<MEdge,std::vector<int>,Less_Edge> ed2tri;
   std::map<double,std::vector<MVertex*> > bord; //border(s)
   std::set<MEdge,Less_Edge> borderEdg; // border edges
-  GFace *gf;
-  int idNum; // number of identification, for hashing purposes
-
+ 
   std::list<GEdge*> my_GEdges;
+  std::set<int> fillingHoles;
 
   //---- methods
-
   double geodesicDistance ();
 
   double aspectRatio()
diff --git a/Geo/discreteFace.cpp b/Geo/discreteFace.cpp
index 22e70ab8e1..a6e6196cec 100644
--- a/Geo/discreteFace.cpp
+++ b/Geo/discreteFace.cpp
@@ -20,7 +20,6 @@ extern "C" {
 }
 #endif
 
-int cp=0;
 
 discreteFace::discreteFace(GModel *model, int num) : GFace(model, num)
 {
@@ -216,6 +215,7 @@ void discreteFace::gatherMeshes()
 
 void discreteFace::mesh(bool verbose)
 {
+  
 #if defined(HAVE_ANN) && defined(HAVE_SOLVER) && defined(HAVE_MESH)
   if (!CTX::instance()->meshDiscrete) return;
   for (unsigned int i=0;i<_atlas.size();i++){
@@ -707,20 +707,312 @@ void discreteFace::fillHoles(triangulation* trian)
     this->mesh_vertices.push_back(center);
     center->setEntity(this);
     trian->vert.insert(center);
-    for(unsigned int j=1; j<mv.size(); j++)
+    for(unsigned int j=1; j<mv.size(); j++){
+      if(std::abs(tri3Darea(mv[j],mv[j-1],center))<1e-15){
+	MVertex temp(center->x()+mv[j]->x()/mv.size(),center->y()+mv[j-1]->y()/mv.size(),(1+1./mv.size())*center->z());
+	*center = temp;
+	center->setEntity(this);
+      }
       addTriangle(trian,new MTriangle(mv[j],mv[j-1],center));
+    }
+    if(std::abs(tri3Darea(mv[0],mv[mv.size()-1],center))<1e-15){
+      MVertex temp(center->x()+mv[0]->x()/mv.size(),center->y()+mv[mv.size()-1]->y()/mv.size(),(1+1./mv.size())*center->z());
+      *center = temp;
+      center->setEntity(this);
+    }
     addTriangle(trian,new MTriangle(mv[0],mv[mv.size()-1],center));
   }
 #endif
 }
 
+void discreteFace::bisectionEdg(triangulation* trian)
+{
+  std::map<MEdge,double,Less_Edge> ed2angle;
+  std::map<double,std::vector<MEdge> > ed2refine;
+  /*
+    checkEdges
+    for each ed in ed2refine
+    ...while ed exists
+    ......terminal from lepp(ed)
+    ......refine terminal
+    ......update ed2refine
+  */
+  int count = 1;
+  checkEdgesBis(trian,ed2refine,ed2angle);
+  while(!ed2refine.empty()){
+    //for(it = ed2refine.rbegin(); it != ed2refine.rend(); ++it){
+    std::map<double,std::vector<MEdge> >::reverse_iterator it = ed2refine.rbegin();
+    double key = it->first;
+    std::vector<MEdge> & ved = it->second;
+    while(!ved.empty()){
+      //for(unsigned int i=0; i<ved.size(); i++){
+      MEdge ed = ved[0];
+      while(ed2angle.find(ed) != ed2angle.end()){
+	MEdge terminal = lepp(trian,ed);
+	ed2angle.erase(terminal);
+	std::vector<MEdge> ed2update;
+	refineTriangles(trian,terminal,ed2update);
+	updateEd2refineBis(trian,ed2angle,ed2update,ed2refine);
+	printAtlasMesh(trian->tri,-count++);	
+      }// end while exists
+      ed2refine[key].erase(ved.begin());
+      ved = ed2refine[key];
+    }// end for unsigned
+    ed2refine.erase(key);
+  }// end for it  
+  
+}
+
+bool discreteFace::checkEdges(triangulation* trian,std::map<double,std::vector<MEdge> >& ed2refine,std::map<MEdge,double,Less_Edge>& ed2angle)
+{
+  
+  for(unsigned int i=0; i<trian->tri.size(); i++){
+    MElement* t = trian->tri[i];
+    std::vector<MEdge> eds;
+    eds.push_back(t->getEdge(0));eds.push_back(t->getEdge(1));eds.push_back(t->getEdge(2));
+    for(int j=0; j<3; j++){
+      if(trian->ed2tri[eds[j]].size()>1){
+      MEdge ed1 = eds[j+1>2?j-2:j+1];      
+      MEdge ed2 = eds[j+2>2?j-1:j+2];
+      SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
+		  ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
+		  ed1.getVertex(0)->z()-ed1.getVertex(1)->z()); 
+      SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
+		  ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
+		  ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
+      double dotp = dot(v1,v2);
+      double lp = ed1.length()*ed2.length();
+      std::map<MEdge,double,Less_Edge>::iterator check = ed2angle.find(eds[j]);
+      if(check!=ed2angle.end()){
+	ed2angle[eds[j]] += std::acos(dotp/lp);
+	if(ed2angle[eds[j]]>M_PI)
+	  ed2refine[eds[j].length()].push_back(eds[j]);
+	else
+	  ed2angle.erase(eds[j]);
+      }
+      else
+	  ed2angle[eds[j]] = std::acos(dotp/lp);
+      }//end if size()>1
+    }// end for j
+  }//end for tri  
+  return !(ed2refine.empty());
+}
+
+
+bool discreteFace::checkEdgesBis(triangulation* trian,std::map<double,std::vector<MEdge> >& ed2refine,std::map<MEdge,double,Less_Edge>& ed2angle)
+{
+  
+  for(unsigned int i=0; i<trian->tri.size(); i++){
+    MElement* t = trian->tri[i];
+    std::vector<MEdge> eds;
+    eds.push_back(t->getEdge(0));eds.push_back(t->getEdge(1));eds.push_back(t->getEdge(2));
+    for(int j=0; j<3; j++){
+      MEdge ed1 = eds[j+1>2?j-2:j+1];      
+      MEdge ed2 = eds[j+2>2?j-1:j+2];
+      SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
+		  ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
+		  ed1.getVertex(0)->z()-ed1.getVertex(1)->z()); 
+      SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
+		  ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
+		  ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
+      double dotp = dot(v1,v2);
+      double lp = ed1.length()*ed2.length();
+      std::map<MEdge,double,Less_Edge>::iterator check = ed2angle.find(eds[j]);
+      if(check==ed2angle.end()){
+	ed2angle[eds[j]] = std::acos(dotp/lp);
+	if(ed2angle[eds[j]]>M_PI/2.)
+	  ed2refine[eds[j].length()].push_back(eds[j]);
+	else
+	  ed2angle.erase(eds[j]);
+      }
+    }// end for j
+  }//end for tri  
+  return !(ed2refine.empty());
+}
+
+
+MEdge discreteFace::lepp(triangulation* trian,MEdge ed){  
+  std::vector<int> intri = trian->ed2tri[ed];
+  bool isTerminal = false;
+  while(intri.size()>1 && !isTerminal){
+    MEdge ed0 = maxEdge(trian->tri[intri[0]]);	
+    MEdge ed1 = maxEdge(trian->tri[intri[1]]);
+    if(ed != ed0){
+      ed = ed0;
+      intri = trian->ed2tri[ed];
+    }
+    else if(ed != ed1){
+      ed = ed1;
+      intri = trian->ed2tri[ed];
+    }
+    else isTerminal = true;
+  }// end while 
+  return ed;
+}
+
+void discreteFace::refineTriangles(triangulation* trian,MEdge ed,std::vector<MEdge>&ed2update){  
+
+  SPoint3 mid = ed.barycenter();
+  MVertex* mv = new MVertex(mid.x(),mid.y(),mid.z());  
+  trian->vert.insert(mv);
+
+  std::vector<int> t = trian->ed2tri[ed];
+
+  MTriangle *t00, *t01;
+  int ie;
+
+  ie = edgeLocalNum(trian->tri[t[0]],ed);
+  t00 = new MTriangle(trian->tri[t[0]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(0),trian->tri[t[0]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(1),mv);
+  t01 = new MTriangle(trian->tri[t[0]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(0),trian->tri[t[0]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(1),mv);
+
+  trian->tri[t[0]] = t00;
+  trian->ed2tri[t00->getEdge(2)] = trian->ed2tri[ed]; 
+  trian->ed2tri[t00->getEdge(1)].push_back(t[0]);
+  trian->ed2tri[t00->getEdge(1)].push_back(trian->tri.size());
+
+  std::vector<int> oldtri = trian->ed2tri[ed];
+  oldtri[0] == t[0] ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
+  trian->ed2tri[t01->getEdge(1)] = oldtri;
+  oldtri = trian->ed2tri[t01->getEdge(0)];
+  oldtri[0] == t[0]  ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
+  trian->ed2tri[t01->getEdge(0)] = oldtri;
+  trian->tri.push_back(t01);  
+
+  ed2update.push_back(t00->getEdge(0));
+  ed2update.push_back(t01->getEdge(0));
+
+  if(t.size()>1){
+
+    ed2update.push_back(t01->getEdge(1));
+    ed2update.push_back(t00->getEdge(2));
+    MTriangle  *t10, *t11;
+
+    this->mesh_vertices.push_back(mv);
+    mv->setEntity(this);
+
+    ie = edgeLocalNum(trian->tri[t[1]],ed);
+    t11 = new MTriangle(trian->tri[t[1]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(0),trian->tri[t[1]]->getEdge(ie+1 > 2 ? ie-2 : ie+1).getVertex(1),mv);
+    t10 = new MTriangle(trian->tri[t[1]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(0),trian->tri[t[1]]->getEdge(ie+2 > 2 ? ie-1 : ie+2).getVertex(1),mv);
+
+    trian->tri[t[1]] = t10;
+    trian->ed2tri[t10->getEdge(1)] = trian->ed2tri[ed];
+    trian->ed2tri[t10->getEdge(2)].push_back(t[1]);
+    trian->ed2tri[t10->getEdge(2)].push_back(trian->tri.size());
+
+    oldtri = trian->ed2tri[t11->getEdge(2)];
+    oldtri[0] == t[1] ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
+    trian->ed2tri[t11->getEdge(2)] = oldtri;
+    oldtri = trian->ed2tri[t11->getEdge(0)];
+    oldtri[0] == t[1]  ? oldtri[0] = trian->tri.size() : oldtri[1] = trian->tri.size();
+    trian->ed2tri[t11->getEdge(0)] = oldtri;
+    trian->tri.push_back(t11);  
+    
+    ed2update.push_back(t10->getEdge(0));
+    ed2update.push_back(t11->getEdge(0));
+
+  }
+  else{
+    std::list<GEdge*> gGEdges = trian->my_GEdges;
+    std::list<GEdge*>::iterator oe = gGEdges.begin();
+    while(oe != gGEdges.end() && ed.getVertex(0)->onWhat() != *oe && ed.getVertex(0)->onWhat() != (*oe)->getBeginVertex())
+	    ++oe;
+    GEdge* ged = *oe;
+    std::vector<MLine*> mlines = ged->lines;
+    std::vector<MLine*> conca;
+    for (unsigned int i=0; i<mlines.size(); i++){
+      if ((mlines[i]->getVertex(0)==ed.getVertex(0)&&mlines[i]->getVertex(1)==ed.getVertex(1))||
+	  (mlines[i]->getVertex(1)==ed.getVertex(0)&&mlines[i]->getVertex(0)==ed.getVertex(1))){
+	conca.push_back(new MLine(mlines[i]->getVertex(0),mv));
+	conca.push_back(new MLine(mv,mlines[i]->getVertex(1)));// delete MLine ?
+      }
+      else conca.push_back(mlines[i]);      
+    }
+    discreteEdge* de = new discreteEdge(this->model(),NEWLINE(),ged->getBeginVertex(),ged->getEndVertex());
+    setupDiscreteEdge(de,conca,NULL);
+    trian->my_GEdges.remove(ged);
+    ged->lines.clear();
+    ged->mesh_vertices.clear();
+    trian->my_GEdges.push_back(de);
+    trian->borderEdg.erase(ed);
+    trian->borderEdg.insert(t00->getEdge(2));
+    trian->borderEdg.insert(t01->getEdge(1));
+  }    
+}
+
+void discreteFace::updateEd2refine(triangulation* trian,std::map<MEdge,double,Less_Edge>&ed2angle,std::vector<MEdge>&ed2update,std::map<double,std::vector<MEdge> >&ed2refine){
+
+  for(unsigned int i=0; i<ed2update.size(); i++){
+    MEdge current = ed2update[i];   
+    std::vector<int> intri = trian->ed2tri[current];
+    if(intri.size()>1 && ed2angle.find(current) == ed2angle.end() ){
+      ed2angle[current] = 0.;	
+      for(unsigned int j=0; j<intri.size(); j++){
+	MElement* tri = trian->tri[intri[j]];
+	int num = edgeLocalNum(tri,current);
+	MEdge ed1 = tri->getEdge(num+1>2?num-2:num+1);      
+	MEdge ed2 = tri->getEdge(num+2>2?num-1:num+2);
+	SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
+		    ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
+		    ed1.getVertex(0)->z()-ed1.getVertex(1)->z()); 
+	SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
+		    ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
+		    ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
+	double dotp = dot(v1,v2);
+	double lp = ed1.length()*ed2.length();
+	if(ed2angle[current]==0.)
+	  ed2angle[current] = std::acos(dotp/lp);
+	else{
+	  ed2angle[current] += std::acos(dotp/lp);
+	  if(ed2angle[current] > M_PI)
+	    ed2refine[current.length()].push_back(current);
+	  else
+	    ed2angle.erase(current);	  
+	}
+      }//end for j
+    }
+  }// end for i
+
+}
+
+
+void discreteFace::updateEd2refineBis(triangulation* trian,std::map<MEdge,double,Less_Edge>&ed2angle,std::vector<MEdge>&ed2update,std::map<double,std::vector<MEdge> >&ed2refine){
+
+  for(unsigned int i=0; i<ed2update.size(); i++){
+    MEdge current = ed2update[i];   
+    std::vector<int> intri = trian->ed2tri[current];
+    for(unsigned int j=0; j<intri.size(); j++){
+      if(ed2angle.find(current) == ed2angle.end() ){	
+	MElement* tri = trian->tri[intri[j]];
+	int num = edgeLocalNum(tri,current);
+	MEdge ed1 = tri->getEdge(num+1>2?num-2:num+1);      
+	MEdge ed2 = tri->getEdge(num+2>2?num-1:num+2);
+	SVector3 v1(ed1.getVertex(0)->x()-ed1.getVertex(1)->x(),
+		    ed1.getVertex(0)->y()-ed1.getVertex(1)->y(),
+		    ed1.getVertex(0)->z()-ed1.getVertex(1)->z()); 
+	SVector3 v2(ed2.getVertex(1)->x()-ed2.getVertex(0)->x(),
+		    ed2.getVertex(1)->y()-ed2.getVertex(0)->y(),
+		    ed2.getVertex(1)->z()-ed2.getVertex(0)->z());
+	double dotp = dot(v1,v2);
+	double lp = ed1.length()*ed2.length();
+	ed2angle[current] = std::acos(dotp/lp);
+	if (ed2angle[current]>M_PI/2.)
+	  ed2refine[current.length()].push_back(current);
+	else
+	  ed2angle.erase(current);
+      }//end for j
+    }    
+  }// end for i
+
+}
+
 void discreteFace::addTriangle(triangulation* trian, MTriangle* t)
 {
 #if defined(HAVE_SOLVER) && defined(HAVE_ANN)
-  // #mark quid borders ?
   for(int i=0; i<3; i++){
     MEdge ed = t->getEdge(i);
-    trian->ed2tri[ed].push_back(trian->tri.size());
+    int n = trian->tri.size();
+    trian->fillingHoles.insert(n);
+    trian->ed2tri[ed].push_back(n);
   }
   trian->tri.push_back(t);
 #endif
diff --git a/Geo/discreteFace.h b/Geo/discreteFace.h
index 1f6b0f61af..2515f1fbbc 100644
--- a/Geo/discreteFace.h
+++ b/Geo/discreteFace.h
@@ -37,6 +37,13 @@ class discreteFace : public GFace {
   void updateTopology(std::vector<triangulation*>&);
   void split(triangulation*,std::vector<triangulation*>&,int);
   void fillHoles(triangulation*);
+  void bisectionEdg(triangulation*);
+  bool checkEdges(triangulation*,std::map<double,std::vector<MEdge> >&,std::map<MEdge,double,Less_Edge>&);
+  bool checkEdgesBis(triangulation*,std::map<double,std::vector<MEdge> >&,std::map<MEdge,double,Less_Edge>&);
+  MEdge lepp(triangulation*,MEdge);
+  void refineTriangles(triangulation*,MEdge,std::vector<MEdge>&);
+  void updateEd2refine(triangulation*,std::map<MEdge,double,Less_Edge>&,std::vector<MEdge>&,std::map<double,std::vector<MEdge> >&);
+   void updateEd2refineBis(triangulation*,std::map<MEdge,double,Less_Edge>&,std::vector<MEdge>&,std::map<double,std::vector<MEdge> >&);
   void addTriangle(triangulation*,MTriangle*);
   GPoint point(double par1, double par2) const;
   SPoint2 parFromPoint(const SPoint3 &p, bool onSurface=true) const;
-- 
GitLab