From c4a07b595db73471c377c24fb2379a06c2364715 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 15 Mar 2009 19:33:43 +0000
Subject: [PATCH] orient triangles in a consistent way (really ugly
 implementation at the moment; we need to change the actual algorithm to
 ensure that we create correctly oriented triangles in the first place)

---
 Mesh/Generator.cpp                  | 12 ----------
 Mesh/meshGFaceDelaunayInsertion.cpp |  5 ++--
 Mesh/meshGFaceOptimize.cpp          | 37 +++++++++++++++++++++++++----
 Mesh/meshGFaceOptimize.h            | 36 ++++++++++++++++------------
 4 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index c54768843a..d3ea91950c 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -369,18 +369,6 @@ static void PrintMesh2dStatistics(GModel *m)
 static void Mesh2D(GModel *m)
 {
   if(TooManyElements(m, 2)) return;
-
-  if(!CTX::instance()->expertMode && (CTX::instance()->mesh.algo2d == ALGO_2D_DELAUNAY ||
-                                      CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL)){
-    if(!Msg::GetBinaryAnswer
-       ("The 2D Delaunay and Frontal algorithms are still experimental\n"
-	"and produce triangles with random orientations. Do you really\n"
-	"want to continue?\n\n"
-	"(To disable this warning in the future, select `Enable expert\n"
-	"mode' in the option dialog.)",
-	"Continue", "Cancel")) return;
-  }
-  
   Msg::StatusBar(1, true, "Meshing 2D...");
   double t1 = Cpu();
 
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index f96d7d54a0..2a4298869d 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -615,7 +615,7 @@ void gmshBowyerWatson(GFace *gf)
   std::set<MTri3*,compareTri3Ptr> AllTris;
   std::vector<double> vSizes, vSizesBGM, Us, Vs;
 
-  buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
+  buildMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
 
   // _printTris ("before.pos", AllTris, Us,Vs);
   int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
@@ -701,7 +701,8 @@ void gmshBowyerWatsonFrontal(GFace *gf)
   std::set<MTri3*,compareTri3Ptr> AllTris;
   std::set<MTri3*,compareTri3Ptr> ActiveTris;
   std::vector<double> vSizes, vSizesBGM, Us, Vs;
-  buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
+
+  buildMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
 
   // delaunise the initial mesh
   int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index d0df634c99..9317b2dac3 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -11,6 +11,7 @@
 #include "MVertex.h"
 #include "MElement.h"
 #include "BackgroundMesh.h"
+#include "Numeric.h"
 #include "GmshMessage.h"
 #include "Generator.h"
 
@@ -44,11 +45,12 @@ static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes)
   }
 }
 
-void buidMeshGenerationDataStructures(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris,
-                                      std::vector<double> &vSizes,
-                                      std::vector<double> &vSizesBGM,
-                                      std::vector<double> &Us,
-                                      std::vector<double> &Vs)
+void buildMeshGenerationDataStructures(GFace *gf, 
+                                       std::set<MTri3*, compareTri3Ptr> &AllTris,
+                                       std::vector<double> &vSizes,
+                                       std::vector<double> &vSizesBGM,
+                                       std::vector<double> &Us,
+                                       std::vector<double> &Vs)
 {
   std::map<MVertex*, double> vSizesMap;
   std::list<GEdge*> edges = gf->edges();
@@ -103,6 +105,31 @@ void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris)
     delete worst;
     AllTris.erase(AllTris.begin());      
   }
+
+  // make sure all the triangles are oriented in the same way (in
+  // parameter space). FIXME: this is really ugly and slow. JF: we
+  // need to change the actual algorithm to ensure that we create
+  // correctly oriented triangles in the first place
+  if(gf->triangles.size() > 1){
+    double u[3], v[3], n1[3], n2[3];
+    MTriangle *t = gf->triangles[0];
+    SPoint2 uv[3];
+    for(int i = 0; i < 3; i++)
+      reparamMeshVertexOnFace(t->getVertex(i), gf, uv[i]);
+    normal3points(uv[0].x(), uv[0].y(), 0., 
+                  uv[1].x(), uv[1].y(), 0., 
+                  uv[2].x(), uv[2].y(), 0., n1);
+    for(unsigned int j = 1; j < gf->triangles.size(); j++){
+      t = gf->triangles[j];
+      for(int i = 0; i < 3; i++)
+        reparamMeshVertexOnFace(t->getVertex(i), gf, uv[i]);
+      normal3points(uv[0].x(), uv[0].y(), 0., 
+                    uv[1].x(), uv[1].y(), 0., 
+                    uv[2].x(), uv[2].y(), 0., n2);
+      double pp; prosca(n1, n2, &pp);
+      if(pp < 0) t->revert();
+    }
+  }
 }
 
 template <class T>
diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h
index a4b44c955e..fb96c8ea83 100644
--- a/Mesh/meshGFaceOptimize.h
+++ b/Mesh/meshGFaceOptimize.h
@@ -14,38 +14,44 @@
 
 class GFace;
 class MVertex;
+
 typedef std::map<MVertex*, std::vector<MElement*> > v2t_cont;
-typedef std::map<MEdge, std::pair<MElement*,MElement*>, Less_Edge> e2t_cont;
+typedef std::map<MEdge, std::pair<MElement*, MElement*>, Less_Edge> e2t_cont;
+
 void buildVertexToTriangle(std::vector<MTriangle*> &, v2t_cont &adj);
 void buildEdgeToTriangle(std::vector<MTriangle*> &, e2t_cont &adj);
 void laplaceSmoothing(GFace *gf);
 void edgeSwappingLawson(GFace *gf);
-enum gmshSwapCriterion {SWCR_DEL, SWCR_QUAL,SWCR_NORM, SWCR_CLOSE};
+
+enum gmshSwapCriterion {SWCR_DEL, SWCR_QUAL, SWCR_NORM, SWCR_CLOSE};
 enum gmshSplitCriterion {SPCR_CLOSE, SPCR_QUAL, SPCR_ALLWAYS};
-int edgeSwapPass(GFace *gf, std::set<MTri3*, compareTri3Ptr> &allTris, 
+
+int edgeSwapPass(GFace *gf, 
+                 std::set<MTri3*, compareTri3Ptr> &allTris, 
                  const gmshSwapCriterion &cr,
-                 const std::vector<double> &Us,
+                 const std::vector<double> &Us, 
                  const std::vector<double> &Vs,
-                 const std::vector<double> &vSizes,
+                 const std::vector<double> &vSizes, 
                  const std::vector<double> &vSizesBGM);
-int edgeSplitPass(double maxLC,
-                  GFace *gf, std::set<MTri3*, compareTri3Ptr> &allTris,
+int edgeSplitPass(double maxLC, GFace *gf, 
+                  std::set<MTri3*, compareTri3Ptr> &allTris,
                   const gmshSplitCriterion &cr,   
-                  std::vector<double> &Us ,
+                  std::vector<double> &Us,
                   std::vector<double> &Vs,
                   std::vector<double> &vSizes ,
                   std::vector<double> &vSizesBGM);
-int edgeCollapsePass(double minLC,
-                     GFace *gf, std::set<MTri3*, compareTri3Ptr> &allTris,
+int edgeCollapsePass(double minLC, GFace *gf, 
+                     std::set<MTri3*, compareTri3Ptr> &allTris,
                      std::vector<double> &Us,
                      std::vector<double> &Vs,
                      std::vector<double> &vSizes ,
                      std::vector<double> &vSizesBGM);
-void buidMeshGenerationDataStructures(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris,
-                                      std::vector<double> &vSizes,
-                                      std::vector<double> &vSizesBGM,
-                                      std::vector<double> &Us,
-                                      std::vector<double> &Vs);
+void buildMeshGenerationDataStructures(GFace *gf, 
+                                       std::set<MTri3*, compareTri3Ptr> &AllTris,
+                                       std::vector<double> &vSizes,
+                                       std::vector<double> &vSizesBGM,
+                                       std::vector<double> &Us,
+                                       std::vector<double> &Vs);
 void transferDataStructure (GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris);
 void gmshRecombineIntoQuads(GFace *gf);
 
-- 
GitLab