From 48a2438a2c7305195d2a246f0027c5138511a534 Mon Sep 17 00:00:00 2001
From: Amaury Johnan <amjohnen@gmail.com>
Date: Sun, 12 Feb 2012 14:09:24 +0000
Subject: [PATCH] added QualAngle at vertices (bug volume not always positive)

---
 Mesh/meshGFaceRecombine.cpp | 151 +++++++++++++++++++++++++++++-------
 Mesh/meshGFaceRecombine.h   |  19 +++--
 2 files changed, 132 insertions(+), 38 deletions(-)

diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp
index 801931708d..1bc42878ec 100644
--- a/Mesh/meshGFaceRecombine.cpp
+++ b/Mesh/meshGFaceRecombine.cpp
@@ -50,12 +50,20 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
   }
   Recombine2D::_current = this;
   
+  Rec2DVertex::initStaticTable();
   backgroundMesh::set(_gf);
   _bgm = backgroundMesh::current();
   _data = new Rec2DData();
-  Rec2DVertex::initStaticTable();
   _numChange = 0;
   
+  static int po = -1;
+  if (po < 1)
+    Msg::Warning("FIXME Why {mesh 2} then {mesh 0} then {mesh 2} imply not corner vertices");
+  
+  static int pi = -1;
+  if (pi < 1)
+    Msg::Warning("FIXME Why more vertices after first mesh generation");
+  
   // Be able to compute geometrical angle at corners
   std::map<MVertex*, AngleData> mapCornerVert;
   {
@@ -76,6 +84,10 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
     // triangles
     for (unsigned int i = 0; i < gf->triangles.size(); ++i) {
       MTriangle *t = gf->triangles[i];
+      //Msg::Info("[%d %d %d]", t->getVertex(0)->getNum(), t->getVertex(1)->getNum(), t->getVertex(2)->getNum());
+      t->setVolumePositive();
+      static int tia = -1;
+      if (++tia < 1) Msg::Warning("FIXME Sometimes negative volume");
       Rec2DElement *rel = new Rec2DElement(t);
       Rec2DVertex *rv[3];
       for (int j = 0; j < 3; ++j) {
@@ -93,18 +105,19 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
           rv[j] = new Rec2DVertex(v);
           mapVert[v] = rv[j];
         }
-        rv[j]->add(rel); //up data
+        rv[j]->add(rel, false); //up data
       }
       for (int j = 0; j < 3; ++j) {
         Rec2DEdge *re;
         if ( !(re = Rec2DVertex::getCommonEdge(rv[j], rv[(j+1)%3])) )
           re = new Rec2DEdge(rv[j], rv[(j+1)%3]);
-        rel->add(re); //up data
+        rel->add(re);
       }
     }
     // quadrangles
     for (unsigned int i = 0; i < gf->quadrangles.size(); ++i) {
       MQuadrangle *q = gf->quadrangles[i];
+      q->setVolumePositive();
       Rec2DElement *rel = new Rec2DElement(q);
       Rec2DVertex *rv[4];
       for (int j = 0; j < 4; ++j) {
@@ -122,15 +135,12 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
           rv[j] = new Rec2DVertex(v);
           mapVert[v] = rv[j];
         }
-        rv[j]->add(rel);
+        rv[j]->add(rel, false);
       }
       for (int j = 0; j < 4; ++j) {
         Rec2DEdge *re;
-        if ( !(re = Rec2DVertex::getCommonEdge(rv[i], rv[(i+1)%3])) ) {
+        if ( !(re = Rec2DVertex::getCommonEdge(rv[i], rv[(i+1)%3])) )
           re = new Rec2DEdge(rv[i], rv[(i+1)%3]);
-          rv[i]->add(re);
-          rv[(i+1)%3]->add(re);
-        }
         rel->add(re);
       }
     }
@@ -169,11 +179,12 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
       }
     }
   }
-  // set parity on boundary, create 'Rec2DFourTri2Quad'
+  // set parity on boundary, create the 'Rec2DFourTri2Quad', add quality of angle at vertices
   {
     Rec2DData::iter_rv it = Rec2DData::firstVertex();
     for (; it != Rec2DData::lastVertex(); ++it) {
       Rec2DVertex *rv = *it;
+      rv->initQualAngle();
       if (rv->getOnBoundary()) {
         if (!rv->getParity()) {
           int base = Rec2DData::getNewParity();
@@ -233,6 +244,10 @@ bool Recombine2D::recombine()
     delete nextAction;
   }
   
+  //Rec2DData::iter_rv it = Rec2DData::firstVertex();
+  //for (; it != Rec2DData::lastVertex(); ++it) {
+  //  Msg::Info("%d -> %g", (*it)->getMVertex()->getNum(), (*it)->getQualAngle());
+  //}
   _data->printState();
 #ifdef REC2D_SMOOTH
     laplaceSmoothing(_gf,100);
@@ -311,17 +326,18 @@ double Recombine2D::_geomAngle(MVertex *v,
   double angle2 = 2. * M_PI - angle1;
   
   double angleMesh = .0;
-  std::vector<MElement*>::iterator it2 = elem.begin();
-  for (; it2 != elem.end(); ++it2) {
-    MElement *el = *it2;
+  for (unsigned int i = 0; i < elem.size(); ++i) {
+    MElement *el = elem[i];
     int k = 0, numV = el->getNumVertices();
     while (el->getVertex(k) != v && k < numV) ++k;
     if (k == numV) {
       Msg::Error("[Recombine2D] Wrong element, returning pi/2");
       return M_PI / 2.;
     }
-    angleMesh += angle3Vertices(el->getVertex((k+1) % numV), v,
-                                el->getVertex((k+2) % numV)    );
+    if (el->getNumVertices() > 3)
+      Msg::Warning("[Recombine2D] angle3Vertices() ok for triangle... but not for other");
+    angleMesh += angle3Vertices(el->getVertex((k+numV-1) % numV), v,
+                                el->getVertex((k+1) % numV)    );
   }
   
   if (angleMesh < M_PI)
@@ -810,14 +826,14 @@ void Rec2DData::revertAssumedParities()
 double Rec2DData::getGlobalValue()
 {
   double a = (_current->_valVert) / (_current->_numVert);
-  return a *a* (_current->_valEdge) / (_current->_numEdge);
+  return a * (_current->_valEdge) / (_current->_numEdge);
 }
 
 double Rec2DData::getGlobalValue(int numEdge, double valEdge,
                                    int numVert, double valVert)
 {
   double a = (_current->_valVert + valVert) / (_current->_numVert + numVert);
-  return a *a* (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge);
+  return a * (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge);
 }
 
 Rec2DAction* Rec2DData::getBestAction()
@@ -830,7 +846,7 @@ Rec2DAction* Rec2DData::getBestAction()
 
 Rec2DAction* Rec2DData::getBestNonHiddenAction()
 {
-  _current->_actions.sort(greaterRec2DAction());
+  _current->_actions.sort(gterRec2DAction());
   std::list<Rec2DAction*>::iterator it = _current->_actions.begin();
   while (it != _current->_actions.end() && Rec2DData::isOutOfDate(*it)) ++it;
   if (it == _current->_actions.end())
@@ -891,7 +907,7 @@ bool lessRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
   return *ra1 < *ra2;
 }
 
-bool greaterRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
+bool gterRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const
 {
   return *ra2 < *ra1;
 }
@@ -930,6 +946,16 @@ Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DElement *el0, Rec2DElement *el1)
     if (edges[i] != _edges[4])
       _edges[++k] = edges[i];
   }
+  if (edges[1] == _edges[4]) {
+    Rec2DEdge *re = _edges[0];
+    _edges[0] = _edges[1];
+    _edges[1] = re;
+  }
+  if (edges[4] == _edges[4]) {
+    Rec2DEdge *re = _edges[2];
+    _edges[2] = _edges[3];
+    _edges[3] = re;
+  }
   if (k > 3)
     Msg::Error("[Rec2DTwoTri2Quad] too much edges");
   
@@ -1194,8 +1220,6 @@ void Rec2DEdge::reveal()
   //_rv0->add(this);
   //_rv1->add(this);
   //Rec2DData::remove(this);
-  static int a = 0;
-  static double b = .0;
   Rec2DData::addEdge(_weight, getVal());
 }
 
@@ -1318,7 +1342,7 @@ Rec2DVertex* Rec2DEdge::getOtherVertex(Rec2DVertex *rv) const
 /*******************/
 Rec2DVertex::Rec2DVertex(MVertex *v, bool toSave)
 : _v(v), _angle(4*M_PI), _onWhat(1), _parity(0), _assumedParity(0),
-  _lastMove(-1), _isMesh(toSave)
+  _lastMove(-1), _isMesh(toSave), _sumQualAngle(.0)
 {
   reparamMeshVertexOnFace(_v, Recombine2D::getGFace(), _param);
   if (_isMesh) {
@@ -1331,7 +1355,7 @@ Rec2DVertex::Rec2DVertex(MVertex *v, bool toSave)
 
 Rec2DVertex::Rec2DVertex(Rec2DVertex *rv, double ang)
 : _v(rv->_v), _angle(ang), _onWhat(-1), _parity(0), _assumedParity(0),
-  _lastMove(-1), _isMesh(true)
+  _lastMove(-1), _isMesh(true), _sumQualAngle(.0)
 {
   _edges = rv->_edges;
   _elements = rv->_elements;
@@ -1354,7 +1378,10 @@ Rec2DVertex::~Rec2DVertex()
     Rec2DData::removeAssumedParity(this, _assumedParity);
   if (_isMesh) {
     Rec2DData::remove(this);
-    Rec2DData::addVert(-1, -getQual());
+    if  (_elements.empty())
+      Rec2DData::addVert(-2, -getQual());
+    else
+      Rec2DData::addVert(-2, -getQual() - _sumQualAngle/_elements.size());
   }
 }
 
@@ -1385,6 +1412,19 @@ void Rec2DVertex::initStaticTable()
   }
 }
 
+void Rec2DVertex::initQualAngle()
+{
+  if (_sumQualAngle != .0) {
+    Msg::Error("[Rec2DVertex] Mmmh... Sorry, I won't do that !");
+    return;
+  }
+  for (unsigned int i = 0; i < _elements.size(); ++i)
+    _sumQualAngle += _angle2Qual(_elements[i]->getAngle(this));
+  Rec2DData::addVert(1, _sumQualAngle/_elements.size());
+  //if (_v->getNum() < 5)
+  //  Msg::Info("ini %d %g", _v->getNum(), _sumQualAngle/_elements.size());
+}
+
 Rec2DEdge* Rec2DVertex::getCommonEdge(Rec2DVertex *rv0, Rec2DVertex *rv1)
 {
   for (unsigned int i = 0; i < rv0->_edges.size(); ++i) {
@@ -1639,7 +1679,7 @@ void Rec2DVertex::remove(Rec2DEdge *re)
   Msg::Error("[Rec2DVertex] Didn't removed edge, didn't have it");
 }
 
-void Rec2DVertex::add(Rec2DElement *rel)
+void Rec2DVertex::add(Rec2DElement *rel, bool compQualAngle)
 {
   for (unsigned int i = 0; i < _elements.size(); ++i) {
     if (_elements[i] == rel) {
@@ -1647,9 +1687,19 @@ void Rec2DVertex::add(Rec2DElement *rel)
       return;
     }
   }
-  if (_isMesh)
-    Rec2DData::addValVert(getGain(1));
+  if (_isMesh) {
+    if (compQualAngle && !_elements.empty())
+      Rec2DData::addValVert(getGain(1) - _sumQualAngle/_elements.size());
+    else
+      Rec2DData::addValVert(getGain(1));
+    if (compQualAngle)
+      _sumQualAngle += _angle2Qual(rel->getAngle(this));
+  }
   _elements.push_back(rel);
+  if (_isMesh && compQualAngle)
+    Rec2DData::addValVert(_sumQualAngle/_elements.size());
+  //if (_v->getNum() < 5)
+  //  Msg::Info("add %d %g", _v->getNum(), _sumQualAngle/_elements.size());
 }
 
 bool Rec2DVertex::has(Rec2DElement *rel) const
@@ -1665,11 +1715,16 @@ void Rec2DVertex::remove(Rec2DElement *rel)
 {
   unsigned int i = 0;
   while (i < _elements.size()) {
-    if (_elements[i] == rel) {      
+    if (_elements[i] == rel) {
       if (_isMesh)
-        Rec2DData::addValVert(getGain(-1));
+        Rec2DData::addValVert(getGain(-1) - _sumQualAngle/_elements.size());
+      _sumQualAngle -= _angle2Qual(_elements[i]->getAngle(this));
       _elements[i] = _elements.back();
       _elements.pop_back();
+      if (_isMesh && !_elements.empty())
+        Rec2DData::addValVert(_sumQualAngle/_elements.size());
+      //if (_v->getNum() < 5)
+      //  Msg::Info("rmv %d %g", _v->getNum(), _sumQualAngle/_elements.size());
       return;
     }
     ++i;
@@ -1857,6 +1912,34 @@ void Rec2DElement::removeNeighbour(Rec2DEdge *re, Rec2DElement *rel)
 }
 
 
+double Rec2DElement::getAngle(Rec2DVertex *rv)
+{
+  std::vector<Rec2DVertex*> vert;
+  getVertices(vert);
+  int index = -1;
+  
+  for (int i = 0; i < _numEdge; ++i) {
+    if (vert[i] == rv) {
+      index = i;
+      break;
+    }
+  }
+  if (index == -1) {
+    Msg::Error("[Rec2DElement] I don't have your vertex...");
+    return -1.;
+  }
+  int i0 = (index+_numEdge-1)%_numEdge;
+  int i2 = (index+1)%_numEdge;
+  double ang =  atan2(vert[i2]->v() - rv->v(), vert[i2]->u() - rv->u())
+                - atan2(vert[i0]->v() - rv->v(), vert[i0]->u() - rv->u());
+  if (ang < 0.)
+    return ang + 2*M_PI;
+  if (ang >= 2*M_PI)
+    return ang - 2*M_PI;
+  return ang;
+}
+
+
 void Rec2DElement::getAssumedParities(int *p) const
 {
   if (_numEdge == 4) {
@@ -1892,7 +1975,15 @@ void Rec2DElement::getVertices(std::vector<Rec2DVertex*> &verts) const
       if (verts[k] == verts[j])
         b = false;
     }
-    if (b) ++k;
+    if (b) {
+      // 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;
   }
 }
@@ -1979,7 +2070,7 @@ bool lessRec2DNode::operator()(Rec2DNode *rn1, Rec2DNode *rn2) const
   return *rn1 < *rn2;
 }
 
-bool greaterRec2DNode::operator()(Rec2DNode *rn1, Rec2DNode *rn2) const
+bool gterRec2DNode::operator()(Rec2DNode *rn1, Rec2DNode *rn2) const
 {
   return *rn2 < *rn1;
 }
diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h
index f2f40808f8..5c1095fa32 100644
--- a/Mesh/meshGFaceRecombine.h
+++ b/Mesh/meshGFaceRecombine.h
@@ -29,14 +29,14 @@ class Rec2DData;
 struct lessRec2DAction {
   bool operator()(Rec2DAction*, Rec2DAction*) const;
 };
-struct greaterRec2DAction {
+struct gterRec2DAction {
   bool operator()(Rec2DAction*, Rec2DAction*) const;
 };
 
 struct lessRec2DNode {
   bool operator()(Rec2DNode*, Rec2DNode*) const;
 };
-struct greaterRec2DNode {
+struct gterRec2DNode {
   bool operator()(Rec2DNode*, Rec2DNode*) const;
 };
 struct moreRec2DNode {
@@ -44,11 +44,6 @@ struct moreRec2DNode {
 };
 
 //typedef std::list<Rec2DAction*> setofRec2DAction;
-//typedef std::map<MVertex*, Rec2DVertex*> mapofVertices;
-//typedef std::map<MEdge, Rec2DEdge*, Less_Edge> mapofEdges;
-//typedef std::map<MElement*, Rec2DElement*> mapofElements;
-//typedef std::map<MElement*, std::set<Rec2DAction*> > mapofElementActions;
-//typedef std::map<MQuadrangle*, std::set<MElement*> > mapofAdjacencies;
 
 class Recombine2D {
   private :
@@ -127,6 +122,8 @@ class Rec2DData {
     
     static inline int getNumEdge() {return _current->_numEdge;}
     static inline double getValEdge() {return (double)_current->_valEdge;}
+    static inline int getNumVert() {return _current->_numVert;}
+    static inline double getValVert() {return (double)_current->_valVert;}
     static Rec2DAction* getBestAction();
     static Rec2DAction* getBestNonHiddenAction();
     
@@ -288,6 +285,7 @@ class Rec2DVertex {
     const double _angle;
     std::vector<Rec2DEdge*> _edges;
     std::vector<Rec2DElement*> _elements;
+    double _sumQualAngle;
     int _lastMove, _onWhat; // _onWhat={-1:corner,0:edge,1:face}
     int _parity, _assumedParity;
     SPoint2 _param;
@@ -303,6 +301,8 @@ class Rec2DVertex {
     
     double getQual(int numEl = -1) const;
     double getGain(int) const;
+    void initQualAngle();
+    inline double getQualAngle() {return _sumQualAngle/_elements.size();}
     
     inline void setOnBoundary();
     inline bool getOnBoundary() const {return _onWhat < 1;}
@@ -333,7 +333,7 @@ class Rec2DVertex {
     bool has(Rec2DEdge*) const;
     void remove(Rec2DEdge*);
     
-    void add(Rec2DElement*);
+    void add(Rec2DElement*, bool b = true);
     bool has(Rec2DElement*) const;
     void remove(Rec2DElement*);
     
@@ -344,6 +344,7 @@ class Rec2DVertex {
     
   private :
     bool _recursiveBoundParity(Rec2DVertex *prev, int p0, int p1);
+    inline double _angle2Qual(double ang) {return 1. - fabs(ang*2/M_PI - 1.);}
 };
 
 class Rec2DElement {
@@ -393,6 +394,8 @@ class Rec2DElement {
     }
 #endif
     
+    double getAngle(Rec2DVertex*);
+    
     inline int getNumActions() const {return _actions.size();}
     inline Rec2DAction* getAction(int i) const {return _actions[i];}
     void getUniqueActions(std::vector<Rec2DAction*>&) const;
-- 
GitLab