From 45f9b1ea630f6b33f322d2fa0857d47a30b7ac50 Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Thu, 19 Jul 2012 15:32:52 +0000
Subject: [PATCH] new quality criterion : it's now the average of a certain
 vertex quality. need debug

---
 Mesh/meshGFaceRecombine.cpp | 488 +++++++++++++++++++++++++++++++-----
 Mesh/meshGFaceRecombine.h   | 105 ++++----
 2 files changed, 486 insertions(+), 107 deletions(-)

diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp
index 105a4c32e8..dc2f2c873f 100644
--- a/Mesh/meshGFaceRecombine.cpp
+++ b/Mesh/meshGFaceRecombine.cpp
@@ -578,9 +578,14 @@ void Recombine2D::add(MTriangle *t)
 
 /**  Rec2DData  **/
 /*****************/
-bool Rec2DData::gterAction::operator()(Action *ra1, Action *ra2) const
+bool Rec2DData::gterAction::operator()(const Action *ra1, const Action *ra2) const
 {
-  return *((Rec2DAction*)ra2->action) < *((Rec2DAction*)ra1->action);
+  return *ra2->action < *ra1->action;
+}
+
+bool Rec2DData::lessAction::operator()(const Action *ra1, const Action *ra2) const
+{
+  return *ra1->action < *ra2->action;
 }
 
 Rec2DData::Rec2DData() : _remainingTri(0)
@@ -749,18 +754,26 @@ void Rec2DData::printState() const
   Msg::Info(" ");
   iter_re ite;
   long double valEdge = .0;
+  int numEdge = 0;
   for (ite = firstEdge(); ite != lastEdge(); ++ite) {
     valEdge += (long double)(*ite)->getWeightedQual();
+    numEdge += (*ite)->getWeight();
   }
-  Msg::Info("valEdge : %g >< %g", (double)valEdge, (double)_valEdge);
+  Msg::Info("valEdge : %g >< %g, numEdge %d >< %d (real><data)",
+            (double)valEdge, (double)_valEdge,
+            numEdge, _numEdge);
   iter_rv itv;
   long double valVert = .0;
+  int numVert = 0;
   for (itv = firstVertex(); itv != lastVertex(); ++itv) {
     valVert += (long double)(*itv)->getQual();
     if ((*itv)->getParity() == -1 || (*itv)->getParity() == 1)
       Msg::Error("parity %d, I'm very angry", (*itv)->getParity());
+    ++numVert;
   }
-  Msg::Info("valVert : %g >< %g", (double)valVert, (double)_valVert);
+  Msg::Info("valVert : %g >< %g, numVert %d >< %d (real><data)",
+            (double)valVert, (double)_valVert,
+            numVert, _numVert);
 }
 
 void Rec2DData::checkQuality() const
@@ -961,15 +974,23 @@ void Rec2DData::associateParity(int pOld, int pNew, Rec2DDataChange *rdc)
 
 double Rec2DData::getGlobalQuality()
 {
+#ifdef REC2D_VERT_ONLY
+  return (double)_cur->_valVert / (double)_cur->_numVert;
+#else
   double a = (double)_cur->_valVert / (double)_cur->_numVert;
   return a * (double)_cur->_valEdge / (double)_cur->_numEdge;
+#endif
 }
 
-double Rec2DData::getGlobalQuality(int numEdge, double valEdge,
-                                   int numVert, double valVert )
+double Rec2DData::getGlobalQuality(int numVert, double valVert,
+                                   int numEdge, double valEdge )
 {
+#ifdef REC2D_VERT_ONLY
+  return ((double)_cur->_valVert + valVert) / ((double)_cur->_numVert + numVert);
+#else
   double a = ((double)_cur->_valVert + valVert) / (double)(_cur->_numVert + numVert);
   return a * ((double)_cur->_valEdge + valEdge) / (double)(_cur->_numEdge + numEdge);
+#endif
 }
 
 Rec2DAction* Rec2DData::getBestAction()
@@ -979,7 +1000,8 @@ Rec2DAction* Rec2DData::getBestAction()
   if (_cur->_actions.size() == 0)
     return NULL;
   Action *ac = *std::max_element(_cur->_actions.begin(),
-                                 _cur->_actions.end(), gterAction());
+                                 _cur->_actions.end(), lessAction());
+  
   return (Rec2DAction*)ac->action;
 }
 
@@ -1055,7 +1077,7 @@ void Rec2DData::drawEndNode(int num)
     std::map<int, std::vector<double> > data;
     Rec2DNode *currentNode = _cur->_endNodes[i];
     Msg::Info("%d -> %g", i+1, currentNode->getGlobQual());
-    int k = 0;
+    //int k = 0;
     if ( !((i+1) % ((int)std::sqrt(num)+1)) ) {
       dx = .0;
       dy -= 1.2;
@@ -1541,12 +1563,12 @@ void Rec2DDataChange::revert()
 
 /**  Rec2DAction  **/
 /*******************/
-bool lessRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
+bool lessRec2DAction::operator()(const Rec2DAction *ra1, const Rec2DAction *ra2) const
 {
   return *ra1 < *ra2;
 }
 
-bool gterRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
+bool gterRec2DAction::operator()(const Rec2DAction *ra1, const Rec2DAction *ra2) const
 {
   return *ra2 < *ra1;
 }
@@ -1556,7 +1578,7 @@ Rec2DAction::Rec2DAction()
 {
 }
 
-bool Rec2DAction::operator<(Rec2DAction &other)
+bool Rec2DAction::operator<(const Rec2DAction &other) const
 {
   return getReward() < other.getReward();
 }
@@ -1577,10 +1599,10 @@ void Rec2DAction::removeDuplicate(std::vector<Rec2DAction*> &actions)
   }
 }
 
-double Rec2DAction::getReward()
+double Rec2DAction::getReward() const
 {
   if (_lastUpdate < Recombine2D::getNumChange())
-    _computeGlobQual();
+    ((Rec2DAction*)this)->_computeGlobQual();
   
   return _globQualIfExecuted/* - Rec2DData::getGlobalQuality()*/;
 }
@@ -1588,6 +1610,12 @@ double Rec2DAction::getReward()
 
 /**  Rec2DTwoTri2Quad  **/
 /************************/
+/*(2)---0---(0)
+ * | {0}   / |
+ * 1    4    3
+ * | /   {1} |
+ *(1)---2---(3)
+ */
 Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DElement *el0, Rec2DElement *el1)
 {
   _triangles[0] = el0;
@@ -1620,6 +1648,11 @@ Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DElement *el0, Rec2DElement *el1)
   _vertices[1] = _edges[4]->getVertex(1);
   _vertices[2] = _triangles[0]->getOtherVertex(_vertices[0], _vertices[1]);
   _vertices[3] = _triangles[1]->getOtherVertex(_vertices[0], _vertices[1]);
+  if (_vertices[0] == _edges[1]->getOtherVertex(_vertices[2])) {
+    Rec2DVertex *rv = _vertices[0];
+    _vertices[0] = _vertices[1];
+    _vertices[1] = rv;
+  }
   
   _triangles[0]->add(this);
   _triangles[1]->add(this);
@@ -1747,6 +1780,14 @@ void Rec2DTwoTri2Quad::printIdentity() const
   Msg::Info("Recombine |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
 }
 
+void Rec2DTwoTri2Quad::printVertices() const
+{
+  for (int i = 0; i < 4; ++i) {
+    Msg::Info("vert %d : %g", _vertices[i]->getNum(), _vertices[i]->getQual());
+    //_vertices[i]->printQual();
+  }
+}
+
 //void Rec2DTwoTri2Quad::print()
 //{
 //  Msg::Info("Printing Action %d |%d|%d|...", this, _triangles[0]->getNum(), _triangles[1]->getNum());
@@ -1756,45 +1797,64 @@ void Rec2DTwoTri2Quad::printIdentity() const
 //  Msg::Info("edge3 %g (%g, %g)", _edges[3]->getQual(), _edges[3]->getQualL(), _edges[3]->getQualO());
 //  Msg::Info("edge4 %g (%g, %g)", _edges[4]->getQual(), _edges[4]->getQualL(), _edges[4]->getQualO());
 //  Msg::Info("angles %g - %g", _vertices[0]->getAngle(), _vertices[1]->getAngle());
-//  Msg::Info("merge0 %g", _vertices[0]->getGainMerge(_triangles[0], _triangles[1]));
-//  Msg::Info("merge1 %g", _vertices[1]->getGainMerge(_triangles[0], _triangles[1]));
+//  Msg::Info("merge0 %g", _vertices[0]->getGainRecomb(_triangles[0], _triangles[1]));
+//  Msg::Info("merge1 %g", _vertices[1]->getGainRecomb(_triangles[0], _triangles[1]));
 //  //_vertices[0]->printGainMerge(_triangles[0], _triangles[1]);
 //  //_vertices[1]->printGainMerge(_triangles[0], _triangles[1]);
 //}
 
 void Rec2DTwoTri2Quad::printReward() const
 {
+#ifdef REC2D_VERT_ONLY
+  Msg::Info("reward rec : %g  %g  %g  %g",
+            _vertices[0]->getGainRecomb(_triangles[0], _triangles[1], _edges[4], _edges[0], _edges[3]),
+            _vertices[1]->getGainRecomb(_triangles[0], _triangles[1], _edges[4], _edges[1], _edges[2]),
+            _vertices[2]->getGainQuad(_triangles[0], _edges[0], _edges[1]),
+            _vertices[3]->getGainQuad(_triangles[1], _edges[2], _edges[3]));
+#else
   double valEdge1 = _edges[4]->getQual();
   double valEdge2 = 0;
   for (int i = 0; i < 4; ++i)
     valEdge2 += _edges[i]->getQual();
   
   double valVert;
-  valVert = _vertices[0]->getGainMerge(_triangles[0], _triangles[1]);
-  valVert += _vertices[1]->getGainMerge(_triangles[0], _triangles[1]);
+  valVert = _vertices[0]->getGainRecomb(_triangles[0], _triangles[1]);
+  valVert += _vertices[1]->getGainRecomb(_triangles[0], _triangles[1]);
   Msg::Info("-%de%g +%de%g +0v%g -> %g", REC2D_EDGE_BASE, valEdge1, 4 * REC2D_EDGE_QUAD,
             valEdge2/4, valVert/2,
-            Rec2DData::getGlobalQuality(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE,
-                                -REC2D_EDGE_BASE*valEdge1
-                                +REC2D_EDGE_QUAD*valEdge2 , 0, valVert));
+            Rec2DData::getGlobalQuality(0, valVert,
+                          4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE,
+                          -REC2D_EDGE_BASE*valEdge1+REC2D_EDGE_QUAD*valEdge2));
+#endif
 }
 
 void Rec2DTwoTri2Quad::_computeGlobQual()
 {
+#ifdef REC2D_VERT_ONLY
+  _valVert = .0;
+  _valVert += _vertices[0]->getGainRecomb(_triangles[0], _triangles[1],
+                                          _edges[4], _edges[0], _edges[3]);
+  _valVert += _vertices[1]->getGainRecomb(_triangles[0], _triangles[1],
+                                          _edges[4], _edges[1], _edges[2]);
+  _valVert += _vertices[2]->getGainQuad(_triangles[0], _edges[0], _edges[1]);
+  _valVert += _vertices[3]->getGainQuad(_triangles[1], _edges[2], _edges[3]);
+  
+  _globQualIfExecuted = Rec2DData::getGlobalQuality(0, _valVert);
+#else
   double valEdge = -REC2D_EDGE_BASE * _edges[4]->getQual();
   for (int i = 0; i < 4; ++i)
     valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual();
   
   if (_vertices[0]->getLastUpdate() > _lastUpdate ||
       _vertices[1]->getLastUpdate() > _lastUpdate   ) {
-    _valVert = _vertices[0]->getGainMerge(_triangles[0], _triangles[1]);
-    _valVert += _vertices[1]->getGainMerge(_triangles[0], _triangles[1]);
+    _valVert = _vertices[0]->getGainRecomb(_triangles[0], _triangles[1]);
+    _valVert += _vertices[1]->getGainRecomb(_triangles[0], _triangles[1]);
   }
   
   _globQualIfExecuted =
-    Rec2DData::getGlobalQuality(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE,
-                                valEdge, 0, _valVert                );
-  
+    Rec2DData::getGlobalQuality(0, _valVert,
+                                4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE, valEdge);
+#endif
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -2082,6 +2142,69 @@ void Rec2DCollapse::reveal()
 
 void Rec2DCollapse::printReward() const
 {
+#ifdef REC2D_VERT_ONLY
+  SPoint2 p[2];
+  _rec->_vertices[0]->getParam(&p[0]);
+  _rec->_vertices[1]->getParam(&p[1]);
+  int b0 = _rec->_vertices[0]->getOnBoundary();
+  int b1 = _rec->_vertices[1]->getOnBoundary();
+  
+  double valVert = .0;
+  if (b0 || b1) {
+    int iOK = 1, iKO = 0;
+    if (b0) {
+      iOK = 0;
+      iKO = 1;
+    }
+    double oldValVert = Rec2DData::getSumVert();
+    _rec->_vertices[iKO]->relocate(p[iOK]);
+    double qualRelocation = Rec2DData::getSumVert() - oldValVert;
+    
+    valVert += _rec->_vertices[iOK]->getGainMerge(_rec->_vertices[iKO],
+                                                  &_rec->_edges[1], 2  );
+    valVert += _rec->_vertices[2]->getGainTriLess(_rec->_edges[1]);
+    valVert += _rec->_vertices[3]->getGainTriLess(_rec->_edges[2]);
+    
+    for (int i = 0; i < 4; ++i) {
+      Msg::Info("vert %d : %g", _rec->_vertices[i]->getNum(), _rec->_vertices[i]->getQual());
+    }
+    
+    Msg::Info("qual col %g %g %g %g", qualRelocation,
+              _rec->_vertices[iOK]->getGainMerge(_rec->_vertices[iKO], &_rec->_edges[1], 2),
+              _rec->_vertices[2]->getGainTriLess(_rec->_edges[1]),
+              _rec->_vertices[3]->getGainTriLess(_rec->_edges[2])
+             );
+    
+    _rec->_vertices[iKO]->relocate(p[iKO]);
+  }
+  else {
+    double u = (_rec->_vertices[0]->u() + _rec->_vertices[1]->u()) / 2;
+    double v = (_rec->_vertices[0]->v() + _rec->_vertices[1]->v()) / 2;
+    SPoint2 pNew(u, v);
+    double oldValVert = Rec2DData::getSumVert();
+    _rec->_vertices[0]->relocate(pNew);
+    _rec->_vertices[1]->relocate(pNew);
+    double qualRelocation = Rec2DData::getSumVert() - oldValVert;
+    
+    valVert += _rec->_vertices[0]->getGainMerge(_rec->_vertices[1],
+                                                &_rec->_edges[1], 2);
+    valVert += _rec->_vertices[2]->getGainTriLess(_rec->_edges[0]);
+    valVert += _rec->_vertices[3]->getGainTriLess(_rec->_edges[2]);
+    
+    for (int i = 0; i < 4; ++i) {
+      Msg::Info("vert %d : %g", _rec->_vertices[i]->getNum(), _rec->_vertices[i]->getQual());
+    }
+    
+    Msg::Info("qual col %g %g %g %g", qualRelocation,
+              _rec->_vertices[0]->getGainMerge(_rec->_vertices[1], &_rec->_edges[1], 2),
+              _rec->_vertices[2]->getGainTriLess(_rec->_edges[1]),
+              _rec->_vertices[3]->getGainTriLess(_rec->_edges[2])
+             );
+    
+    _rec->_vertices[0]->relocate(p[0]);
+    _rec->_vertices[1]->relocate(p[1]);
+  }
+#else
   std::vector<Rec2DVertex*> verts;
   std::vector<Rec2DEdge*> edges;
   _rec->_vertices[0]->getEdges(edges);
@@ -2161,6 +2284,7 @@ void Rec2DCollapse::printReward() const
                                            numEdgeAft, weightEdgeAft, valEdgeAft/weightEdgeAft,
                                            vert01Bef/4, vert01Aft/2, (vert23Aft-vert23Bef)/2,
                                            numVertOther, vertOtherAft-vertOtherBef);
+#endif
 }
 
 void Rec2DCollapse::_computeGlobQual()
@@ -2181,18 +2305,49 @@ void Rec2DCollapse::_computeGlobQual()
   int b0 = _rec->_vertices[0]->getOnBoundary();
   int b1 = _rec->_vertices[1]->getOnBoundary();
   
+#ifdef REC2D_VERT_ONLY
+  double valVert = .0;
+  if (b0 || b1) {
+    int iOK = 1, iKO = 0;
+    if (b0) {
+      iOK = 0;
+      iKO = 1;
+    }
+    _rec->_vertices[iKO]->relocate(p[iOK]);
+    
+    valVert += _rec->_vertices[iOK]->getGainMerge(_rec->_vertices[iKO],
+                                                  &_rec->_edges[1], 2  );
+    valVert += _rec->_vertices[2]->getGainTriLess(_rec->_edges[1]);
+    valVert += _rec->_vertices[3]->getGainTriLess(_rec->_edges[2]);
+    _globQualIfExecuted = Rec2DData::getGlobalQuality(-1, valVert);
+    
+    _rec->_vertices[iKO]->relocate(p[iKO]);
+  }
+  else {
+    double u = (_rec->_vertices[0]->u() + _rec->_vertices[1]->u()) / 2;
+    double v = (_rec->_vertices[0]->v() + _rec->_vertices[1]->v()) / 2;
+    SPoint2 pNew(u, v);
+    _rec->_vertices[0]->relocate(pNew);
+    _rec->_vertices[1]->relocate(pNew);
+    
+    valVert += _rec->_vertices[0]->getGainMerge(_rec->_vertices[1],
+                                                &_rec->_edges[1], 2);
+    valVert += _rec->_vertices[2]->getGainTriLess(_rec->_edges[0]);
+    valVert += _rec->_vertices[3]->getGainTriLess(_rec->_edges[2]);
+    _globQualIfExecuted = Rec2DData::getGlobalQuality(-1, valVert);
+    
+    _rec->_vertices[0]->relocate(p[0]);
+    _rec->_vertices[1]->relocate(p[1]);
+  }
+#else
   int numEdge = 0;
   double valEdge = .0, valVert = .0;
   if (b0 || b1) {
-    int iOK, iKO;
+    int iOK = 1, iKO = 0;
     if (b0) {
       iOK = 0;
       iKO = 1;
     }
-    else {
-      iOK = 1;
-      iKO = 0;
-    }
     _rec->_vertices[iKO]->relocate(p[iOK]);
     
     valVert += _rec->_vertices[2]->getGainOneElemLess();
@@ -2204,8 +2359,8 @@ void Rec2DCollapse::_computeGlobQual()
     valEdge -= _rec->_edges[4]->getWeightedQual();
     numEdge -= _rec->_edges[4]->getWeight();
     
-    _globQualIfExecuted = Rec2DData::getGlobalQuality(numEdge, valEdge,
-                                                      -REC2D_NUMB_VERT, valVert);
+    _globQualIfExecuted = Rec2DData::getGlobalQuality(-1, valVert,
+                                                      numEdge, valEdge);
     
     _rec->_vertices[iKO]->relocate(p[iKO]);
   }
@@ -2225,13 +2380,13 @@ void Rec2DCollapse::_computeGlobQual()
     valEdge -= _rec->_edges[4]->getWeightedQual();
     numEdge -= _rec->_edges[4]->getWeight();
     
-    _globQualIfExecuted = Rec2DData::getGlobalQuality(numEdge, valEdge,
-                                                      -REC2D_NUMB_VERT, valVert);
+    _globQualIfExecuted = Rec2DData::getGlobalQuality(-1, valVert,
+                                                      numEdge, valEdge);
     
     _rec->_vertices[0]->relocate(p[0]);
     _rec->_vertices[1]->relocate(p[1]);
   }
-  
+#endif
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -2439,7 +2594,7 @@ void Rec2DEdge::hide()
   _rv0->rmv(this);
   _rv1->rmv(this);
   Rec2DData::rmv(this);
-  Rec2DData::addEdge(-_weight, -getWeightedQual());
+  Rec2DData::addEdgeQual(-getWeightedQual(), -_weight);
 }
 
 void Rec2DEdge::reveal()
@@ -2447,7 +2602,7 @@ void Rec2DEdge::reveal()
   _rv0->add(this);
   _rv1->add(this);
   Rec2DData::add(this);
-  Rec2DData::addEdge(_weight, getWeightedQual());
+  Rec2DData::addEdgeQual(getWeightedQual(), _weight);
 }
 
 bool Rec2DEdge::checkCoherence() const
@@ -2474,7 +2629,13 @@ void Rec2DEdge::_computeQual()
   double adimLength = _straightAdimLength();
   if (adimLength > 1)
     adimLength = 1./adimLength;
-  _qual = adimLength * ((double)(1-REC2D_ALIGNMENT) + (double)REC2D_ALIGNMENT * alignment);
+#ifdef REC2D_VERT_ONLY
+  _qual = REC2D_COEF_ORIE * alignment +
+          REC2D_COEF_LENG * adimLength +
+          REC2D_COEF_ORLE * alignment * adimLength;
+#else
+  _qual = adimLength * (1 - REC2D_ALIGNMENT + REC2D_ALIGNMENT * alignment);
+#endif
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -2508,14 +2669,24 @@ void Rec2DEdge::_addWeight(int w)
   if (_weight < REC2D_EDGE_BASE)
     Msg::Error("[Rec2DEdge] Weight too low : %d (%d min)",
                _weight, REC2D_EDGE_BASE                   );
-  Rec2DData::addEdge(w, (double)w*getQual());
+#ifdef REC2D_VERT_ONLY
+  _rv0->addEdgeQual(w*getQual(), w);
+  _rv1->addEdgeQual(w*getQual(), w);
+#else
+  Rec2DData::addEdgeQual(w*getQual(), w);
+#endif
 }
 
 void Rec2DEdge::updateQual()
 {
   double oldQual = _qual;
   _computeQual();
-  Rec2DData::addValEdge(_weight*(_qual-oldQual));
+#ifdef REC2D_VERT_ONLY
+  _rv0->addEdgeQual(_weight*(_qual-oldQual));
+  _rv1->addEdgeQual(_weight*(_qual-oldQual));
+#else
+  Rec2DData::addEdgeQual(_weight*(_qual-oldQual));
+#endif
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -2659,6 +2830,9 @@ void Rec2DEdge::getActions(std::vector<Rec2DAction*> &actions) const
 Rec2DVertex::Rec2DVertex(MVertex *v)
 : _v(v), _angle(4.*M_PI), _onWhat(1), _parity(0),
   _lastUpdate(-1), _sumQualAngle(.0), _pos(-1)
+#ifdef REC2D_VERT_ONLY
+  , _sumQualEdge(.0), _sumEdge(0), _sumAngle(0)
+#endif
 {
   reparamMeshVertexOnFace(_v, Recombine2D::getGFace(), _param);
   Rec2DData::add(this);
@@ -2674,6 +2848,10 @@ Rec2DVertex::Rec2DVertex(Rec2DVertex *rv, double ang)
   _lastUpdate(rv->_lastUpdate),
   _sumQualAngle(rv->_sumQualAngle), _edges(rv->_edges),
   _elements(rv->_elements), _param(rv->_param), _pos(-1)
+#ifdef REC2D_VERT_ONLY
+  , _sumQualEdge(rv->_sumQualEdge), _sumEdge(rv->_sumEdge),
+  _sumAngle(rv->_sumAngle)
+#endif
 {
   static int a = -1;
   if (++a < -1) Msg::Warning("FIXME Edges really necessary ?");
@@ -2702,7 +2880,7 @@ void Rec2DVertex::hide()
   
   Rec2DData::rmv(this);
   if  (_elements.size())
-    Rec2DData::addVert(-REC2D_NUMB_VERT, -getQual());
+    Rec2DData::addVertQual(-getQual(), -1);
 }
 
 void Rec2DVertex::reveal()
@@ -2712,7 +2890,7 @@ void Rec2DVertex::reveal()
   
   Rec2DData::add(this);
   if  (_elements.size())
-    Rec2DData::addVert(REC2D_NUMB_VERT, getQual());
+    Rec2DData::addVertQual(getQual(), 1);
 }
 
 bool Rec2DVertex::checkCoherence() const
@@ -2745,9 +2923,9 @@ void Rec2DVertex::initStaticTable()
     _qualVSnum[0][0] = -10.;
     _qualVSnum[1][0] = -10.;
     for (int i = 1; i < nE; ++i)
-      _qualVSnum[0][i] = 1. - fabs(2./(double)i - 1.);
+      _qualVSnum[0][i] = 1. - fabs(2./i - 1.);
     for (int i = 1; i < nF; ++i)
-      _qualVSnum[1][i] = 1. - fabs(4./(double)i - 1.);
+      _qualVSnum[1][i] = std::max(1. - fabs(4./i - 1.), .0);
       
     _gains = new double*[2];
     _gains[0] = new double[nE-1];
@@ -2832,9 +3010,9 @@ bool Rec2DVertex::_recursiveBoundParity(const Rec2DVertex *prevRV, int p0, int p
 void Rec2DVertex::setOnBoundary()
 {
   if (_onWhat > 0) {
-    Rec2DData::addValVert(-getQual());
+    double oldQual = getQual();
     _onWhat = 0;
-    Rec2DData::addValVert(getQual());
+    Rec2DData::addVertQual(getQual()-oldQual);
     _lastUpdate = Recombine2D::getNumChange();
   }
 }
@@ -2887,11 +3065,21 @@ void Rec2DVertex::relocate(SPoint2 p)
 
 void Rec2DVertex::_updateQualAngle()
 {
-  double oldQualAngle = _getQualAngle();
+  double oldQual = getQual();
   _sumQualAngle = .0;
-  for (unsigned int i = 0; i < _elements.size(); ++i)
+#ifdef REC2D_VERT_ONLY
+  _sumAngle = 0;
+#endif
+  for (unsigned int i = 0; i < _elements.size(); ++i) {
+#ifdef REC2D_VERT_ONLY
+    int n = _elements[i]->getAngleNb();
+    _sumAngle += n;
+    _sumQualAngle += n * _angle2Qual(_elements[i]->getAngle(this));
+#else
     _sumQualAngle += _angle2Qual(_elements[i]->getAngle(this));
-  Rec2DData::addValVert(_getQualAngle()-oldQualAngle);
+#endif
+  }
+  Rec2DData::addVertQual(getQual()-oldQual);
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -2938,8 +3126,61 @@ double Rec2DVertex::getQualDegree(int numEl) const
     Msg::Error("[Rec2DVertex] I don't want this anymore !");
     return -10.;
   }
-  return 1. - fabs(2./M_PI * _angle/(double)nEl - 1.);
+  return std::max(1. - fabs(2./M_PI * _angle/(double)nEl - 1.), .0);
+}
+
+#ifdef REC2D_VERT_ONLY
+double Rec2DVertex::getQual() const
+{
+  double qual = getQualDegree();
+  qual =   (REC2D_COEF_ANGL + REC2D_COEF_ANDE*qual) * _sumQualAngle/_sumAngle
+         + REC2D_COEF_DEGR * qual                                            ;
+  return qual;// * _sumQualEdge / _sumEdge;
+}
+
+void Rec2DVertex::printQual() const
+{
+  Msg::Info("d:%g, a:%g, e:%g (sa:%d, se:%d)",
+            getQualDegree(), _sumQualAngle/_sumAngle, _sumQualEdge / _sumEdge,
+            _sumAngle, _sumEdge);
+}
+
+double Rec2DVertex::getQual(int numAngl, double valAngl,
+                            int numEdge, double valEdge, int numElem) const
+{
+  double qual = getQualDegree(numElem);
+  qual =   (REC2D_COEF_ANGL + REC2D_COEF_ANDE*qual) * valAngl / numAngl
+         + REC2D_COEF_DEGR * qual                                      ;
+  return qual;// * valEdge / numEdge;
+}
+
+void Rec2DVertex::addEdgeQual(double val, int num)
+{
+  double oldQual = getQual();
+  _sumQualEdge += val;
+  _sumEdge += num;
+  if (_elements.size())
+    Rec2DData::addVertQual(getQual()-oldQual);
+  _lastUpdate = Recombine2D::getNumChange();
+}
+
+double Rec2DVertex::getGainQuad(const Rec2DElement *rel,
+                                const Rec2DEdge *re0,
+                                const Rec2DEdge *re1    ) const
+{
+  double qualAngle = _sumQualAngle
+                     + (REC2D_VERT_QUAD - REC2D_VERT_TRIA)
+                       * _angle2Qual(rel->getAngle(this)) ;
+  int sumAngle = _sumAngle + REC2D_VERT_QUAD - REC2D_VERT_TRIA;
+  double qualEdge = _sumQualEdge
+                    + REC2D_EDGE_QUAD * re0->getQual()
+                    + REC2D_EDGE_QUAD * re1->getQual();
+  int sumEdge = _sumEdge + 2 * REC2D_EDGE_QUAD;
+  
+  return getQual(sumAngle, qualAngle, sumEdge, qualEdge,
+                 (int)_elements.size()                  ) - getQual();
 }
+#endif
 
 double Rec2DVertex::getGainDegree(int n) const
 {
@@ -2977,16 +3218,103 @@ double Rec2DVertex::getGainDegree(int n) const
          - fabs(2./M_PI * _angle/(double)(_elements.size() + n) - 1.);
 }
 
-double Rec2DVertex::getGainMerge(const Rec2DElement *rel1,
-                                 const Rec2DElement *rel2 ) const
+#ifdef REC2D_VERT_ONLY
+double Rec2DVertex::getGainRecomb(const Rec2DElement *rel1,
+                                  const Rec2DElement *rel2,
+                                  const Rec2DEdge *re0,
+                                  const Rec2DEdge *re1,
+                                  const Rec2DEdge *re2     ) const
+{
+  double qualAngle = _sumQualAngle, qualEdge = _sumQualEdge;
+  int sumAngle = _sumAngle, sumEdge = _sumEdge;
+  
+  qualAngle -= REC2D_VERT_TRIA * _angle2Qual(rel1->getAngle(this));
+  qualAngle -= REC2D_VERT_TRIA * _angle2Qual(rel2->getAngle(this));
+  qualAngle += REC2D_VERT_QUAD * (_angle2Qual(rel1->getAngle(this) +
+                                              rel2->getAngle(this)  ));
+  sumAngle += REC2D_VERT_QUAD - 2 * REC2D_VERT_TRIA;
+  qualEdge -= re0->getWeightedQual();
+  qualEdge += REC2D_EDGE_QUAD * re1->getQual();
+  qualEdge += REC2D_EDGE_QUAD * re2->getQual();
+  sumEdge += 2 * REC2D_EDGE_QUAD - REC2D_EDGE_BASE;
+  
+  return getQual(sumAngle, qualAngle, sumEdge, qualEdge,
+                 (int)_elements.size()-1                ) - getQual();
+}
+
+double Rec2DVertex::getGainTriLess(const Rec2DEdge *re) const
+{
+  return getQual(_sumAngle - REC2D_VERT_TRIA, _sumQualAngle,
+                 _sumEdge - REC2D_EDGE_BASE, _sumQualEdge - re->getQual(),
+                 (int)_elements.size() - 1)
+         - getQual();
+}
+
+double Rec2DVertex::getGainMerge(const Rec2DVertex *rv,
+                                 const Rec2DEdge *const*edges, int nEdges) const
+{
+  int sumAngle = 0;
+  double sumQualAngle = .0;
+  int *numAngle = new int[_elements.size()];
+  double *qualAngle = new double[_elements.size()];
+  for (unsigned int i = 0; i < _elements.size(); ++i) {
+    int n = _elements[i]->getAngleNb();
+    numAngle[i] = n;
+    qualAngle[i] = n * _angle2Qual(_elements[i]->getAngle(this));
+  }
+  for (unsigned int i = 0; i < rv->_elements.size(); ++i) {
+    unsigned int j = 0;
+    while (j < _elements.size() && _elements[j] != rv->_elements[i]) ++j;
+    if (j >= _elements.size()) {
+      int n = rv->_elements[i]->getAngleNb();
+      sumAngle += n;
+      sumQualAngle += n * _angle2Qual(rv->_elements[i]->getAngle(rv));
+    }
+    else {
+      numAngle[j] = 0;
+      qualAngle[j] = .0;
+    }
+  }
+  for (unsigned int i = 0; i < _elements.size(); ++i) {
+    sumAngle += numAngle[i];
+    sumQualAngle += qualAngle[i];
+  }
+  int numElem = _elements.size() + rv->_elements.size() - 4;
+  
+  int sumEdge = 0;
+  double sumQualEdge = .0;
+  for (unsigned int i = 0; i < _edges.size(); ++i) {
+    sumEdge += _edges[i]->getWeight();
+    sumQualEdge += _edges[i]->getWeightedQual();
+  }
+  for (unsigned int i = 0; i < rv->_edges.size(); ++i) {
+    sumEdge += rv->_edges[i]->getWeight();
+    sumQualEdge += rv->_edges[i]->getWeightedQual();
+  }
+  for (int i = 0; i < nEdges; ++i) {
+    sumEdge -= REC2D_EDGE_BASE;
+    sumQualEdge -= REC2D_EDGE_BASE * edges[i]->getQual();
+  }
+  
+  return Rec2DVertex::getQual(sumAngle, sumQualAngle,
+                              sumEdge, sumQualEdge, numElem)
+         - getQual() - rv->getQual()                        ;
+}
+#else
+double Rec2DVertex::getGainRecomb(const Rec2DElement *rel1,
+                                  const Rec2DElement *rel2 ) const
 {
   double qualAngle = _sumQualAngle;
   qualAngle -= _angle2Qual(rel1->getAngle(this));
   qualAngle -= _angle2Qual(rel2->getAngle(this));
   qualAngle += _angle2Qual(rel1->getAngle(this) + rel2->getAngle(this));
   
-  return qualAngle / (double)(_elements.size()-1) - getQualAngle()
-         + getGainDegree(-1);
+  return qualAngle / (_elements.size()-1) - getQualAngle() + getGainDegree(-1);
+}
+
+double Rec2DVertex::getGainOneElemLess() const
+{
+  return getGainDegree(-1) + _sumQualAngle / (_elements.size()-1) - getQualAngle();
 }
 
 double Rec2DVertex::getGainMerge(const Rec2DVertex *rv) const
@@ -3013,11 +3341,7 @@ double Rec2DVertex::getGainMerge(const Rec2DVertex *rv) const
   ans += getQualDegree(numElem) + sumQualAngle / numElem;
   return ans;
 }
-
-double Rec2DVertex::getGainOneElemLess() const
-{
-  return getGainDegree(-1) + _sumQualAngle/(_elements.size()-1) - getQualAngle();
-}
+#endif
 
 void Rec2DVertex::add(const Rec2DEdge *re)
 {
@@ -3027,7 +3351,17 @@ void Rec2DVertex::add(const Rec2DEdge *re)
       return;
     }
   }
+#ifdef REC2D_VERT_ONLY
+  double oldQual = getQual();
+#endif
   _edges.push_back((Rec2DEdge*)re);
+#ifdef REC2D_VERT_ONLY
+  _sumQualEdge += re->getWeightedQual();
+  _sumEdge += re->getWeight();
+  if (_elements.size())
+    Rec2DData::addVertQual(getQual()-oldQual);
+  _lastUpdate = Recombine2D::getNumChange();
+#endif
 }
 
 bool Rec2DVertex::has(const Rec2DEdge *re) const
@@ -3044,8 +3378,18 @@ void Rec2DVertex::rmv(const Rec2DEdge *re)
   unsigned int i = 0;
   while (i < _edges.size()) {
     if (_edges[i] == re) {
+#ifdef REC2D_VERT_ONLY
+      double oldQual = getQual();
+#endif
       _edges[i] = _edges.back();
       _edges.pop_back();
+#ifdef REC2D_VERT_ONLY
+      _sumQualEdge -= re->getWeightedQual();
+      _sumEdge -= re->getWeight();
+      if (_elements.size())
+        Rec2DData::addVertQual(getQual()-oldQual);
+      _lastUpdate = Recombine2D::getNumChange();
+#endif
       return;
     }
     ++i;
@@ -3061,12 +3405,21 @@ void Rec2DVertex::add(const Rec2DElement *rel)
       return;
     }
   }
+  double oldQual = .0;
   if (_elements.size())
-    Rec2DData::addVert(-REC2D_NUMB_VERT, -getQual());
+    oldQual = getQual();
   
   _elements.push_back((Rec2DElement*)rel);
+#ifdef REC2D_VERT_ONLY
+  _sumAngle += rel->getAngleNb();
+  _sumQualAngle += rel->getAngleNb() * _angle2Qual(rel->getAngle(this));
+#else
   _sumQualAngle += _angle2Qual(rel->getAngle(this));
-  Rec2DData::addVert(REC2D_NUMB_VERT, getQual());
+#endif
+  if (_elements.size() == 1)
+    Rec2DData::addVertQual(getQual(), 1);
+  else
+    Rec2DData::addVertQual(getQual()-oldQual);
   _lastUpdate = Recombine2D::getNumChange();
 }
 
@@ -3084,13 +3437,21 @@ void Rec2DVertex::rmv(const Rec2DElement *rel)
   unsigned int i = 0;
   while (i < _elements.size()) {
     if (_elements[i] == rel) {
-      Rec2DData::addVert(-REC2D_NUMB_VERT, -getQual());
+      double oldQual = getQual();
+#ifdef REC2D_VERT_ONLY
+      double n = _elements[i]->getAngleNb();
+      _sumAngle -= n;
+      _sumQualAngle -= n * _angle2Qual(_elements[i]->getAngle(this));
+#else
       _sumQualAngle -= _angle2Qual(_elements[i]->getAngle(this));
+#endif
       _elements[i] = _elements.back();
       _elements.pop_back();
       
       if (_elements.size())
-        Rec2DData::addVert(REC2D_NUMB_VERT, getQual());
+        Rec2DData::addVertQual(getQual()-oldQual);
+      else
+        Rec2DData::addVertQual(-oldQual, -1);
       _lastUpdate = Recombine2D::getNumChange();
       return;
     }
@@ -3694,7 +4055,6 @@ Rec2DNode::Rec2DNode(Rec2DNode *father, Rec2DAction *ra,
     }
     else {
       for (unsigned int i = 0; i < actions.size(); ++i) {
-        
         if (depth < 0 && depth > -7) {
           Msg::Info("| %d %d/%d", -depth, i+1, actions.size());
         }
diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h
index f91c87327e..6ec9d2ee85 100644
--- a/Mesh/meshGFaceRecombine.h
+++ b/Mesh/meshGFaceRecombine.h
@@ -10,11 +10,19 @@
 #ifndef _MESH_GFACE_RECOMBINE_H_
 #define _MESH_GFACE_RECOMBINE_H_
 
+#define REC2D_VERT_ONLY
+#define REC2D_ALIGNMENT .5
 #define REC2D_EDGE_BASE 2
 #define REC2D_EDGE_QUAD 1
-#define REC2D_NUMB_VERT 1
-#define REC2D_ALIGNMENT .5
+#define REC2D_VERT_TRIA 1
+#define REC2D_VERT_QUAD 2
 #define REC2D_NUMB_SONS 6
+#define REC2D_COEF_ANGL .5
+#define REC2D_COEF_DEGR .5
+#define REC2D_COEF_ANDE .0 //(1. - REC2D_COEF_ANGL - REC2D_COEF_DEGR)
+#define REC2D_COEF_ORIE .0
+#define REC2D_COEF_LENG .5
+#define REC2D_COEF_ORLE .5 //(1. - REC2D_COEF_ORIE - REC2D_COEF_LENG)
 
 #include "GFace.h"
 #include "BackgroundMesh.h"
@@ -31,10 +39,10 @@ class Rec2DData;
 class Rec2DDataChange;
 class Rec2DCollapse;
 struct lessRec2DAction {
-  bool operator()(Rec2DAction*, Rec2DAction*) const;
+  bool operator()(const Rec2DAction*, const Rec2DAction*) const;
 };
 struct gterRec2DAction {
-  bool operator()(Rec2DAction*, Rec2DAction*) const;
+  bool operator()(const Rec2DAction*, const Rec2DAction*) const;
 };
 
 struct lessRec2DNode {
@@ -100,7 +108,10 @@ class Rec2DData {
     };
     template<class T> friend void std::swap(T&, T&);
     struct gterAction {
-      bool operator()(Action*, Action*) const;
+      bool operator()(const Action*, const Action*) const;
+    };
+    struct lessAction {
+      bool operator()(const Action*, const Action*) const;
     };
     
   private :
@@ -149,23 +160,17 @@ class Rec2DData {
     void checkQuality() const;
     
     static double getGlobalQuality();
-    static double getGlobalQuality(int numEdge, double valEdge,
-                                 int numVert, double valVert   );
-    static inline void addVert(int num, double val) {
+    static double getSumVert() {return _cur->_valVert;}
+    static double getGlobalQuality(int numVert, double valVert,
+                                   int numEdge = 0, double valEdge = .0);
+    static inline void addVertQual(double val, int num = 0) {
       _cur->_numVert += num;
       _cur->_valVert += (long double)val;
     }
-    static inline void addValVert(double val) {
-      _cur->_valVert += (long double)val;
-    }
-    static inline void addEdge(int num, double val) {
+    static inline void addEdgeQual(double val, int num = 0) {
       _cur->_numEdge += num;
       _cur->_valEdge += (long double)val;
     }
-    static inline void addValEdge(double val) {
-      _cur->_valEdge += (long double)val;
-    }
-    
     static inline int getNumEdge() {return _cur->_numEdge;}
     static inline double getValEdge() {return (double)_cur->_valEdge;}
     static inline int getNumVert() {return _cur->_numVert;}
@@ -312,8 +317,8 @@ class Rec2DAction {
     virtual void reveal() = 0;
     virtual bool checkCoherence() const = 0;
     
-    bool operator<(Rec2DAction&);
-    double getReward();
+    bool operator<(const Rec2DAction&) const;
+    double getReward() const;
     inline void *getDataAction() const {return _dataAction;}
     virtual void color(int, int, int) const = 0;
     virtual void apply(std::vector<Rec2DVertex*> &newPar) = 0;
@@ -337,6 +342,7 @@ class Rec2DAction {
     virtual void swap(Rec2DEdge*, Rec2DEdge*) = 0;
     virtual void printAdress() = 0;
     virtual void printReward() const = 0;
+    virtual void printVertices() const = 0;
     inline void addPointing() {++_numPointing;}
     inline void rmvPointing() {--_numPointing;}
     inline bool getPointing() {return _numPointing;}
@@ -386,6 +392,7 @@ class Rec2DTwoTri2Quad : public Rec2DAction {
     virtual void swap(Rec2DEdge*, Rec2DEdge*);
     virtual void printAdress() {Msg::Info(" %d", this);}
     virtual void printReward() const;
+    virtual void printVertices() const;
     virtual void printIdentity() const;
     
   private :
@@ -408,9 +415,7 @@ class Rec2DCollapse : public Rec2DAction {
     virtual void reveal();
     virtual bool checkCoherence() const {return _rec->checkCoherence();}
     
-    virtual void color(int c1, int c2, int c3) const {
-      _rec->color(c1, c2, c3);
-    }
+    virtual void color(int c1, int c2, int c3) const {_rec->color(c1, c2, c3);}
     virtual void apply(std::vector<Rec2DVertex*> &newPar);
     virtual void apply(Rec2DDataChange*, std::vector<Rec2DAction*>*&) const;
     
@@ -428,9 +433,7 @@ class Rec2DCollapse : public Rec2DAction {
                                       Rec2DElement*                ) const;
     virtual void getNeighbElemWithActions(std::vector<Rec2DElement*> &vec,
                                           Rec2DElement *rel               ) const;
-    virtual int getNum(double shiftx, double shifty) {
-      return -1;
-    }
+    virtual int getNum(double shiftx, double shifty) {return -1;}
     virtual inline Rec2DElement* getRandomElement() const {
       return _rec->getRandomElement();
     }
@@ -442,6 +445,7 @@ class Rec2DCollapse : public Rec2DAction {
     inline virtual void swap(Rec2DEdge *re0, Rec2DEdge *re1) {_rec->swap(re0, re1);}
     virtual void printAdress() {_rec->printAdress();}
     virtual void printReward() const;
+    virtual void printVertices() const {_rec->printVertices();}
     virtual void printIdentity() const;
     
   private :
@@ -512,8 +516,12 @@ class Rec2DVertex {
     std::vector<Rec2DEdge*> _edges;
     std::vector<Rec2DElement*> _elements;
     SPoint2 _param;
-    
     int _pos;
+#ifdef REC2D_VERT_ONLY
+    double _sumQualEdge;
+    int _sumEdge, _sumAngle;
+#endif
+    
     friend void Rec2DData::add(const Rec2DVertex*);
     friend void Rec2DData::rmv(const Rec2DVertex*);
     
@@ -529,14 +537,31 @@ class Rec2DVertex {
     bool checkCoherence() const;
     
     inline int getNum() const {return _v->getNum();}
-    inline double getAngle() const {return _angle;}
-    inline double getQual() const {return getQualDegree() + getQualAngle();}
+    inline double getGeomAngle() const {return _angle;}
+#ifndef REC2D_VERT_ONLY
     inline double getQualAngle() const {return _sumQualAngle/_elements.size();}
+#endif
     double getQualDegree(int numEl = -1) const;
     double getGainDegree(int) const;
-    double getGainMerge(const Rec2DElement*, const Rec2DElement*) const;
-    double getGainMerge(const Rec2DVertex*) const;
+#ifdef REC2D_VERT_ONLY
+    double getQual() const;
+    void printQual() const;
+    double getQual(int numAngl, double valAngl,
+                   int numEdge, double valEdge, int numElem) const;
+    double getGainQuad(const Rec2DElement*,
+                       const Rec2DEdge*, const Rec2DEdge*) const;
+    double getGainTriLess(const Rec2DEdge*) const;
+    double getGainRecomb(const Rec2DElement*, const Rec2DElement*,
+                         const Rec2DEdge*, const Rec2DEdge*,
+                         const Rec2DEdge*                         ) const;
+    void addEdgeQual(double val, int num = 0);
+    double getGainMerge(const Rec2DVertex*, const Rec2DEdge*const*, int) const;
+#else
+    inline double getQual() const {return getQualDegree() + getQualAngle();}
     double getGainOneElemLess() const;
+    double getGainRecomb(const Rec2DElement*, const Rec2DElement*) const;
+    double getGainMerge(const Rec2DVertex*) const;
+#endif
     
     inline void setOnBoundary();
     inline bool getOnBoundary() const {return _onWhat < 1;}
@@ -584,22 +609,11 @@ class Rec2DVertex {
                                   std::vector<Rec2DElement*>&            );
     
   private :
-    inline double _getQualAngle() const {return _sumQualAngle/(double)_elements.size();}
+    //inline double _getQualAngle() const {return _sumQualAngle/_elements.size();}
     bool _recursiveBoundParity(const Rec2DVertex *prev, int p0, int p1);
     void _updateQualAngle();
     inline double _angle2Qual(double ang) const {
-      static int a = -1;
-      if (++a < 1) Msg::Warning("regarder angle 2 qual");
-      static const double angMin = M_PI/200;
-      static const double angMax = M_PI - angMin;
-      static const double min = std::log(4/M_PI*angMin) / std::log(2);
-      static const double log2 = std::log(2);
-      
-      if (ang < angMin || ang > angMax) return min;
-      if (ang < M_PI/2)
-        return std::log(4/M_PI * ang) / log2;
-      else
-        return std::log(4 - 4/M_PI * ang) / log2;
+      return std::max(1. - fabs(ang*2./M_PI - 1.), .0); 
     }
 };
 
@@ -609,7 +623,7 @@ class Rec2DElement {
     int _numEdge;
     Rec2DEdge *_edges[4];
     Rec2DElement *_elements[4];  // NULL if no neighbour
-    std::vector<Rec2DAction*> _actions;;
+    std::vector<Rec2DAction*> _actions;
     
     int _pos;
     friend void Rec2DData::add(const Rec2DElement*);
@@ -663,6 +677,11 @@ class Rec2DElement {
     void createElement(double shiftx, double shifty) const;
     
     double getAngle(const Rec2DVertex*) const;
+#ifdef REC2D_VERT_ONLY
+    int getAngleNb() const {
+      return _numEdge > 3 ? REC2D_VERT_QUAD : REC2D_VERT_TRIA;
+    }
+#endif
     
     inline int getNumActions() const {return _actions.size();}
     inline Rec2DAction* getAction(int i) const {return _actions[i];}
-- 
GitLab