diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp index b1b38c7347321f0e76c6f0814611e2c25a1f2600..e344ac5d3a77e4f7083f3ed8f5e496bb760e4899 100644 --- a/Mesh/meshGFaceRecombine.cpp +++ b/Mesh/meshGFaceRecombine.cpp @@ -1,4 +1,4 @@ -// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle +// Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. @@ -7,28 +7,21 @@ // Amaury Johnen (a.johnen@ulg.ac.be) // -#define REC2D_EDGE_BASE 1 -#define REC2D_EDGE_QUAD 1 -#define REC2D_ALIGNMENT .5 -#define REC2D_WAIT_TIME .01 -#define REC2D_NUM_ACTIO 550 - #include "meshGFaceRecombine.h" -#include "MElement.h" +//#include "MElement.h" #include "MTriangle.h" #include "MQuadrangle.h" -#include "meshGFaceOptimize.h" - -#include "drawContext.h" -#include "FlGui.h" -#include "Context.h" -#include "OS.h" +//#include "meshGFaceOptimize.h" -// #define REC2D_SMOOTH - #define REC2D_DRAW +#ifdef REC2D_DRAW + #include "drawContext.h" + #include "FlGui.h" + #include "Context.h" + #include "OS.h" +#endif Recombine2D *Recombine2D::_current = NULL; -bool Recombine2D::bo = 0; +Rec2DData *Rec2DData::_current = NULL; double **Rec2DVertex::_qualVSnum = NULL; double **Rec2DVertex::_gains = NULL; @@ -38,661 +31,455 @@ int otherParity(int a) { return a + 1; } -/* - TODO : - - map -> myset<pair> (mapCornerVert, mapVert, mapEdge) - - set -> myset - (_vertices, _edges, _elements) -> set - (_vertices, _edges, _elements) -> set -*/ - -void Recombine2D::associateParity(int pOld, int pNew) -{ - std::set<Rec2DVertex*>::iterator it = _current->_parities[pOld].begin(); - for (; it != _current->_parities[pOld].end(); ++it) - (*it)->setParity(pNew); - _current->_parities.erase(pOld); - pOld = otherParity(pOld); - pNew = otherParity(pNew); - it = _current->_parities[pOld].begin(); - for (; it != _current->_parities[pOld].end(); ++it) - (*it)->setParity(pNew); - _current->_parities.erase(pOld); -} - /** Recombine2D **/ /*******************/ Recombine2D::Recombine2D(GFace *gf) : _gf(gf) { if (Recombine2D::_current != NULL) { - Msg::Warning("An instance of recombination is already in execution"); + Msg::Warning("[Recombine2D] An instance already in execution"); return; } Recombine2D::_current = this; - backgroundMesh::set(gf); + backgroundMesh::set(_gf); _bgm = backgroundMesh::current(); - _numChange = 0; - _numEdge = _numVert = 0; - _valEdge = _valVert = .0; + _data = new Rec2DData(gf->triangles.size(), gf->quadrangles.size()); Rec2DVertex::initStaticTable(); + _numChange = 0; - _tri = _gf->triangles; +#ifdef REC2D_DRAW + //_data->_tri = _gf->triangles; + //_data->_quad = _gf->quadrangles; +#endif // Be able to compute geometrical angle at corners - std::map<MVertex*, std::set<GEdge*> > mapCornerVert; // TOBE myset + std::map<MVertex*, AngleData> mapCornerVert; { std::list<GEdge*> listge = gf->edges(); std::list<GEdge*>::iterator itge = listge.begin(); for (; itge != listge.end(); ++itge) { mapCornerVert[(*itge)->getBeginVertex()->getMeshElement(0)->getVertex(0)] - .insert(*itge); + ._gEdges.push_back(*itge); mapCornerVert[(*itge)->getEndVertex()->getMeshElement(0)->getVertex(0)] - .insert(*itge); - } - } - - // Find all Vertices and edges and create the 'Rec2DElement' - std::map<MVertex*, std::vector<MTriangle*> > mapVert; // TOBE myset - std::map<MEdge, std::vector<MTriangle*>, Less_Edge> mapEdge; // TOBE myset - for (unsigned int i = 0; i < gf->triangles.size(); ++i) { - MTriangle *t = gf->triangles[i]; - Rec2DElement *el = new Rec2DElement(t); - _elements[t] = el; // ISITTOKEEP keep only list of relem, map local - for (int j = 0; j < 3; ++j) { - mapVert[t->getVertex(j)].push_back(t); - mapEdge[t->getEdge(j)].push_back(t); + ._gEdges.push_back(*itge); } } - // Create the 'Rec2DVertex' and store iterator to vertices which have degree 4 - std::list<std::map<MVertex*, std::vector<MTriangle*> >::iterator> fourTri; // TOBE vector + // Create the 'Rec2DEdge', the 'Rec2DVertex' and the 'Rec2DElement' { - mapofVertices::iterator itV2N = _vertices.begin(); - std::map<MVertex*, std::vector<MTriangle*> >::iterator itvert = mapVert.begin(); - for (; itvert != mapVert.end(); ++itvert) { - MVertex *v = itvert->first; - int onWhat = 1; - if (mapCornerVert.find(v) != mapCornerVert.end()) - onWhat = -1; - Rec2DVertex *rv = new Rec2DVertex(v, itvert->second, onWhat, mapCornerVert); - itV2N = _vertices.insert(itV2N, std::make_pair(v,rv)); // ISITTOKEEP keep only list of rvert, map local - if (itvert->second.size() == 4) - fourTri.push_back(itvert); + std::map<MVertex*, Rec2DVertex*> mapVert; + std::map<MVertex*, Rec2DVertex*>::iterator itV; + std::map<MVertex*, AngleData>::iterator itCorner; + + // triangles + for (unsigned int i = 0; i < gf->triangles.size(); ++i) { + MTriangle *t = gf->triangles[i]; + Rec2DElement *rel = new Rec2DElement(t); + Rec2DVertex *rv[3]; + for (int j = 0; j < 3; ++j) { + MVertex *v = t->getVertex(j); + if ( (itCorner = mapCornerVert.find(v)) != mapCornerVert.end() ) { + if (!itCorner->second._rv) + itCorner->second._rv = new Rec2DVertex(v, false); + rv[j] = itCorner->second._rv; + itCorner->second._mElements.push_back((MElement*)t); + } + else if ( (itV = mapVert.find(v)) != mapVert.end() ) { + rv[j] = itV->second; + } + else { + rv[j] = new Rec2DVertex(v); + mapVert[v] = rv[j]; + } + rv[j]->add(rel); //up data + } + for (int j = 0; j < 3; ++j) { + Rec2DEdge *re; + if ( (re = Rec2DVertex::getCommonEdge(rv[j], rv[(j+1)%3])) == NULL) + re = new Rec2DEdge(rv[j], rv[(j+1)%3]); + rel->add(re); //up data + } } - } - - // Create the 'Rec2DEdge' and store boundary edges - std::map<MVertex*, std::list<MEdge> > boundV2E; // TOBE myset - { - mapofEdges::iterator itE2E = _edges.begin(); - std::map<MEdge, std::vector<MTriangle*> >::iterator itedge = mapEdge.begin(); - for (; itedge != mapEdge.end(); ++itedge) { - MEdge e = itedge->first; - Rec2DEdge *re = new Rec2DEdge(e, _vertices, itedge->second); - itE2E = _edges.insert(itE2E, std::make_pair(e,re)); - _numEdge += REC2D_EDGE_BASE; - _valEdge += REC2D_EDGE_BASE * re->getQual(); - if (itedge->second.size() == 1) { - _numEdge += REC2D_EDGE_QUAD; - _valEdge += REC2D_EDGE_QUAD * re->getQual(); - _vertices[e.getVertex(0)]->setOnBoundary(); - _vertices[e.getVertex(1)]->setOnBoundary(); - boundV2E[e.getVertex(0)].push_back(e); - boundV2E[e.getVertex(1)].push_back(e); + + // quadrangles + for (unsigned int i = 0; i < gf->quadrangles.size(); ++i) { + MQuadrangle *q = gf->quadrangles[i]; + Rec2DElement *rel = new Rec2DElement(q); + Rec2DVertex *rv[4]; + for (int j = 0; j < 4; ++j) { + MVertex *v = q->getVertex(j); + if ( (itCorner = mapCornerVert.find(v)) != mapCornerVert.end() ) { + if (!itCorner->second._rv) + itCorner->second._rv = new Rec2DVertex(v, false); + rv[j] = itCorner->second._rv; + itCorner->second._mElements.push_back((MElement*)q); + } + else if ( (itV = mapVert.find(v)) == mapVert.end() ) { + rv[j] = itV->second; + } + else { + rv[j] = new Rec2DVertex(v); + mapVert[v] = rv[j]; + } + rv[j]->add(rel); + } + for (int j = 0; j < 4; ++j) { + Rec2DEdge *re; + if ( (re = Rec2DVertex::getCommonEdge(rv[i], rv[(i+1)%3])) == NULL) { + re = new Rec2DEdge(rv[i], rv[(i+1)%3]); + rv[i]->add(re); + rv[(i+1)%3]->add(re); + } + rel->add(re); } } } - - // We know now on what are vertices, compute reward + // update corner { - mapofVertices::iterator itV2N = _vertices.begin(); - for (; itV2N != _vertices.end(); ++itV2N) { - ++_numVert; - _valVert += itV2N->second->getQual(); + std::map<MVertex*, AngleData>::iterator it = mapCornerVert.begin(); + for (; it != mapCornerVert.end(); ++it) { + double angle = _geomAngle(it->first, + it->second._gEdges, + it->second._mElements); + //new Rec2DVertex(it->second._rv, angle); } } - - // Be dealing with "parity" on boundaries + mapCornerVert.clear(); + // update neighbouring, create the 'Rec2DTwoTri2Quad' { - std::map<MVertex*, std::list<MEdge> >::iterator itBound = boundV2E.begin(); - int actualParity = 0; - bool p = 0; - while (itBound != boundV2E.end()) { - MVertex *firstV = itBound->first, *actualV = firstV; - MEdge actualEdge = *itBound->second.begin(); - Rec2DVertex *rv = _vertices[firstV]; - rv->setParity(actualParity+p); - _parities[actualParity+p].insert(rv); - p = !p; - if (actualEdge.getVertex(0) == actualV) - actualV = actualEdge.getVertex(1); - else - actualV = actualEdge.getVertex(0); - while (actualV != firstV) { - rv = _vertices[actualV]; - rv->setParity(actualParity+p); - _parities[actualParity+p].insert(rv); - p = !p; - itBound = boundV2E.find(actualV); - std::list<MEdge>::iterator it = itBound->second.begin(); - if (*it == actualEdge) - actualEdge = *(++it); - else - actualEdge = *it; - if (actualEdge.getVertex(0) == actualV) - actualV = actualEdge.getVertex(1); - else - actualV = actualEdge.getVertex(0); - boundV2E.erase(itBound); + Rec2DData::iter_re it = Rec2DData::firstEdge(); + for (; it != Rec2DData::lastEdge(); ++it) { + Rec2DVertex *rv0 = (*it)->getVertex(0), *rv1 = (*it)->getVertex(1); + if ((*it)->isOnBoundary()) { + rv0->setOnBoundary(); + rv1->setOnBoundary(); + } + else { + std::vector<Rec2DElement*> elem; + Rec2DVertex::getCommonElements(rv0, rv1, elem); + if (elem.size() != 2) + Msg::Error("[Recombine2D] %d elements instead of 2 for neighbour link", + elem.size() ); + else { + elem[0]->addNeighbour(*it, elem[1]); + elem[1]->addNeighbour(*it, elem[0]); + new Rec2DTwoTri2Quad(elem[0], elem[1]); + } } - if (_vertices[actualV]->getParity() != actualParity+p) - Msg::Error("[Recombine2D] Not even number of mesh edges on boundary !"); - - boundV2E.erase(boundV2E.begin()); - itBound = boundV2E.begin(); - actualParity += 2; } } - // Create the 'Rec2DTwoTri2Quad' and 'Rec2DCollapseTri' + // set parity on boundary, create 'Rec2DFourTri2Quad' { - mapofEdges::iterator itE2E = _edges.begin(); - std::map<MEdge, std::vector<MTriangle*> >::iterator ite = mapEdge.begin(); - for (; ite != mapEdge.end(); ++ite) - if (ite->second.size() == 2) { - Rec2DTwoTri2Quad *q = new Rec2DTwoTri2Quad(_edges[ite->first], ite->second); - //Rec2DCollapseTri *c = new Rec2DCollapseTri(_edges[ite->first], ite->second); - _actions.push_back(q); - //_actions.insert(c); - std::vector<MTriangle*>::iterator it = ite->second.begin(); - _mea[*it].insert(q); - //_mea[*it].insert(c); - ++it; - _mea[*it].insert(q); - //_mea[*it].insert(c); + Rec2DData::iter_rv it = Rec2DData::firstVertex(); + for (; it != Rec2DData::lastVertex(); ++it) { + Rec2DVertex *rv = *it; + if (rv->getOnBoundary()) { + if (rv->getParity() == -1) { + int base = Rec2DData::getNewParity(); + rv->setBoundaryParity(base, base+1); + } + } + else if (rv->getNumElements() == 4) { + ; + } } } - // Create the 'Rec2DFourTri2Quad' and 'Rec2DCollapseTri' - //{ - // std::list<std::map<MVertex*, std::vector<MTriangle*> >::iterator>::iterator it4; - // for (it4 = fourTri.begin(); it4 != fourTri.end(); it4++) { - // Rec2DVertex *rv = _vertices[(*it4)->first]; - // if (!rv->getIsOnBoundary()) { - // Rec2DFourTri2Quad *q = new Rec2DFourTri2Quad(rv, (*it4)->second); - // //Rec2DCollapseTri *c = new Rec2DCollapseTri(rv, (*it4)->second); - // _actions.push_back(q); - // //_actions.insert(c); - // std::vector<MTriangle*>::iterator it = (*it4)->second.begin(); - // for (; it != (*it4)->second.end(); ++it) { - // _mea[*it].insert(q); - // //_mea[*it].insert(c); - // } - // } - // } - //} - - Msg::Info("State"); - Msg::Info("-----"); - Msg::Info("numEdge %d (%d), valEdge %g", _numEdge, _edges.size(), _valEdge); - Msg::Info("numVert %d (%d), valVert %g", _numVert, _vertices.size(), _valVert); - Msg::Info("global Value %g", Recombine2D::getGlobalValue(0,0,0,0)); - Msg::Info("num action %d", _actions.size()); - std::map<int, std::set<Rec2DVertex*> >::iterator it = _parities.begin(); - for (; it != _parities.end(); ++it) { - Msg::Info("par %d, #%d", it->first, it->second.size()); - } - mapofElementActions::iterator it2 = _mea.begin(); - int a = 0; - for (; it2 != _mea.end(); ++it2) { - a += it2->second.size(); - } - if (a > 0) - Msg::Info("%d elements in mapof elem to action, with average action %g", _mea.size(), (double)a/_mea.size()); - Msg::Info(" "); + _data->printState(); } Recombine2D::~Recombine2D() { - Recombine2D::_current = NULL; - //delete vertices, edges, elements, actions; + delete _data; + if (Recombine2D::_current == this) + Recombine2D::_current = NULL; } bool Recombine2D::recombine() { Rec2DAction *nextAction; - int i = -1; - while (_actions.size() > 0 && ++i < REC2D_NUM_ACTIO) { - double t = Cpu(); - nextAction = *std::max_element(_actions.begin(), _actions.end(), - lessRec2DAction() ); + while (nextAction = Rec2DData::getBestAction()) { + FlGui::instance()->check(); + double time = Cpu(); +#ifdef REC2D_DRAW nextAction->color(0, 0, 200); - CTX::instance()->mesh.changed = (ENT_ALL); - FlGui::instance()->check(); drawContext::global()->draw(); - //if (nextAction->getReward() > 0) { - if (_isAllQuad(nextAction)) - _choose(nextAction); - else { - nextAction->color(190, 0, 0); - _removeReference(nextAction); - } - /*} - else { - nextAction->color(0, 100, 0); - _removeReference(nextAction); - }*/ +#endif + + ++_numChange; + nextAction->apply(); - _gf->triangles = _tri; - _gf->quadrangles = _quad; #ifdef REC2D_DRAW - //Msg::Info("%d", REC2D_NUM_ACTIO-i); - //Msg::GetAnswer("Continue ?", 1, "no", "yes"); + _gf->triangles = _data->_tri; + _gf->quadrangles = _data->_quad; CTX::instance()->mesh.changed = (ENT_ALL); - FlGui::instance()->check(); - if (i%5 == 0) drawContext::global()->draw(); - while (Cpu()-t < REC2D_WAIT_TIME) + while (Cpu()-time < REC2D_WAIT_TIME) FlGui::instance()->check(); #endif -#ifdef REC2D_SMOOTH - laplaceSmoothing(_gf,1); -#endif - - std::map<int, std::set<Rec2DVertex*> >::iterator it = _parities.begin(); - for (; it != _parities.end(); ++it) { - //Msg::Info("par %d, #%d", it->first, it->second.size()); - } + + delete nextAction; } -// -// Msg::Info("State"); -// Msg::Info("-----"); -// Msg::Info("numEdge %d (%d), valEdge %g", _numEdge, _edges.size(), _valEdge); -// Msg::Info("numVert %d (%d), valVert %g", _numVert, _vertices.size(), _valVert); -// Msg::Info("global Value %g", Recombine2D::getGlobalValue(0,0,0,0)); -// Msg::Info("num action %d", _actions.size()); -// std::map<int, std::set<Rec2DVertex*> >::iterator it = _parities.begin(); -// for (; it != _parities.end(); ++it) { -// Msg::Info("par %d, #%d", it->first, it->second.size()); -// } -// mapofElementActions::iterator it2 = _mea.begin(); -// int a = 0; -// for (; it2 != _mea.end(); ++it2) { -// a += it2->second.size(); -// } -// if (a > 0) -// Msg::Info("%d elements in mapof elem to action, with average action %g", _mea.size(), (double)a/_mea.size()); -// Msg::Info(" "); -// return 1; } -bool Recombine2D::_isAllQuad(Rec2DAction *action) +double Recombine2D::_geomAngle(MVertex *v, + std::vector<GEdge*> &gEdge, + std::vector<MElement*> &elem) //* { - //Msg::Info(" ---new isAllQuad---"); - - int p[4]; - action->getParities(p); - - if (p[0] < 0 && p[1] < 0 && p[2] < 0 && p[3] < 0) { - Msg::Info("is isolated"); - return true; - } - - if (action->isObsolete()) { - Msg::Error("[Recombine2D] obsolete action (allQuad)"); - return false; + if (gEdge.size() != 2) { + Msg::Error("[Recombine2D] Wrong number of edge : %d, returning pi/2", + gEdge.size() ); + return M_PI / 2.; } + static const double prec = 100.; - std::set<Rec2DVertex*> setRv; - std::set<Rec2DElement*> neighbours, checked; - for (int i = 0; i < Recombine2D::getNumVertAllQuad(); ++i) { - if (Recombine2D::getVertAllQuad(i)->hasTriangle()) - Recombine2D::getVertAllQuad(i)->getElements(neighbours); - else - setRv.insert(Recombine2D::getVertAllQuad(i)); - } - std::set<Rec2DVertex*>::iterator itit = setRv.begin(); - for (; itit != setRv.end(); ++itit) - Recombine2D::removeVertAllQuad(*itit); - setRv.clear(); + SVector3 vectv = SVector3(v->x(), v->y(), v->z()); + SVector3 firstDer0, firstDer1; - int min = 100, index; - for (int i = 0; i < 4; ++i) { - if (p[i] > -1 && min > p[i]) { - min = p[i]; - index = i; + for (unsigned int k = 0; k < 2; ++k) { + GEdge *ge = gEdge[k]; + SVector3 vectlb = ge->position(ge->getLowerBound()); + SVector3 vectub = ge->position(ge->getUpperBound()); + vectlb -= vectv; + vectub -= vectv; + double normlb, normub; + if ((normlb = norm(vectlb)) > prec * (normub = norm(vectub))) + firstDer1 = -1 * ge->firstDer(ge->getUpperBound()); + else if (normub > prec * normlb) + firstDer1 = ge->firstDer(ge->getLowerBound()); + else { + Msg::Error("[Recombine2D] Bad precision, returning pi/2"); + return M_PI / 2.; } + if (k == 0) + firstDer0 = firstDer1; } - //Msg::Info("Passsed through there, [%d %d %d %d] -> min %d", p[0], p[1], p[2], p[3], min); - std::map<Rec2DVertex*, int> newParVert; - std::map<Rec2DVertex*, int>::iterator it2; - std::map<int, int> parAssoc; // first parity value become second parity value - std::map<int, int>::iterator itassoc; + firstDer0 = firstDer0 * (1 / norm(firstDer0)); + firstDer1 = firstDer1 * (1 / norm(firstDer1)); - for (int i = 0; i < 4; i += 2) { - int par; - if ((index/2) * 2 == i) - par = min; - else - par = otherParity(min); - for (int j = 0; j < 2; ++j) { - if (p[i+j] == -1) { - newParVert.insert(std::make_pair(action->getRVertex(i+j), par)); - action->getRVertex(i+j)->getElements(neighbours); - } - else if (p[i+j] != par) { - if (parAssoc.find(p[i+j]) == parAssoc.end()) { - parAssoc[p[i+j]] = par; - parAssoc[otherParity(p[i+j])] = otherParity(par); - _getElemToLook(p[i+j], neighbours); - _getElemToLook(otherParity(p[i+j]), neighbours); - } - } - } - } + double angle1 = acos(dot(firstDer0, firstDer1)); + double angle2 = 2. * M_PI - angle1; - while (neighbours.size() > 0) { - //Msg::Info("num vert %d, num neigh %d", newParVert.size(), neighbours.size()); - - std::set<Rec2DElement*>::iterator itel = neighbours.begin(); - Rec2DElement *element = *itel; - if (element->isQuad()) { - neighbours.erase(itel); - continue; - } - - Rec2DVertex *v[3]; - element->getVertices(v); - int p[3]; - for (int i = 0; i < 3; ++i) { - if ((it2 = newParVert.find(v[i])) != newParVert.end()) { - p[i] = it2->second; - while ((itassoc = parAssoc.find(p[i])) != parAssoc.end()) { - p[i] = itassoc->second; - } - it2->second = p[i]; - } - else { - p[i] = v[i]->getParity(); - if ((itassoc = parAssoc.find(p[i])) != parAssoc.end()) { - do - p[i] = itassoc->second; - while ((itassoc = parAssoc.find(p[i])) != parAssoc.end()); - newParVert[v[i]] = p[i]; - } - } - } - //Msg::Info("tri %d [%d %d %d]", (*itel)->getNum(), p[0], p[1], p[2]); - - bool hasIdentical = false; - for (int i = 0; i < 3; ++i) { - if (p[i] > -1 && p[i] == p[(i+1)%3]) hasIdentical = true; - } - if (!hasIdentical) { - neighbours.erase(itel); - continue; - } - if (p[0] == p[1] && p[0] == p[2]) { - Msg::Info("3 identical par"); - return false; - } - //Msg::Info("has identical"); - - bool hasAction = false; - std::map<Rec2DVertex*, std::vector<int> > suggestions; - for (int i = 0; i < element->getNumActions(); ++i) { - if (element->getAction(i)->whatImply(v, p, suggestions)) - hasAction = true; - } - //Msg::Info("suggest %d", suggestions.size()); - - if (!hasAction) { - Msg::Info("No action %d", (*itel)->getNum()); - return false; - } - - std::map<Rec2DVertex*, std::vector<int> >::iterator itsug; - itsug = suggestions.begin(); - for (; itsug != suggestions.end(); ++itsug) { - int par = itsug->second.front(); - bool onlyOnePar = true; - for (unsigned int i = 1; i < itsug->second.size(); ++i) { - if (itsug->second[i] != par) { - onlyOnePar = false; - break; - } - } - if (onlyOnePar) { - if ((itassoc = parAssoc.find(par)) != parAssoc.end()) { - do - par = itassoc->second; - while ((itassoc = parAssoc.find(par)) != parAssoc.end()); - } - - int oldPar; - Rec2DVertex *v = itsug->first; - - if ((it2 = newParVert.find(v)) != newParVert.end()) { - oldPar = it2->second; - while ((itassoc = parAssoc.find(oldPar)) != parAssoc.end()) { - oldPar = itassoc->second; - } - it2->second = oldPar; - } - else { - oldPar = v->getParity(); - if ((itassoc = parAssoc.find(oldPar)) != parAssoc.end()) { - do - oldPar = itassoc->second; - while ((itassoc = parAssoc.find(oldPar)) != parAssoc.end()); - newParVert[v] = oldPar; - } - } - - //Msg::Info("a %d, %d", par, oldPar); - if (oldPar == -1) { - //Msg::Info("b"); - newParVert[v] = par; - v->getElements(neighbours); - } - else if ((par/2)*2 != (oldPar/2)*2) { - //Msg::Info("c"); - if (oldPar < par) { - int a = oldPar; - oldPar = par; - par = a; - } - parAssoc[oldPar] = par; - parAssoc[otherParity(oldPar)] = otherParity(par); - _getElemToLook(oldPar, neighbours); - _getElemToLook(otherParity(oldPar), neighbours); - } - else if (par%2 != oldPar%2) { - //Msg::Info("d"); - Msg::Info("not all quad"); - return false; - } - } + double angleMesh = .0; + std::vector<MElement*>::iterator it2 = elem.begin(); + for (; it2 != elem.end(); ++it2) { + MElement *el = *it2; + 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.; } - neighbours.erase(itel); + angleMesh += angle3Vertices(el->getVertex((k+1) % numV), v, + el->getVertex((k+2) % numV) ); } - Msg::Info("all quad"); - return true; + + if (angleMesh < M_PI) + return angle1; + return angle2; } -void Recombine2D::_choose(Rec2DAction *action) -{ - action->apply(); //to check - _removeIncompatible(action); //to check - ++_numChange; //to check -} -void Recombine2D::_removeIncompatible(Rec2DAction *action) //to check +/** Rec2DData **/ +/*****************/ +Rec2DData::Rec2DData(int numTri, int numQuad) { - std::set<Rec2DElement*> touchedTri; - action->getRTriangles(touchedTri); - std::set<Rec2DElement*>::iterator itTri; - - std::set<Rec2DAction*> incomp; - { - itTri = touchedTri.begin(); - for (; itTri != touchedTri.end(); ++itTri) - (*itTri)->getActions(incomp); + if (Rec2DData::_current != NULL) { + Msg::Error("[Rec2DData] An instance in execution"); + return; } + Rec2DData::_current = this; + _numEdge = _numVert = 0; + _valEdge = _valVert = .0; - //Msg::Warning("size %d", incomp.size()); - - std::set<Rec2DAction*>::iterator itAction = incomp.begin(); - for (; itAction != incomp.end(); ++itAction) { - delete *itAction; - } + //_elements.reserve((int) (numTri + numQuad) * 1.1); + //_edges.reserve((int) (numTri * 1.8 + numQuad * 2.4)); + //_vertices.reserve((int) (numTri * .6 + numQuad * 1.2)); } -void Recombine2D::_removeReference(Rec2DAction *action) -{ - delete action; -} - -//void Recombine2D::_getNeighbours(Rec2DAction *ra, std::set<Rec2DAction*> &actions) -//{ -// std::set<Rec2DElement*> touchedTri, neighbourTri; -// ra->getRTriangles(touchedTri); -// std::set<Rec2DElement*>::iterator itTri; -// -// { -// itTri = touchedTri.begin(); -// for (; itTri != touchedTri.end(); ++itTri) -// (*itTri)->getNeighbours(neighbourTri); -// //itTri = touchedTri.begin(); -// //for (; itTri != touchedTri.end(); ++itTri) -// // neighbourTri.erase(*itTri); -// } -// -// std::set<Rec2DAction*> incomp, neighbours; -// { -// itTri = touchedTri.begin(); -// for (; itTri != touchedTri.end(); ++itTri) -// (*itTri)->getActions(neighbours); -// itTri = neighbourTri.begin(); -// for (; itTri != neighbourTri.end(); ++itTri) -// (*itTri)->getActions(neighbours); -// } -// -// std::set<Rec2DAction*>::iterator itAction = incomp.begin(); -// for (; itAction != incomp.end(); ++itAction) { -// bool b = neighbours.erase(*itAction); -// if (!b) -// Msg::Error("[Recombine2D] didn't found incomp action"); -// } -// -// for (itAction = neighbours.begin(); itAction != neighbours.end(); ++itAction) { -// actions.insert(*itAction); -// } -//} - -void Recombine2D::_getElemToLook(int par, std::set<Rec2DElement*> &elem) -{ - std::set<Rec2DVertex*>::iterator it = _parities[par].begin(); - std::set<Rec2DVertex*>::iterator itend = _parities[par].end(); - for (; it != itend; ++it) { - (*it)->getElements(elem); - } +Rec2DData::~Rec2DData() +{ + if (Rec2DData::_current == this) + Rec2DData::_current = NULL; } - -double Recombine2D::getGlobalValue(int numEdge, double valEdge, - int numVert, double valVert ) +#ifdef REC2D_DRAW +void Rec2DData::add(Rec2DElement *rel) { - double a = (_current->_valVert + valVert) / (_current->_numVert + numVert); - return (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge) * a * a; + _current->_elements.insert(rel); + + MTriangle *t = rel->getMTriangle(); + if (t) + _current->_tri.push_back(t); + MQuadrangle *q = rel->getMQuadrangle(); + if (q) + _current->_quad.push_back(q); + } +#endif -//Rec2DVertex* Recombine2D::getRVertex(MVertex *v) -//{ -// mapofVertices::iterator it = _current->_vertices.find(v); -// if (it != _current->_vertices.end()) -// return it->second; -// Msg::Error("[Recombine2D::getRVertex] vertex not found"); -// return NULL; -//} - -Rec2DEdge* Recombine2D::getREdge(MEdge e) +void Rec2DData::remove(Rec2DEdge *re) { - mapofEdges::iterator it = _current->_edges.find(e); - if (it != _current->_edges.end()) - return it->second; - Msg::Error("[Recombine2D::getREdge] edge not found"); - return NULL; + /*bool b = false; + unsigned int i = 0; + while (i < _current->_edges.size()) { + if (_current->_edges[i] == re) { + _current->_edges[i] = _current->_edges.back(); + _current->_edges.pop_back(); + if (b) + Msg::Error("[Rec2DData] Two or more times same edge"); + b = true; + } + else + ++i; + }*/ + _current->_edges.erase(re); } -Rec2DElement* Recombine2D::getRElement(MElement *el) +void Rec2DData::remove(Rec2DVertex *rv) { - mapofElements::iterator it = _current->_elements.find(el); - if (it != _current->_elements.end()) - return it->second; - Msg::Error("[Recombine2D::getRElement] element not found"); - return NULL; + _current->_vertices.erase(rv); } -void Recombine2D::remove(MEdge e) +void Rec2DData::remove(Rec2DElement *rel) { - mapofEdges::iterator it = _current->_edges.find(e); - if (it != _current->_edges.end()) - _current->_edges.erase(it); - else - Msg::Error("[Recombine2D::getREdge] edge not found"); + /*bool b = false; + unsigned int i = 0; + while (i < _current->_elements.size()) { + if (_current->_elements[i] == rel) { + _current->_elements[i] = _current->_elements.back(); + _current->_elements.pop_back(); + if (b) + Msg::Error("[Rec2DData] Two or more times same element"); + b = true; + } + else + ++i; + }*/ + _current->_elements.erase(rel); +#ifdef REC2D_DRAW + MTriangle *t = rel->getMTriangle(); + if (t) { + for (unsigned int i = 0; i < _current->_tri.size(); ++i) { + if (_current->_tri[i] == t) { + _current->_tri[i] = _current->_tri.back(); + _current->_tri.pop_back(); + return; + } + } + Msg::Info("[Rec2DData] Didn't erased mtriangle :("); + } + MQuadrangle *q = rel->getMQuadrangle(); + if (q) { + for (unsigned int i = 0; i < _current->_quad.size(); ++i) { + if (_current->_quad[i] == q) { + _current->_quad[i] = _current->_quad.back(); + _current->_quad.pop_back(); + return; + } + } + Msg::Info("[Rec2DData] Didn't erased mquadrangle :("); + } +#endif } -void Recombine2D::remove(MVertex *v) +void Rec2DData::remove(Rec2DAction *ra) { - mapofVertices::iterator it = _current->_vertices.find(v); - if (it != _current->_vertices.end()) - _current->_vertices.erase(it); - else - Msg::Error("[Recombine2D::getRVertex] vertex not found"); + std::list<Rec2DAction*>::iterator it = _current->_actions.begin(); + while (it != _current->_actions.end()) { + if (*it == ra) + it = _current->_actions.erase(it); + else + ++it; + } } -void Recombine2D::remove(Rec2DElement *tri) +void Rec2DData::printState() { - Rec2DVertex *v[3]; - tri->getVertices(v); - for (int i = 0; i < 3; ++i) { - v[i]->remove(tri); + Msg::Info("State"); + Msg::Info("-----"); + Msg::Info("numEdge %d (%d), valEdge %g => %g", _numEdge, _edges.size(), _valEdge, _valEdge/_numEdge); + Msg::Info("numVert %d (%d), valVert %g => %g", _numVert, _vertices.size(), _valVert, _valVert/_numVert); + Msg::Info("Element (%d)", _elements.size()); + Msg::Info("global Value %g", Rec2DData::getGlobalValue()); + Msg::Info("num action %d", _actions.size()); + std::map<int, std::vector<Rec2DVertex*> >::iterator it = _parities.begin(); + for (; it != _parities.end(); ++it) { + Msg::Info("par %d, #%d", it->first, it->second.size()); } - MTriangle *t = tri->getMTriangle(); - std::vector<MTriangle*>::iterator it = _current->_tri.begin(); - for (; it != _current->_tri.end(); ++it) { - if (*it == t) { - _current->_tri.erase(it); - return; - } + Msg::Info(" "); + iter_re ite; + long double valEdge = .0; + for (ite = firstEdge(); ite != lastEdge(); ++ite) { + valEdge += (*ite)->getQual(); + } + Msg::Info("valEdge : %g >< %g", valEdge, _valEdge); + iter_rv itv; + long double valVert = .0; + for (itv = firstVertex(); itv != lastVertex(); ++itv) { + valVert += (*itv)->getQual(); } - Msg::Error("[Recombine2D] triangle was not there"); + Msg::Info("valVert : %g >< %g", valVert, _valVert); + Msg::Info(" : %g", valVert); + Msg::Info(" : %g", _valVert); +} + +int Rec2DData::getNewParity() +{ + if (!_current->_parities.size()) + return 0; + std::map<int, std::vector<Rec2DVertex*> >::iterator it; + it = _current->_parities.end(); + --it; + return (it->first/2)*2 + 2; } -void Recombine2D::remove(Rec2DAction *ra) +void Rec2DData::removeParity(Rec2DVertex *rv, int p) { - setofRec2DAction::iterator itAction = _current->_actions.begin(); + std::map<int, std::vector<Rec2DVertex*> >::iterator it; + if ( (it = _current->_parities.find(p)) == _current->_parities.end() ) { + Msg::Error("[Rec2DData] Don't have parity %d", p); + return; + } bool b = false; - while (itAction != _current->_actions.end()) { - if (*itAction == ra) { - _current->_actions.erase(itAction); + std::vector<Rec2DVertex*> *vect = &it->second; + unsigned int i = 0; + while (i < vect->size()) { + if (vect->at(i) == rv) { + vect->at(i) = vect->back(); + vect->pop_back(); + if (b) + Msg::Error("[Rec2DData] Two or more times same vertex"); b = true; - break; } - ++itAction; + else + ++i; } - if (!b) - Msg::Error("[Recombine2D] action to delete not found"); } -void Recombine2D::add(MQuadrangle *quad) +double Rec2DData::getGlobalValue() +{ + double a = (_current->_valVert) / (_current->_numVert); + 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 * (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge); +} + +Rec2DAction* Rec2DData::getBestAction() { - _current->_quad.push_back(quad); + if (_current->_actions.size() == 0) + return NULL; + return *std::max_element(_current->_actions.begin(), + _current->_actions.end(), lessRec2DAction()); } @@ -709,112 +496,76 @@ bool Rec2DAction::operator<(Rec2DAction &other) return getReward() < other.getReward(); } -MQuadrangle* Rec2DAction::_createQuad(std::vector<Rec2DEdge*> &boundEdge) const +double Rec2DAction::getReward() { - //Msg::Info("Imhere"); - if (boundEdge.size() != 4) { - Msg::Error("[Rec2DAction] Not 4 edges for quad creation"); - return new MQuadrangle(NULL, NULL, NULL, NULL); - } - MVertex *v1, *v2, *v3, *v4; - v1 = boundEdge[0]->getRVertex(0)->getMVertex(); - v2 = boundEdge[0]->getRVertex(1)->getMVertex(); - int I; - for (unsigned int i = 1; i < 4; ++i) { - if (v2 == boundEdge[i]->getRVertex(0)->getMVertex()) { - v3 = boundEdge[i]->getRVertex(1)->getMVertex(); - I = i; - break; - } - if (v2 == boundEdge[i]->getRVertex(1)->getMVertex()) { - v3 = boundEdge[i]->getRVertex(0)->getMVertex(); - I = i; - break; - } - } - for (unsigned int i = 1; i < 4; ++i) { - if (i == I) continue; - if (v3 == boundEdge[i]->getRVertex(0)->getMVertex()) { - v4 = boundEdge[i]->getRVertex(1)->getMVertex(); - break; - } - if (v3 == boundEdge[i]->getRVertex(1)->getMVertex()) { - v4 = boundEdge[i]->getRVertex(0)->getMVertex(); - break; - } - } - return new MQuadrangle(v1, v2, v3, v4); + if (_lastUpdate < Recombine2D::getNumChange()) + _computeGlobVal(); + return _globValIfExecuted - Rec2DData::getGlobalValue(); } /** Rec2DTwoTri2Quad **/ /************************/ -Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DEdge *re, std::vector<MTriangle*> &tri) +Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DElement *el0, Rec2DElement *el1) { - int i; - std::set<MEdge, Less_Edge> extEdges; - { - std::vector<MTriangle*>::iterator it = tri.begin(); - for (i = 0; it != tri.end() && i < 2; ++it, ++i) { - _rtriangles[i] = Recombine2D::getRElement(*it); - _rtriangles[i]->add(this); - for (int j = 0; j < 3; ++j) - extEdges.insert((*it)->getEdge(j)); - } - if (it != tri.end() || i < 2) - Msg::Error("[Rec2DTwoTri2Quad] Wrong number of triangles"); - extEdges.erase(re->getMEdge()); - } + _triangles[0] = el0; + _triangles[1] = el1; + _edges[4] = Rec2DElement::getCommonEdge(el0, el1); - _edges[0] = re; - std::set<MEdge>::iterator ite = extEdges.begin(); - for (i = 1; ite != extEdges.end() && i < 5; ++ite, ++i) - _edges[i] = Recombine2D::getREdge(*ite); - if (ite != extEdges.end() || i < 5) - Msg::Error("[Rec2DTwoTri2Quad] Wrong number of edges"); + std::vector<Rec2DEdge*> edges; + el0->getMoreEdges(edges); + el1->getMoreEdges(edges); + int k = -1; + for (unsigned int i = 0; i < edges.size(); ++i) { + if (edges[i] != _edges[4]) + _edges[++k] = edges[i]; + } + if (k > 3) + Msg::Error("[Rec2DTwoTri2Quad] too much edges"); - _vertices[0] = re->getRVertex(0); - _vertices[1] = re->getRVertex(1); - _vertices[2] = _rtriangles[0]->getOtherVertex(_vertices[0], _vertices[1]); - _vertices[3] = _rtriangles[1]->getOtherVertex(_vertices[0], _vertices[1]); + _vertices[0] = _edges[4]->getVertex(0); + _vertices[1] = _edges[4]->getVertex(1); + _vertices[2] = _triangles[0]->getOtherVertex(_vertices[0], _vertices[1]); + _vertices[3] = _triangles[1]->getOtherVertex(_vertices[0], _vertices[1]); - _computeGlobVal(); + _triangles[0]->add(this); + _triangles[1]->add(this); + Rec2DData::add(this); } Rec2DTwoTri2Quad::~Rec2DTwoTri2Quad() { - _rtriangles[0]->remove(this); - _rtriangles[1]->remove(this); + if (_triangles[0]) + _triangles[0]->removeT(this); + if (_triangles[1]) + _triangles[1]->removeT(this); + Rec2DData::remove(this); } -bool Rec2DTwoTri2Quad::isObsolete() +void Rec2DTwoTri2Quad::_computeGlobVal() { - int p[4]; - p[0] = _vertices[0]->getParity(); - p[1] = _vertices[1]->getParity(); - p[2] = _vertices[2]->getParity(); - p[3] = _vertices[3]->getParity(); - return Rec2DTwoTri2Quad::isObsolete(p); + double valEdge = - REC2D_EDGE_BASE * _edges[4]->getQual(); + for (int i = 0; i < 4; ++i) + valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); + + double valVert = _vertices[0]->getGain(-1) + _vertices[1]->getGain(-1); + + _globValIfExecuted = + Rec2DData::getGlobalValue(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE, + valEdge, 0, valVert ); + _lastUpdate = Recombine2D::getNumChange(); } -bool Rec2DTwoTri2Quad::isObsolete(int *p) +void Rec2DTwoTri2Quad::color(int a, int b, int c) { - if (p[0]>-1 && p[1]>-1 && p[0]/2 == p[1]/2 && p[0]%2 != p[1]%2 || - p[2]>-1 && p[3]>-1 && p[2]/2 == p[3]/2 && p[2]%2 != p[3]%2 || - p[0]>-1 && (p[0] == p[2] || p[0] == p[3]) || - p[1]>-1 && (p[1] == p[2] || p[1] == p[3]) ) - return true; - return false; + unsigned int col = CTX::instance()->packColor(a, b, c, 255); + _triangles[0]->getMElement()->setCol(col); + _triangles[1]->getMElement()->setCol(col); } -void Rec2DTwoTri2Quad::apply() //to check +void Rec2DTwoTri2Quad::apply() { - if (isObsolete()) { - Msg::Error("[Rec2DTwoTri2Quad] Applying obsolet action"); - return; - } - - int min = 100, index = -1; + /*int min = 100, index = -1; for (int i = 0; i < 4; ++i) { if (_vertices[i]->getParity() > -1 && min > _vertices[i]->getParity()) { min = _vertices[i]->getParity(); @@ -848,836 +599,635 @@ void Rec2DTwoTri2Quad::apply() //to check Recombine2D::associateParity(_vertices[0]->getParity(), par); } } - } + }*/ - double valEdge = - REC2D_EDGE_BASE * _edges[0]->getQual(); - for (int i = 1; i < 5; ++i) - valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); + _triangles[0]->removeT(this); + _triangles[1]->removeT(this); - Recombine2D::addNumEdge(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE); - Recombine2D::addValEdge(valEdge); - //Recombine2D::addValVert(_vertices[0]->getGain(-1) + _vertices[1]->getGain(-1)); + std::vector<Rec2DAction*> actions; + _triangles[0]->getUniqueActions(actions); + _triangles[1]->getUniqueActions(actions); + for (unsigned int i = 0; i < actions.size(); ++i) + delete actions[i]; - Recombine2D::remove(_rtriangles[0]); // FIXME not performant at all !!! - Recombine2D::remove(_rtriangles[1]); - std::vector<Rec2DEdge*> edges; - for (int i = 1; i < 5; ++i) - edges.push_back(_edges[i]); - Recombine2D::add(_createQuad(edges)); + delete _triangles[0]; + delete _triangles[1]; + _triangles[0] = NULL; + _triangles[1] = NULL; + delete _edges[4]; + + /*new Rec2DCollapse(*/new Rec2DElement(_edges)/*)*/; - _vertices[0]->remove(_edges[0]); - _vertices[1]->remove(_edges[0]); - Recombine2D::remove(_edges[0]->getMEdge()); // could also delete REdge - delete _edges[0]; } -void Rec2DTwoTri2Quad::getParities(int *par) + +/** Rec2DEdge **/ +/*****************/ +Rec2DEdge::Rec2DEdge(Rec2DVertex *rv0, Rec2DVertex *rv1) +: _rv0(rv0), _rv1(rv1), _weight(REC2D_EDGE_BASE), _boundary(-1), _lastUpdate(-2) { - par[0] = _vertices[0]->getParity(); - par[1] = _vertices[1]->getParity(); - par[2] = _vertices[2]->getParity(); - par[3] = _vertices[3]->getParity(); + _rv0->add(this); + _rv1->add(this); + Rec2DData::add(this); + _computeQual(); + Rec2DData::addEdge(_weight, _weight*getQual()); } -void Rec2DTwoTri2Quad::_computeGlobVal() +Rec2DEdge::~Rec2DEdge() { - double valEdge = - REC2D_EDGE_BASE * _edges[0]->getQual(); - for (int i = 1; i < 5; ++i) - valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); - - double valVert = _vertices[0]->getGain(-1) + _vertices[1]->getGain(-1); - - _globValIfExecuted = Recombine2D::getGlobalValue(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE, - valEdge, 0, valVert ); - _lastUpdate = Recombine2D::getNumChange(); + _rv0->remove(this); + _rv1->remove(this); + Rec2DData::remove(this); + Rec2DData::addEdge(-_weight, -_weight*getQual()); } -void Rec2DTwoTri2Quad::color(int a, int b, int c) +void Rec2DEdge::_computeQual() //* { - unsigned int col = CTX::instance()->packColor(a, b, c, 255); - _rtriangles[0]->getMElement()->setCol(col); - _rtriangles[1]->getMElement()->setCol(col); + double adimLength = _straightAdimLength(); + double alignment = _straightAlignment(); + if (adimLength > 1) + adimLength = 1/adimLength; + _qual = adimLength * ((1-REC2D_ALIGNMENT) + REC2D_ALIGNMENT * alignment); + _lastUpdate = Recombine2D::getNumChange(); +} + +double Rec2DEdge::getQual() +{ + if (_lastUpdate < Recombine2D::getNumChange() && + _rv0->getLastMove() > _lastUpdate || + _rv1->getLastMove() > _lastUpdate ) { + _computeQual(); + } + return _qual; } +double Rec2DEdge::addNeighbour() +{ + if (++_boundary > 1) + Msg::Error("[Rec2DEdge] Too much boundary element"); +} -bool Rec2DTwoTri2Quad::whatImply( - Rec2DVertex **rv, int *par, - std::map<Rec2DVertex*, std::vector<int> > &suggestions) +double Rec2DEdge::addQuadNeighbour() { - int num = 0, p[4]; - for (int i = 0; i < 4; ++i) { - bool b = false; - for (int j = 0; j < 3; ++j) { - if (_vertices[i] == rv[j]) { - ++num; - p[i] = par[j]; - b = true; - } - } - if (!b) - p[i] = _vertices[i]->getParity(); + _weight += REC2D_EDGE_QUAD; + if (_weight > REC2D_EDGE_BASE + 2*REC2D_EDGE_QUAD) + Msg::Error("[Rec2DEdge] Weight too higher : %d (%d max)", + _weight, REC2D_EDGE_BASE + 2*REC2D_EDGE_QUAD ); + Rec2DData::addEdge(REC2D_EDGE_QUAD, REC2D_EDGE_QUAD*getQual()); +} + + +Rec2DElement* Rec2DEdge::getSingleElement(Rec2DEdge *re) +{ + std::vector<Rec2DElement*> elem; + Rec2DVertex::getCommonElements(re->getVertex(0), re->getVertex(1), elem); + if (elem.size() == 1) + return elem[0]; + if (elem.size() != 0) + Msg::Error("[Rec2DEdge] Edge bound %d elements, returning NULL", elem.size()); + return NULL; +} + +void Rec2DEdge::swap(Rec2DVertex *oldRV, Rec2DVertex *newRV) +{ + if (_rv0 == oldRV) { + _rv0 = newRV; + return; } - if (num != 3) - Msg::Error("[Rec2DTwoTri2Quad] %d corresponding vertices instead of 3", num); - - if (Rec2DTwoTri2Quad::isObsolete(p)) { - //Msg::Info(" obsolete action"); - return false; + if (_rv1 == oldRV) { + _rv1 = newRV; + return; } + Msg::Error("[Rec2DEdge] oldRV not found"); +} + +double Rec2DEdge::_straightAdimLength() const +{ + double dx, dy, dz, *xyz0 = new double[3], *xyz1 = new double[3]; + _rv0->getxyz(xyz0); + _rv1->getxyz(xyz1); + dx = xyz0[0] - xyz1[0]; + dy = xyz0[1] - xyz1[1]; + dz = xyz0[2] - xyz1[2]; + double length = sqrt(dx * dx + dy * dy + dz * dz); + delete[] xyz0; + delete[] xyz1; - //Msg::Info(" [%d %d %d %d]", p[0], p[1], p[2], p[3]); + double lc0 = (*Recombine2D::bgm())(_rv0->u(), _rv0->v(), .0); + double lc1 = (*Recombine2D::bgm())(_rv1->u(), _rv1->v(), .0); - int min = 100, index = -1; - for (int i = 0; i < 4; ++i) { - if (p[i] > -1 && min > p[i]) { - min = p[i]; - index = i; - } - } - if (index == -1) { - Msg::Error("[Rec2DTwoTri2Quad] no parities"); - return false; - } + return length * (1/lc0 + 1/lc1) / 2; +} + +double Rec2DEdge::_straightAlignment() const +{ + double angle0 = Recombine2D::bgm()->getAngle(_rv0->u(), _rv0->v(), .0); + double angle1 = Recombine2D::bgm()->getAngle(_rv1->u(), _rv1->v(), .0); + double angleEdge = atan2(_rv0->u()-_rv1->u(), _rv0->v()-_rv1->v()); - for (int i = 0; i < 4; i += 2) { - int par; - if ((index/2)*2 == i) - par = min; - else - par = otherParity(min); - for (int j = 0; j < 2; ++j) { - if (p[i+j] != par) - suggestions[_vertices[i+j]].push_back(par); - } - } - //Msg::Info(" ok"); - return true; -} - - -///** Rec2DFourTri2Quad **/ -///*************************/ -//Rec2DFourTri2Quad::Rec2DFourTri2Quad(Rec2DVertex *rv, std::vector<MTriangle*> &tri) -//{ -// int i, j; -// std::set<MEdge, Less_Edge> edges; -// { -// std::vector<MTriangle*>::iterator it = tri.begin(); -// for (i = 0; it != tri.end() && i < 4; ++it, ++i) { -// for (j = 0; j < 3; ++j) -// edges.insert((*it)->getEdge(j)); -// _rtriangles[i] = Recombine2D::getRElement(*it); -// _rtriangles[i]->add(this); -// } -// if (it != tri.end() || i < 4) -// Msg::Error("[Rec2DFourTri2Quad] Wrong number of triangles"); -// } -// -// std::set<MEdge>::iterator ite = edges.begin(); -// for (i = 0, j = 4; ite != edges.end() && (i < 4 || j < 8); ++ite) { -// if ((*ite).getVertex(0) == rv->getMVertex() || -// (*ite).getVertex(1) == rv->getMVertex() ) -// _edges[i++] = Recombine2D::getREdge(*ite); -// else if (j < 8) -// _edges[j++] = Recombine2D::getREdge(*ite); -// else -// Msg::Error("[Rec2DFourTri2Quad] Too much exterior edges"); -// } -// if (edges.size() > 8 || ite != edges.end() || i < 4 || i > 4 || j < 8) -// Msg::Error("[Rec2DFourTri2Quad] Wrong number of edges"); -// -// _vertices[4] = rv; -// // the 4 other must be in order : 2 non adjacent + last 2 -// _vertices[1] = _edges[4]->getRVertex(0); -// _vertices[3] = _edges[4]->getRVertex(1); -// for (int i = 5; i < 8; ++i) { -// if (_edges[i]->getRVertex(0) == _vertices[1]) -// _vertices[0] = _edges[i]->getRVertex(1); -// if (_edges[i]->getRVertex(1) == _vertices[1]) -// _vertices[0] = _edges[i]->getRVertex(0); -// if (_edges[i]->getRVertex(0) == _vertices[3]) -// _vertices[2] = _edges[i]->getRVertex(1); -// if (_edges[i]->getRVertex(1) == _vertices[3]) -// _vertices[2] = _edges[i]->getRVertex(0); -// } -// -// _computeGlobVal(); -//} -// -//Rec2DFourTri2Quad::~Rec2DFourTri2Quad() -//{ -// _rtriangles[0]->remove(this); -// _rtriangles[1]->remove(this); -// _rtriangles[2]->remove(this); -// _rtriangles[3]->remove(this); -//} -// -//bool Rec2DFourTri2Quad::isObsolete() -//{ -// int p[4]; -// p[0] = _vertices[0]->getParity(); -// p[1] = _vertices[1]->getParity(); -// p[2] = _vertices[2]->getParity(); -// p[3] = _vertices[3]->getParity(); -// return Rec2DTwoTri2Quad::isObsolete(p); -//} -// -//void Rec2DFourTri2Quad::apply() -//{ -// double valEdge = 0; -// for (int i = 0; i < 4; ++i) -// valEdge -= REC2D_EDGE_BASE * _edges[i]->getQual(); -// for (int i = 4; i < 8; ++i) -// valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); -// -// double valVert = - _vertices[4]->getQual(); -// for (int i = 0; i < 4; ++i) -// valEdge += _vertices[i]->getGain(-1); -// -// Recombine2D::addNumEdge(4*REC2D_EDGE_QUAD - 4*REC2D_EDGE_BASE); -// Recombine2D::addNumVert(-1); -// Recombine2D::addValEdge(valEdge); -// Recombine2D::addValVert(valVert); -// -// Recombine2D::remove(_rtriangles[0]); // FIXME not performant at all !!! -// Recombine2D::remove(_rtriangles[1]); -// Recombine2D::remove(_rtriangles[2]); -// Recombine2D::remove(_rtriangles[3]); -// std::vector<Rec2DEdge*> edges; -// for (int i = 4; i < 8; ++i) -// edges.push_back(_edges[i]); -// Recombine2D::add(_createQuad(edges)); -// -// for (int i = 0; i < 4; ++i) { -// _edges[i]->getRVertex(0)->remove(_edges[i]); -// _edges[i]->getRVertex(1)->remove(_edges[i]); -// Recombine2D::remove(_edges[i]->getMEdge()); -// delete _edges[i]; -// } -// Recombine2D::remove(_vertices[4]->getMVertex()); -// delete _vertices[4]; -//} -// -//void Rec2DFourTri2Quad::getParities(int *par) -//{ -// par[0] = _vertices[0]->getParity(); -// par[1] = _vertices[1]->getParity(); -// par[2] = _vertices[2]->getParity(); -// par[3] = _vertices[3]->getParity(); -//} -// -//void Rec2DFourTri2Quad::_computeGlobVal() -//{ -// double valEdge = 0; -// for (int i = 0; i < 4; ++i) -// valEdge -= REC2D_EDGE_BASE * _edges[i]->getQual(); -// for (int i = 4; i < 8; ++i) -// valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); -// -// double valVert = - _vertices[4]->getQual(); -// for (int i = 0; i < 4; ++i) -// valEdge += _vertices[i]->getGain(-1); -// -// _globValIfExecuted = Recombine2D::getGlobalValue(4*REC2D_EDGE_QUAD - 4*REC2D_EDGE_BASE, -// valEdge, -1, valVert ); -// _lastUpdate = Recombine2D::getNumChange(); -//} -// -//void Rec2DFourTri2Quad::color(int a, int b, int c) -//{ -// unsigned int col = CTX::instance()->packColor(a, b, c, 255); -// _rtriangles[0]->getMElement()->setCol(col); -// _rtriangles[1]->getMElement()->setCol(col); -// _rtriangles[2]->getMElement()->setCol(col); -// _rtriangles[3]->getMElement()->setCol(col); -//} -// -// -///** Rec2DCollapseTri **/ -///*********************/ -//Rec2DCollapseTri::Rec2DCollapseTri(Rec2DVertex *rv, std::vector<MTriangle*> &tri) -//{ -// int i; -// std::set<MEdge, Less_Edge> extEdges; -// { -// std::vector<MTriangle*>::iterator it = tri.begin(); -// for (i = 0; it != tri.end() && i < 4; ++it, ++i) { -// for (int j = 0; j < 3; ++j) { -// if ((*it)->getEdge(j).getVertex(0) != rv->getMVertex() && -// (*it)->getEdge(j).getVertex(1) != rv->getMVertex() ) -// extEdges.insert((*it)->getEdge(j)); -// } -// _rtriangles[i] = Recombine2D::getRElement(*it); -// _rtriangles[i]->add(this); -// } -// if (it != tri.end() || i < 4) -// Msg::Error("[Rec2DFourTri2Quad] Wrong number of triangles"); -// } -// -// _vertices[4] = rv; -// // the 4 other must be in order : 2 non adjacent + last 2 -// std::set<MEdge>::iterator ite = extEdges.begin(); -// Rec2DEdge *re = Recombine2D::getREdge(*ite); -// _vertices[1] = re->getRVertex(0); -// _vertices[3] = re->getRVertex(1); -// ++ite; -// for (; ite != extEdges.end(); ++ite) { -// re = Recombine2D::getREdge(*ite); -// if (re->getRVertex(0) == _vertices[1]) -// _vertices[0] = re->getRVertex(1); -// if (re->getRVertex(1) == _vertices[1]) -// _vertices[0] = re->getRVertex(0); -// if (re->getRVertex(0) == _vertices[3]) -// _vertices[2] = re->getRVertex(1); -// if (re->getRVertex(1) == _vertices[3]) -// _vertices[2] = re->getRVertex(0); -// } -// -// _computeGlobVal(); -//} -// -//Rec2DCollapseTri::Rec2DCollapseTri(Rec2DEdge *re, std::vector<MTriangle*> &tri) -//: _edge(re) -//{ -// int i; -// std::set<MEdge, Less_Edge> extEdges; -// { -// std::vector<MTriangle*>::iterator it = tri.begin(); -// for (i = 0; it != tri.end() && i < 2; ++it, ++i) { -// for (int j = 0; j < 3; ++j) -// extEdges.insert((*it)->getEdge(j)); -// _rtriangles[i] = Recombine2D::getRElement(*it); -// _rtriangles[i]->add(this); -// } -// if (it != tri.end() || i < 2) -// Msg::Error("[Rec2DTwoTri2Quad] Wrong number of triangles"); -// extEdges.erase(re->getMEdge()); -// } -// _rtriangles[2] = _rtriangles[3] = NULL; -// -// _vertices[0] = re->getRVertex(0); -// _vertices[1] = re->getRVertex(1); -// _vertices[2] = _rtriangles[0]->getOtherVertex(_vertices[0], _vertices[1]); -// _vertices[3] = _rtriangles[1]->getOtherVertex(_vertices[0], _vertices[1]); -// _vertices[4] = NULL; -// -// _computeGlobVal(); -//} -// -//Rec2DCollapseTri::~Rec2DCollapseTri() -//{ -// //_rtriangles[0]->remove(this); -// //_rtriangles[1]->remove(this); -//} -// -//bool Rec2DCollapseTri::isObsolete() -//{ -// int p0 = _vertices[0]->getParity(); -// int p1 = _vertices[1]->getParity(); -// int p2 = _vertices[2]->getParity(); -// int p3 = _vertices[3]->getParity(); -// int b0 = _vertices[0]->getIsOnBoundary(); -// int b1 = _vertices[1]->getIsOnBoundary(); -// int b2 = _vertices[2]->getIsOnBoundary(); -// int b3 = _vertices[3]->getIsOnBoundary(); -// if ((b0 && b1) || (p0>-1 && p1>-1 && p0/2 == p1/2 && p0 % 2 != p1 % 2) && -// (b2 && b3) || (p2>-1 && p3>-1 && p2/2 == p3/2 && p2 % 2 != p3 % 2) ) -// return true; -// return false; -//} -// -//void Rec2DCollapseTri::apply() -//{ -// return; -//} -// -//void Rec2DCollapseTri::getParities(int *par) -//{ -// par[0] = _vertices[0]->getParity(); -// par[1] = _vertices[1]->getParity(); -// par[2] = _vertices[2]->getParity(); -// par[3] = _vertices[3]->getParity(); -//} -// -//void Rec2DCollapseTri::_computeGlobVal() -//{ -// int b0 = _vertices[0]->getIsOnBoundary(); -// int b1 = _vertices[1]->getIsOnBoundary(); -// int b2 = _vertices[2]->getIsOnBoundary(); -// int b3 = _vertices[3]->getIsOnBoundary(); -// -// std::map<Rec2DVertex*, int> neighbourVert; -// std::set<Rec2DEdge*> neighbourEdge; -// if (!b0 || !b1) { -// _vertices[0]->getNeighbours(neighbourVert, neighbourEdge); -// _vertices[1]->getNeighbours(neighbourVert, neighbourEdge); -// if (_vertices[4]) { -// neighbourVert.erase(_vertices[4]); -// _vertices[4]->getNeighbourEdges(neighbourEdge); -// } -// //else -// // neighbourEdge.insert(_edge); -// -// int numEdge = 0, numVert = 0; -// double valEdge = .0, valVert = .0; -// { -// std::set<Rec2DEdge*>::iterator it = neighbourEdge.begin(); -// for (; it != neighbourEdge.end(); ++it) { -// valEdge -= (*it)->getWeightedQual(); -// numEdge -= (*it)->getWeight(); -// } -// valVert -= _vertices[0]->getQual(); -// valVert -= _vertices[1]->getQual(); -// if (_vertices[4]) { -// valVert -= _vertices[4]->getQual(); -// numVert -= 1; -// valVert += _vertices[2]->getGain(-2); -// valVert += _vertices[3]->getGain(-2); -// } -// else { -// valVert += _vertices[2]->getGain(-1); -// valVert += _vertices[3]->getGain(-1); -// } -// } -// if (b0) -// _qualCavity(valVert, valEdge, numEdge, neighbourVert, _vertices[0]); -// else if (b1) -// _qualCavity(valVert, valEdge, numEdge, neighbourVert, _vertices[1]); -// else -// _qualCavity(valVert, valEdge, numEdge, neighbourVert); -// numVert -= 1; -// -// _globValIfExecuted = -// Recombine2D::getGlobalValue(numEdge, valEdge, numVert, valVert); -// } -// else -// _globValIfExecuted = -1.; -// -// -// neighbourVert.clear(); -// neighbourEdge.clear(); -// if (!b2 || !b3) { -// _vertices[2]->getNeighbours(neighbourVert, neighbourEdge); -// _vertices[3]->getNeighbours(neighbourVert, neighbourEdge); -// if (_vertices[4]) { -// neighbourVert.erase(_vertices[4]); -// _vertices[4]->getNeighbourEdges(neighbourEdge); -// } -// else -// neighbourEdge.insert(_edge); -// -// int numEdge = 0, numVert = 0; -// double valEdge = .0, valVert = .0; -// { -// std::set<Rec2DEdge*>::iterator it = neighbourEdge.begin(); -// for (; it != neighbourEdge.end(); ++it) { -// valEdge -= (*it)->getWeightedQual(); -// numEdge -= (*it)->getWeight(); -// } -// valVert -= _vertices[2]->getQual(); -// valVert -= _vertices[3]->getQual(); -// if (_vertices[4]) { -// valVert -= _vertices[4]->getQual(); -// numVert -= 1; -// valVert += _vertices[0]->getGain(-2); -// valVert += _vertices[1]->getGain(-2); -// } -// else { -// valVert += _vertices[0]->getGain(-2); -// valVert += _vertices[1]->getGain(-2); -// } -// } -// if (b2) -// _qualCavity(valVert, valEdge, numEdge, neighbourVert, _vertices[2]); -// else if (b3) -// _qualCavity(valVert, valEdge, numEdge, neighbourVert, _vertices[3]); -// else -// _qualCavity(valVert, valEdge, numEdge, neighbourVert); -// numVert -= 1; -// -// _globValIfExecuted2 = -// Recombine2D::getGlobalValue(numEdge, valEdge, numVert, valVert); -// } -// else -// _globValIfExecuted2 = -1.; -// -// _lastUpdate = Recombine2D::getNumChange(); -//} -// -//void Rec2DCollapseTri::_qualCavity(double &valVert, double &valEdge, -// int &numEdge, -// std::map<Rec2DVertex*, int> &vert, -// Rec2DVertex *imposedVert ) -//{ -// Recombine2D::bo = true; -// std::map<Rec2DVertex*, int>::iterator it; -// Rec2DVertex *rv = imposedVert; -// if (rv == NULL) { -// double u, v = u = .0; -// it = vert.begin(); -// for (; it != vert.end(); ++it) { -// u += it->first->u(); -// v += it->first->v(); -// } -// u /= vert.size(); -// v /= vert.size(); -// -// rv = new Rec2DVertex(u, v); -// } -// valVert = rv->getQual(vert.size()); -// it = vert.begin(); -// for (; it != vert.end(); ++it) { -// Rec2DEdge re(rv, it->first); -// valEdge += it->second * re.getQual(); -// numEdge += it->second; -// } -// if (imposedVert == NULL) { -// rv->deleteMVertex(); -// delete rv; -// } -//} -// -//void Rec2DCollapseTri::color(int a, int b, int c) -//{ -// unsigned int col = CTX::instance()->packColor(a, b, c, 255); -// _rtriangles[0]->getMElement()->setCol(col); -// _rtriangles[1]->getMElement()->setCol(col); -// if (_rtriangles[2]) { -// _rtriangles[2]->getMElement()->setCol(col); -// _rtriangles[3]->getMElement()->setCol(col); -// } -//} -// -// + double alpha0 = angleEdge - angle0; + double alpha1 = angleEdge - angle1; + crossField2d::normalizeAngle(alpha0); + crossField2d::normalizeAngle(alpha1); + alpha0 = 1 - 4 * std::min(alpha0, .5 * M_PI - alpha0) / M_PI; + alpha1 = 1 - 4 * std::min(alpha1, .5 * M_PI - alpha1) / M_PI; + + double lc0 = (*Recombine2D::bgm())(_rv0->u(), _rv0->v(), .0); + double lc1 = (*Recombine2D::bgm())(_rv1->u(), _rv1->v(), .0); + + return (alpha0/lc0 + alpha1/lc1) / (1/lc0 + 1/lc1); +} + +Rec2DVertex* Rec2DEdge::getOtherVertex(Rec2DVertex *rv) const +{ + if (rv == _rv0) + return _rv1; + if (rv == _rv1) + return _rv0; + Msg::Error("[Rec2DEdge] You are wrong, I don't have this vertex !"); + return NULL; +} + + /** Rec2DVertex **/ /*******************/ -Rec2DVertex::Rec2DVertex(MVertex *v, std::vector<MTriangle*> tri, int onWhat, - std::map<MVertex*, std::set<GEdge*> > gEdges) -: _v(v), _onWhat(onWhat), _parity(-1), _lastChange(-1), _numEl(tri.size()) +Rec2DVertex::Rec2DVertex(MVertex *v, bool toSave) +: _v(v), _onWhat(1), _parity(-1), _lastMove(-1), _angle(4*M_PI), _isMesh(toSave) { - for (unsigned int i = 0; i < tri.size(); ++i) - _elements.push_back(Recombine2D::getRElement(tri[i])); - - if (_onWhat == -1) { - std::map<MVertex*, std::set<GEdge*> >::iterator it = gEdges.find(_v); - if (it != gEdges.end()) - _angle = _computeAngle(_v, tri, it->second); - else { - Msg::Warning("[meshRecombine2D] Can't compute corner angle, setting angle to pi/2"); - _angle = M_PI / 2.; - } - } reparamMeshVertexOnFace(_v, Recombine2D::getGFace(), _param); - _computeQual(); + if (_isMesh) { + Rec2DData::add(this); + Rec2DData::addVert(1, getQual()); + } } -Rec2DVertex::Rec2DVertex(double u, double v) -: _onWhat(1), _parity(-1), _lastChange(-1) +Rec2DVertex::Rec2DVertex(Rec2DVertex *rv, double ang) +: _v(rv->_v), _onWhat(-1), _parity(-1), _lastMove(-1), _angle(ang), _isMesh(true) { - _param[0] = u; - _param[1] = v; - - GPoint p = Recombine2D::getGFace()->point(_param); - _v = new MVertex(p.x(), p.y(), p.z(), Recombine2D::getGFace()); - static int i = 0; - if (++i < 20) - Msg::Info("resulting point = [%g, %g, %g]", p.x(), p.y(), p.z()); + _edges = rv->_edges; + _elements = rv->_elements; + _param = rv->_param; + for (int i = 0; i < _edges.size(); ++i) { + _edges[i]->swap(rv, this); + } + Rec2DData::add(this); + Rec2DData::addVert(1, getQual()); + delete rv; } -double Rec2DVertex::_computeAngle(MVertex *v, - std::vector<MTriangle*> &tri, - std::set<GEdge*> &setEdge) +Rec2DVertex::~Rec2DVertex() { - if (setEdge.size() != 2) { - Msg::Warning("[meshGFaceRecombine] Wrong number of edge : %d, returning pi/2", setEdge.size()); - return M_PI / 2.; + Rec2DData::remove(this); + Rec2DData::addVert(-1, -getQual()); +} + +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 + + _qualVSnum = new double*[2]; + _qualVSnum[0] = new double[nE]; + _qualVSnum[1] = new double[nF]; + _qualVSnum[0][0] = -10.; + _qualVSnum[1][0] = -10.; + for (int i = 1; i < nE; ++i) + _qualVSnum[0][i] = 1. - fabs(2./i - 1.); + for (int i = 1; i < nF; ++i) + _qualVSnum[1][i] = 1. - fabs(4./i - 1.); + + _gains = new double*[2]; + _gains[0] = new double[nE-1]; + for (int i = 0; i < nE-1; ++i) + _gains[0][i] = _qualVSnum[0][i+1] - _qualVSnum[0][i]; + _gains[1] = new double[nF-1]; + for (int i = 0; i < nF-1; ++i) + _gains[1][i] = _qualVSnum[1][i+1] - _qualVSnum[1][i]; } - static const double prec = 100.; - - SVector3 vectv = SVector3(v->x(), v->y(), v->z()); - SVector3 firstDer0, firstDer1; - - std::set<GEdge*>::iterator it = setEdge.begin(); - for (int k = 0; k < 2; ++it, ++k) { - GEdge *ge = *it; - SVector3 vectlb = ge->position(ge->getLowerBound()); - SVector3 vectub = ge->position(ge->getUpperBound()); - vectlb -= vectv; - vectub -= vectv; - double normlb, normub; - if ((normlb = norm(vectlb)) > prec * (normub = norm(vectub))) - firstDer1 = ge->firstDer(ge->getUpperBound()); - else if (normub > prec * normlb) - firstDer1 = ge->firstDer(ge->getLowerBound()); - else { - Msg::Warning("[meshGFaceRecombine] Bad precision, returning pi/2"); - return M_PI / 2.; - } - if (k == 0) - firstDer0 = firstDer1; +} + +Rec2DEdge* Rec2DVertex::getCommonEdge(Rec2DVertex *rv0, Rec2DVertex *rv1) +{ + for (unsigned int i = 0; i < rv0->_edges.size(); ++i) { + if (rv1->has(rv0->_edges[i])) + return rv0->_edges[i]; } - - firstDer0 = firstDer0 * (1 / norm(firstDer0)); - firstDer1 = firstDer1 * (1 / norm(firstDer1)); - - double angle1 = acos(dot(firstDer0, firstDer1)); - double angle2 = 2. * M_PI - angle1; - - double angleMesh = .0; - std::vector<MTriangle*>::iterator it2 = tri.begin(); - for (; it2 != tri.end(); ++it2) { - MTriangle *t = *it2; - int k = 0; - while (t->getVertex(k) != v && k < 3) - ++k; - if (k == 3) { - Msg::Warning("[meshGFaceRecombine] Wrong triangle, returning pi/2"); - return M_PI / 2.; + //Msg::Warning("[Rec2DVertex] didn't find edge, returning NULL"); + return NULL; +} + +void Rec2DVertex::getCommonElements(Rec2DVertex *rv0, Rec2DVertex *rv1, + std::vector<Rec2DElement*> &elem ) +{ + for (unsigned int i = 0; i < rv0->_elements.size(); ++i) { + if (rv1->has(rv0->_elements[i])) + elem.push_back(rv0->_elements[i]); + } +} + +bool Rec2DVertex::setBoundaryParity(int p0, int p1) +{ + if (_parity > -1) { + Msg::Error("[Rec2DVertex] Are you kidding me ? Already have a parity !"); + return false; + } + setParity(p0); + int num = 0; + Rec2DVertex *nextRV = NULL; + for (unsigned int i = 0; i < _edges.size(); ++i) { + if (_edges[i]->isOnBoundary()) { + nextRV = _edges[i]->getOtherVertex(this); + ++num; } - angleMesh += angle3Vertices(t->getVertex((k+1)%3), v, t->getVertex((k+2)%3)); } - - if (angleMesh < M_PI) - return angle1; - return angle2; + if (num != 2) + Msg::Error("[Rec2DVertex] What's happening ? Am I on boundary or not ? TELL ME !"); + if (nextRV) + return nextRV->_recursiveBoundParity(this, p1, p0); // alternate parity + Msg::Error("[Rec2DVertex] Have I really to say that I didn't find neighbouring vertex ?"); + return false; } -double Rec2DVertex::getQual(int numEdge) +bool Rec2DVertex::_recursiveBoundParity(Rec2DVertex *prevRV, int p0, int p1) { - if (numEdge > 1) { - switch (_onWhat) { - case 1 : - return _qualVSnum[_onWhat][numEdge-1]; - case 0 : - return _qualVSnum[_onWhat][numEdge-2]; - case -1 : - return 1. - fabs(2./M_PI * _angle/(numEdge-1) - 1.); - default : - Msg::Error("[Rec2DVertex] Don't know on what is the vertex"); - return -1.; + if (_parity == p0) + return true; + if (_parity > -1) { + Msg::Error("[Rec2DVertex] Sorry, have parity %d, can't set it to %d... " + "You failed ! Try again !", _parity, p0); + return false; + } + setParity(p0); + int num = 0; + Rec2DVertex *nextRV = NULL; + for (unsigned int i = 0; i < _edges.size(); ++i) { + if (_edges[i]->isOnBoundary() && _edges[i]->getOtherVertex(this) != prevRV) { + nextRV = _edges[i]->getOtherVertex(this); + ++num; } } - if (_lastChange < Recombine2D::getNumChange()) - _computeQual(); - return _qual; + if (num != 1) + Msg::Error("[Rec2DVertex] Holy shit !"); + if (nextRV) + return nextRV->_recursiveBoundParity(this, p1, p0); // alternate parity + Msg::Error("[Rec2DVertex] Have I really to say that I didn't find next vertex ?"); + return false; } -bool Rec2DVertex::hasTriangle() +void Rec2DVertex::setParity(int p) { - bool b = false; - for (int i = 0; i < _elements.size(); ++i) - if (!_elements[i]->isQuad()) b = true; - return b; + if (_parity > -1) { + Rec2DData::removeParity(this, _parity); + } + _parity = p; + Rec2DData::addParity(this, _parity); } -void Rec2DVertex::_computeQual() +double Rec2DVertex::getQual(int numEl) const { + int nEl = numEl > -1 ? numEl : _elements.size(); if (_onWhat > -1) - _qual = _qualVSnum[_onWhat][_numEl-1]; - else - _qual = 1. - fabs(2./M_PI * _angle/_numEl - 1.); - _lastChange = Recombine2D::getNumChange(); + return _qualVSnum[_onWhat][nEl]; + if (nEl == 0) + return -10.; + return 1. - fabs(2./M_PI * _angle/nEl - 1.); } -double Rec2DVertex::getGain(int n) +double Rec2DVertex::getGain(int n) const { + if (!n) + return .0; + if (_elements.size() + n < 0) { + Msg::Error("[Rec2DVertex] gain for %d elements unavailable", + _elements.size() + n ); + return .0; + } + if (_onWhat > -1) { switch (n) { case 1 : - return _gains[_onWhat][_numEl-1]; + return _gains[_onWhat][_elements.size()]; case -1 : - return - _gains[_onWhat][_numEl-2]; + return - _gains[_onWhat][_elements.size()-1]; default : - return _qualVSnum[_onWhat][_numEl-1+n] - _qualVSnum[_onWhat][_numEl-1]; + return _qualVSnum[_onWhat][_elements.size()+n] + - _qualVSnum[_onWhat][_elements.size()-1]; } } - else - return fabs(2./M_PI * _angle/_numEl - 1.) - - fabs(2./M_PI * _angle/(_numEl + n) - 1.); + + if (_elements.size() == 0) + return 11 - fabs(2./M_PI * _angle/(_elements.size() + n) - 1.); + + if (_elements.size() + n == 0) + return fabs(2./M_PI * _angle/_elements.size() - 1.) - 11; + + return fabs(2./M_PI * _angle/_elements.size() - 1.) + - fabs(2./M_PI * _angle/(_elements.size() + n) - 1.); } -void Rec2DVertex::getNeighbours(std::map<Rec2DVertex*, int> &vert, - std::set<Rec2DEdge*> &edge ) +void Rec2DVertex::add(Rec2DEdge *re) { - Rec2DVertex *rv; - std::map<Rec2DVertex*, int>::iterator it; - for (unsigned int i = 0; i < _edges.size(); ++i){ - edge.insert(_edges[i]); - if (_edges[i]->getRVertex(0) != this) - rv = _edges[i]->getRVertex(0); - else - rv = _edges[i]->getRVertex(1); - if ((it = vert.find(rv)) != vert.end()) - it->second += _edges[i]->getWeight() - REC2D_EDGE_BASE; - else - vert[rv] = _edges[i]->getWeight(); + for (unsigned int i = 0; i < _edges.size(); ++i) { + if (_edges[i] == re) { + Msg::Warning("[Rec2DVertex] Edge was already there"); + return; + } } + _edges.push_back(re); } -void Rec2DVertex::getNeighbourEdges(std::set<Rec2DEdge*> &edge) +bool Rec2DVertex::has(Rec2DEdge *re) const { - for (unsigned int i = 0; i < _edges.size(); ++i) - edge.insert(_edges[i]); + for (unsigned int i = 0; i < _edges.size(); ++i) { + if (_edges[i] == re) + return true; + } + return false; } -void Rec2DVertex::initStaticTable() +void Rec2DVertex::remove(Rec2DEdge *re) { - if (_qualVSnum == NULL) { - // _qualVSnum[onWhat][nEl]; onWhat={0:edge,1:face} / nEl=_numEl-1 - // _gains[onWhat][nEl]; onWhat={0:edge,1:face} / nEl=_numEl-1 (earning of adding an element) - int nE = 10, nF = 20; - - _qualVSnum = new double*[2]; - _qualVSnum[0] = new double[nE]; - for (int i = 0; i < nE; ++i) - _qualVSnum[0][i] = 1. - fabs(2./(i+1) - 1.); - _qualVSnum[1] = new double[nF]; - for (int i = 0; i < nF; ++i) - _qualVSnum[1][i] = 1. - fabs(4./(i+1) - 1.); - - _gains = new double*[2]; - _gains[0] = new double[nE-1]; - for (int i = 0; i < nE-1; ++i) - _gains[0][i] = _qualVSnum[0][i+1] - _qualVSnum[0][i]; - _gains[1] = new double[nF-1]; - for (int i = 0; i < nF-1; ++i) - _gains[1][i] = _qualVSnum[1][i+1] - _qualVSnum[1][i]; + unsigned int i = 0; + while (i < _edges.size()) { + if (_edges[i] == re) { + _edges[i] = _edges.back(); + _edges.pop_back(); + return; + } + ++i; } + Msg::Warning("[Rec2DVertex] Didn't removed edge, didn't have it"); } -void Rec2DVertex::remove(Rec2DEdge *re) +void Rec2DVertex::add(Rec2DElement *rel) { - std::vector<Rec2DEdge*>::iterator it = _edges.begin(); - bool b = false; - for (; it != _edges.end() ; ++it) - if (*it == re) { - _edges.erase(it--); - b = true; - break; + for (unsigned int i = 0; i < _elements.size(); ++i) { + if (_elements[i] == rel) { + Msg::Warning("[Rec2DVertex] Element was already there"); + return; } - if (b) { - Recombine2D::addValVert(getGain(-1)); - --_numEl; } - else - Msg::Error("[Rec2DVertex] Edge not found"); + if (_isMesh) + Rec2DData::addValVert(getGain(1)); + _elements.push_back(rel); } -void Rec2DVertex::getElements(std::set<Rec2DElement*> &elem) +bool Rec2DVertex::has(Rec2DElement *rel) const { - for (unsigned int i = 0; i < _elements.size(); ++i) - elem.insert(_elements[i]); + for (unsigned int i = 0; i < _elements.size(); ++i) { + if (_elements[i] == rel) + return true; + } + return false; } +void Rec2DVertex::remove(Rec2DElement *rel) +{ + unsigned int i = 0; + while (i < _elements.size()) { + if (_elements[i] == rel) { + _elements[i] = _elements.back(); + _elements.pop_back(); + return; + } + ++i; + } + Msg::Warning("[Rec2DVertex] Didn't removed element, didn't have it"); +} -/** Rec2DEdge **/ -/*****************/ -Rec2DEdge::Rec2DEdge(MEdge e, mapofVertices &vert, std::vector<MTriangle*> &tri) -: _lastChange(-1), _qual(.0), _weight(REC2D_EDGE_BASE), - _rv1(vert[e.getVertex(0)]), _rv2(vert[e.getVertex(1)]) + +/** Rec2DElement **/ +/********************/ +Rec2DElement::Rec2DElement(MTriangle *t) : _mEl((MElement *)t), _numEdge(3) { - _rv1->add(this); - _rv2->add(this); - if (tri.size() == 2) { - Rec2DElement *t0 = Recombine2D::getRElement(tri[0]); - Rec2DElement *t1 = Recombine2D::getRElement(tri[1]); - t0->add(this, t1); - t1->add(this, t0); + for (int i = 0; i < 4; ++i) { + _edges[i] = NULL; + _elements[i] = NULL; } - else if (tri.size() == 1) - Recombine2D::getRElement(tri[0])->add(this); - else - Msg::Error("[Rec2DEdge] Wrong number of triangles"); + Rec2DData::add(this); } -Rec2DEdge::Rec2DEdge(Rec2DVertex *rv1, Rec2DVertex *rv2) -: _lastChange(-1), _qual(.0), _weight(REC2D_EDGE_BASE), _rv1(rv1), _rv2(rv2) +Rec2DElement::Rec2DElement(MQuadrangle *q) : _mEl((MElement *)q), _numEdge(4) { + for (int i = 0; i < 4; ++i) { + _edges[i] = NULL; + _elements[i] = NULL; + } + Rec2DData::add(this); } -double Rec2DEdge::getQual() +Rec2DElement::Rec2DElement(Rec2DEdge **edges) : _mEl(NULL), _numEdge(4) { - if (_lastChange < Recombine2D::getNumChange()) - _computeQual(); - return _qual; + for (int i = 0; i < 4; ++i) { + _edges[i] = edges[i]; + _elements[i] = Rec2DEdge::getSingleElement(edges[i]); + if (_elements[i]) + _elements[i]->addNeighbour(_edges[i], this); + } + std::vector<Rec2DVertex*> vertices(4); + getVertices(vertices); + for (unsigned int i = 0; i < 4; ++i) { + vertices[i]->add(this); + } + Rec2DData::add(this); } -void Rec2DEdge::_computeQual() //* +Rec2DElement::~Rec2DElement() { - //if (!_rv1->update() && !_rv2->update()) - // return; - static int i = 0; if (++i < 2) Msg::Warning("FIXME compute qual edge and update of vertex"); - //_rv1->update(); - //_rv2->update(); - double adimLength = _straightAdimLength(); - double alignment = _straightAlignment(); - if (adimLength > 1) - adimLength = 1/adimLength; - _qual = adimLength * ((1-REC2D_ALIGNMENT) + REC2D_ALIGNMENT * alignment); - _lastChange = Recombine2D::getNumChange(); + if (_actions.size()) + Msg::Error("[Rec2DElement] I didn't want to be deleted :'("); + for (int i = 0; i < _numEdge; ++i) { + if (_elements[i]) + _elements[i]->removeNeighbour(_edges[i], this); + } + std::vector<Rec2DVertex*> vertices(_numEdge); + getVertices(vertices); + for (unsigned int i = 0; i < _numEdge; ++i) { + vertices[i]->remove(this); + } + Rec2DData::remove(this); } -double Rec2DEdge::_straightAdimLength() +void Rec2DElement::add(Rec2DEdge *re) { - double dx, dy, dz, **xyz; - xyz = new double*[2]; - xyz[0] = new double[3]; - xyz[1] = new double[3]; - _rv1->getxyz(xyz[0]); - _rv2->getxyz(xyz[1]); - dx = xyz[0][0] - xyz[1][0]; - dy = xyz[0][1] - xyz[1][1]; - dz = xyz[0][2] - xyz[1][2]; - double length = sqrt(dx * dx + dy * dy + dz * dz); - delete[] xyz[0]; - delete[] xyz[1]; - delete[] xyz; - - double lc1 = (*Recombine2D::bgm())(_rv1->u(), _rv1->v(), .0); - double lc2 = (*Recombine2D::bgm())(_rv2->u(), _rv2->v(), .0); + int i; + for (i = 0; i < _numEdge; ++i) { + if (_edges[i] == re) { + Msg::Warning("[Rec2DElement] Edge was already there"); + return; + } + if (_edges[i] == NULL) { + _edges[i] = re; + break; + } + } + if (i == _numEdge) + Msg::Error("[Rec2DElement] Already %d edges, can't add anymore", _numEdge); - return length * (1/lc1 + 1/lc2) / 2; + if (_numEdge == 4) + re->addQuadNeighbour(); + re->addNeighbour(); } -double Rec2DEdge::_straightAlignment() +bool Rec2DElement::has(Rec2DEdge *re) const { - double angle1 = Recombine2D::bgm()->getAngle(_rv1->u(), _rv1->v(), .0); - double angle2 = Recombine2D::bgm()->getAngle(_rv1->u(), _rv1->v(), .0); - double angleEdge = atan2(_rv1->u()-_rv2->u(), _rv1->v()-_rv2->v()); - - double alpha1 = angleEdge - angle1; - double alpha2 = angleEdge - angle2; - crossField2d::normalizeAngle(alpha1); - crossField2d::normalizeAngle(alpha2); - alpha1 = 1 - 4 * std::min(alpha1, .5 * M_PI - alpha1) / M_PI; - alpha2 = 1 - 4 * std::min(alpha2, .5 * M_PI - alpha2) / M_PI; - - double lc1 = (*Recombine2D::bgm())(_rv1->u(), _rv1->v(), .0); - double lc2 = (*Recombine2D::bgm())(_rv1->u(), _rv1->v(), .0); - - return (alpha1/lc1 + alpha2/lc2) / (1/lc1 + 1/lc2); + for (unsigned int i = 0; i < _numEdge; ++i) { + if (_edges[i] == re) + return true; + } + return false; } +void Rec2DElement::add(Rec2DAction *ra) +{ + for (unsigned int i = 0; i < _actions.size(); ++i) { + if (_actions[i] == ra) { + Msg::Warning("[Rec2DElement] Action was already there"); + return; + } + } + _actions.push_back(ra); +} -/** Rec2DElement **/ -/********************/ -void Rec2DElement::add(Rec2DEdge *re) +void Rec2DElement::removeT(Rec2DAction *ra) +{ + unsigned int i = 0; + while (i < _actions.size()) { + if (_actions[i] == ra) { + _actions[i] = _actions.back(); + _actions.pop_back(); + return; + } + ++i; + } + Msg::Warning("[Rec2DElement] Didn't removed action, didn't have it"); +} + +void Rec2DElement::addNeighbour(Rec2DEdge *re, Rec2DElement *rel) +{ + for (int i = 0; i < _numEdge; ++i) { + if (_edges[i] == re) { + if (_elements[i] != NULL && _elements[i] != rel) + Msg::Error("[Rec2DElement] Have already a neighbour element"); + _elements[i] = rel; + return; + } + } + Msg::Error("[Rec2DElement] Edge not found"); +} + + +void Rec2DElement::removeNeighbour(Rec2DEdge *re, Rec2DElement *rel) +{ + for (int i = 0; i < _numEdge; ++i) { + if (_edges[i] == re) { + if (_elements[i] == rel) + _elements[i] = NULL; + else + Msg::Error("[Rec2DElement] I didn't know this element was my neighbour..."); + return; + } + } + Msg::Error("[Rec2DElement] Edge not found"); +} + + +void Rec2DElement::getMoreEdges(std::vector<Rec2DEdge*> &edges) const +{ + for (int i = 0; i < _numEdge; ++i) + edges.push_back(_edges[i]); +} + +void Rec2DElement::getVertices(std::vector<Rec2DVertex*> &verts) const +{ + verts.resize(_numEdge); + int i = 0, k = 0; + while (k < _numEdge) { + verts[k] = _edges[i/2]->getVertex(i%2); + bool b = true; + for (unsigned int j = 0; j < k; ++j) { + if (verts[k] == verts[j]) + b = false; + } + if (b) ++k; + ++i; + } +} + +void Rec2DElement::getUniqueActions(std::vector<Rec2DAction*> &vectRA) const +{ + for (unsigned int i = 0; i < _actions.size(); ++i) { + unsigned int j = -1; + while (++j < vectRA.size() && vectRA[j] != _actions[i]); + if (j == vectRA.size()) + vectRA.push_back(_actions[i]); + } +} + +Rec2DEdge* Rec2DElement::getCommonEdge(Rec2DElement *rel0, Rec2DElement *rel1) +{ + for (unsigned int i = 0; i < rel0->_numEdge; ++i) { + if (rel1->has(rel0->_edges[i])) + return rel0->_edges[i]; + } + Msg::Error("[Rec2DElement] didn't find edge, returning NULL"); + return NULL; +} + +Rec2DVertex* Rec2DElement::getOtherVertex(Rec2DVertex *rv1, Rec2DVertex *rv2) const { - int i = -1; - while (_redges[++i] && i < 4); - if (_redges[i]) - Msg::Error("[Rec2DElement] too much edges"); - _redges[i] = re; + if (_numEdge == 4) { + Msg::Error("[Rec2DElement] I'm not a triangle"); + return NULL; + } + for (int i = 0; i < 2; ++i) { + Rec2DVertex *rv = _edges[i]->getVertex(0); + if (rv != rv1 && rv != rv2) + return rv; + rv = _edges[i]->getVertex(1); + if (rv != rv1 && rv != rv2) + return rv; + } + Msg::Error("[Rec2DElement] I should not be here... Why this happen to me ?"); + return NULL; } -void Rec2DElement::add(Rec2DEdge *re, Rec2DElement *el) +MQuadrangle* Rec2DElement::_createQuad() const { - int i = -1; - while (_redges[++i] && i < 4); - if (_redges[i]) - Msg::Error("[Rec2DElement] too much edges"); - _redges[i] = re; - _relements[i] = el; + if (_numEdge != 4) { + Msg::Error("[Rec2DElement] Why do you ask me to do this ? You know I can't do it ! COULD YOU LEAVE ME KNOW ?"); + return new MQuadrangle(NULL, NULL, NULL, NULL); + } + MVertex *v1, *v2, *v3, *v4; + v1 = _edges[0]->getVertex(0)->getMVertex(); + v2 = _edges[0]->getVertex(1)->getMVertex(); + int I; + for (unsigned int i = 1; i < 4; ++i) { + if (v2 == _edges[i]->getVertex(0)->getMVertex()) { + v3 = _edges[i]->getVertex(1)->getMVertex(); + I = i; + break; + } + if (v2 == _edges[i]->getVertex(1)->getMVertex()) { + v3 = _edges[i]->getVertex(0)->getMVertex(); + I = i; + break; + } + } + for (unsigned int i = 1; i < 4; ++i) { + if (i == I) continue; + if (v3 == _edges[i]->getVertex(0)->getMVertex()) { + v4 = _edges[i]->getVertex(1)->getMVertex(); + break; + } + if (v3 == _edges[i]->getVertex(1)->getMVertex()) { + v4 = _edges[i]->getVertex(0)->getMVertex(); + break; + } + } + return new MQuadrangle(v1, v2, v3, v4); } diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h index ebd9f872adcd0d1f8aa077ac9f9fece409bba74a..f786283249f6fd2d452b13f1c501144e97cce1bd 100644 --- a/Mesh/meshGFaceRecombine.h +++ b/Mesh/meshGFaceRecombine.h @@ -1,4 +1,4 @@ -// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle +// Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. @@ -11,414 +11,306 @@ #define _MESH_GFACE_RECOMBINE_H_ #include "GFace.h" -#include "GModel.h" -#include "MEdge.h" #include "BackgroundMesh.h" +//#include "GModel.h" +//#include "MEdge.h" + +#define REC2D_EDGE_BASE 1 +#define REC2D_EDGE_QUAD 1 +#define REC2D_ALIGNMENT .5 +#define REC2D_WAIT_TIME .05 +#define REC2D_NUM_ACTIO 1000 +// #define REC2D_SMOOTH + #define REC2D_DRAW class Rec2DVertex; class Rec2DEdge; class Rec2DElement; class Rec2DAction; +class Rec2DData; -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; - -struct lessRec2DAction { - bool operator()(Rec2DAction*, Rec2DAction*) const; -}; +//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 : - int _numEdge, _numVert, _numChange; - double _valEdge, _valVert; GFace *_gf; backgroundMesh *_bgm; - mapofVertices _vertices; - mapofEdges _edges; - mapofElements _elements; - setofRec2DAction _actions; - mapofElementActions _mea; - mapofAdjacencies _ma; - std::map<int, std::set<Rec2DVertex*> > _parities; - std::vector<Rec2DAction*> _obsoleteAction; + Rec2DData *_data; static Recombine2D *_current; - std::vector<MTriangle*> _tri; - std::vector<MQuadrangle*> _quad; - std::vector<Rec2DVertex*> _checkAllQuad; + int _numChange; public : - static bool bo; - Recombine2D(GFace*); - Recombine2D(GModel*); ~Recombine2D(); bool recombine(); - void apply(bool){return;} - - static int getNumVertAllQuad() {return _current->_checkAllQuad.size();} - static Rec2DVertex* getVertAllQuad(int i) {return _current->_checkAllQuad[i];} - static void removeVertAllQuad(Rec2DVertex *rv) { - std::vector<Rec2DVertex*>::iterator it = _current->_checkAllQuad.begin(); - while (it != _current->_checkAllQuad.end()) { - if (*it == rv) - it = _current->_checkAllQuad.erase(it); - else - ++it; - } - } - static void addVertAllQuad(Rec2DVertex *rv) { - _current->_checkAllQuad.push_back(rv); - } - //static inline double edgeReward(double adimLength, double alignment) - // {return adimLength * ((1-REC2D_ALIGNMENT) + REC2D_ALIGNMENT * alignment);} + static inline GFace* getGFace() {return _current->_gf;} static inline int getNumChange() {return _current->_numChange;} static inline backgroundMesh* bgm() {return _current->_bgm;} + //recombine : if _current==this ok ! + + private : + double _geomAngle(MVertex*, + std::vector<GEdge*>&, + std::vector<MElement*>&); +}; + +class Rec2DData { + private : + int _numEdge, _numVert; + double _valEdge, _valVert; + static Rec2DData *_current; + + std::set<Rec2DEdge*> _edges; + std::set<Rec2DVertex*> _vertices; + std::set<Rec2DElement*> _elements; + + std::list<Rec2DAction*> _actions; + std::map<int, std::vector<Rec2DVertex*> > _parities; + + public : + Rec2DData(int numTri, int numQuad); + ~Rec2DData(); + + void printState(); +#ifdef REC2D_DRAW + std::vector<MTriangle*> _tri; + std::vector<MQuadrangle*> _quad; +#endif + + static double getGlobalValue(); static double getGlobalValue(int numEdge, double valEdge, int numVert, double valVert ); - //static Rec2DVertex* getRVertex(MVertex*); - static Rec2DEdge* getREdge(MEdge); - static Rec2DElement* getRElement(MElement*); - static void remove(MEdge); - static void remove(MVertex*); - static inline GFace* getGFace() {return _current->_gf;} - static inline void addObsleteAction(Rec2DAction *a) { - _current->_obsoleteAction.push_back(a); - } // correct ? - static inline void addNumEdge(int a) {_current->_numEdge += a;} - static inline void addNumVert(int a) {_current->_numVert += a;} - static inline void addValEdge(double a) {_current->_valEdge += a;} - static inline void addValVert(double a) {_current->_valVert += a;} + static Rec2DAction* getBestAction(); + + typedef std::set<Rec2DEdge*>::iterator iter_re; + typedef std::set<Rec2DVertex*>::iterator iter_rv; + typedef std::set<Rec2DElement*>::iterator iter_rel; + static inline iter_re firstEdge() {return _current->_edges.begin();} + static inline iter_rv firstVertex() {return _current->_vertices.begin();} + static inline iter_rel firstElement() {return _current->_elements.begin();} + static inline iter_re lastEdge() {return _current->_edges.end();} + static inline iter_rv lastVertex() {return _current->_vertices.end();} + static inline iter_rel lastElement() {return _current->_elements.end();} + + static inline void add(Rec2DEdge *re) {_current->_edges.insert(re);} + static inline void add(Rec2DVertex *rv) {_current->_vertices.insert(rv);} +#ifndef REC2D_DRAW + static inline void add(Rec2DElement *rel) {_current->_elements.insert(rel);} +#else + static void add(Rec2DElement *rel); +#endif + static inline void add(Rec2DAction *ra) {_current->_actions.push_back(ra);} + static void remove(Rec2DEdge*); + static void remove(Rec2DVertex*); static void remove(Rec2DElement*); static void remove(Rec2DAction*); - static void add(MQuadrangle*); - - static inline void addVert2Par(Rec2DVertex *rv, int a) - {_current->_parities[a].insert(rv);} - static void associateParity(int pOld, int pNew); - static inline int highPar() { - std::map<int, std::set<Rec2DVertex*> >::iterator it; - it = _current->_parities.end(); - --it; - return it->first + 1; - } - private : - bool _isAllQuad(Rec2DAction *action); - void _choose(Rec2DAction*); - void _removeIncompatible(Rec2DAction*); - void _removeReference(Rec2DAction*); - void _getNeighbours(Rec2DAction*, std::set<Rec2DAction*>&); - void _getElemToLook(int par, std::set<Rec2DElement*>&); + static int getNewParity(); + static void removeParity(Rec2DVertex*, int); + static inline void addParity(Rec2DVertex *rv, int p) + {_current->_parities[p].push_back(rv);} + + static inline void addVert(int num, double val) { + _current->_numVert += num; + _current->_valVert += val; + } + static inline void addValVert(double val) {_current->_valVert += val;} + static inline void addEdge(int num, double val) { + _current->_numEdge += num; + _current->_valEdge += val; + } +}; + +struct lessRec2DAction { + bool operator()(Rec2DAction*, Rec2DAction*) const; }; class Rec2DAction { - private : - int _position; - protected : - int _lastUpdate; // + _lastCheck double _globValIfExecuted; + int _lastUpdate; public : - virtual ~Rec2DAction() {Recombine2D::remove(this);} + virtual inline ~Rec2DAction() {Rec2DData::remove(this);} bool operator<(Rec2DAction&); - inline int getVectPosition() const {return _position;} - inline void setVectPosition(int p) {_position = p;} - - virtual int getNum() = 0; - virtual double getReward() { - if (_lastUpdate < Recombine2D::getNumChange()) - _computeGlobVal(); - return _globValIfExecuted - Recombine2D::getGlobalValue(0, .0, 0, .0); - } - virtual bool isObsolete() = 0; - virtual void getRTriangles(std::set<Rec2DElement*>&) = 0; - virtual Rec2DElement* getRTriangle(int) = 0; - virtual void apply() = 0; - virtual void getParities(int*) = 0; - virtual Rec2DVertex* getRVertex(int) = 0; + virtual double getReward(); virtual void color(int, int, int) = 0; - virtual bool whatImply(Rec2DVertex**, int*, - std::map<Rec2DVertex*, std::vector<int> >&) = 0; - - protected : - MQuadrangle* _createQuad(std::vector<Rec2DEdge*>&) const; - + virtual void apply() = 0; + private : virtual void _computeGlobVal() = 0; }; class Rec2DTwoTri2Quad : public Rec2DAction { private : - Rec2DElement *_rtriangles[2]; - Rec2DEdge *_edges[5]; // 1 embedded, 4 boundary + Rec2DElement *_triangles[2]; + Rec2DEdge *_edges[5]; // 4 boundary, 1 embedded Rec2DVertex *_vertices[4]; // 4 boundary (2 on embedded edge + 2) public : - Rec2DTwoTri2Quad(Rec2DEdge*, std::vector<MTriangle*>&); + Rec2DTwoTri2Quad(Rec2DElement*, Rec2DElement*); ~Rec2DTwoTri2Quad(); - bool isObsolete(); - void getRTriangles(std::set<Rec2DElement*> &tri) { - tri.insert(_rtriangles[0]); - tri.insert(_rtriangles[1]); - } - Rec2DElement* getRTriangle(int a) { - return _rtriangles[a]; - } - void apply(); - void getParities(int*); - Rec2DVertex* getRVertex(int i) {return _vertices[i];} - void color(int, int, int); - virtual bool whatImply(Rec2DVertex**, int*, - std::map<Rec2DVertex*, std::vector<int> >&); - static bool isObsolete(int*); - - int getNum() {return 1;} - private : - void _computeGlobVal(); -}; - -/*class Rec2DFourTri2Quad : public Rec2DAction { - private : - Rec2DElement *_rtriangles[4]; - Rec2DEdge *_edges[8]; // 4 embedded, 4 boundary - Rec2DVertex *_vertices[5]; // 4 boundary (2 non adjacent + 2), 1 embedded - public : - Rec2DFourTri2Quad(Rec2DVertex*, std::vector<MTriangle*>&); - ~Rec2DFourTri2Quad(); - bool isObsolete(); - void getRTriangles(std::set<Rec2DElement*> &tri) { - tri.insert(_rtriangles[0]); - tri.insert(_rtriangles[1]); - tri.insert(_rtriangles[2]); - tri.insert(_rtriangles[3]); - } - Rec2DElement* getRTriangle(int a) { - return _rtriangles[a]; - } - void apply(); - void getParities(int*); - Rec2DVertex* getRVertex(int i) {return _vertices[i];} - void color(int, int, int); - virtual void whatImply(Rec2DVertex**, int*, - std::map<Rec2DVertex*, std::vector<int> >&) - {return;} - - int getNum() {return 2;} + virtual void color(int, int, int); + virtual void apply(); + private : - void _computeGlobVal(); + virtual void _computeGlobVal(); }; -class Rec2DCollapseTri : public Rec2DAction { +class Rec2DEdge { private : - Rec2DElement *_rtriangles[4]; // either 2 or 4 triangles - Rec2DEdge *_edge; // 1 embedded or NULL - Rec2DVertex *_vertices[5]; // 4 boundary (2 on embedded edge + 2), 1 embedded or NULL - double _globValIfExecuted2; + Rec2DVertex *_rv0, *_rv1; + double _qual; + int _lastUpdate, _weight; + int _boundary; public : - Rec2DCollapseTri(Rec2DVertex*, std::vector<MTriangle*>&); - Rec2DCollapseTri(Rec2DEdge*, std::vector<MTriangle*>&); - ~Rec2DCollapseTri(); - double getReward() { - return std::max(_globValIfExecuted, _globValIfExecuted2) - - Recombine2D::getGlobalValue(0, .0, 0, .0); - } - bool isObsolete(); - void getRTriangles(std::set<Rec2DElement*> &tri) { - tri.insert(_rtriangles[0]); - tri.insert(_rtriangles[1]); - if (_rtriangles[2]) { - tri.insert(_rtriangles[2]); - tri.insert(_rtriangles[3]); - } - } - Rec2DElement* getRTriangle(int a) { - return _rtriangles[a]; - } - void apply(); - void getParities(int*); - Rec2DVertex* getRVertex(int i) {return _vertices[i];} - void color(int, int, int); - virtual void whatImply(Rec2DVertex**, int*, - std::map<Rec2DVertex*, std::vector<int> >&) - {return;} - - int getNum() {return 3;} - private : - void _computeGlobVal(); - void _qualCavity(double &valVert, double &valEdge, int &numEdge, - std::map<Rec2DVertex*, int> &vertices, - Rec2DVertex *imposedVert = NULL ); -};*/ -// - -class Rec2DListAction { - private : + Rec2DEdge(Rec2DVertex*, Rec2DVertex*); + ~Rec2DEdge(); + double getQual(); + double addNeighbour(); + double addQuadNeighbour(); - public : + inline bool isOnBoundary() const {return !_boundary;} + inline Rec2DVertex* getVertex(int i) const {if (i) return _rv1; return _rv0;} + + static Rec2DElement* getSingleElement(Rec2DEdge*); + + void swap(Rec2DVertex *oldRV, Rec2DVertex *newRV); + Rec2DVertex* getOtherVertex(Rec2DVertex*) const; + + private : + void _computeQual(); + double _straightAdimLength() const; + double _straightAlignment() const; +}; + +struct AngleData { + std::vector<GEdge*> _gEdges; + std::vector<MElement*> _mElements; + Rec2DVertex *_rv; + + AngleData() : _rv(NULL) {} }; class Rec2DVertex { private : MVertex *_v; + const double _angle; std::vector<Rec2DEdge*> _edges; std::vector<Rec2DElement*> _elements; - int _onWhat, _numEl, _parity, _lastChange; //lastMove + int _onWhat, _parity, _lastMove; // _onWhat={-1:corner,0:edge,1:face,(2:volume)} - double _angle, _qual; SPoint2 _param; + bool _isMesh; static double **_qualVSnum; static double **_gains; public : - Rec2DVertex(MVertex*, std::vector<MTriangle*>, int onWhat, - std::map<MVertex*, std::set<GEdge*> >); - Rec2DVertex(double u, double v); - - bool hasTriangle(); - inline void add(Rec2DEdge *re) {_edges.push_back(re);} - void remove(Rec2DEdge*); - inline void setOnBoundary() {if (_onWhat > 0) _onWhat = 0; - static bool a=1; if(a){Msg::Warning("FIXME boundary");a=0;}} - inline bool getIsOnBoundary() {return _onWhat < 1;} - double getQual(int numEdge = -1); - inline int getParity() {return _parity;} - inline void setParity(int p) { - _parity = p; - Recombine2D::addVert2Par(this, p); - } - inline MVertex* getMVertex() {return _v;} - void getxyz(double *xyz) { - xyz[0] = _v->x(); xyz[1] = _v->y(); xyz[2] = _v->z();} - inline double u() {return _param[0];} - inline double v() {return _param[1];} - inline void deleteMVertex() {delete _v;} - - double getGain(int); - void getNeighbours(std::map<Rec2DVertex*, int>&, std::set<Rec2DEdge*>&); - void getNeighbourEdges(std::set<Rec2DEdge*>&); - void getElements(std::set<Rec2DElement*>&); - - void remove(Rec2DElement *rel) { - std::vector<Rec2DElement*>::iterator it = _elements.begin(); - while (it != _elements.end()) { - if (*it == rel) - it = _elements.erase(it); - else - ++it; - } - } + Rec2DVertex(MVertex*, bool toSave = true); + Rec2DVertex(Rec2DVertex*, double angle); + ~Rec2DVertex(); static void initStaticTable(); + static Rec2DEdge* getCommonEdge(Rec2DVertex*, Rec2DVertex*); + static void getCommonElements(Rec2DVertex*, Rec2DVertex*, + std::vector<Rec2DElement*>&); + + inline void setOnBoundary() {if (_onWhat > 0) _onWhat = 0;} + inline bool getOnBoundary() const {return _onWhat < 1;} + bool setBoundaryParity(int p0, int p1); + inline int getParity() const {return _parity;} + void setParity(int); + inline int getNumElements() const {return _elements.size();} + inline MVertex* getMVertex() const {return _v;} + + inline int getLastMove() const {return _lastMove;} + inline void getxyz(double *xyz) const { + xyz[0] = _v->x(); + xyz[1] = _v->y(); + xyz[2] = _v->z(); + } + inline double u() const {return _param[0];} + inline double v() const {return _param[1];} - private : - void _computeQual(); - double _computeAngle(MVertex*, std::vector<MTriangle*>&, std::set<GEdge*>&); -}; - -class Rec2DEdge { - private : - Rec2DVertex *_rv1, *_rv2; - double _qual; - int _lastChange, _weight; //lastUpdate + double getQual(int numEl = -1) const; + double getGain(int) const; - public : - Rec2DEdge(MEdge, mapofVertices&, std::vector<MTriangle*>&); - Rec2DEdge(Rec2DVertex*, Rec2DVertex*); + void add(Rec2DEdge*); + bool has(Rec2DEdge*) const; + void remove(Rec2DEdge*); - double getQual(); - inline MEdge getMEdge() {return MEdge(_rv1->getMVertex(), _rv2->getMVertex());} - inline Rec2DVertex* getRVertex(int i) {if (i) return _rv2; return _rv1;} - int getWeight() {return _weight;} - double getWeightedQual() {return _weight * _qual;} + void add(Rec2DElement*); + bool has(Rec2DElement*) const; + void remove(Rec2DElement*); private : - void _computeQual(); - double _straightAdimLength(); - double _straightAlignment(); + bool _recursiveBoundParity(Rec2DVertex *prev, int p0, int p1); }; class Rec2DElement { private : - Rec2DEdge *_redges[4]; // if triangle, _redges[3] == NULL - Rec2DElement *_relements[4]; // NULL if no neighbour - MElement *_mEl; // can be NULL + int _numEdge; + Rec2DEdge *_edges[4]; + Rec2DElement *_elements[4]; // NULL if no neighbour + MElement *_mEl; // can be NULL std::vector<Rec2DAction*> _actions; public : - Rec2DElement(MTriangle *t) : _mEl((MElement *)t) { - for (int i = 0; i < 4; ++i) { - _redges[i] = NULL; - } - } + Rec2DElement(MTriangle*); + Rec2DElement(MQuadrangle*); + Rec2DElement(Rec2DEdge**); + ~Rec2DElement(); void add(Rec2DEdge*); - void add(Rec2DEdge*, Rec2DElement*); - inline MElement* getMElement() {return _mEl;} - inline MTriangle* getMTriangle() - {if (_redges[3])return NULL; return (MTriangle*) _mEl;} - inline bool isQuad() {return _redges[3];} - inline void add(Rec2DAction *ra) {_actions.push_back(ra);} - void remove(Rec2DAction *ra) { - std::vector<Rec2DAction*>::iterator it = _actions.begin(); - while (it != _actions.end()) { - if (*it == ra) it = _actions.erase(it); - else ++it; - } - } - inline int getNum() {return _mEl->getNum();} - inline int getNumActions() {return _actions.size();} - inline Rec2DAction* getAction(int i) {return _actions[i];} - void getVertices(Rec2DVertex **v) { - v[0] = _redges[0]->getRVertex(0); - v[1] = _redges[0]->getRVertex(1); - if (_redges[1]->getRVertex(0) == v[0] || - _redges[1]->getRVertex(0) == v[1] ) - v[2] = _redges[1]->getRVertex(1); - else - v[2] = _redges[1]->getRVertex(0); - } - void getActions(std::set<Rec2DAction*> &actions) { - for (unsigned int i = 0; i < _actions.size(); ++i) - actions.insert(_actions[i]); - } - void getNeighbours(std::set<Rec2DElement*> &elem) { - for (int i = 0; i < 4; ++i) { - if (_relements[i]) - elem.insert(_relements[i]); + bool has(Rec2DEdge*) const; + void add(Rec2DAction*); + void removeT(Rec2DAction*); + void addNeighbour(Rec2DEdge*, Rec2DElement*); + void removeNeighbour(Rec2DEdge*, Rec2DElement*); + inline MElement* getMElement() const {return _mEl;} +#ifdef REC2D_DRAW + MTriangle* getMTriangle() { + if (_numEdge == 3) { + if (_mEl) + return (MTriangle*) _mEl; + else + Msg::Error("[Rec2DElement] Do you thing I'll create a triangle for you ?"); } + return NULL; } - Rec2DVertex* getOtherVertex(Rec2DVertex *rv1, Rec2DVertex *rv2) { - if (_redges[3]) { - Msg::Error("[Rec2DElement] I'm not a triangle"); - return NULL; + MQuadrangle* getMQuadrangle() { + if (_numEdge == 4) { + if (!_mEl) + _mEl = (MElement*) _createQuad(); + return (MQuadrangle*) _mEl; } - std::set<Rec2DVertex*> vert; - for (int i = 0; i < 3; ++i) { - vert.insert(_redges[i]->getRVertex(0)); - vert.insert(_redges[i]->getRVertex(1)); - } - std::set<Rec2DVertex*>::iterator it = vert.begin(); - for (; it != vert.end(); ++it) { - if (*it != rv1 && *it != rv2) - return *it; - } - Msg::Error("[Rec2DElement] I should not be here... Why this happen to me ?"); return NULL; } +#endif + + void getMoreEdges(std::vector<Rec2DEdge*>&) const; + void getVertices(std::vector<Rec2DVertex*>&) const; + void getUniqueActions(std::vector<Rec2DAction*>&) const; + static Rec2DEdge* getCommonEdge(Rec2DElement*, Rec2DElement*); + + Rec2DVertex* getOtherVertex(Rec2DVertex*, Rec2DVertex*) const; + + private : + MQuadrangle* _createQuad() const; }; #endif \ No newline at end of file