From 436fe6a4d490065d9bf09bc7fc6195ad92d7ae5c Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 15 Mar 2009 10:36:40 +0000
Subject: [PATCH] fix orientation of surface mesh for OCC models

---
 Mesh/meshGFace.cpp | 65 ++++++++++++++++++++++++++++++----------------
 doc/VERSIONS.txt   |  5 ++--
 2 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index b6b6555d94..e89f889131 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1418,31 +1418,52 @@ void orientMeshGFace::operator()(GFace *gf)
 
   if(gf->geomType() == GEntity::ProjectionFace) return;
 
-  // surface orientions in OCC are not consistent with the orientation
-  // of the bounding edges, so just leave them unchanged:
-  if(gf->getNativeType() == GEntity::OpenCascadeModel) return;
-
   // in old versions we did not reorient transfinite surface meshes;
   // we could add the following to provide backward compatibility:
   // if(gf->meshAttributes.Method == MESH_TRANSFINITE) return;
 
-  // orients the mesh to match the orientation of the first edge
-  std::list<GEdge*> edges = gf->edges();
-  std::list<int> ori = gf->orientations();
-  if(edges.empty() || ori.empty()) return;
-  GEdge *ge = *edges.begin();
-  GVertex *beg = ge->getBeginVertex();
-  GVertex *end = ge->getEndVertex();
-  if(!beg || beg->mesh_vertices.empty() || !end || end->mesh_vertices.empty()) return;
-  MVertex *v1 = beg->mesh_vertices[0];
-  MVertex *v2 = ge->mesh_vertices.empty() ? end->mesh_vertices[0] : ge->mesh_vertices[0];
-  int sign = *ori.begin();
-  MEdge ref(sign > 0 ? v1 : v2, sign > 0 ? v2 : v1);
-  if(shouldRevert(ref, gf->triangles) || shouldRevert(ref, gf->quadrangles)){
-    Msg::Debug("Reverting orientation of mesh in face %d", gf->tag());
-    for(unsigned int i = 0; i < gf->triangles.size(); i++)
-      gf->triangles[i]->revert();
-    for(unsigned int i = 0; i < gf->quadrangles.size(); i++)
-      gf->quadrangles[i]->revert();
+  if(gf->getNativeType() == GEntity::OpenCascadeModel){
+    // surface orientions in OCC do not seem to be consistent with the
+    // orientation of the bounding edges, so we compare the normals
+    // pointwise in an element
+    for(int i = 0; i < gf->getNumMeshElements(); i++){
+      MElement *e = gf->getMeshElement(i);
+      for(int j = 0; j < e->getNumVertices(); j++){
+        MVertex *v = e->getVertex(j);
+        SPoint2 param;
+        if(reparamMeshVertexOnFace(v, gf, param)){
+          SVector3 ne = e->getFace(0).normal();
+          SVector3 nf = gf->normal(param); 
+          if(dot(ne, nf) < 0){
+            Msg::Debug("Reverting orientation of mesh in face %d", gf->tag());
+            for(int k = 0; k < gf->getNumMeshElements(); k++)
+              gf->getMeshElement(k)->revert();
+          }
+          return;
+        }
+      }
+    }
+    Msg::Warning("Could not orient mesh in face %d", gf->tag());
+  }
+  else{
+    // orient the mesh to match the orientation of the first edge
+    std::list<GEdge*> edges = gf->edges();
+    std::list<int> ori = gf->orientations();
+    if(edges.empty() || ori.empty()) return;
+    GEdge *ge = *edges.begin();
+    GVertex *beg = ge->getBeginVertex();
+    GVertex *end = ge->getEndVertex();
+    if(!beg || beg->mesh_vertices.empty() || !end || end->mesh_vertices.empty()) return;
+    MVertex *v1 = beg->mesh_vertices[0];
+    MVertex *v2 = ge->mesh_vertices.empty() ? end->mesh_vertices[0] : ge->mesh_vertices[0];
+    int sign = *ori.begin();
+    MEdge ref(sign > 0 ? v1 : v2, sign > 0 ? v2 : v1);
+    if(shouldRevert(ref, gf->triangles) || shouldRevert(ref, gf->quadrangles)){
+      Msg::Debug("Reverting orientation of mesh in face %d", gf->tag());
+      for(unsigned int i = 0; i < gf->triangles.size(); i++)
+        gf->triangles[i]->revert();
+      for(unsigned int i = 0; i < gf->quadrangles.size(); i++)
+        gf->quadrangles[i]->revert();
+    }
   }
 }
diff --git a/doc/VERSIONS.txt b/doc/VERSIONS.txt
index a363ed8972..79b58b29ad 100644
--- a/doc/VERSIONS.txt
+++ b/doc/VERSIONS.txt
@@ -1,8 +1,9 @@
-$Id: VERSIONS.txt,v 1.38 2009-03-13 08:04:38 geuzaine Exp $
+$Id: VERSIONS.txt,v 1.39 2009-03-15 10:36:40 geuzaine Exp $
 
 (?): removed GSL dependency (Gmsh now simply requires Blas and
 Lapack); new per-window visibility; added support for composite window
-printing and background images; fixes for string options in parser.
+printing and background images; fixes for string options in parser;
+fixed surface mesh orientation for Open Cascade models.
 
 2.3.0 (Jan 23, 2009): major graphics and GUI code refactoring; new
 full-quad/hexa subdivision algorithm (removed Mesh.RecombineAlgo);
-- 
GitLab