Skip to content
Snippets Groups Projects
Commit 48fbd739 authored by Thomas Toulorge's avatar Thomas Toulorge
Browse files

Fixed orientation of surface meshes with boundary layers

parent 40310658
Branches
Tags
No related merge requests found
...@@ -2814,6 +2814,64 @@ void partitionAndRemesh(GFaceCompound *gf) ...@@ -2814,6 +2814,64 @@ void partitionAndRemesh(GFaceCompound *gf)
#endif #endif
} }
static bool getGFaceNormalFromVert(GFace *gf, MElement *el, SVector3 &nf)
{
bool found = false;
for (int iElV = 0; iElV < el->getNumVertices(); iElV++) {
MVertex *v = el->getVertex(iElV);
SPoint2 param;
if(v->onWhat() == gf && v->getParameter(0, param[0]) &&
v->getParameter(1, param[1])) {
nf = gf->normal(param);
found = true;
break;
}
}
return found;
}
static bool getGFaceNormalFromBary(GFace *gf, MElement *el, SVector3 &nf)
{
SPoint2 param(0., 0.);
bool ok = true;
for (int j = 0; j < el->getNumVertices(); j++) {
SPoint2 p;
// FIXME: use inexact reparam because some vertices might not be
// exactly on the surface after the 3D Delaunay
ok = reparamMeshVertexOnFace(el->getVertex(j), gf, p, false);
if (!ok) break;
param += p;
}
if (ok) {
param *= 1. / el->getNumVertices();
nf = gf->normal(param);
}
return ok;
}
static void getGFaceOrientation(GFace *gf, BoundaryLayerColumns *blc,
bool existBL, bool fromVert,
int &orientNonBL, int &orientBL)
{
for (unsigned int iEl = 0; iEl < gf->getNumMeshElements(); iEl++) {
MElement *e = gf->getMeshElement(iEl);
const bool isBLEl = existBL &&
(blc->_toFirst.find(e) != blc->_toFirst.end());
SVector3 nf;
if ((!isBLEl && orientNonBL == 0) || (isBLEl && orientBL == 0)) { // Check only if orientation of BL/non-BL el. not already known
const bool found = fromVert ? getGFaceNormalFromVert(gf, e, nf) :
getGFaceNormalFromBary(gf, e, nf);
if (found) {
SVector3 ne = e->getFace(0).normal();
const int orient = (dot(ne, nf) > 0.) ? 1 : -1;
if (isBLEl) orientBL = orient;
else orientNonBL = orient;
}
}
if ((orientNonBL != 0) && (orientBL != 0)) break; // Stop when orientation found for non-BL and BL el.
}
}
void orientMeshGFace::operator()(GFace *gf) void orientMeshGFace::operator()(GFace *gf)
{ {
if(!gf->getNumMeshElements()) return; if(!gf->getNumMeshElements()) return;
...@@ -2826,8 +2884,8 @@ void orientMeshGFace::operator()(GFace *gf) ...@@ -2826,8 +2884,8 @@ void orientMeshGFace::operator()(GFace *gf)
gf->geomType() == GEntity::CompoundSurface){ gf->geomType() == GEntity::CompoundSurface){
// don't do anything // don't do anything
} }
else{ else {
// in old versions we checked the orientation by comparing the orientation // In old versions we checked the orientation by comparing the orientation
// of a line element on the boundary w.r.t. its connected surface // of a line element on the boundary w.r.t. its connected surface
// element. This is probably better than what follows, but // element. This is probably better than what follows, but
// * it failed when the 3D Delaunay changes the 1D mesh (since we don't // * it failed when the 3D Delaunay changes the 1D mesh (since we don't
...@@ -2835,66 +2893,48 @@ void orientMeshGFace::operator()(GFace *gf) ...@@ -2835,66 +2893,48 @@ void orientMeshGFace::operator()(GFace *gf)
// * it failed with OpenCASCADE geometries, where surface orientions do not // * it failed with OpenCASCADE geometries, where surface orientions do not
// seem to be consistent with the orientation of the bounding edges // seem to be consistent with the orientation of the bounding edges
bool done = false; // Now: orient surface elements w.r.t. normal to geometric model.
// first, try to find an element with one vertex categorized on the // Assumes that originally, orientation is consistent among boundary layer
// surface and for which we have valid surface parametric // (BL) elements, and orientation is consistent among non-BL elements, but
// coordinates // BL and non-BL elements can be oriented differently
for(unsigned int i = 0; i < gf->getNumMeshElements(); i++){
MElement *e = gf->getMeshElement(i); // Determine whether there is a boundary layer (BL)
for(int j = 0; j < e->getNumVertices(); j++){ BoundaryLayerColumns *blc = gf->getColumns();
MVertex *v = e->getVertex(j); const bool existBL = !blc->_toFirst.empty();
SPoint2 param;
if(v->onWhat() == gf && v->getParameter(0, param[0]) && // Get orientation of BL and non-BL elements.
v->getParameter(1, param[1])){ // First, try to get normal to GFace from vertices.
SVector3 nf = gf->normal(param); // If it fails, try to get normal to GFace from element barycenter
SVector3 ne = e->getFace(0).normal(); int orientNonBL = 0, orientBL = existBL ? 0 : 1;
if(dot(ne, nf) < 0){ getGFaceOrientation(gf, blc, existBL, true, orientNonBL, orientBL);
Msg::Debug("Reversing orientation of mesh in face %d (param)", gf->tag()); if ((orientNonBL == 0) || (orientBL == 0))
for(unsigned int k = 0; k < gf->getNumMeshElements(); k++) getGFaceOrientation(gf, blc, existBL, false, orientNonBL, orientBL);
gf->getMeshElement(k)->reverse();
} // Exit if could not determine orientation of both non-BL el. and BL el.
done = true; if ((orientNonBL == 0) && (orientBL == 0)) {
break; Msg::Warning("Could not orient mesh in face %d", gf->tag());
} return;
} }
if(done) break;
} // Reverse BL and non-BL elements if needed
if (existBL) { // If there is a BL, test BL/non-BL elements
if(!done){ if ((orientNonBL == -1) || (orientBL == -1))
// if we could not find such an element, just try to evaluate the for (unsigned int iEl = 0; iEl < gf->getNumMeshElements(); iEl++) {
// normal at the barycenter of an element on the surface MElement *e = gf->getMeshElement(iEl);
for(unsigned int i = 0; i < gf->getNumMeshElements(); i++){ if (blc->_toFirst.find(e) == blc->_toFirst.end()) { // If el. outside of BL...
MElement *e = gf->getMeshElement(i); if (orientNonBL == -1) e->reverse(); // ... reverse if needed
SPoint2 param(0., 0.);
bool ok = true;
for(int j = 0; j < e->getNumVertices(); j++){
SPoint2 p;
// FIXME: use inexact reparam because some vertices might not be
// exactly on the surface after the 3D Delaunay
ok = reparamMeshVertexOnFace(e->getVertex(j), gf, p, false);
if(!ok) break;
param += p;
}
if(ok){
param *= 1. / e->getNumVertices();
SVector3 nf = gf->normal(param);
SVector3 ne = e->getFace(0).normal();
if(dot(ne, nf) < 0){
Msg::Debug("Reversing 2 orientation of mesh in face %d (cog)", gf->tag());
for(unsigned int k = 0; k < gf->getNumMeshElements(); k++)
gf->getMeshElement(k)->reverse();
} }
done = true; else // If el. in BL
break; if (orientBL == -1) e->reverse(); // ... reverse if needed
} }
}
} }
else // If no BL, reverse all elements if needed
if(!done) if (orientNonBL == -1)
Msg::Warning("Could not orient mesh in face %d", gf->tag()); for (unsigned int iEl = 0; iEl < gf->getNumMeshElements(); iEl++)
gf->getMeshElement(iEl)->reverse();
} }
// apply user-specified mesh orientation constraints // Apply user-specified mesh orientation constraints
if(gf->meshAttributes.reverseMesh) if(gf->meshAttributes.reverseMesh)
for(unsigned int k = 0; k < gf->getNumMeshElements(); k++) for(unsigned int k = 0; k < gf->getNumMeshElements(); k++)
gf->getMeshElement(k)->reverse(); gf->getMeshElement(k)->reverse();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment