diff --git a/Mesh/meshRecombine2D.cpp b/Mesh/meshRecombine2D.cpp
index ac9a18f2e332f38115e1cf6fe202d357dcfd9e3b..c28768c0b3d22998c42f669faeee1801fcb8dfda 100644
--- a/Mesh/meshRecombine2D.cpp
+++ b/Mesh/meshRecombine2D.cpp
@@ -28,8 +28,8 @@ Recombine2D::Recombine2D(GFace *gf, int horizon)
   
   //return;
   
-  laplaceSmoothing(gf,100);
-  gf->model()->writeMSH("befSquare.msh");
+  //laplaceSmoothing(gf,100);
+  //gf->model()->writeMSH("befSquare.msh");
   
   Msg::Info("Branching with horizon %d", _horizon = HORIZ);
   
@@ -120,7 +120,7 @@ void Recombine2D::_buildEdgeToElement(std::vector<E*> &elements, e2t_cont &adj)
 
 void Recombine2D::_recombine()
 {
-  SetBoundingBox();
+  //SetBoundingBox();
   
   /*Map_Tri_Recomb::iterator itt;
   
diff --git a/Mesh/meshRecombine2D.h b/Mesh/meshRecombine2D.h
index c441b108db46543422de546ab38b5d1b4217902f..d80ca7e9950b2aae97331bb09ce2627f6f6d7d23 100644
--- a/Mesh/meshRecombine2D.h
+++ b/Mesh/meshRecombine2D.h
@@ -20,12 +20,14 @@
 
 class RecombTriangle;
 class Recomb2D_Node;
-class Rec2d_node;
-class Rec2d_edge;
-class Rec2d_cycle;
+class TrianglesUnion;
+class Rec2d_vertex;
 struct lessRecombTri {
   bool operator()(RecombTriangle *rt1, RecombTriangle *rt2) const;
 };
+struct lessTriUnion {
+  bool operator()(TrianglesUnion *, TrianglesUnion *) const;
+};
 
 typedef std::set<RecombTriangle*,lessRecombTri> Set_Recomb;
 typedef std::map<MElement*,std::set<RecombTriangle*> > Map_Tri_Recomb;
@@ -55,13 +57,15 @@ class Recombine2D {
     ~Recombine2D();
     
     int apply();
-    double getBenef() const {return _benef;}
-    int numTriangle() const {return _isolated.size();}
+    int apply(bool);
+    inline double getBenef() const {return _benef;}
+    inline int numTriangle() const {return _isolated.size();}
     
   private :
-    std::set<Rec2d_node*> _nodes;
-    std::set<Rec2d_edge*> _edges;
-    std::set<Rec2d_cycle*> _cycles;
+    //std::set<TrianglesUnion*, lessTriUnion> _setQuads;
+    std::list<TrianglesUnion*> _setQuads;
+    void _removeImpossible(std::list<TrianglesUnion*>::iterator);
+    void _recombine(bool);
 };
 
 class RecombTriangle {
@@ -82,15 +86,15 @@ class RecombTriangle {
     MQuadrangle *createQuad() const;
     bool operator<(const RecombTriangle &other) const;
     
-    void triangles(std::vector<MElement *> &v) const {v = _t;}
-    int numTriangles() const {return (int) _t.size();}
+    inline void triangles(std::vector<MElement *> &v) const {v = _t;}
+    inline int numTriangles() const {return (int) _t.size();}
     MElement *triangle(int i) const {
       if (i >= 0 && i < _t.size())
-	return _t[i];
+        return _t[i];
       return NULL;
     }
-    bool isQuad() const {return _formingQuad;}
-    double getBenef() const {return _benefit;}
+    inline bool isQuad() const {return _formingQuad;}
+    inline double getBenef() const {return _benefit;}
     
     double compute_alignment(const MEdge&, MElement*, MElement*);
 };
@@ -114,51 +118,71 @@ class Recomb2D_Node {
     
     void erase();
     void blocking(const Map_Tri_Node::iterator &);
-    bool isBetter() {return _blocking.size() < 2;}
-    Set_Recomb::iterator getItRecomb() {return _recomb;}
-    double getTotBenef() {return _totBenef;}
-    int getnSkip() {return _nskip;}
-    double getBound() {return _totBenef + _benef * _depth;}
+    inline bool isBetter() {return _blocking.size() < 2;}
+    inline Set_Recomb::iterator getItRecomb() {return _recomb;}
+    inline double getTotBenef() {return _totBenef;}
+    inline int getnSkip() {return _nskip;}
+    inline double getBound() {return _totBenef + _benef * _depth;}
 };
 
 
-class Rec2d_node {
+class Rec2d_vertex {
   private :
-    std::set<Rec2d_edge*> _freeEdges;
-    std::set<Rec2d_cycle*> _cycle3;
-    std::set<Rec2d_cycle*> _cycle4;
-  
-  public :
-    Rec2d_node(){}
-    
-    void addCycle(Rec2d_cycle*, int n = 0);
-    void addEdge(Rec2d_edge*);
+    // _onWhat={-1:corner,0:edge,1:face,(2:volume)}
+    int _onWhat, _numEl;
+    double _angle;
+    // GEdge : virtual SVector3 firstDer(double par) const = 0;
+    // GEntity : virtual Range<double> parBounds(int i)
+    static double **_Vvalues;
+    static double **_Vbenefs;
     
-    void print();
-};
-class Rec2d_edge {
-  private :
-    Rec2d_node *_nodes[2];
-    std::set<Rec2d_cycle*> _cycles;
+    void _initStaticTable();
+    double _computeAngle(MVertex *, std::list<MTriangle*> &, std::set<GEdge*> &);
   
   public :
-    Rec2d_edge(Rec2d_node*, Rec2d_node*);
-    
-    void addCycle(Rec2d_cycle*);
+    Rec2d_vertex(MVertex *, std::list<MTriangle*> &,
+                 std::map<MVertex*, std::set<GEdge*> > &);
     
-    void print();
+    inline void changeNumEl(int c) {_numEl += c;}
+    double getReward();
+    double getReward(int);
 };
-class Rec2d_cycle {
+
+class TrianglesUnion {
   private :
-    std::set<Rec2d_edge*> _edges;
-  
-  public :
-    Rec2d_cycle(){}
-    void addEdge(Rec2d_edge*);
-    int size() {return _edges.size();}
+    int _numEmbEdge, _numEmbVert, _numBoundVert, _numTri, _computation;
+    double _embEdgeValue, _embVertValue, _globValIfExecuted;
+    Rec2d_vertex **_vertices;
+    MTriangle **_triangles;
+    static int _RECOMPUTE; //incremented when a recombination is executed
+    public:
+    static int _NumEdge, _NumVert;
+    static double _ValEdge, _ValVert;
+    private:
+    
+    double _computeEdgeLength(GFace *, MVertex **, double *u, double *v,
+                              int numIntermedPoint= 1);
+    double _computeAlignment(MEdge &, std::list<MTriangle*> &);
+    void _update();
     
-    void print();
+  public :
+    TrianglesUnion(GFace *, std::list<MTriangle*> &, std::list<MEdge> &,
+                   std::list<Rec2d_vertex*> &, std::map<MVertex*,double*> &);
+    
+    bool operator<(TrianglesUnion &other);
+    inline double getEdgeValue() {return _embEdgeValue;}
+    inline double getNumTriangles() {return _numTri;}
+    inline MTriangle *getTriangle(int num) {return _triangles[num];}
+    void select() {
+      _ValEdge -= _embEdgeValue;
+      _NumEdge -= _numEmbEdge;
+      _ValVert -= _embVertValue;
+      _NumVert -= _numEmbVert;
+      for (int i = 0; i < _numBoundVert; i++) {
+        _ValVert += _vertices[i]->getReward(-1);
+      }
+      _RECOMPUTE++;
+    }
+    MQuadrangle *createQuad() const;
 };
-
-
 #endif
diff --git a/Mesh/meshRecombine2D_2.cpp b/Mesh/meshRecombine2D_2.cpp
index 8ed74c74205b0bead78408e1962c8bc3582412d5..15ffe9716dd3d72a86325abe4cd247c6e473c781 100644
--- a/Mesh/meshRecombine2D_2.cpp
+++ b/Mesh/meshRecombine2D_2.cpp
@@ -8,6 +8,7 @@
 //
 
 #include "meshRecombine2D.h"
+#include "BackgroundMesh.h"
 #include "GFace.h"
 #include <cmath>
 #include <FL/Fl.H>
@@ -18,102 +19,541 @@
 
 static int HORIZ = 20;
 
+double **Rec2d_vertex::_Vvalues = NULL;
+double **Rec2d_vertex::_Vbenefs = NULL;
+int TrianglesUnion::_RECOMPUTE = 0;
+int TrianglesUnion::_NumEdge = 0;
+int TrianglesUnion::_NumVert = 0;
+double TrianglesUnion::_ValEdge = .0;
+double TrianglesUnion::_ValVert = .0;
+
 Recombine2D::Recombine2D(GFace *gf)
 : _horizon(0), _gf(gf), _benef(.0), _applied(true)
 {
-  std::map<MEdge, Rec2d_edge*, Less_Edge> mapEdge;
-  std::map<MVertex*, Rec2d_node*> mapNode;
+  Msg::Warning("[meshRecombine2D] Alignement computation ok uniquely for xy or yz plane mesh !");
+  
+  // be able to compute geometrical angle at corners
+  std::map<MVertex*, std::set<GEdge*> > mapCornerVert;
+  {
+    std::list<GEdge*> listge = gf->edges();
+    std::list<GEdge*>::iterator itge = listge.begin();
+    
+    for (; itge != listge.end(); itge++) {
+      if ((*itge)->getBeginVertex()->getNumMeshElements() > 1 ||
+          (*itge)->getEndVertex()->getNumMeshElements() > 1     )
+        Msg::Warning("[meshRecombine2D] Why more than one MPoint, what should I do ?");
+      mapCornerVert[(*itge)->getBeginVertex()->getMeshElement(0)->getVertex(0)].insert(*itge);
+      mapCornerVert[(*itge)->getEndVertex()->getMeshElement(0)->getVertex(0)].insert(*itge);
+    }
+  }
   
+  // Find all Vertices and edges
+  std::map<MVertex*, std::list<MTriangle*> > mapVert;
+  std::map<MEdge, std::list<MTriangle*>, Less_Edge> mapEdge;
   for (unsigned int i = 0; i < gf->triangles.size(); i++) {
-    Rec2d_cycle *rc = new Rec2d_cycle();
-    _cycles.insert(rc);
     MTriangle *t = gf->triangles[i];
-    
     for (int j = 0; j < 3; j++) {
-      MVertex *v = t->getVertex(j);
-      std::map<MVertex*, Rec2d_node*>::iterator itn = mapNode.find(v);
-      if (itn == mapNode.end()) {
-        Rec2d_node *rn = new Rec2d_node();
-        mapNode[v] = rn;
-        _nodes.insert(rn);
-        rn->addCycle(rc, 3);
+      mapVert[t->getVertex(j)].push_back(t);
+      mapEdge[t->getEdge(j)].push_back(t);
+    }
+  }
+  
+  // Create the 'Rec2d_vertex' and store iterator to vertices which have degree 4
+  std::map<MVertex*, std::list<MTriangle*> >::iterator itvert = mapVert.begin();
+  std::map<MVertex*, Rec2d_vertex*> mapV2N;
+  std::map<MVertex*, Rec2d_vertex*>::iterator itV2N = mapV2N.begin();
+  std::list<std::map<MVertex*, std::list<MTriangle*> >::iterator> fourTri;
+  for (; itvert != mapVert.end(); itvert++) {
+    if ((*itvert).second.size() == 4)
+      fourTri.push_back(itvert);
+    Rec2d_vertex *n = new Rec2d_vertex((*itvert).first, (*itvert).second, mapCornerVert);
+    itV2N = mapV2N.insert(itV2N, std::make_pair((*itvert).first,n));
+    TrianglesUnion::_NumVert++;
+    TrianglesUnion::_ValVert += n->getReward();
+  }
+  
+  // store mesh size and parametric coordinates for better performance
+  std::map<MVertex*,double*> mapV2LcUV;
+  
+  // Create 'TrianglesUnion' for pattern of 4 triangles
+/*
+  +-----+
+  |\   /|
+  | \ / |
+  |  +  |
+  | / \ |
+  |/   \|
+  +-----+
+*/
+  std::list<std::map<MVertex*, std::list<MTriangle*> >::iterator>::iterator it4;
+  int j = 0;
+  for (it4 = fourTri.begin(); it4 != fourTri.end(); it4++) {
+    std::list<MEdge> listEmbEdge;
+    std::list<Rec2d_vertex*> listVert;
+    {
+      std::set<MVertex*> setVert;
+      std::multiset<MEdge, Less_Edge> msetEdge;
+      std::list<MTriangle*>::iterator itTri = (*(*it4)).second.begin();
+      for (; itTri != (*(*it4)).second.end(); itTri++) {
+        MVertex *vt;
+        for (int i = 0; i < 3; i++) {
+          msetEdge.insert((*itTri)->getEdge(i));
+          vt = (*itTri)->getVertex(i);
+          if (vt != (*(*it4)).first)
+            setVert.insert(vt);
+        }
       }
-      else
-        (*itn).second->addCycle(rc, 3);
+      std::multiset<MEdge>::iterator itEdge = msetEdge.begin();
+      MEdge me = *(itEdge++);
+      for (; itEdge != msetEdge.end(); itEdge++) {
+        if (*itEdge == me)
+          listEmbEdge.push_back(*itEdge);
+        me = *itEdge;
+      }
+      std::set<MVertex*>::iterator itsVert = setVert.begin();
+      for (; itsVert != setVert.end(); itsVert++)
+        listVert.push_back(mapV2N[*itsVert]);
+      listVert.push_back(mapV2N[(*(*it4)).first]);
     }
+    Msg::Info("%d",++j);
+    _setQuads.push_back(new TrianglesUnion(gf, (*(*it4)).second, listEmbEdge, listVert, mapV2LcUV));
+  }
+  
+  // Create 'TrianglesUnion' for pattern of 2 triangles
+/*
+  +---+
+  |\  |
+  | \ |
+  |  \|
+  +---+
+*/
+  /*std::map<MEdge, std::list<MTriangle*> >::iterator itedge = mapEdge.begin();
+  for (; itedge != mapEdge.end(); itedge++) {
+    if ((*itedge).second.size() == 2) {
+      std::list<MEdge> listEmbEdge;
+      listEmbEdge.push_back((*itedge).first);
+      std::list<Rec2d_vertex*> listVert;
+      listVert.push_back(mapV2N[(*itedge).first.getVertex(0)]);
+      listVert.push_back(mapV2N[(*itedge).first.getVertex(1)]);
+      TrianglesUnion *tu = new TrianglesUnion(gf, (*itedge).second, listEmbEdge, listVert, mapV2LcUV);
+      _setQuads.push_back(tu);
+      TrianglesUnion::_NumEdge++;
+      TrianglesUnion::_ValEdge += tu->getEdgeValue();
+    }
+    else
+      Msg::Info("[bord] %d", (*itedge).second.size());
+  }
+  _setQuads.sort(lessTriUnion());
+  
+  _recombine(true);
+  _applied = true;*/
+}
+
+
+void Recombine2D::_recombine(bool a)
+{ 
+  int i = 0;
+  while (!_setQuads.empty()) {
+    Msg::Info("%d",i);
+    std::list<TrianglesUnion*>::iterator it = _setQuads.begin();
     
-    for (int j = 0; j < 3; j++) {
-      MEdge e = t->getEdge(j);
-      std::map<MEdge, Rec2d_edge*>::iterator ite = mapEdge.find(e);
-      if (ite == mapEdge.end()) {
-        Rec2d_node *n0 = mapNode[e.getVertex(0)];
-        Rec2d_node *n1 = mapNode[e.getVertex(1)];
-        Rec2d_edge *re = new Rec2d_edge(n0, n1);
-        n0->addEdge(re);
-        n1->addEdge(re);
-        mapEdge[e] = re;
-        _edges.insert(re);
-        rc->addEdge(re);
-        re->addCycle(rc);
-      }
-      else {
-        rc->addEdge((*ite).second);
-        (*ite).second->addCycle(rc);
+    (*it)->select();
+    
+    _quads.push_back((*it)->createQuad());
+    
+    _removeImpossible(it);
+    
+    _setQuads.sort(lessTriUnion());
+    i++;
+  }
+  Msg::Info("Done %d (%d)", i, _pairs.size());
+}
+
+MQuadrangle *TrianglesUnion::createQuad() const
+{
+  std::list<MEdge> listBoundEdge;
+  {
+    std::multiset<MEdge, Less_Edge> msetEdge;
+    for (int i = 0; i < _numTri; i++) {
+      MTriangle *t = _triangles[i];
+      for (int i = 0; i < 3; i++) {
+        msetEdge.insert(t->getEdge(i));
       }
     }
+    std::multiset<MEdge>::iterator itEdge = msetEdge.begin();
+    MEdge me = *(itEdge++);
+    bool precWasSame = false;
+    for (; itEdge != msetEdge.end(); itEdge++) {
+      if (*itEdge == me)
+        precWasSame = true;
+      else if (precWasSame)
+        precWasSame = false;
+      else
+        listBoundEdge.push_back(me);
+      me = *itEdge;
+    }
+    if (!precWasSame)
+      listBoundEdge.push_back(me);
   }
-  }ZzZ
+  if (listBoundEdge.size() != 4)
+    Msg::Warning("[meshRecombine2D] Not 4 edges !");
+  
+  MVertex *v1, *v2, *v3, *v4;
+  v1 = listBoundEdge.begin()->getMinVertex();
+  v2 = listBoundEdge.begin()->getMinVertex();
+  std::list<MEdge>::iterator it = listBoundEdge.begin();
+  for (it++; it != listBoundEdge.end(); it++) {
+    if (v2 == (*it).getMinVertex()) {
+      v3 = (*it).getMaxVertex();
+      listBoundEdge.erase(it);
+      break;
+    }
+    if (v2 == (*it).getMaxVertex()) {
+      v3 = (*it).getMinVertex();
+      listBoundEdge.erase(it);
+      break;
+    }
+  }
+  for (it = listBoundEdge.begin(); it != listBoundEdge.end(); it++) {
+    if (v3 == (*it).getMinVertex()) {
+      v4 = (*it).getMaxVertex();
+      break;
+    }
+    if (v3 == (*it).getMaxVertex()) {
+      v4 = (*it).getMinVertex();
+      break;
+    }
+  }
+  
+  return new MQuadrangle(v1, v2, v3, v4);
 }
 
-void Rec2d_node::addCycle(Rec2d_cycle *c, int n)
+
+int Recombine2D::apply(bool a)
 {
-  if (n == 3) {
-    _cycle3.insert(c);
-    return;
+  if (!_haveParam || _applied) return 0;
+  
+  std::vector<MTriangle*> triangles2;
+  for (int i = 0; i < _gf->triangles.size(); i++) {
+    delete _gf->triangles[i];
   }
-  if (n == 4) {
-    _cycle4.insert(c);
-    return;
+  _gf->triangles = triangles2;
+  _gf->quadrangles = _quads;
+  
+  _applied = true;
+  return 1;
+}
+
+void Recombine2D::_removeImpossible(std::list<TrianglesUnion*>::iterator it)
+{
+  std::set<MTriangle *> touched;
+  
+  for (int i = 0; i < (*it)->getNumTriangles(); i++) {
+    touched.insert((*it)->getTriangle(i));
   }
-  if (c->size() == 3) {
-    _cycle3.insert(c);
-    return;
+  
+  for (it = _setQuads.begin(); it != _setQuads.end();) {
+    bool b = false;
+    for (int i = 0; i < (*it)->getNumTriangles(); i++) {
+      if (touched.find((*it)->getTriangle(i)) != touched.end())
+        b = true;
+    }
+    if (b)
+      _setQuads.erase(it++);
+    else
+      it++;
   }
-  if (c->size() == 4) {
-    _cycle4.insert(c);
-    return;
+}
+
+
+
+Rec2d_vertex::Rec2d_vertex(MVertex *v,
+                           std::list<MTriangle*> &setTri,
+                           std::map<MVertex*, std::set<GEdge*> > &mapVert)
+: _numEl(setTri.size()), _angle(.0)
+{
+  _onWhat = v->onWhat()->dim() - 1;
+  
+  if (_onWhat < 0) {
+    std::map<MVertex*, std::set<GEdge*> >::iterator it = mapVert.find(v);
+    if (it != mapVert.end()) {
+      _angle = _computeAngle(v, setTri, (*it).second);
+    }
+    else {
+      Msg::Warning("[meshRecombine2D] Can't compute corner angle, setting angle to pi/2");
+      _angle = M_PI / 2.;
+    }
   }
-  Msg::Error("[Recombine2D] Can't tell if it's a cycle3 or a cycle4");
+  
+  if (_Vvalues == NULL)
+    _initStaticTable();
 }
-void Rec2d_node::addEdge(Rec2d_edge *e)
+
+void Rec2d_vertex::_initStaticTable()
 {
-  _freeEdges.insert(e); //que faire ?
+  if (_Vvalues == NULL) {
+    // _Vvalues[onWhat][nEl]; onWhat={0:edge,1:face} / nEl=_numEl-1
+    // _Vbenefs[onWhat][nEl]; onWhat={0:edge,1:face} / nEl=_numEl-1 (benef of adding an element)
+    int nE = 5, nF = 10;
+    
+    _Vvalues = new double*[2];
+    _Vvalues[0] = new double[nE]; //AVERIFIER SI CA MARCHE
+    for (int i = 0; i < nE; i++)
+      _Vvalues[0][i] = 1. - fabs(2. / (i+1) - 1.);
+    _Vvalues[1] = new double[nF];
+    for (int i = 0; i < nF; i++)
+      _Vvalues[1][i] = 1. - fabs(4. / (i+1) - 1.);
+      
+    _Vbenefs = new double*[2];
+    _Vbenefs[0] = new double[nE-1];
+    for (int i = 0; i < nE-1; i++)
+      _Vbenefs[0][i] = _Vvalues[0][i+1] - _Vvalues[0][i];
+    _Vbenefs[1] = new double[nF-1];
+    for (int i = 0; i < nF-1; i++)
+      _Vbenefs[1][i] = _Vvalues[1][i+1] - _Vvalues[1][i];
+  }
 }
-void Rec2d_node::print()
+
+
+double Rec2d_vertex::_computeAngle(MVertex *v,
+                                   std::list<MTriangle*> &setTri,
+                                   std::set<GEdge*> &setEdge)
 {
-  Msg::Info("Node : %d cycle3, %d cycle4, %d edges", _cycle3.size(), _cycle4.size(), _freeEdges.size());
+  if (setEdge.size() != 2) {
+    Msg::Warning("[meshRecombine2D] Wrong number of edge : %d, returning pi/2", setEdge.size());
+    return M_PI / 2.;
+  }
+  const double prec = 100.;
+  
+  SVector3 vectv = SVector3(v->x(), v->y(), v->z());
+  SVector3 firstDer0, firstDer1;
+  
+  std::set<GEdge*>::iterator it = setEdge.begin();
+  for (int k = 0; k < 2; it++, k++) {
+    GEdge *ge = *it;
+    SVector3 vectlb = ge->position(ge->getLowerBound());
+    SVector3 vectub = ge->position(ge->getUpperBound());
+    vectlb -= vectv;
+    vectub -= vectv;
+    double normlb, normub;
+    if ((normlb = norm(vectlb)) > prec * (normub = norm(vectub)))
+      firstDer1 = vectub;
+    else if (normub > prec * normlb)
+      firstDer1 = vectlb;
+    else {
+      Msg::Warning("[meshRecombine2D] Bad precision, returning pi/2");
+      return M_PI / 2.;
+    }
+    if (k == 0)
+      firstDer0 = firstDer1;
+  }
+  
+  Msg::Info("-- %lf, %lf, %lf", norm(firstDer0), norm(firstDer1), dot(firstDer0, firstDer1));
+  double n = 1 / norm(firstDer0);
+  firstDer0 = firstDer0 * n;
+  n = 1 / norm(firstDer1);
+  firstDer1 = firstDer1 * n;
+  Msg::Info("--Angles : %lf, %lf, %lf", norm(firstDer0), norm(firstDer1), dot(firstDer0, firstDer1));
+  
+  double angle1 = acos(dot(firstDer0, firstDer1));
+  double angle2 = 2. * M_PI - angle1;
+  
+  double angleMesh = .0;
+  std::list<MTriangle*>::iterator it2 = setTri.begin();
+  for (; it2 != setTri.end(); it2++) {
+    MTriangle *t = *it2;
+    int k = 0;
+    while (t->getVertex(k) != v && k < 3)
+      k++;
+    if (k == 3) {
+      Msg::Warning("[meshRecombine2D] Wrong triangle, returning pi/2");
+      return M_PI / 2.;
+    }
+    angleMesh += angle3Vertices(t->getVertex((k+1)%3), v, t->getVertex((k+2)%3));
+  }
+  
+  Msg::Info("Angles : %lf, %lf, %lf", angle1, angleMesh, angle2);
+  
+  return M_PI / 2.;
+  
+  if (angleMesh < M_PI)
+    return angle1;
+  return angle2;
 }
 
-Rec2d_edge::Rec2d_edge(Rec2d_node *n0, Rec2d_node *n1)
+double Rec2d_vertex::getReward()
 {
-  _nodes[0] = n0;
-  _nodes[1] = n1;
+  if (_onWhat > -1)
+    return _Vvalues[_onWhat][_numEl-1];
+  else
+    return 1. - fabs(2. / M_PI * _angle / _numEl - 1.);
 }
-void Rec2d_edge::addCycle(Rec2d_cycle *c)
+
+double Rec2d_vertex::getReward(int n)
 {
-  _cycles.insert(c);
+  if (n == 0) return .0;
+  if (_onWhat > -1) {
+    if (n > 0)
+      return _Vbenefs[_onWhat][_numEl-1];
+    else
+      return - _Vbenefs[_onWhat][_numEl-2];
+  }
+  else
+    return fabs(2./M_PI*_angle/_numEl - 1.) - fabs(2./M_PI*_angle/(_numEl + n) - 1.);
 }
-void Rec2d_edge::print()
+
+
+TrianglesUnion::TrianglesUnion(GFace *gf,
+                               std::list<MTriangle*> &t,
+                               std::list<MEdge> &e,
+                               std::list<Rec2d_vertex*> &v,
+                               std::map<MVertex*,double*> &v2lcUV)
 {
-  Msg::Info("Edge : %d cycles", _cycles.size());
+  _numTri = t.size();
+  _numEmbEdge = e.size();
+  _numBoundVert = v.size() == 2 ? 2 : 4;
+  _numEmbVert = v.size() - _numBoundVert;
+  _globValIfExecuted = _embEdgeValue = _embVertValue = .0;
+  
+  _triangles = new MTriangle*[_numTri];
+  std::list<MTriangle*>::iterator itt = t.begin();
+  for (int k = 0; itt != t.end(); itt++, k++) {
+    _triangles[k] = *itt;
+  }
+  
+  std::list<MEdge>::iterator ite = e.begin();
+  for (; ite != e.end(); ite++) {
+    double sumlc = .0, u[2], v[2];
+    MVertex *vert[2];
+    for (int i = 0; i < 2; i++) {
+      vert[i] = (*ite).getVertex(i);
+      std::map<MVertex*,double*>::iterator itlc;
+      if ((itlc = v2lcUV.find(vert[i])) == v2lcUV.end()) {
+        double *a = new double[3];
+        gf->XYZtoUV(vert[i]->x(), vert[i]->y(), vert[i]->z(), a[1], a[2], 1.);
+        sumlc += a[0] = BGM_MeshSize(gf, a[1], a[2], vert[i]->x(), vert[i]->y(), vert[i]->z());
+        u[i] = a[1];
+        v[i] = a[2];
+        v2lcUV[vert[i]] = a;
+      }
+      else {
+        sumlc += (*itlc).second[0];
+        u[i] = (*itlc).second[1];
+        v[i] = (*itlc).second[2];
+      }
+    }
+
+    double length = _computeEdgeLength(gf, vert, u, v, 0);
+    _embEdgeValue += length / sumlc * (1 + _computeAlignment(*ite, t));
+    Msg::Info("Edge a : %lf/%lf = %lf <-> %lf", length, sumlc / 2, 2 * length / sumlc, _computeAlignment(*ite, t));
+  }
+  
+  _vertices = new Rec2d_vertex*[_numBoundVert];
+  std::list<Rec2d_vertex*>::iterator itv = v.begin();
+  for (int k = 0; itv != v.end() && k < _numBoundVert; itv++, k++) {
+    _globValIfExecuted += (*itv)->getReward(-1);
+    _vertices[k] = *itv;
+  }
+  for (_numEmbVert = 0; itv != v.end(); itv++, _numEmbVert++)
+    _embVertValue += (*itv)->getReward();
+  
+  _computation = _RECOMPUTE - 1;
+  _update();
 }
 
-void Rec2d_cycle::addEdge(Rec2d_edge *e)
+
+double TrianglesUnion::_computeEdgeLength(GFace *gf, MVertex **vert,
+                                          double *u, double *v, int n)
 {
-  _edges.insert(e);
+  double dx, dy, dz, l = .0;
+  if (n == 0) {
+    dx = vert[1]->x() - vert[0]->x();
+    dy = vert[1]->y() - vert[0]->y();
+    dz = vert[1]->z() - vert[0]->z();
+    l = sqrt(dx * dx + dy * dy + dz * dz);
+  }
+  else if (n == 1) {
+    double edgeCenter[2] ={(u[0] + u[1]) * .5, (v[0] + v[1]) * .5};
+    GPoint GP = gf->point (edgeCenter[0], edgeCenter[1]);
+    dx = vert[1]->x() - GP.x();
+    dy = vert[1]->y() - GP.y();
+    dz = vert[1]->z() - GP.z();
+    l += sqrt(dx * dx + dy * dy + dz * dz);
+    dx = vert[0]->x() - GP.x();
+    dy = vert[0]->y() - GP.y();
+    dz = vert[0]->z() - GP.z();
+    l += sqrt(dx * dx + dy * dy + dz * dz);
+  }
+  else {
+    Msg::Warning("[meshRecombine2D] edge length computation not implemented for n=%d, returning 0", n);
+    return .0;
+  }
+  return l;
 }
-void Rec2d_cycle::print()
+double TrianglesUnion::_computeAlignment(MEdge &e, std::list<MTriangle*> &lt)
 {
-  Msg::Info("Cycle : %d edges", _edges.size());
+  std::list<MTriangle*>::iterator itlt = lt.begin();
+  if (lt.size() == 2)
+    return Temporary::compute_alignment(e, *itlt, *(++itlt));
+  
+  MVertex *v0 = e.getVertex(0);
+  MVertex *v1 = e.getVertex(1);
+  MTriangle *tris[2];
+  int k = 0;
+  for (; itlt != lt.end(); itlt++) {
+    MTriangle *t = *itlt;
+    if ((t->getVertex(0) == v0 || t->getVertex(1) == v0 || t->getVertex(2) == v0) &&
+        (t->getVertex(0) == v1 || t->getVertex(1) == v1 || t->getVertex(2) == v1)   )
+      tris[k++] = t;
+  }
+  if (k < 2 || k > 2) {
+    Msg::Warning("[meshRecombine2D] error in alignment computation, returning 0");
+    return .0;
+  }
+  return Temporary::compute_alignment(e, tris[0], tris[1]);
+}
+void TrianglesUnion::_update()
+{
+  if (_computation >= _RECOMPUTE)
+    return;
+  double alpha = _ValVert - _embVertValue;
+  for (int i = 0; i < _numBoundVert; i++) {
+    alpha += _vertices[i]->getReward(-1);
+  }
+  alpha /= _NumVert - _numEmbVert;
+  double beta = (_ValEdge - _embEdgeValue) / (_NumEdge - _numEmbEdge);
+  _globValIfExecuted = alpha * beta;
+  
+  _computation = _RECOMPUTE;
+}
+bool TrianglesUnion::operator<(TrianglesUnion &other)
+{
+  _update();
+  other._update();
+  return _globValIfExecuted < other._globValIfExecuted; 
 }
 
+bool lessTriUnion::operator()(TrianglesUnion *tu1, TrianglesUnion *tu2) const
+{
+  return *tu1 < *tu2;
+}
+
+/*map tri to recomb
+//map edge to double value (constructor)
+set Recomb sorted
+function best(copy vertex*[], copy set Recomb sorted);
+
+construction :
+ - list of vertex
+ - set of recomb
+ - map tri to recomb
+ 
+destruction :
+ - vertices, recomb
+ 
+execution :
+ - take best recomb
+ - determine recomb to execute
+ - maj E N e n
+ - reduce maptrirecomb, setrecomb
+ - sort setrecomb*/