From ea2ec757c7db07f387feeb461bf7a43ccaac8e01 Mon Sep 17 00:00:00 2001 From: Amaury Johnan <amjohnen@gmail.com> Date: Mon, 16 Jan 2012 07:44:08 +0000 Subject: [PATCH] --- Mesh/meshGFaceRecombine.cpp | 734 ++++++++++++++++++++++++++++++++++-- Mesh/meshGFaceRecombine.h | 132 ++++++- 2 files changed, 814 insertions(+), 52 deletions(-) diff --git a/Mesh/meshGFaceRecombine.cpp b/Mesh/meshGFaceRecombine.cpp index 53abddba3d..af69ab0b1a 100644 --- a/Mesh/meshGFaceRecombine.cpp +++ b/Mesh/meshGFaceRecombine.cpp @@ -7,21 +7,49 @@ // Amaury Johnen (a.johnen@ulg.ac.be) // -// TODO : -// - recombine w. take care of parity, update of quality... - #include "meshGFaceRecombine.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" -#define EDGE_BASE 2 -#define EDGE_QUAD 1 +#define REC2D_EDGE_BASE 1 +#define REC2D_EDGE_QUAD 1 +#define REC2D_WAIT_TIME 1 + +// #define REC2D_SMOOTH + #define REC2D_DRAW Recombine2D *Recombine2D::_current = NULL; bool Recombine2D::bo = 0; double **Rec2DVertex::_qualVSnum = NULL; double **Rec2DVertex::_gains = NULL; +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); + if (pOld % 2) + pOld -= 1; + else + pOld +=1; + if (pNew % 2) + pNew -= 1; + else + pNew +=1; + 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) @@ -38,6 +66,8 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf) _numEdge = _numVert = 0; _valEdge = _valVert = .0; + _tri = _gf->triangles; + // Be able to compute geometrical angle at corners std::map<MVertex*, std::set<GEdge*> > mapCornerVert; { @@ -91,11 +121,11 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf) itE2E = _edges.insert(itE2E, std::make_pair(e,re)); _vertices[e.getVertex(0)]->add(re); _vertices[e.getVertex(1)]->add(re); - _numEdge += EDGE_BASE; - _valEdge += EDGE_BASE * re->getQual(); + _numEdge += REC2D_EDGE_BASE; + _valEdge += REC2D_EDGE_BASE * re->getQual(); if (itedge->second.size() == 1) { - _numEdge += EDGE_QUAD; - _valEdge += EDGE_QUAD * re->getQual(); + _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); @@ -145,7 +175,7 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf) boundV2E.erase(itBound); } if (_vertices[actualV]->getParity() != actualParity+p) - Msg::Error("Not even number of mesh edges on boundary !"); + Msg::Error("[Recombine2D] Not even number of mesh edges on boundary !"); boundV2E.erase(boundV2E.begin()); itBound = boundV2E.begin(); @@ -159,19 +189,68 @@ Recombine2D::Recombine2D(GFace *gf) : _gf(gf) std::map<MEdge, std::list<MTriangle*> >::iterator ite = mapEdge.begin(); for (; ite != mapEdge.end(); ++ite) if (ite->second.size() == 2) { - _actions.insert(new Rec2DTwoTri2Quad(_edges[ite->first], ite->second)); - _actions.insert(new Rec2DCollapseTri(_edges[ite->first], ite->second)); + 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::list<MTriangle*>::iterator it = ite->second.begin(); + _mea[*it].insert(q); + //_mea[*it].insert(c); + ++it; + _mea[*it].insert(q); + //_mea[*it].insert(c); } } + // Rec2DTwoTri2Quad + /*{ + std::list<std::map<MVertex*, std::list<MTriangle*> >::iterator>::iterator it4; + for (it4 = fourTri.begin(); it4 != fourTri.end(); it4++) { + Rec2DVertex *rv = _vertices[(*it4)->first]; + std::set<MEdge, Less_Edge> setEdge; + { + std::list<MTriangle*>::iterator it = (*it4)->second.begin(); + for (; it != (*it4)->second.end(); ++it) { + setEdge.insert((*it)->getEdge(0)); + setEdge.insert((*it)->getEdge(1)); + setEdge.insert((*it)->getEdge(2)); + } + } + + std::set<MEdge>::iterator it = setEdge.begin(); + for (; it != setEdge.end(); ++it) { + std::map<MEdge, std::list<MTriangle*> >::iterator it2; + it2 = mapEdge.find(*it); + if (it2 != mapEdge.end()) + if (it2->second.size() == 2) { + Rec2DTwoTri2Quad *q = new Rec2DTwoTri2Quad(_edges[it2->first], it2->second); + _actions.insert(q); + std::list<MTriangle*>::iterator it = it2->second.begin(); + _mea[*it].insert(q); + ++it; + _mea[*it].insert(q); + } + else + Msg::Error("fjdaks;lfjkdsa;"); + } + } + }*/ + // Create the 'Rec2DFourTri2Quad' and 'Rec2DCollapseTri' { std::list<std::map<MVertex*, std::list<MTriangle*> >::iterator>::iterator it4; for (it4 = fourTri.begin(); it4 != fourTri.end(); it4++) { Rec2DVertex *rv = _vertices[(*it4)->first]; if (!rv->getIsOnBoundary()) { - _actions.insert(new Rec2DFourTri2Quad(rv, (*it4)->second)); - _actions.insert(new Rec2DCollapseTri(rv, (*it4)->second)); + Rec2DFourTri2Quad *q = new Rec2DFourTri2Quad(rv, (*it4)->second); + //Rec2DCollapseTri *c = new Rec2DCollapseTri(rv, (*it4)->second); + _actions.push_back(q); + //_actions.insert(c); + std::list<MTriangle*>::iterator it = (*it4)->second.begin(); + for (; it != (*it4)->second.end(); ++it) { + _mea[*it].insert(q); + //_mea[*it].insert(c); + } } } } @@ -202,11 +281,340 @@ Recombine2D::~Recombine2D() //delete vertices, edges, actions; } +bool Recombine2D::recombine() +{ + Rec2DAction *nextAction; + while (_actions.size() > 0) { + double t = Cpu(); + nextAction = *std::max_element(_actions.begin(), _actions.end(), + lessRec2DAction() ); + 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); + } + + _gf->triangles = _tri; + _gf->quadrangles = _quad; +#ifdef REC2D_DRAW + CTX::instance()->mesh.changed = (ENT_ALL); + FlGui::instance()->check(); + drawContext::global()->draw(); + while (Cpu()-t < 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()); + } + } + + 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) +{ + int p[4]; + action->getParities(p); + + if (p[0] < 0 && p[1] < 0 && p[2] < 0 && p[3] < 0) + return true; + + if (action->isObsolete()) { + Msg::Error("[Recombine2D] obsolete action"); + return false; + } + + int min = 100, index; + for (int i = 0; i < 4; ++i) { + if (p[i] > -1 && min > p[i]) { + min = p[i]; + index = i; + } + } + + //Quid si p[0..4] = -1 ? + + std::map<Rec2DVertex*, int> newParVert; + std::map<int, int> parAssoc; // first parity value become second parity value + + for (int i = 0; i < 4; i += 2) { + int par; + if ((index/2) * 2 == i) + par = min; + else if (min % 2) + par = min - 1; + else + par = min + 1; + for (int j = 0; j < 2; ++j) { + if (p[i+j] == -1) + newParVert.insert(std::make_pair(action->getRVertex(i+j), par)); + else if (p[i+j] != par) + parAssoc.insert(std::make_pair(p[i+j], par)); + } + } + + std::set<Rec2DAction*> neighbours; + _getNeighbours(action, neighbours); + + while (neighbours.size() > 0) { + std::set<Rec2DAction*>::iterator it = neighbours.begin(); + if ((*it)->getNum() != 1) { + neighbours.erase(it); + continue; + } + Rec2DVertex *v0 = (*it)->getRVertex(0); + Rec2DVertex *v1 = (*it)->getRVertex(1); + std::map<Rec2DVertex*, int>::iterator it2; + int p0 = v0->getParity(), p1 = v1->getParity(); + if (p0 < 0 && (it2 = newParVert.find(v0)) == newParVert.end()) { + neighbours.erase(it); + continue; + } + if (p0 < 0) + p0 = it2->second; + + if (p1 < 0 && (it2 = newParVert.find(v1)) == newParVert.end()) { + neighbours.erase(it); + continue; + } + if (p1 < 0) + p1 = it2->second; + + std::map<int, int>::iterator it3; + if ((it3 = parAssoc.find(p0)) != parAssoc.end()) + p0 = it3->second; + if ((it3 = parAssoc.find(p1)) != parAssoc.end()) + p1 = it3->second; + + if (p0 != p1) { + neighbours.erase(it); + continue; + } + + int par; + bool hasChange = false; + if (p0 % 2) + par = p0 - 1; + else + par = p0 + 1; + (*it)->getParities(p); + for (int j = 2; j < 4; ++j) { + if (p[j] == -1) { + if ((it2 = newParVert.find((*it)->getRVertex(j))) == newParVert.end()) { + newParVert.insert(std::make_pair(action->getRVertex(j), par)); + hasChange = true; + } + else if (it2->second != par) + return false; + } + else if (p[j] != par) { + if ((it3 = parAssoc.find(p[j])) == parAssoc.end()) { + parAssoc.insert(std::make_pair(p[j], par)); + hasChange = true; + } + else { + int a = it3->second; + while (a != par && (it3 = parAssoc.find(a)) != parAssoc.end()) { + a = it3->second; + } + if (a != par) + return false; + } + } + } + Rec2DAction *ra = *it; + neighbours.erase(it); + if (hasChange) + _getNeighbours(ra, neighbours); + } + return true; +} + +void Recombine2D::_choose(Rec2DAction *action) +{ + action->apply(); + _removeIncompatible(action); + ++_numChange; +} + +void Recombine2D::_removeIncompatible(Rec2DAction *action) +{ + std::set<MTriangle*> touchedTri; + action->getTriangles(touchedTri); + std::set<MTriangle*>::iterator itTouched; + + std::set<Rec2DAction*> incomp; + { + itTouched = touchedTri.begin(); + for (; itTouched != touchedTri.end(); ++itTouched) { + mapofElementActions::iterator ite2a = _mea.find(*itTouched); + if (ite2a != _mea.end()) { + std::set<Rec2DAction*>::iterator ita = ite2a->second.begin(); + for (; ita != ite2a->second.end(); ++ita) + incomp.insert(*ita); + } + else + Msg::Error("[Recombine2D] didn't found triangle %d (rmIncomp1)", (*itTouched)->getNum()); + } + } + + std::set<Rec2DAction*>::iterator itIncomp = incomp.begin(); + for (; itIncomp != incomp.end(); ++itIncomp) { + std::set<MTriangle*> touched; + (*itIncomp)->getTriangles(touched); + for (itTouched = touched.begin(); itTouched != touched.end(); ++itTouched) { + mapofElementActions::iterator ite2a = _mea.find(*itTouched); + if (ite2a != _mea.end()) { + bool b = ite2a->second.erase(*itIncomp); + if (!b) + Msg::Error("[Recombine2D] Tri->Action not found (rmIncomp)"); + } + else + Msg::Error("[Recombine2D] didn't found triangle %d (rmIncomp)", (*itTouched)->getNum()); + } + //bool b = _actions.erase(*itIncomp); + setofRec2DAction::iterator it2 = _actions.begin(); + bool b = false; + while (it2 != _actions.end()) { + if (*it2 == *itIncomp) { + _actions.erase(it2); + b = true; + break; + } + ++it2; + } + if (!b) + Msg::Error("[Recombine2D] action not found (rmIncomp2)"); + delete *itIncomp; + } + + itTouched = touchedTri.begin(); + for (; itTouched != touchedTri.end(); ++itTouched) { + bool b = _mea.erase(*itTouched); + if (!b) + Msg::Error("[Recombine2D] triangle not found %d", (*itTouched)->getNum()); + } +} + +void Recombine2D::_removeReference(Rec2DAction *action) +{ + std::set<MTriangle*> touchedTri; + action->getTriangles(touchedTri); + std::set<MTriangle*>::iterator it = touchedTri.begin(); + for (; it != touchedTri.end(); ++it) { + mapofElementActions::iterator ite2a = _mea.find(*it); + if (ite2a != _mea.end()) { + bool b = ite2a->second.erase(action); + if (!b) + Msg::Error("[Recombine2D] Tri->Action not found (rmRef)"); + } + else + Msg::Error("[Recombine2D] didn't found triangle %d (rmRef)", (*it)->getNum()); + } + //bool b = _actions.erase(action); + setofRec2DAction::iterator it2 = _actions.begin(); + bool b = false; + while (it2 != _actions.end()) { + if (*it2 == action) { + _actions.erase(it2); + b = true; + break; + } + ++it2; + } + if (!b) + Msg::Error("[Recombine2D] action not found (rmRef)"); + delete action; +} + +void Recombine2D::_getNeighbours(Rec2DAction *ra, std::set<Rec2DAction*> &actions) +{ + std::set<MTriangle*> touchedTri; + ra->getTriangles(touchedTri); + std::set<MTriangle*>::iterator itTouched; + + std::set<Rec2DAction*> incomp; + { + itTouched = touchedTri.begin(); + for (; itTouched != touchedTri.end(); ++itTouched) { + mapofElementActions::iterator ite2a = _mea.find(*itTouched); + if (ite2a != _mea.end()) { + std::set<Rec2DAction*>::iterator ita = ite2a->second.begin(); + for (; ita != ite2a->second.end(); ++ita) + incomp.insert(*ita); + } + else + Msg::Error("[Recombine2D.] didn't found triangle %d (rmIncomp1)", (*itTouched)->getNum()); + } + } + + std::set<Rec2DAction*>::iterator it = incomp.begin(); + for (; it != incomp.end(); ++it) { + (*it)->getTriangles(touchedTri); + } + + std::set<Rec2DAction*> neighbours; + { + itTouched = touchedTri.begin(); + for (; itTouched != touchedTri.end(); ++itTouched) { + mapofElementActions::iterator ite2a = _mea.find(*itTouched); + if (ite2a != _mea.end()) { + std::set<Rec2DAction*>::iterator ita = ite2a->second.begin(); + for (; ita != ite2a->second.end(); ++ita) + neighbours.insert(*ita); + } + else + Msg::Error("[Recombine2D.] didn't found triangle %d (rmIncomp1)", (*itTouched)->getNum()); + } + std::set<Rec2DAction*>::iterator itIncomp = incomp.begin(); + for (; itIncomp != incomp.end(); ++itIncomp) { + bool b = neighbours.erase(*itIncomp); + if (!b) + Msg::Error("[Recombine2D] didn't found incomp action"); + } + } + + for (it = neighbours.begin(); it != neighbours.end(); ++it) { + actions.insert(*it); + } +} + double Recombine2D::getGlobalValue(int numEdge, double valEdge, int numVert, double valVert ) { - return (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge) * - (_current->_valVert + valVert) / (_current->_numVert + numVert); + double a = (_current->_valVert + valVert) / (_current->_numVert + numVert); + return (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge) * a * a; } Rec2DEdge* Recombine2D::getREdge(MEdge e) @@ -227,6 +635,85 @@ Rec2DVertex* Recombine2D::getRVertex(MVertex *v) return NULL; } +void Recombine2D::remove(MEdge e) +{ + mapofEdges::iterator it = _current->_edges.find(e); + if (it != _current->_edges.end()) + _current->_edges.erase(it); + else + Msg::Error("[Recombine2D::getREdge] edge not found"); +} + +void Recombine2D::remove(MVertex *v) +{ + mapofVertices::iterator it = _current->_vertices.find(v); + if (it != _current->_vertices.end()) + _current->_vertices.erase(it); + else + Msg::Error("[Recombine2D::getRVertex] vertex not found"); +} + +void Recombine2D::remove(MTriangle *tri) +{ + std::vector<MTriangle*>::iterator it = _current->_tri.begin(); + for (; it != _current->_tri.end(); ++it) { + if (*it == tri) { + _current->_tri.erase(it); + return; + } + } + Msg::Error("[Recombine2D] triangle %d was not there", tri->getNum()); +} + +void Recombine2D::add(MQuadrangle *quad) +{ + _current->_quad.push_back(quad); +} + + +/** Rec2DAction **/ +/*******************/ +bool Rec2DAction::operator<(Rec2DAction &other) +{ + return getReward() < other.getReward(); +} + +MQuadrangle* Rec2DAction::_createQuad(std::vector<Rec2DEdge*> &boundEdge) const +{ + 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); +} + /** Rec2DTwoTri2Quad **/ /************************/ @@ -282,19 +769,97 @@ bool Rec2DTwoTri2Quad::isObsolete() return false; } +void Rec2DTwoTri2Quad::apply() +{ + if (isObsolete()) { + Msg::Error("[Rec2DTwoTri2Quad] Applying obsolet action"); + return; + } + + int min = 100, index = -1; + for (int i = 0; i < 4; ++i) { + if (_vertices[0]->getParity() > -1 && min > _vertices[0]->getParity()) { + min = _vertices[0]->getParity(); + index = i; + } + } + if (index == -1) { + int par = Recombine2D::highPar(); + _vertices[0]->setParity(par); + _vertices[1]->setParity(par); + _vertices[2]->setParity(par+1); + _vertices[3]->setParity(par+1); + } + else { + for (int i = 0; i < 4; i += 2) { + int par; + if ((index/2) * 2 == i) + par = min; + else if (min % 2) + par = min - 1; + else + par = min + 1; + Msg::Info("%d", par); + for (int j = 0; j < 2; ++j) { + Msg::Info(" %d %d", _vertices[i+j]->getParity(), par); + if (_vertices[i+j]->getParity() == -1) + _vertices[i+j]->setParity(par); + else if (_vertices[i+j]->getParity() != par) + 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(); + + Recombine2D::addNumEdge(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE); + Recombine2D::addValEdge(valEdge); + //Recombine2D::addValVert(_vertices[0]->getGain(-1) + _vertices[1]->getGain(-1)); + + Recombine2D::remove(_triangles[0]); // FIXME not performant at all !!! + Recombine2D::remove(_triangles[1]); + std::vector<Rec2DEdge*> edges; + for (int i = 1; i < 5; ++i) + edges.push_back(_edges[i]); + Recombine2D::add(_createQuad(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) +{ + par[0] = _vertices[0]->getParity(); + par[1] = _vertices[1]->getParity(); + par[2] = _vertices[2]->getParity(); + par[3] = _vertices[3]->getParity(); +} + void Rec2DTwoTri2Quad::_computeGlobVal() { - double valEdge = - EDGE_BASE * _edges[0]->getQual(); + double valEdge = - REC2D_EDGE_BASE * _edges[0]->getQual(); for (int i = 1; i < 5; ++i) - valEdge += EDGE_QUAD * _edges[i]->getQual(); + valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); double valVert = _vertices[0]->getGain(-1) + _vertices[1]->getGain(-1); - _globValIfExecuted = Recombine2D::getGlobalValue(4*EDGE_QUAD - EDGE_BASE, + _globValIfExecuted = Recombine2D::getGlobalValue(4*REC2D_EDGE_QUAD - REC2D_EDGE_BASE, valEdge, 0, valVert ); _lastUpdate = Recombine2D::getNumChange(); } +void Rec2DTwoTri2Quad::color(int a, int b, int c) +{ + unsigned int col = CTX::instance()->packColor(a, b, c, 255); + _triangles[0]->setCol(col); + _triangles[1]->setCol(col); +} + + /** Rec2DFourTri2Quad **/ /*************************/ Rec2DFourTri2Quad::Rec2DFourTri2Quad(Rec2DVertex *rv, std::list<MTriangle*> &tri) @@ -359,23 +924,77 @@ bool Rec2DFourTri2Quad::isObsolete() return false; } +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(_triangles[0]); // FIXME not performant at all !!! + Recombine2D::remove(_triangles[1]); + Recombine2D::remove(_triangles[2]); + Recombine2D::remove(_triangles[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 -= EDGE_BASE * _edges[i]->getQual(); + valEdge -= REC2D_EDGE_BASE * _edges[i]->getQual(); for (int i = 4; i < 8; ++i) - valEdge += EDGE_QUAD * _edges[i]->getQual(); + valEdge += REC2D_EDGE_QUAD * _edges[i]->getQual(); - double valVert = - _vertices[0]->getQual(); - for (int i = 1; i < 5; ++i) + double valVert = - _vertices[4]->getQual(); + for (int i = 0; i < 4; ++i) valEdge += _vertices[i]->getGain(-1); - _globValIfExecuted = Recombine2D::getGlobalValue(4*EDGE_QUAD - 4*EDGE_BASE, + _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); + _triangles[0]->setCol(col); + _triangles[1]->setCol(col); + _triangles[2]->setCol(col); + _triangles[3]->setCol(col); +} + + /** Rec2DCollapseTri **/ /*********************/ Rec2DCollapseTri::Rec2DCollapseTri(Rec2DVertex *rv, std::list<MTriangle*> &tri) @@ -464,6 +1083,19 @@ bool Rec2DCollapseTri::isObsolete() 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(); @@ -602,6 +1234,18 @@ void Rec2DCollapseTri::_qualCavity(double &valVert, double &valEdge, } } +void Rec2DCollapseTri::color(int a, int b, int c) +{ + unsigned int col = CTX::instance()->packColor(a, b, c, 255); + _triangles[0]->setCol(col); + _triangles[1]->setCol(col); + if (_triangles[2]) { + _triangles[2]->setCol(col); + _triangles[3]->setCol(col); + } +} + + /** Rec2DVertex **/ /*******************/ Rec2DVertex::Rec2DVertex(MVertex *v, std::list<MTriangle*> tri, int onWhat, @@ -632,7 +1276,7 @@ Rec2DVertex::Rec2DVertex(double u, double v) _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()); + Msg::Info("resulting point = [%g, %g, %g]", p.x(), p.y(), p.z()); } double Rec2DVertex::_computeAngle(MVertex *v, @@ -751,7 +1395,7 @@ void Rec2DVertex::getNeighbours(std::map<Rec2DVertex*, int> &vert, else rv = _edges[i]->getRVertex(1); if ((it = vert.find(rv)) != vert.end()) - it->second += _edges[i]->getWeight() - EDGE_BASE; + it->second += _edges[i]->getWeight() - REC2D_EDGE_BASE; else vert[rv] = _edges[i]->getWeight(); } @@ -788,10 +1432,29 @@ void Rec2DVertex::initStaticTable() } } +void Rec2DVertex::remove(Rec2DEdge *re) +{ + std::vector<Rec2DEdge*>::iterator it = _edges.begin(); + bool b = false; + for (; it != _edges.end() ; ++it) + if (*it == re) { + _edges.erase(it--); + b = true; + break; + } + if (b) { + Recombine2D::addValVert(getGain(-1)); + --_numEl; + } + else + Msg::Error("[Rec2DVertex] Edge not found"); +} + + /** Rec2DEdge **/ /*****************/ Rec2DEdge::Rec2DEdge(MEdge e, mapofVertices &vert, std::list<MTriangle*> &tri) -: _lastChange(-1), _qual(.0), _weight(EDGE_BASE), +: _lastChange(-1), _qual(.0), _weight(REC2D_EDGE_BASE), _rv1(vert[e.getVertex(0)]), _rv2(vert[e.getVertex(1)]) { _rv1->add(this); @@ -799,7 +1462,7 @@ Rec2DEdge::Rec2DEdge(MEdge e, mapofVertices &vert, std::list<MTriangle*> &tri) } Rec2DEdge::Rec2DEdge(Rec2DVertex *rv1, Rec2DVertex *rv2) -: _lastChange(-1), _qual(.0), _weight(EDGE_BASE), _rv1(rv1), _rv2(rv2) +: _lastChange(-1), _qual(.0), _weight(REC2D_EDGE_BASE), _rv1(rv1), _rv2(rv2) { } @@ -810,13 +1473,15 @@ double Rec2DEdge::getQual() return _qual; } -void Rec2DEdge::_computeQual() +void Rec2DEdge::_computeQual() //* { 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 = Recombine2D::edgeReward(adimLength, alignment); _lastChange = Recombine2D::getNumChange(); } @@ -853,11 +1518,16 @@ double Rec2DEdge::_straightAlignment() double alpha2 = angleEdge - angle2; crossField2d::normalizeAngle(alpha1); crossField2d::normalizeAngle(alpha2); - alpha1 = std::min(alpha1, .5 * M_PI - alpha1); - alpha2 = std::min(alpha2, .5 * M_PI - 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); -} \ No newline at end of file +} + +bool lessRec2DAction::operator()(Rec2DAction *ra1, Rec2DAction *ra2) const +{ + return *ra1 < *ra2; +} diff --git a/Mesh/meshGFaceRecombine.h b/Mesh/meshGFaceRecombine.h index 619221cec5..868fff33f4 100644 --- a/Mesh/meshGFaceRecombine.h +++ b/Mesh/meshGFaceRecombine.h @@ -19,12 +19,16 @@ class Rec2DEdge; class Rec2DVertex; class Rec2DAction; -typedef std::set<Rec2DAction*/*, lessRec2DAction*/> setofRec2DAction; +typedef std::list<Rec2DAction*> setofRec2DAction; typedef std::map<MVertex*, Rec2DVertex*> mapofVertices; typedef std::map<MEdge, Rec2DEdge*, Less_Edge> mapofEdges; typedef std::map<MElement*, std::set<Rec2DAction*> > mapofElementActions; typedef std::map<MQuadrangle*, std::set<MElement*> > mapofAdjacencies; +struct lessRec2DAction { + bool operator()(Rec2DAction*, Rec2DAction*) const; +}; + class Recombine2D { private : int _numEdge, _numVert, _numChange; @@ -40,6 +44,9 @@ class Recombine2D { std::vector<Rec2DAction*> _obsoleteAction; static Recombine2D *_current; + std::vector<MTriangle*> _tri; + std::vector<MQuadrangle*> _quad; + public : static bool bo; @@ -47,6 +54,7 @@ class Recombine2D { Recombine2D(GModel*); ~Recombine2D(); + bool recombine(); void apply(bool){return;} static inline double edgeReward(double adimLength, double alignment) @@ -57,11 +65,36 @@ class Recombine2D { int numVert, double valVert ); static Rec2DEdge* getREdge(MEdge); static Rec2DVertex* getRVertex(MVertex*); + 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 void remove(MTriangle*); + 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; } - //static inline int* getPtrNumChange() {return &_numChange;} + + private : + bool _isAllQuad(Rec2DAction *action); + void _choose(Rec2DAction*); + void _removeIncompatible(Rec2DAction*); + void _removeReference(Rec2DAction*); + void _getNeighbours(Rec2DAction*, std::set<Rec2DAction*>&); }; class Rec2DAction { @@ -73,10 +106,26 @@ class Rec2DAction { double _globValIfExecuted; public : - inline int getVectPosition() {return _position;} + bool operator<(Rec2DAction&); + inline int getVectPosition() const {return _position;} inline void setVectPosition(int p) {_position = p;} - //virtual double getReward() = 0; + + 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 getTriangles(std::set<MTriangle*>&) = 0; + virtual MTriangle* getTriangle(int) = 0; + virtual void apply() = 0; + virtual void getParities(int*) = 0; + virtual Rec2DVertex* getRVertex(int) = 0; + virtual void color(int, int, int) = 0; + + protected : + MQuadrangle* _createQuad(std::vector<Rec2DEdge*>&) const; private : virtual void _computeGlobVal() = 0; @@ -90,9 +139,20 @@ class Rec2DTwoTri2Quad : public Rec2DAction { public : Rec2DTwoTri2Quad(Rec2DEdge*, std::list<MTriangle*>&); - //double getReward(); bool isObsolete(); - + void getTriangles(std::set<MTriangle*> &tri) { + tri.insert(_triangles[0]); + tri.insert(_triangles[1]); + } + MTriangle* getTriangle(int a) { + return _triangles[a]; + } + void apply(); + void getParities(int*); + Rec2DVertex* getRVertex(int i) {return _vertices[i];} + void color(int, int, int); + + int getNum() {return 1;} private : void _computeGlobVal(); }; @@ -105,9 +165,22 @@ class Rec2DFourTri2Quad : public Rec2DAction { public : Rec2DFourTri2Quad(Rec2DVertex*, std::list<MTriangle*>&); - //double getReward(); bool isObsolete(); - + void getTriangles(std::set<MTriangle*> &tri) { + tri.insert(_triangles[0]); + tri.insert(_triangles[1]); + tri.insert(_triangles[2]); + tri.insert(_triangles[3]); + } + MTriangle* getTriangle(int a) { + return _triangles[a]; + } + void apply(); + void getParities(int*); + Rec2DVertex* getRVertex(int i) {return _vertices[i];} + void color(int, int, int); + + int getNum() {return 2;} private : void _computeGlobVal(); }; @@ -122,15 +195,33 @@ class Rec2DCollapseTri : public Rec2DAction { public : Rec2DCollapseTri(Rec2DVertex*, std::list<MTriangle*>&); Rec2DCollapseTri(Rec2DEdge*, std::list<MTriangle*>&); - //double getReward(); + double getReward() { + return std::max(_globValIfExecuted, _globValIfExecuted2) + - Recombine2D::getGlobalValue(0, .0, 0, .0); + } bool isObsolete(); - + void getTriangles(std::set<MTriangle*> &tri) { + tri.insert(_triangles[0]); + tri.insert(_triangles[1]); + if (_triangles[2]) { + tri.insert(_triangles[2]); + tri.insert(_triangles[3]); + } + } + MTriangle* getTriangle(int a) { + return _triangles[a]; + } + void apply(); + void getParities(int*); + Rec2DVertex* getRVertex(int i) {return _vertices[i];} + void color(int, int, int); + + 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 { @@ -158,13 +249,17 @@ class Rec2DVertex { std::map<MVertex*, std::set<GEdge*> >); Rec2DVertex(double u, double v); - void add(Rec2DEdge *re) {_edges.push_back(re);} - void setOnBoundary() {if (_onWhat > 0) _onWhat = -1; - static bool a=1; if(a){Msg::Error("FIXME boundary");a=0;}} - bool getIsOnBoundary() {return _onWhat < 1;} + 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;} + 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();} @@ -205,7 +300,4 @@ class Rec2DEdge { double _straightAlignment(); }; -#endif - -//idee : lors du parcours de larbre avec un horizon : copier les Rec2dVertex et les Rec2DEdge. -//idee : faire carrŽment : arrete d'un triangle = 0, arrete d'un quad = 1/2 +#endif \ No newline at end of file -- GitLab