Skip to content
Snippets Groups Projects
Commit 97b5d8ba authored by Amaury Johnen's avatar Amaury Johnen
Browse files

Creation of actions

parent 5d2da96a
No related branches found
No related tags found
No related merge requests found
// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// 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"
#define EDGE_BASE 2
#define EDGE_QUAD 1
Recombine2D *Recombine2D::_current = NULL;
bool Recombine2D::bo = 0;
double **Rec2DVertex::_qualVSnum = NULL;
double **Rec2DVertex::_gains = NULL;
/** Recombine2D **/
/*******************/
Recombine2D::Recombine2D(GFace *gf) : _gf(gf)
{
if (Recombine2D::_current != NULL) {
Msg::Info("An instance of recombination is already in execution");
return;
}
Recombine2D::_current = this;
_numChange = 0;
backgroundMesh::set(gf);
_bgm = backgroundMesh::current();
Rec2DVertex::initStaticTable();
_numEdge = _numVert = 0;
_valEdge = _valVert = .0;
// Be able to compute geometrical angle at corners
std::map<MVertex*, std::set<GEdge*> > 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);
mapCornerVert[(*itge)->getEndVertex()->getMeshElement(0)->getVertex(0)]
.insert(*itge);
}
}
// Find all Vertices and edges
std::map<MVertex*, std::list<MTriangle*> > mapVert;
std::map<MEdge, std::list<MTriangle*>, Less_Edge> mapEdge;
for (unsigned int i = 0; i < gf->triangles.size(); ++i) {
MTriangle *t = gf->triangles[i];
for (int j = 0; j < 3; ++j) {
mapVert[t->getVertex(j)].push_back(t);
mapEdge[t->getEdge(j)].push_back(t);
}
}
// Create the 'Rec2DVertex' and store iterator to vertices which have degree 4
std::list<std::map<MVertex*, std::list<MTriangle*> >::iterator> fourTri;
{
mapofVertices::iterator itV2N = _vertices.begin();
std::map<MVertex*, std::list<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));
++_numVert;
if (itvert->second.size() == 4)
fourTri.push_back(itvert);
}
}
// Create the 'Rec2DEdge' and store boundary edges
std::map<MVertex*, std::list<MEdge> > boundV2E;
{
mapofEdges::iterator itE2E = _edges.begin();
std::map<MEdge, std::list<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));
_vertices[e.getVertex(0)]->add(re);
_vertices[e.getVertex(1)]->add(re);
_numEdge += EDGE_BASE;
_valEdge += EDGE_BASE * re->getQual();
if (itedge->second.size() == 1) {
_numEdge += EDGE_QUAD;
_valEdge += 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);
}
}
}
// We know now on what are vertices, compute reward
{
mapofVertices::iterator itV2N = _vertices.begin();
for (; itV2N != _vertices.end(); ++itV2N)
_valVert += itV2N->second->getQual();
}
// Be dealing with "parity" on boundaries
{
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);
}
if (_vertices[actualV]->getParity() != actualParity+p)
Msg::Error("Not even number of mesh edges on boundary !");
boundV2E.erase(boundV2E.begin());
itBound = boundV2E.begin();
actualParity += 2;
}
}
// Create the 'Rec2DTwoTri2Quad' and 'Rec2DCollapseTri'
{
mapofEdges::iterator itE2E = _edges.begin();
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));
}
}
// 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));
}
}
}
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(" ");
}
Recombine2D::~Recombine2D()
{
Recombine2D::_current = NULL;
//delete vertices, edges, actions;
}
double Recombine2D::getGlobalValue(int numEdge, double valEdge,
int numVert, double valVert )
{
return (_current->_valEdge + valEdge) / (_current->_numEdge + numEdge) *
(_current->_valVert + valVert) / (_current->_numVert + numVert);
}
Rec2DEdge* Recombine2D::getREdge(MEdge e)
{
mapofEdges::iterator it = _current->_edges.find(e);
if (it != _current->_edges.end())
return it->second;
Msg::Error("[Recombine2D::getREdge] edge not found");
return NULL;
}
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;
}
/** Rec2DTwoTri2Quad **/
/************************/
Rec2DTwoTri2Quad::Rec2DTwoTri2Quad(Rec2DEdge *re, std::list<MTriangle*> &tri)
{
int i;
std::set<MEdge, Less_Edge> extEdges;
{
std::list<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));
_triangles[i] = *it;
}
if (it != tri.end() || i < 2)
Msg::Error("[Rec2DTwoTri2Quad] Wrong number of triangles");
extEdges.erase(re->getMEdge());
}
_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");
_vertices[0] = re->getRVertex(0);
_vertices[1] = re->getRVertex(1);
MVertex *v2, *v3;
v2 = _triangles[0]->getOtherVertex(_vertices[0]->getMVertex(),
_vertices[1]->getMVertex());
v3 = _triangles[1]->getOtherVertex(_vertices[0]->getMVertex(),
_vertices[1]->getMVertex());
_vertices[2] = Recombine2D::getRVertex(v2);
_vertices[3] = Recombine2D::getRVertex(v3);
_computeGlobVal();
}
bool Rec2DTwoTri2Quad::isObsolete()
{
int p0 = _vertices[0]->getParity();
int p1 = _vertices[1]->getParity();
int p2 = _vertices[2]->getParity();
int p3 = _vertices[3]->getParity();
if (p0>-1 && p1>-1 && p0/2 == p1/2 && p0 % 2 != p1 % 2 ||
p2>-1 && p3>-1 && p2/2 == p3/2 && p2 % 2 != p3 % 2 ||
p0>-1 && p0 == p2 ||
p0>-1 && p0 == p3 ||
p1>-1 && p1 == p2 ||
p1>-1 && p1 == p3 )
return true;
return false;
}
void Rec2DTwoTri2Quad::_computeGlobVal()
{
double valEdge = - EDGE_BASE * _edges[0]->getQual();
for (int i = 1; i < 5; ++i)
valEdge += EDGE_QUAD * _edges[i]->getQual();
double valVert = _vertices[0]->getGain(-1) + _vertices[1]->getGain(-1);
_globValIfExecuted = Recombine2D::getGlobalValue(4*EDGE_QUAD - EDGE_BASE,
valEdge, 0, valVert );
_lastUpdate = Recombine2D::getNumChange();
}
/** Rec2DFourTri2Quad **/
/*************************/
Rec2DFourTri2Quad::Rec2DFourTri2Quad(Rec2DVertex *rv, std::list<MTriangle*> &tri)
{
int i, j;
std::set<MEdge, Less_Edge> edges;
{
std::list<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));
_triangles[i] = *it;
}
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();
}
bool Rec2DFourTri2Quad::isObsolete()
{
int p0 = _vertices[0]->getParity();
int p1 = _vertices[1]->getParity();
int p2 = _vertices[2]->getParity();
int p3 = _vertices[3]->getParity();
if (p0>-1 && p1>-1 && p0/2 == p1/2 && p0 % 2 != p1 % 2 ||
p2>-1 && p3>-1 && p2/2 == p3/2 && p2 % 2 != p3 % 2 ||
p0>-1 && p0 == p2 ||
p0>-1 && p0 == p3 ||
p1>-1 && p1 == p2 ||
p1>-1 && p1 == p3 )
return true;
return false;
}
void Rec2DFourTri2Quad::_computeGlobVal()
{
double valEdge = 0;
for (int i = 0; i < 4; ++i)
valEdge -= EDGE_BASE * _edges[i]->getQual();
for (int i = 4; i < 8; ++i)
valEdge += EDGE_QUAD * _edges[i]->getQual();
double valVert = - _vertices[0]->getQual();
for (int i = 1; i < 5; ++i)
valEdge += _vertices[i]->getGain(-1);
_globValIfExecuted = Recombine2D::getGlobalValue(4*EDGE_QUAD - 4*EDGE_BASE,
valEdge, -1, valVert );
_lastUpdate = Recombine2D::getNumChange();
}
/** Rec2DCollapseTri **/
/*********************/
Rec2DCollapseTri::Rec2DCollapseTri(Rec2DVertex *rv, std::list<MTriangle*> &tri)
{
int i;
std::set<MEdge, Less_Edge> extEdges;
{
std::list<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));
}
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::list<MTriangle*> &tri)
: _edge(re)
{
int i;
std::set<MEdge, Less_Edge> extEdges;
{
std::list<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));
_triangles[i] = *it;
}
if (it != tri.end() || i < 2)
Msg::Error("[Rec2DTwoTri2Quad] Wrong number of triangles");
extEdges.erase(re->getMEdge());
}
_triangles[2] = _triangles[3] = NULL;
_vertices[0] = re->getRVertex(0);
_vertices[1] = re->getRVertex(1);
MVertex *v2, *v3;
v2 = _triangles[0]->getOtherVertex(_vertices[0]->getMVertex(),
_vertices[1]->getMVertex());
v3 = _triangles[1]->getOtherVertex(_vertices[0]->getMVertex(),
_vertices[1]->getMVertex());
_vertices[2] = Recombine2D::getRVertex(v2);
_vertices[3] = Recombine2D::getRVertex(v3);
_vertices[4] = NULL;
_computeGlobVal();
}
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::_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;
}
}
/** Rec2DVertex **/
/*******************/
Rec2DVertex::Rec2DVertex(MVertex *v, std::list<MTriangle*> tri, int onWhat,
std::map<MVertex*, std::set<GEdge*> > gEdges)
: _v(v), _onWhat(onWhat), _parity(-1), _lastChange(-1), _numEl(tri.size())
{
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();
}
Rec2DVertex::Rec2DVertex(double u, double v)
: _onWhat(1), _parity(-1), _lastChange(-1)
{
_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());
}
double Rec2DVertex::_computeAngle(MVertex *v,
std::list<MTriangle*> &listTri,
std::set<GEdge*> &setEdge)
{
if (setEdge.size() != 2) {
Msg::Warning("[meshGFaceRecombine] Wrong number of edge : %d, returning pi/2", setEdge.size());
return M_PI / 2.;
}
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;
}
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::list<MTriangle*>::iterator it2 = listTri.begin();
for (; it2 != listTri.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.;
}
angleMesh += angle3Vertices(t->getVertex((k+1)%3), v, t->getVertex((k+2)%3));
}
if (angleMesh < M_PI)
return angle1;
return angle2;
}
double Rec2DVertex::getQual(int numEdge)
{
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 (_lastChange < Recombine2D::getNumChange())
_computeQual();
return _qual;
}
void Rec2DVertex::_computeQual()
{
if (_onWhat > -1)
_qual = _qualVSnum[_onWhat][_numEl-1];
else
_qual = 1. - fabs(2./M_PI * _angle/_numEl - 1.);
_lastChange = Recombine2D::getNumChange();
}
double Rec2DVertex::getGain(int n)
{
if (_onWhat > -1) {
switch (n) {
case 1 :
return _gains[_onWhat][_numEl-1];
case -1 :
return - _gains[_onWhat][_numEl-2];
default :
return _qualVSnum[_onWhat][_numEl-1+n] - _qualVSnum[_onWhat][_numEl-1];
}
}
else
return fabs(2./M_PI * _angle/_numEl - 1.)
- fabs(2./M_PI * _angle/(_numEl + n) - 1.);
}
void Rec2DVertex::getNeighbours(std::map<Rec2DVertex*, int> &vert,
std::set<Rec2DEdge*> &edge )
{
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() - EDGE_BASE;
else
vert[rv] = _edges[i]->getWeight();
}
}
void Rec2DVertex::getNeighbourEdges(std::set<Rec2DEdge*> &edge)
{
for (unsigned int i = 0; i < _edges.size(); ++i)
edge.insert(_edges[i]);
}
void Rec2DVertex::initStaticTable()
{
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];
}
}
/** Rec2DEdge **/
/*****************/
Rec2DEdge::Rec2DEdge(MEdge e, mapofVertices &vert, std::list<MTriangle*> &tri)
: _lastChange(-1), _qual(.0), _weight(EDGE_BASE),
_rv1(vert[e.getVertex(0)]), _rv2(vert[e.getVertex(1)])
{
_rv1->add(this);
_rv2->add(this);
}
Rec2DEdge::Rec2DEdge(Rec2DVertex *rv1, Rec2DVertex *rv2)
: _lastChange(-1), _qual(.0), _weight(EDGE_BASE), _rv1(rv1), _rv2(rv2)
{
}
double Rec2DEdge::getQual()
{
if (_lastChange < Recombine2D::getNumChange())
_computeQual();
return _qual;
}
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();
_qual = Recombine2D::edgeReward(adimLength, alignment);
_lastChange = Recombine2D::getNumChange();
}
double Rec2DEdge::_straightAdimLength()
{
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);
return length * (1/lc1 + 1/lc2) / 2;
}
double Rec2DEdge::_straightAlignment()
{
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 = std::min(alpha1, .5 * M_PI - alpha1);
alpha2 = std::min(alpha2, .5 * M_PI - alpha2);
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
// Gmsh - Copyright (C) 1997-2011 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// Amaury Johnen (a.johnen@ulg.ac.be)
//
#ifndef _MESH_GFACE_RECOMBINE_H_
#define _MESH_GFACE_RECOMBINE_H_
#include "GFace.h"
#include "GModel.h"
#include "MEdge.h"
#include "BackgroundMesh.h"
class Rec2DEdge;
class Rec2DVertex;
class Rec2DAction;
typedef std::set<Rec2DAction*/*, lessRec2DAction*/> 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;
class Recombine2D {
private :
int _numEdge, _numVert, _numChange;
double _valEdge, _valVert;
GFace *_gf;
backgroundMesh *_bgm;
mapofEdges _edges;
mapofVertices _vertices;
setofRec2DAction _actions;
mapofElementActions _mea;
mapofAdjacencies _ma;
std::map<int, std::set<Rec2DVertex*> > _parities;
std::vector<Rec2DAction*> _obsoleteAction;
static Recombine2D *_current;
public :
static bool bo;
Recombine2D(GFace*);
Recombine2D(GModel*);
~Recombine2D();
void apply(bool){return;}
static inline double edgeReward(double adimLength, double alignment)
{return adimLength * (.5 + .5 * alignment);}
static inline int getNumChange() {return _current->_numChange;}
static inline backgroundMesh* bgm() {return _current->_bgm;}
static inline double getGlobalValue(int numEdge, double valEdge,
int numVert, double valVert );
static Rec2DEdge* getREdge(MEdge);
static Rec2DVertex* getRVertex(MVertex*);
static inline GFace* getGFace() {return _current->_gf;}
static inline void addObsleteAction(Rec2DAction *a) {
_current->_obsoleteAction.push_back(a);
}
//static inline int* getPtrNumChange() {return &_numChange;}
};
class Rec2DAction {
private :
int _position;
protected :
int _lastUpdate;
double _globValIfExecuted;
public :
inline int getVectPosition() {return _position;}
inline void setVectPosition(int p) {_position = p;}
//virtual double getReward() = 0;
virtual bool isObsolete() = 0;
private :
virtual void _computeGlobVal() = 0;
};
class Rec2DTwoTri2Quad : public Rec2DAction {
private :
MTriangle *_triangles[2];
Rec2DEdge *_edges[5]; // 1 embedded, 4 boundary
Rec2DVertex *_vertices[4]; // 4 boundary (2 on embedded edge + 2)
public :
Rec2DTwoTri2Quad(Rec2DEdge*, std::list<MTriangle*>&);
//double getReward();
bool isObsolete();
private :
void _computeGlobVal();
};
class Rec2DFourTri2Quad : public Rec2DAction {
private :
MTriangle *_triangles[4];
Rec2DEdge *_edges[8]; // 4 embedded, 4 boundary
Rec2DVertex *_vertices[5]; // 4 boundary (2 non adjacent + 2), 1 embedded
public :
Rec2DFourTri2Quad(Rec2DVertex*, std::list<MTriangle*>&);
//double getReward();
bool isObsolete();
private :
void _computeGlobVal();
};
class Rec2DCollapseTri : public Rec2DAction {
private :
MTriangle *_triangles[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;
public :
Rec2DCollapseTri(Rec2DVertex*, std::list<MTriangle*>&);
Rec2DCollapseTri(Rec2DEdge*, std::list<MTriangle*>&);
//double getReward();
bool isObsolete();
private :
void _computeGlobVal();
void _qualCavity(double &valVert, double &valEdge, int &numEdge,
std::map<Rec2DVertex*, int> &vertices,
Rec2DVertex *imposedVert = NULL );
};
class Rec2DListAction {
private :
public :
};
class Rec2DVertex {
private :
MVertex *_v;
std::vector<Rec2DEdge*> _edges;
int _onWhat, _numEl, _parity, _lastChange;
// _onWhat={-1:corner,0:edge,1:face,(2:volume)}
double _angle, _qual;
SPoint2 _param;
static double **_qualVSnum;
static double **_gains;
public :
Rec2DVertex(MVertex*, std::list<MTriangle*>, int onWhat,
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;}
double getQual(int numEdge = -1);
inline int getParity() {return _parity;}
inline void setParity(int p) {_parity = 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*>&);
static void initStaticTable();
private :
void _computeQual();
double _computeAngle(MVertex*, std::list<MTriangle*>&, std::set<GEdge*>&);
};
class Rec2DEdge {
private :
Rec2DVertex *_rv1, *_rv2;
double _qual;
int _lastChange, _weight;
public :
Rec2DEdge(MEdge, mapofVertices&, std::list<MTriangle*>&);
Rec2DEdge(Rec2DVertex*, Rec2DVertex*);
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;}
private :
void _computeQual();
double _straightAdimLength();
double _straightAlignment();
};
#endif
//idee : lors du parcours de larbre avec un horizon : copier les Rec2dVertex et les Rec2DEdge.
//idee : faire carrment : arrete d'un triangle = 0, arrete d'un quad = 1/2
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment