From 45485ad6985338b082189d87b3ee241d5b93deeb Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Fri, 30 Mar 2012 13:51:36 +0000
Subject: [PATCH] it works !

---
 Mesh/meshGFaceRecombine.cpp | 629 ++++++++++++++++++++++++++++++++----
 Mesh/meshGFaceRecombine.h   | 104 +++++-
 2 files changed, 663 insertions(+), 70 deletions(-)

diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp
index b295d678e3..cf1aacdacf 100644
--- a/Mesh/meshGFaceRecombine.cpp
+++ b/Mesh/meshGFaceRecombine.cpp
@@ -34,6 +34,66 @@ Rec2DData *Rec2DData::_current = NULL;
 double **Rec2DVertex::_qualVSnum = NULL;
 double **Rec2DVertex::_gains = NULL;
 
+bool edgesInOrder(Rec2DEdge **edges, int numEdges)
+{
+  Rec2DVertex **v, *v0, *v1;
+  v = new Rec2DVertex*[numEdges];
+  v0 = edges[0]->getVertex(0);
+  v1 = edges[0]->getVertex(1);
+  if (edges[1]->getVertex(0) == v0 || edges[1]->getVertex(1) == v0) {
+    v[0] = v0;
+    if (edges[1]->getVertex(0) == v0)
+      v[1] = edges[1]->getVertex(1);
+    else
+      v[1] = edges[1]->getVertex(0);
+  }
+  else if (edges[1]->getVertex(0) == v1 || edges[1]->getVertex(1) == v1) {
+    v[0] = v1;
+    if (edges[1]->getVertex(0) == v1)
+      v[1] = edges[1]->getVertex(1);
+    else
+      v[1] = edges[1]->getVertex(0);
+  }
+  else {
+    Msg::Error("edges not in order (1)");
+    for (int i = 0; i < numEdges; ++i) {
+      edges[i]->print();
+    }
+    return false;
+  }
+  for (int i = 2; i < numEdges; ++i) {
+    if (edges[i]->getVertex(0) == v[i-1])
+      v[i] = edges[i]->getVertex(1);
+    else if (edges[i]->getVertex(1) == v[i-1])
+      v[i] = edges[i]->getVertex(0);
+    else {
+      Msg::Error("edges not in order (2)");
+      for (int i = 0; i < numEdges; ++i) {
+        edges[i]->print();
+      }
+      return false;
+    }
+  }
+  if (v[0] == v1 && v[numEdges-1] != v0 || v[0] == v0 && v[numEdges-1] != v1) {
+    Msg::Error("edges not in order (3)");
+    for (int i = 0; i < numEdges; ++i) {
+      edges[i]->print();
+    }
+    return false;
+  }
+  
+  delete v;
+  return true;
+}
+
+void crash()
+{
+  int a[2];
+  int e = 0;
+  for (int i = 0; i < 10000000; ++i) e+=a[i];
+  Msg::Info("%d",e);
+}
+
 int otherParity(int a)
 {
   if (a % 2)
@@ -275,6 +335,7 @@ double Recombine2D::recombine(int depth)
       FlGui::instance()->check();
     time = Cpu();
 #endif
+  Recombine2D::drawStateOrigin();
   Rec2DNode *root = new Rec2DNode(NULL, NULL, bestGlobalQuality, depth);
   Rec2DNode *currentNode = root->selectBestNode();
   
@@ -284,7 +345,7 @@ double Recombine2D::recombine(int depth)
   while (currentNode) {
     //_data->checkQuality();
     FlGui::instance()->check();
-#ifdef REC2D_DRAW // draw state at origin
+#if 0//def REC2D_DRAW // draw state at origin
     _gf->triangles = _data->_tri;
     _gf->quadrangles = _data->_quad;
     CTX::instance()->mesh.changed = ENT_ALL;
@@ -293,7 +354,7 @@ double Recombine2D::recombine(int depth)
       FlGui::instance()->check();
     time = Cpu();
 #endif
-#ifdef REC2D_DRAW // draw all states
+#if 0//def REC2D_DRAW // draw all states
     if ( !((i+1) % ((int)std::sqrt(num)+1)) ) {
       dx = .0;
       dy -= 1.1;
@@ -417,11 +478,20 @@ void Recombine2D::drawState(double shiftx, double shifty) const
 {
   //_data->drawTriangles(shiftx, shifty);
   _data->drawElements(shiftx, shifty);
-  _data->drawChanges(shiftx, shifty);
+  //_data->drawChanges(shiftx, shifty);
   CTX::instance()->mesh.changed = ENT_ALL;
   drawContext::global()->draw();
 }
 
+void Recombine2D::drawStateOrigin()
+{
+  _current->_gf->triangles = _current->_data->_tri;
+  _current->_gf->quadrangles = _current->_data->_quad;
+  CTX::instance()->mesh.changed = ENT_ALL;
+  drawContext::global()->draw();
+  FlGui::instance()->check();
+}
+
 void Recombine2D::printState() const
 {
   _data->printState();
@@ -675,6 +745,43 @@ void Rec2DData::checkQuality() const
   }
 }
 
+void Rec2DData::checkEntities()
+{
+  iter_rv itv;
+  for (itv = firstVertex(); itv != lastVertex(); ++itv) {
+    if (!(*itv)->checkCoherence()) {
+      Msg::Error("Incoherence vertex");
+      crash();
+      return;
+    }
+  }
+  iter_re ite;
+  for (ite = firstEdge(); ite != lastEdge(); ++ite) {
+    if (!(*ite)->checkCoherence()) {
+      Msg::Error("Incoherence edge");
+      crash();
+      return;
+    }
+  }
+  iter_rel itel;
+  for (itel = firstElement(); itel != lastElement(); ++itel) {
+    if (!(*itel)->checkCoherence()) {
+      Msg::Error("Incoherence element");
+      crash();
+      return;
+    }
+  }
+  std::list<Rec2DAction*>::iterator ita = _current->_actions.begin();
+  for (; ita != _current->_actions.end(); ++ita) {
+    if (!(*ita)->checkCoherence()) {
+      Msg::Error("Incoherence action");
+      crash();
+      return;
+    }
+  }
+  //Msg::Fatal("Je meurs !!");
+}
+
 void Rec2DData::printActions() const
 {
   std::map<int, std::vector<double> > data;
@@ -959,8 +1066,10 @@ Rec2DChange::Rec2DChange(Rec2DAction *ra, bool toHide) : _entity(ra), _info(NULL
     ra->hide();
     _type = HideAction;
   }
-  else
+  else {
+    ra->addPointing();
     _type = CreatedAction;
+  }
 }
 
 Rec2DChange::Rec2DChange(const std::vector<Rec2DAction*> &actions, bool toHide) : _info(NULL)
@@ -1087,6 +1196,26 @@ Rec2DChange::Rec2DChange(Rec2DVertex *rv0, Rec2DVertex *rv1,
   _entity = _info = NULL;
 }
 
+Rec2DChange::Rec2DChange(Rec2DVertex *rv0, Rec2DVertex *rv1,
+                         const std::vector<Rec2DElement*> &elem,
+                         Rec2DChangeType type                   )
+{
+  if (type == SwapMVertInElement) {
+    _type = type;
+    std::vector<Rec2DElement*> *vect = new std::vector<Rec2DElement*>();
+    *vect = elem;
+    _entity = vect;
+    std::pair<Rec2DVertex*, Rec2DVertex*> *pairVert;
+    pairVert = new std::pair<Rec2DVertex*, Rec2DVertex*>(rv1, rv0);
+    _info = pairVert;
+    for (unsigned int i = 0; i < elem.size(); ++i)
+      elem[i]->swapMVertex(rv0, rv1);
+    return;
+  }
+  _type = Error;
+  _entity = _info = NULL;
+}
+
 Rec2DChange::Rec2DChange(Rec2DEdge *re0, Rec2DEdge *re1,
                          const std::vector<Rec2DAction*> &actions,
                          Rec2DChangeType type                     )
@@ -1180,13 +1309,18 @@ void Rec2DChange::revert()
       
     case CreatedAction :
       {
-        Rec2DAction *action = (Rec2DAction*)_entity;
-        if (action->getInfant()) {
-          action->hide();
-          Rec2DData::addHidden(action);
+        Rec2DAction *ra = (Rec2DAction*)_entity;
+        if (ra->getPointing()) {
+          ra->hide();
+        }
+        else {
+          if (ra->getInfant()) {
+            ra->hide();
+            Rec2DData::addHidden(ra);
+          }
+          else
+            delete ra;
         }
-        else
-          delete action;
       }
       break;
       
@@ -1202,8 +1336,19 @@ void Rec2DChange::revert()
     case CreatedActions :
       {
         std::vector<Rec2DAction*> *vect = (std::vector<Rec2DAction*>*)_entity;
-        for (unsigned int i = 0; i < vect->size(); ++i)
-          delete (*vect)[i];
+        for (unsigned int i = 0; i < vect->size(); ++i) {
+          if ((*vect)[i]->getPointing()) {
+            (*vect)[i]->hide();
+          }
+          else {
+            if ((*vect)[i]->getInfant()) {
+              (*vect)[i]->hide();
+              Rec2DData::addHidden((*vect)[i]);
+            }
+            else
+              delete (*vect)[i];
+          }
+        }
         delete vect;
       }
       break;
@@ -1253,6 +1398,18 @@ void Rec2DChange::revert()
       }
       break;
       
+    case SwapMVertInElement :
+      {
+        std::vector<Rec2DElement*> *elem = (std::vector<Rec2DElement*>*)_entity;
+        std::pair<Rec2DVertex*, Rec2DVertex*> *pairVert;
+        pairVert = (std::pair<Rec2DVertex*, Rec2DVertex*>*)_info;
+        for (unsigned int i = 0; i < elem->size(); ++i)
+          (*elem)[i]->swapMVertex(pairVert->first, pairVert->second);
+        delete elem;
+        delete pairVert;
+      }
+      break;
+      
     case RemoveElem :
       {
         std::vector<Rec2DElement*> *elem = (std::vector<Rec2DElement*>*)_info;
@@ -1354,15 +1511,17 @@ void Rec2DDataChange::swapFor(Rec2DVertex *rv0, Rec2DVertex *rv1)
     elem[i]->getUniqueActions(actions);
   }
   Rec2DAction::removeDuplicate(actions);
-  _changes.push_back(new Rec2DChange(rv0, rv1, actions, SwapVertInAction));
   _changes.push_back(new Rec2DChange(rv0, elem, RemoveElem));
   _changes.push_back(new Rec2DChange(rv0, rv1, edges, SwapVertInEdge));
+  _changes.push_back(new Rec2DChange(rv0, rv1, actions, SwapVertInAction));
   _changes.push_back(new Rec2DChange(rv1, elem, AddElem));
+  _changes.push_back(new Rec2DChange(rv0, rv1, elem, SwapMVertInElement));
 }
 
 void Rec2DDataChange::revert()
 {
-  //Msg::Info("reverting");
+  Msg::Info("reverting");
+  _ra->printIdentity();
   for (int i = (int)_changes.size() - 1; i > -1; --i)
     _changes[i]->revert();
   //Msg::Info(".");
@@ -1382,7 +1541,7 @@ bool gterRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
 }
 
 Rec2DAction::Rec2DAction()
-: _globQualIfExecuted(.0), _lastUpdate(-2)
+: _globQualIfExecuted(.0), _lastUpdate(-2), _numPointing(0)
 {
   
 }
@@ -1455,6 +1614,8 @@ Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DElement *el0, Rec2DElement *el1)
   _triangles[0]->add(this);
   _triangles[1]->add(this);
   Rec2DData::add(this);
+  
+  if (!edgesInOrder(_edges, 4)) Msg::Error("recomb |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
 }
 
 void Rec2DTwoTri2Quad::hide()
@@ -1480,6 +1641,84 @@ void Rec2DTwoTri2Quad::reveal()
   Rec2DData::add(this);
 }
 
+bool Rec2DTwoTri2Quad::checkCoherence() const
+{
+  Rec2DEdge *edge4 = Rec2DElement::getCommonEdge(_triangles[0], _triangles[1]);
+  if (!edge4) {
+    if (!_triangles[0]->has(_edges[4]) || !_triangles[1]->has(_edges[4])) {
+      Msg::Error("inco action -1, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+    }
+  }
+  else if (_edges[4] != edge4) {
+    Msg::Error("inco action 0, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+    if (_edges[4])
+      _edges[4]->print();
+    else Msg::Info("no edge");
+    if (Rec2DElement::getCommonEdge(_triangles[0], _triangles[1]))
+      Rec2DElement::getCommonEdge(_triangles[0], _triangles[1])->print();
+    else Msg::Info("no edge");
+    return false;
+  }
+  
+  std::vector<Rec2DEdge*> edges;
+  Rec2DEdge *re[4];
+  _triangles[0]->getMoreEdges(edges);
+  _triangles[1]->getMoreEdges(edges);
+  int k = -1;
+  for (unsigned int i = 0; i < edges.size(); ++i) {
+    if (edges[i] != _edges[4])
+      re[++k] = edges[i];
+  }
+  if (k > 3)
+    Msg::Error("[Rec2DTwoTri2Quad] too much edges");
+  // reoder edges if needed
+  if (edges[1] == _edges[4]) {
+    Rec2DEdge *e = re[0];
+    re[0] = re[1];
+    re[1] = e;
+  }
+  if (edges[4] == _edges[4]) {
+    Rec2DEdge *e = re[2];
+    re[2] = re[3];
+    re[3] = e;
+  }
+  
+  for (int i = 0; i < 4; ++i) {
+    if (re[i] != _edges[i]) {
+      Msg::Error("inco action 1, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+      for (int i = 0; i < 4; ++i) {
+        _edges[i]->print();
+        re[i]->print();
+        Msg::Info(" ");
+      }
+      return false;
+    }
+  }
+  
+  if (_vertices[0] != _edges[4]->getVertex(0)) {
+      Msg::Error("inco action 2, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+      return false;
+  }
+  if (_vertices[1] != _edges[4]->getVertex(1)) {
+      Msg::Error("inco action 3, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+      return false;
+  }
+  if (_vertices[2] != _triangles[0]->getOtherVertex(_vertices[0], _vertices[1])) {
+      Msg::Error("inco action 4, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+      return false;
+  }
+  if (_vertices[3] != _triangles[1]->getOtherVertex(_vertices[0], _vertices[1])) {
+      Msg::Error("inco action 5, |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+      return false;
+  }
+  return true;
+}
+
+void Rec2DTwoTri2Quad::printIdentity() const
+{
+  Msg::Info("Recombine |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+}
+
 //void Rec2DTwoTri2Quad::print()
 //{
 //  Msg::Info("Printing Action %d |%d|%d|...", this, _triangles[0]->getNum(), _triangles[1]->getNum());
@@ -1597,9 +1836,10 @@ void Rec2DTwoTri2Quad::apply(std::vector<Rec2DVertex*> &newPar)
   Recombine2D::incNumChange();
 }
 
-void Rec2DTwoTri2Quad::apply(Rec2DDataChange *rdc) const
+void Rec2DTwoTri2Quad::apply(Rec2DDataChange *rdc,
+                             std::vector<Rec2DAction*> *&createdActions) const
 {
-  //Msg::Info("Applying Rec2DTwoTri2Quad |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
+  Msg::Info("Applying Rec2DTwoTri2Quad |%d|%d|", _triangles[0]->getNum(), _triangles[1]->getNum());
   if (isObsolete()) {
     Msg::Error("[Rec2DTwoTri2Quad] I was obsolete !");
   }
@@ -1868,7 +2108,25 @@ void Rec2DCollapse::printReward() const
 
 void Rec2DCollapse::_computeGlobQual()
 {
-  delete (new Rec2DNode(NULL, this, _globQualIfExecuted, 0));
+  std::vector<Rec2DVertex*> verts;
+  _rec->_vertices[0]->getMoreNeighbourVertices(verts);
+  _rec->_vertices[1]->getMoreNeighbourVertices(verts);
+  for (unsigned int i = 0; i < verts.size(); ++i) {
+    if (verts[i]->getLastUpdate() > _lastUpdate) {
+      //std::vector<Rec2DElement*> elem;
+        //getElements(elem);
+          //Msg::Info("collapse(%d, %d) -> %g", elem[0]->getNum(), elem[1]->getNum(), _globQualIfExecuted);
+        
+      delete (new Rec2DNode(NULL, this, _globQualIfExecuted, 0));
+      _lastUpdate = Recombine2D::getNumChange();
+      return;
+    }
+  }
+}
+
+void Rec2DCollapse::printIdentity() const
+{
+  Msg::Info("Collapse |%d|%d|", _rec->_triangles[0]->getNum(), _rec->_triangles[1]->getNum());
 }
 
 void Rec2DCollapse::apply(std::vector<Rec2DVertex*> &newPar)
@@ -1877,9 +2135,10 @@ void Rec2DCollapse::apply(std::vector<Rec2DVertex*> &newPar)
   if (++a < 1) Msg::Error("FIXME Need definition Rec2DTwoTri2Quad::apply(newPar)");
 }
 
-void Rec2DCollapse::apply(Rec2DDataChange *rdc) const
+void Rec2DCollapse::apply(Rec2DDataChange *rdc,
+                          std::vector<Rec2DAction*> *&createdActions) const
 {
-  //Msg::Info("Applying Rec2DCollapse |%d|%d|", _rec->_triangles[0]->getNum(), _rec->_triangles[1]->getNum());
+  Msg::Info("Applying Rec2DCollapse |%d|%d|", _rec->_triangles[0]->getNum(), _rec->_triangles[1]->getNum());
   if (isObsolete()) {
     Msg::Error("[Rec2DTwoTri2Quad] I was obsolete !");
   }
@@ -1919,6 +2178,7 @@ void Rec2DCollapse::apply(Rec2DDataChange *rdc) const
   //Msg::Info("v--%g", Rec2DData::getValVert());
   bool edge12KO = _rec->_edges[1]->getVertex(0) == vKO ||
                   _rec->_edges[1]->getVertex(1) == vKO   ;
+  //Msg::Info("swap %d for %d", vKO->getNum(), vOK->getNum());
   rdc->swapFor(vKO, vOK);
   //Msg::Info("v---%g", Rec2DData::getValVert());
   rdc->hide(vKO);
@@ -1938,19 +2198,34 @@ void Rec2DCollapse::apply(Rec2DDataChange *rdc) const
     rdc->swapFor(_rec->_edges[i1], _rec->_edges[i3]);
     rdc->hide(_rec->_edges[i0]);
     rdc->hide(_rec->_edges[i1]);
-    Rec2DElement *elem[2];
-    Rec2DTwoTri2Quad *newAction;
-    Rec2DEdge::getElements(_rec->_edges[i2], elem);
-    if (elem[1] && elem[0]->isTri() && elem[1]->isTri()) {
-      newAction = new Rec2DTwoTri2Quad(elem[0], elem[1]);
-      rdc->append(new Rec2DCollapse(newAction));
-      rdc->append(newAction);
+    if (createdActions) {
+      for (unsigned int i = 0; i < createdActions->size(); ++i) {
+        (*createdActions)[i]->reveal();
+        rdc->append((*createdActions)[i]);
+      }
     }
-    Rec2DEdge::getElements(_rec->_edges[i3], elem);
-    if (elem[1] && elem[0]->isTri() && elem[1]->isTri()) {
-      newAction = new Rec2DTwoTri2Quad(elem[0], elem[1]);
-      rdc->append(new Rec2DCollapse(newAction));
-      rdc->append(newAction);
+    else {
+      createdActions = new std::vector<Rec2DAction*>;
+      Rec2DElement *elem[2];
+      Rec2DAction *newAction;
+      Rec2DEdge::getElements(_rec->_edges[i2], elem);
+      if (elem[1] && elem[0]->isTri() && elem[1]->isTri()) {
+        newAction = new Rec2DTwoTri2Quad(elem[0], elem[1]);
+        rdc->append(newAction);
+        createdActions->push_back(newAction);
+        newAction = new Rec2DCollapse((Rec2DTwoTri2Quad*)newAction);
+        rdc->append(newAction);
+        createdActions->push_back(newAction);
+      }
+      Rec2DEdge::getElements(_rec->_edges[i3], elem);
+      if (elem[1] && elem[0]->isTri() && elem[1]->isTri()) {
+        newAction = new Rec2DTwoTri2Quad(elem[0], elem[1]);
+        rdc->append(newAction);
+        createdActions->push_back(newAction);
+        newAction = new Rec2DCollapse((Rec2DTwoTri2Quad*)newAction);
+        rdc->append(newAction);
+        createdActions->push_back(newAction);
+      }
     }
   }
   
@@ -1976,9 +2251,19 @@ bool Rec2DCollapse::isObsolete() const
   int p[2];
   p[0] = _rec->_vertices[0]->getParity();
   p[1] = _rec->_vertices[1]->getParity();
-  return (p[0] && p[0]/2 == p[1]/2 && p[0]%2 != p[1]%2) ||
-         (_rec->_vertices[0]->getOnBoundary() &&
-          _rec->_vertices[1]->getOnBoundary()   )         ;
+  return p[0] && p[0]/2 == p[1]/2 && p[0]%2 != p[1]%2 ||
+         _rec->_vertices[0]->getOnBoundary() &&
+         _rec->_vertices[1]->getOnBoundary()          ||
+         !_rec->_vertices[2]->getOnBoundary() &&
+         _rec->_vertices[2]->getNumElements() < 4     ||
+         !_rec->_vertices[3]->getOnBoundary() &&
+         _rec->_vertices[3]->getNumElements() < 4       ;
+}
+
+bool Rec2DCollapse::_hasIdenticalElement() const
+{
+  return _rec->_triangles[0]->hasIdenticalNeighbour() ||
+         _rec->_triangles[1]->hasIdenticalNeighbour()   ;
 }
 
 bool Rec2DCollapse::whatWouldYouDo
@@ -1993,9 +2278,10 @@ bool Rec2DCollapse::whatWouldYouDo
 /**  Rec2DEdge  **/
 /*****************/
 Rec2DEdge::Rec2DEdge(Rec2DVertex *rv0, Rec2DVertex *rv1)
-: _rv0(rv0), _rv1(rv1), _lastUpdate(-2),
+: _rv0(rv0), _rv1(rv1), _lastUpdate(-1),
   _weight(REC2D_EDGE_BASE+2*REC2D_EDGE_QUAD), _boundary(-1)
 {
+  _computeQual();
   reveal();
 }
 
@@ -2015,6 +2301,24 @@ void Rec2DEdge::reveal()
   Rec2DData::addEdge(_weight, getWeightedQual());
 }
 
+bool Rec2DEdge::checkCoherence() const
+{
+  if (_rv0 == _rv1) return false;
+  if (!_rv0->has(this) || !_rv1->has(this)) return false;
+  return true;
+  Rec2DElement *elem[2];
+  Rec2DEdge::getElements(this, elem);
+  if (elem[1]) {
+    if (!elem[0]->has(this) || !elem[1]->has(this)) return false;
+    if (!elem[0]->isNeighbour(this, elem[1]) ||
+        !elem[1]->isNeighbour(this, elem[0])   ) return false;
+  }
+  else {
+    if (!elem[0]->has(this)) return false;
+    if (!elem[0]->isNeighbour(this, NULL)) return false;
+  }
+}
+
 void Rec2DEdge::_computeQual()
 {
   double alignment = _straightAlignment();
@@ -2214,7 +2518,7 @@ void Rec2DEdge::getActions(std::vector<Rec2DAction*> &actions) const
 /*******************/
 Rec2DVertex::Rec2DVertex(MVertex *v)
 : _v(v), _angle(4.*M_PI), _onWhat(1), _parity(0),
-  _lastUpdate(Recombine2D::getNumChange()), _sumQualAngle(.0)
+  _lastUpdate(-1), _sumQualAngle(.0)
 {
   reparamMeshVertexOnFace(_v, Recombine2D::getGFace(), _param);
   Rec2DData::add(this);
@@ -2273,12 +2577,29 @@ void Rec2DVertex::reveal()
     Rec2DData::addVert(2, getQual());
 }
 
+bool Rec2DVertex::checkCoherence() const
+{
+  for (unsigned int i = 0; i < _edges.size(); ++i) {
+    if (!_edges[i]->has(this)) return false;
+    for (unsigned int j = 0; j < i; ++j) {
+      if (_edges[i] == _edges[j]) return false;
+    }
+  }
+  for (unsigned int i = 0; i < _elements.size(); ++i) {
+    if (!_elements[i]->has(this)) return false;
+    for (unsigned int j = 0; j < i; ++j) {
+      if (_elements[i] == _elements[j]) return false;
+    }
+  }
+  return true;
+}
+
 void Rec2DVertex::initStaticTable()
 {
   // _qualVSnum[onWhat][numEl]; onWhat={0:edge,1:face}
   // _gains[onWhat][numEl];     onWhat={0:edge,1:face} (earning of adding an element)
   if (_qualVSnum == NULL) {
-    int nE = 10, nF = 20; //edge, face
+    int nE = 20, nF = 40; //edge, face
     
     _qualVSnum = new double*[2];
     _qualVSnum[0] = new double[nE];
@@ -2464,6 +2785,13 @@ void Rec2DVertex::getElements(std::vector<Rec2DElement*> &elem) const
   }
 }
 
+void Rec2DVertex::getMoreNeighbourVertices(std::vector<Rec2DVertex*> &verts) const
+{
+  for (unsigned int i = 0; i < _edges.size(); ++i) {
+    verts.push_back(_edges[i]->getOtherVertex(this));
+  }
+}
+
 void Rec2DVertex::getUniqueEdges(std::vector<Rec2DEdge*> &edges) const
 {
   unsigned int size = edges.size();
@@ -2535,7 +2863,7 @@ double Rec2DVertex::getGainMerge(const Rec2DElement *rel1,
          + getGainDegree(-1);
 }
 
-void Rec2DVertex::add(Rec2DEdge *re)
+void Rec2DVertex::add(const Rec2DEdge *re)
 {
   for (unsigned int i = 0; i < _edges.size(); ++i) {
     if (_edges[i] == re) {
@@ -2543,10 +2871,10 @@ void Rec2DVertex::add(Rec2DEdge *re)
       return;
     }
   }
-  _edges.push_back(re);
+  _edges.push_back((Rec2DEdge*)re);
 }
 
-bool Rec2DVertex::has(Rec2DEdge *re) const
+bool Rec2DVertex::has(const Rec2DEdge *re) const
 {
   for (unsigned int i = 0; i < _edges.size(); ++i) {
     if (_edges[i] == re)
@@ -2555,7 +2883,7 @@ bool Rec2DVertex::has(Rec2DEdge *re) const
   return false;
 }
 
-void Rec2DVertex::rmv(Rec2DEdge *re)
+void Rec2DVertex::rmv(const Rec2DEdge *re)
 {
   unsigned int i = 0;
   while (i < _edges.size()) {
@@ -2569,7 +2897,7 @@ void Rec2DVertex::rmv(Rec2DEdge *re)
   Msg::Error("[Rec2DVertex] Didn't removed edge, didn't have it");
 }
 
-void Rec2DVertex::add(Rec2DElement *rel)
+void Rec2DVertex::add(const Rec2DElement *rel)
 {
   for (unsigned int i = 0; i < _elements.size(); ++i) {
     if (_elements[i] == rel) {
@@ -2580,13 +2908,13 @@ void Rec2DVertex::add(Rec2DElement *rel)
   if (_elements.size())
     Rec2DData::addVert(-2, -getQual());
   
-  _elements.push_back(rel);
+  _elements.push_back((Rec2DElement*)rel);
   _sumQualAngle += _angle2Qual(rel->getAngle(this));
   Rec2DData::addVert(2, getQual());
   _lastUpdate = Recombine2D::getNumChange();
 }
 
-bool Rec2DVertex::has(Rec2DElement *rel) const
+bool Rec2DVertex::has(const Rec2DElement *rel) const
 {
   for (unsigned int i = 0; i < _elements.size(); ++i) {
     if (_elements[i] == rel)
@@ -2595,7 +2923,7 @@ bool Rec2DVertex::has(Rec2DElement *rel) const
   return false;
 }
 
-void Rec2DVertex::rmv(Rec2DElement *rel)
+void Rec2DVertex::rmv(const Rec2DElement *rel)
 {
   unsigned int i = 0;
   while (i < _elements.size()) {
@@ -2647,6 +2975,7 @@ Rec2DElement::Rec2DElement(MTriangle *t, const Rec2DEdge **re, Rec2DVertex **rv)
   _elements[3] = NULL;
   
   reveal(rv);
+  if (!edgesInOrder(_edges, 3)) Msg::Error("tri |%d|", getNum());
 }
 
 Rec2DElement::Rec2DElement(MQuadrangle *q, const Rec2DEdge **re, Rec2DVertex **rv)
@@ -2658,6 +2987,7 @@ Rec2DElement::Rec2DElement(MQuadrangle *q, const Rec2DEdge **re, Rec2DVertex **r
     _elements[i] = Rec2DEdge::getUniqueElement(_edges[i]);
   
   reveal(rv);
+  if (!edgesInOrder(_edges, 4)) Msg::Error("quad |%d|", getNum());
 }
 
 void Rec2DElement::hide()
@@ -2704,6 +3034,93 @@ void Rec2DElement::reveal(Rec2DVertex **rv)
   Rec2DData::add(this);
 }
 
+bool Rec2DElement::checkCoherence() const
+{
+  Rec2DVertex *v[4], *v0, *v1;
+  v0 = _edges[0]->getVertex(0);
+  v1 = _edges[0]->getVertex(1);
+  if (_edges[1]->getVertex(0) == v0 || _edges[1]->getVertex(1) == v0) {
+    v[0] = v0;
+    if (_edges[1]->getVertex(0) == v0)
+      v[1] = _edges[1]->getVertex(1);
+    else
+      v[1] = _edges[1]->getVertex(0);
+  }
+  else if (_edges[1]->getVertex(0) == v1 || _edges[1]->getVertex(1) == v1) {
+    v[0] = v1;
+    if (_edges[1]->getVertex(0) == v1)
+      v[1] = _edges[1]->getVertex(1);
+    else
+      v[1] = _edges[1]->getVertex(0);
+  }
+  else {
+    Msg::Error("not only %d vertex or edge not in order 1 (im %d)", _numEdge, getNum());
+    for (int i = 0; i < _numEdge; ++i) {
+      _edges[i]->print();
+    }
+    return false;
+  }
+  for (int i = 2; i < _numEdge; ++i) {
+    if (_edges[i]->getVertex(0) == v[i-1])
+      v[i] = _edges[i]->getVertex(1);
+    else if (_edges[i]->getVertex(1) == v[i-1])
+      v[i] = _edges[i]->getVertex(0);
+    else {
+      Msg::Error("not only %d vertex or edge not in order 2 (im %d)", _numEdge, getNum());
+      for (int i = 0; i < _numEdge; ++i) {
+        _edges[i]->print();
+      }
+      return false;
+    }
+  }
+  if (v[0] == v1 && v[_numEdge-1] != v0 || v[0] == v0 && v[_numEdge-1] != v1) {
+    Msg::Error("not only %d vertex or edge not in order 3 (im %d)", _numEdge, getNum());
+    for (int i = 0; i < _numEdge; ++i) {
+      _edges[i]->print();
+    }
+    return false;
+  }
+  
+  for (int i = 1; i < _numEdge; ++i) {
+    for (int j = 0; j < i; ++j) {
+      if (_edges[i] == _edges[j]) return false;
+      if (v[i] == v[j]) return false;
+    }
+  }
+  
+  for (int i = 0; i < _numEdge; ++i) {
+    if (!v[i]->has(this)) {
+      Msg::Error("vertex don't have me (im %d)", getNum());
+      return false;
+    }
+    if (_elements[i] && (!_elements[i]->has(this) || !_elements[i]->has(_edges[i]))) {
+      Msg::Error("does %d know me ? %d / does it know edge ? %d (im %d)",
+                 _elements[i]->getNum(),
+                 _elements[i]->has(this),
+                 _elements[i]->has(_edges[i]),
+                 getNum()                     );
+      return false;
+    }
+  }
+  return true;
+}
+
+bool Rec2DElement::has(const Rec2DVertex *rv) const
+{
+  std::vector<Rec2DVertex*> verts;
+  getVertices(verts);
+  for (unsigned int i = 0; i < verts.size(); ++i)
+    if (verts[i] == rv) return true;
+  return false;
+}
+
+bool Rec2DElement::has(const Rec2DElement *rel) const
+{
+  for (int i = 0; i < _numEdge; ++i)
+    if (_elements[i] == rel) return true;
+  return false;
+}
+
 void Rec2DElement::add(Rec2DEdge *re)
 {
   int i;
@@ -2813,6 +3230,31 @@ void Rec2DElement::rmvNeighbour(const Rec2DEdge *re, const Rec2DElement *rel)
   Msg::Error("[Rec2DElement] Edge not found (rmv) (im %d, edge %d %d)", getNum(), a, b);
 }
 
+bool Rec2DElement::isNeighbour(const Rec2DEdge *re, const Rec2DElement *rel) const
+{
+  for (int i = 0; i < _numEdge; ++i) {
+    if (_edges[i] == re) {
+      if (_elements[i] == rel)
+        return true;
+      return false;
+    }
+  }
+  return false;
+}
+
+bool Rec2DElement::hasIdenticalNeighbour() const
+{
+  for (int i = 1; i < _numEdge; ++i) {
+    if (_elements[i]) {
+      for (int j = 0; j < i; ++j) {
+        if (_elements[i] == _elements[j])
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
 void Rec2DElement::swap(Rec2DEdge *re1, Rec2DEdge *re2)
 {
   for (int i = 0; i < _numEdge; ++i) {
@@ -2868,6 +3310,35 @@ void Rec2DElement::swap(Rec2DEdge *re1, Rec2DEdge *re2)
   }
 }
 
+void Rec2DElement::swapMVertex(Rec2DVertex *rv0, Rec2DVertex *rv1)
+{
+  for (int i = 0; i < _numEdge; ++i) {
+    if (_mEl->getVertex(i) == rv0->getMVertex()) {
+      _mEl->setVertex(i, rv1->getMVertex());
+      return;
+    }
+  }
+  std::vector<Rec2DVertex*> v;
+  getVertices(v);
+  if (_numEdge == 3) {
+  Msg::Info("im %d, my vert %d %d %d", getNum(), v[0]->getNum(), v[1]->getNum(), v[2]->getNum());
+  Msg::Info("%d %d = %d %d %d", rv0->getNum(), rv1->getNum(),
+            _mEl->getVertex(0)->getNum(),
+            _mEl->getVertex(1)->getNum(),
+            _mEl->getVertex(2)->getNum());
+  }
+  if (_numEdge == 4) {
+  Msg::Info("im %d, my vert %d %d %d %d", getNum(), v[0]->getNum(), v[1]->getNum(), v[2]->getNum(), v[3]->getNum());
+  Msg::Info("%d %d = %d %d %d %d", rv0->getNum(), rv1->getNum(),
+            _mEl->getVertex(0)->getNum(),
+            _mEl->getVertex(1)->getNum(),
+            _mEl->getVertex(2)->getNum(),
+            _mEl->getVertex(3)->getNum());
+  }
+  Msg::Error("[Rec2DElement] Didn't find your MVertex");
+  crash();
+}
+
 double Rec2DElement::getAngle(const Rec2DVertex *rv) const
 {
   std::vector<Rec2DVertex*> vert;
@@ -2882,6 +3353,19 @@ double Rec2DElement::getAngle(const Rec2DVertex *rv) const
   }
   if (index == -1) {
     Msg::Error("[Rec2DElement] I don't have your vertex...");
+    Msg::Info("im %d, this is %d", getNum(), rv->getNum());
+    for (int i = 0; i < _numEdge; ++i) {
+      Rec2DElement *elem[2];
+      Rec2DEdge::getElements(_edges[i], elem);
+      int a, b = a = NULL;
+      if (elem[0])
+        a = elem[0]->getNum();
+      if (elem[1])
+        b = elem[1]->getNum();
+      Msg::Info("edge %d %d - %d %d", _edges[i]->getVertex(0)->getNum(), _edges[i]->getVertex(1)->getNum(),
+                a,b);
+    }
+    crash();
     return -1.;
   }
   
@@ -2916,13 +3400,13 @@ void Rec2DElement::getVertices(std::vector<Rec2DVertex*> &verts) const
         b = false;
     }
     if (b) {
+      ++k;
       // make sure they are well ordered (edges are ordered)
       if (k == 2 && _edges[i/2]->getVertex((i+1)%2) == verts[0]) {
         Rec2DVertex *rv = verts[0];
         verts[0] = verts[1];
         verts[1] = rv;
       }
-      ++k;
     }
     ++i;
   }
@@ -2950,9 +3434,18 @@ void Rec2DElement::getUniqueActions(std::vector<Rec2DAction*> &vectRA) const
 Rec2DEdge* Rec2DElement::getCommonEdge(const Rec2DElement *rel0,
                                        const Rec2DElement *rel1 )
 {
+  bool foundOne = false;
   for (int i = 0; i < rel0->_numEdge; ++i) {
-    if (rel1->has(rel0->_edges[i]))
-      return rel0->_edges[i];
+    if (rel1->has(rel0->_edges[i])) {
+      if (!foundOne) {
+        return rel0->_edges[i];
+        foundOne = true;
+      }
+      else {
+        Msg::Warning("[Rec2DElement] More than one common edge");
+        return NULL;
+      }
+    }
   }
   Msg::Error("[Rec2DElement] didn't find edge, returning NULL");
   return NULL;
@@ -3062,7 +3555,7 @@ bool moreRec2DNode::operator()(Rec2DNode *rn1, Rec2DNode *rn2) const
 Rec2DNode::Rec2DNode(Rec2DNode *father, Rec2DAction *ra,
                      double &bestEndGlobQual, int depth )
 : _father(father), _ra(ra), _globalQuality(.0), _bestEndGlobQual(.0),
-  _dataChange(NULL)
+  _createdActions(NULL), _dataChange(NULL)
 {
   for (int i = 0; i < REC2D_NUM_SON; ++i)
     _son[i] = NULL;
@@ -3072,7 +3565,10 @@ Rec2DNode::Rec2DNode(Rec2DNode *father, Rec2DAction *ra,
     if (depth)
       _ra->getNeighbourElements(neighbours);
     _dataChange = Rec2DData::getNewDataChange();
-    _ra->apply(_dataChange);
+    _ra->apply(_dataChange, _createdActions);
+    Rec2DData::checkEntities();
+    Recombine2D::drawStateOrigin();
+    _ra->addPointing();
   }
   
   if (father)
@@ -3094,12 +3590,13 @@ Rec2DNode::Rec2DNode(Rec2DNode *father, Rec2DAction *ra,
       for (unsigned int i = 0; i < actions.size(); ++i) {
         std::vector<Rec2DElement*> elem;
         actions[i]->getElements(elem);
-        if (actions[i]->getBase())
+        /*if (actions[i]->getBase())
           Msg::Info("collapse[%d](%d, %d) -> %g", i, elem[0]->getNum(), elem[1]->getNum(), actions[i]->getReward());
         else
-          Msg::Info("recombine[%d](%d, %d) -> %g", i, elem[0]->getNum(), elem[1]->getNum(), actions[i]->getReward());
-        actions[i]->printReward();
+          Msg::Info("recombine[%d](%d, %d) -> %g", i, elem[0]->getNum(), elem[1]->getNum(), actions[i]->getReward());*/
+        //actions[i]->printReward();
         double bestSonEGQ;
+        
         _son[i] = new Rec2DNode(this, actions[i], bestSonEGQ, depth-1);
         if (bestSonEGQ > _bestEndGlobQual) {
           _bestEndGlobQual = bestSonEGQ;
@@ -3119,6 +3616,8 @@ Rec2DNode::Rec2DNode(Rec2DNode *father, Rec2DAction *ra,
     if (!Rec2DData::revertDataChange(_dataChange)) {
       Msg::Error(" 1 - don't reverted changes");Msg::Error(" ");
     }
+    Recombine2D::drawStateOrigin();
+    Rec2DData::checkEntities();
     _dataChange = NULL;
   }
 }
@@ -3127,6 +3626,8 @@ Rec2DNode::~Rec2DNode()
 {
   for (int i = 0; i < REC2D_NUM_SON; ++i)
     delete _son[i];
+  if (_ra)
+    _ra->rmvPointing();
 }
 
 Rec2DNode* Rec2DNode::selectBestNode()
@@ -3172,7 +3673,9 @@ void Rec2DNode::develop(int depth, double &bestEndGlobQual)
   }
   if (delChanges) {
     _dataChange = Rec2DData::getNewDataChange();
-    _ra->apply(_dataChange);
+    _ra->apply(_dataChange, _createdActions);
+    Rec2DData::checkEntities();
+    Recombine2D::drawStateOrigin();
   }
   
   if (_son[0]) {
@@ -3199,6 +3702,13 @@ void Rec2DNode::develop(int depth, double &bestEndGlobQual)
           Msg::Error("null %d/%d", i, actions.size());
         }
         double bestSonEGQ;
+        std::vector<Rec2DElement*> elem;
+        actions[i]->getElements(elem);
+        /*if (actions[i]->getBase())
+          Msg::Info("collapse[%d](%d, %d) -> %g", i, elem[0]->getNum(), elem[1]->getNum(), actions[i]->getReward());
+        else
+          Msg::Info("recombine[%d](%d, %d) -> %g", i, elem[0]->getNum(), elem[1]->getNum(), actions[i]->getReward());*/
+        //
         _son[i] = new Rec2DNode(this, actions[i], bestSonEGQ, depth-1);
         if (bestSonEGQ > _bestEndGlobQual) {
           _bestEndGlobQual = bestSonEGQ;
@@ -3218,6 +3728,8 @@ void Rec2DNode::develop(int depth, double &bestEndGlobQual)
     if (!Rec2DData::revertDataChange(_dataChange)) {
       Msg::Error(" 1 - don't reverted changes");Msg::Error(" ");
     }
+    Recombine2D::drawStateOrigin();
+    Rec2DData::checkEntities();
     _dataChange = NULL;
   }
 }
@@ -3235,7 +3747,9 @@ bool Rec2DNode::makeChanges()
   while (Cpu()-time < REC2D_WAIT_TIME)
     FlGui::instance()->check();
 #endif
-  _ra->apply(_dataChange);
+  _ra->apply(_dataChange, _createdActions);
+    Rec2DData::checkEntities();
+    Recombine2D::drawStateOrigin();
   Rec2DData::setNumTri(_remainingTri);
   return true;
 }
@@ -3247,6 +3761,8 @@ bool Rec2DNode::revertChanges()
   if (!Rec2DData::revertDataChange(_dataChange)) {
     Msg::Error(" 1 - don't reverted changes");Msg::Error(" ");
   }
+  Recombine2D::drawStateOrigin();
+  Rec2DData::checkEntities();
   _dataChange = NULL;
   return true;
 }
@@ -3256,4 +3772,3 @@ bool Rec2DNode::operator<(Rec2DNode &other)
   return _globalQuality < other._globalQuality;
 }
 
-
diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h
index 34ab0bacbe..e1950834ad 100644
--- a/Mesh/meshGFaceRecombine.h
+++ b/Mesh/meshGFaceRecombine.h
@@ -70,6 +70,7 @@ class Recombine2D {
     inline void setStrategy(int s) {_strategy = s;}
     void drawState(double shiftx, double shifty) const;
     void printState() const;
+    static void drawStateOrigin();
     
     static inline GFace* getGFace() {return _current->_gf;}
     static inline int getNumChange() {return _current->_numChange;}
@@ -109,7 +110,7 @@ class Rec2DData {
     Rec2DData();
     ~Rec2DData();
     
-    
+    static void checkEntities();
     
     void printState() const;
     void printActions() const;
@@ -214,7 +215,8 @@ enum Rec2DChangeType {
   CreatedAction, CreatedActions, //8-9
   SwapVertInAction, SwapVertInEdge, //10-11
   SwapEdgeInAction, SwapEdgeInElem, //12-13
-  RemoveElem, AddElem, Relocate, ChangePar, SavePar, //14-18 
+  RemoveElem, AddElem, Relocate, ChangePar, SavePar, //14-18
+  SwapMVertInElement,
   Error, Reverted
 };
 
@@ -242,6 +244,9 @@ class Rec2DChange {
     Rec2DChange(Rec2DVertex*, Rec2DVertex*,
                 const std::vector<Rec2DAction*>&,
                 Rec2DChangeType                  ); // swap vertex1 to vertex2 (action)
+    Rec2DChange(Rec2DVertex*, Rec2DVertex*,
+                const std::vector<Rec2DElement*>&,
+                Rec2DChangeType                  ); // swap mvertex1 to mvertex2 (element)
     Rec2DChange(Rec2DEdge*, Rec2DEdge*, Rec2DChangeType); // swap edge1 to edge2 (element)
     Rec2DChange(Rec2DEdge*, Rec2DEdge*,
                 const std::vector<Rec2DAction*>&,
@@ -290,19 +295,20 @@ class Rec2DDataChange {
 class Rec2DAction {
   protected :
     double _globQualIfExecuted;
-    int _lastUpdate;
+    int _lastUpdate, _numPointing;
     
   public :
     Rec2DAction();
     virtual ~Rec2DAction() {}
     virtual void hide() = 0;
     virtual void reveal() = 0;
+    virtual bool checkCoherence() const = 0;
     
     bool operator<(Rec2DAction&);
     double getReward();
     virtual void color(int, int, int) const = 0;
     virtual void apply(std::vector<Rec2DVertex*> &newPar) = 0;
-    virtual void apply(Rec2DDataChange*) const = 0;
+    virtual void apply(Rec2DDataChange*, std::vector<Rec2DAction*>*&) const = 0;
     virtual bool isObsolete() const = 0;
     virtual Rec2DVertex* getVertex(int) const = 0;
     virtual int getNumElement() = 0;
@@ -319,6 +325,10 @@ class Rec2DAction {
     virtual void swap(Rec2DEdge*, Rec2DEdge*) = 0;
     virtual void printAdress() = 0;
     virtual void printReward() const = 0;
+    inline void addPointing() {++_numPointing;}
+    inline void rmvPointing() {--_numPointing;}
+    inline bool getPointing() {return _numPointing;}
+    virtual void printIdentity() const = 0;
     
   private :
     virtual void _computeGlobQual() = 0;
@@ -338,10 +348,11 @@ class Rec2DTwoTri2Quad : public Rec2DAction {
     ~Rec2DTwoTri2Quad() {if (_col) Msg::Error("[Rec2DTwoTri2Quad] have collapse");hide();}
     virtual void hide();
     virtual void reveal();
+    virtual bool checkCoherence() const;
     
     virtual void color(int, int, int) const;
     virtual void apply(std::vector<Rec2DVertex*> &newPar);
-    virtual void apply(Rec2DDataChange*) const;
+    virtual void apply(Rec2DDataChange*, std::vector<Rec2DAction*>*&) const;
     
     virtual bool isObsolete() const;
     
@@ -359,6 +370,7 @@ class Rec2DTwoTri2Quad : public Rec2DAction {
     virtual void swap(Rec2DEdge*, Rec2DEdge*);
     virtual void printAdress() {Msg::Info(" %d", this);}
     virtual void printReward() const;
+    virtual void printIdentity() const;
     
   private :
     virtual void _computeGlobQual();
@@ -377,12 +389,13 @@ class Rec2DCollapse : public Rec2DAction {
     ~Rec2DCollapse() {_rec->_col = NULL; hide();}
     virtual void hide();
     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 apply(std::vector<Rec2DVertex*> &newPar);
-    virtual void apply(Rec2DDataChange*) const;
+    virtual void apply(Rec2DDataChange*, std::vector<Rec2DAction*>*&) const;
     
     virtual bool isObsolete() const;
     virtual bool whatWouldYouDo(std::map<Rec2DVertex*, std::vector<int> >&);
@@ -411,9 +424,11 @@ 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 printIdentity() const;
     
   private :
     virtual void _computeGlobQual();
+    bool _hasIdenticalElement() const;
 };
 
 class Rec2DEdge {
@@ -428,6 +443,8 @@ class Rec2DEdge {
     ~Rec2DEdge() {hide();}
     void hide();
     void reveal();
+    bool checkCoherence() const;
+    inline bool has(const Rec2DVertex *v) const {return v == _rv0 || v == _rv1;}
     
     //double getQualL() const;
     //double getQualO() const;
@@ -486,6 +503,7 @@ class Rec2DVertex {
     ~Rec2DVertex() {hide();}
     void hide();
     void reveal();
+    bool checkCoherence() const;
     
     inline int getNum() const {return _v->getNum();}
     inline double getAngle() const {return _angle;}
@@ -506,6 +524,7 @@ class Rec2DVertex {
     inline int getNumElements() const {return _elements.size();}
     inline void getEdges(std::vector<Rec2DEdge*> &v) const {v = _edges;}
     void getUniqueEdges(std::vector<Rec2DEdge*>&) const;
+    void getMoreNeighbourVertices(std::vector<Rec2DVertex*>&) const;
     void getTriangles(std::set<Rec2DElement*>&) const;
     void getElements(std::vector<Rec2DElement*>&) const;
     inline MVertex* getMVertex() const {return _v;}
@@ -521,13 +540,13 @@ class Rec2DVertex {
     void relocate(SPoint2 p);
     inline void getParam(SPoint2 *p) {*p = _param;}
     
-    void add(Rec2DEdge*);
-    bool has(Rec2DEdge*) const;
-    void rmv(Rec2DEdge*);
+    void add(const Rec2DEdge*);
+    bool has(const Rec2DEdge*) const;
+    void rmv(const Rec2DEdge*);
     
-    void add(Rec2DElement*);
-    bool has(Rec2DElement*) const;
-    void rmv(Rec2DElement*);
+    void add(const Rec2DElement*);
+    bool has(const Rec2DElement*) const;
+    void rmv(const Rec2DElement*);
     
     void getUniqueActions(std::vector<Rec2DAction*>&) const;
     
@@ -559,6 +578,9 @@ class Rec2DElement {
     ~Rec2DElement() {hide();}
     void hide();
     void reveal(Rec2DVertex **rv = NULL);
+    bool checkCoherence() const;
+    bool has(const Rec2DVertex*) const;
+    bool has(const Rec2DElement*) const;
     
     bool inline isTri() const {return _numEdge == 3;}
     bool inline isQuad() const {return _numEdge == 4;}
@@ -569,8 +591,10 @@ class Rec2DElement {
     void remove(const Rec2DAction*);
     void addNeighbour(const Rec2DEdge*, const Rec2DElement*);
     void rmvNeighbour(const Rec2DEdge*, const Rec2DElement*);
+    bool isNeighbour(const Rec2DEdge*, const Rec2DElement*) const;
     
     void swap(Rec2DEdge*, Rec2DEdge*);
+    void swapMVertex(Rec2DVertex*, Rec2DVertex*);
     
     inline MElement* getMElement() const {return _mEl;}
 #ifdef REC2D_DRAW
@@ -606,6 +630,7 @@ class Rec2DElement {
     Rec2DVertex* getOtherVertex(const Rec2DVertex*, const Rec2DVertex*) const;
     static Rec2DEdge* getCommonEdge(const Rec2DElement*, const Rec2DElement*);
     static void getElements(const Rec2DEdge*, Rec2DElement**);
+    bool hasIdenticalNeighbour() const;
     
     inline int getNum() const {return _mEl->getNum();}
     
@@ -620,6 +645,7 @@ class Rec2DNode {
     Rec2DAction *_ra;
     double _globalQuality, _bestEndGlobQual;
     int _remainingTri;
+    std::vector<Rec2DAction*> *_createdActions;
     
     Rec2DDataChange *_dataChange;
     
@@ -642,6 +668,58 @@ class Rec2DNode {
     inline double getGlobQual() const {return _globalQuality;}
     inline int getNumTri() const {return _remainingTri;}
 };
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
-#endif
\ No newline at end of file
-- 
GitLab