From e753867052646ae731b8fff647487f401f524d44 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 19 Jan 2007 15:34:05 +0000
Subject: [PATCH] - fixed infinite loop in edge loop creation (when the loop is
 wrong, just print  a message and abort)

- introduced options to control healing of OCC models
---
 Geo/GEdgeLoop.cpp             | 134 +++++++++++++++++-----------------
 Geo/GEdgeLoop.h               |   1 +
 Mesh/meshGFace.cpp            |   6 +-
 benchmarks/3d/Torus.geo       |   4 -
 doc/TODO                      |   7 +-
 doc/VERSIONS                  |  17 +++--
 doc/gmsh.html                 |  14 ++--
 doc/texinfo/opt_general.texi  |   5 ++
 doc/texinfo/opt_geometry.texi |  15 ++++
 9 files changed, 113 insertions(+), 90 deletions(-)

diff --git a/Geo/GEdgeLoop.cpp b/Geo/GEdgeLoop.cpp
index 7c9b77d15c..b9cac08afd 100644
--- a/Geo/GEdgeLoop.cpp
+++ b/Geo/GEdgeLoop.cpp
@@ -1,4 +1,4 @@
-// $Id: GEdgeLoop.cpp,v 1.4 2006-11-27 22:22:12 geuzaine Exp $
+// $Id: GEdgeLoop.cpp,v 1.5 2007-01-19 15:34:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -28,28 +28,25 @@ void GEdgeSigned::print() const
       ge->tag(), _sign, getBeginVertex()->tag(), getEndVertex()->tag());
 }
 
-int countInList ( std::list<GEdge*> &wire , GEdge *ge)
+int countInList(std::list<GEdge*> &wire, GEdge *ge)
 {
   std::list<GEdge*>::iterator it = wire.begin();
   std::list<GEdge*>::iterator ite = wire.end();
   int count = 0;
-  while (it != ite)
-    {
-      if (*it == ge) count++; 
-      ++it;
-    }
+  while(it != ite){
+    if(*it == ge) count++; 
+    ++it;
+  }
   return count;
 }
 
-GEdgeSigned nextOne ( GEdgeSigned *thisOne, std::list<GEdge*> &wire)
+GEdgeSigned nextOne(GEdgeSigned *thisOne, std::list<GEdge*> &wire)
 {
-
-  if (!thisOne)
-    {
-      GEdge *ge = *(wire.begin());
-      wire.erase(wire.begin());
-      return GEdgeSigned ( 1 , ge );   
-    }
+  if(!thisOne){
+    GEdge *ge = *(wire.begin());
+    wire.erase(wire.begin());
+    return GEdgeSigned(1, ge);   
+  }
 
   GVertex *gv = thisOne->getEndVertex();
 
@@ -57,80 +54,79 @@ GEdgeSigned nextOne ( GEdgeSigned *thisOne, std::list<GEdge*> &wire)
 
   std::list<GEdge*>::iterator it = wire.begin();
   std::list<GEdge*>::iterator ite = wire.end();
-  while (it != ite)
-    {
-      GEdge *ge = *it;
-      GVertex *v1 = ge->getBeginVertex();
-      GVertex *v2 = ge->getEndVertex();
-      if (v1 == gv || v2 == gv)possibleChoices.push_back(ge);
-      ++it;
-    }
+  while(it != ite){
+    GEdge *ge = *it;
+    GVertex *v1 = ge->getBeginVertex();
+    GVertex *v2 = ge->getEndVertex();
+    if(v1 == gv || v2 == gv) possibleChoices.push_back(ge);
+    ++it;
+  }
   it = possibleChoices.begin();
   ite = possibleChoices.end();
-  while (it != ite)
-    {
-      GEdge *ge = *it;
-      if (countInList (possibleChoices , ge) == 2)
-	{
-	  wire.erase(std::remove_if(wire.begin(),wire.end() , std::bind2nd(std::equal_to<GEdge*>(), ge)) , 
+  while(it != ite){
+    GEdge *ge = *it;
+    if(countInList(possibleChoices, ge) == 2){
+      wire.erase(std::remove_if(wire.begin(), wire.end(), 
+				std::bind2nd(std::equal_to<GEdge*>(), ge)), 
 		 wire.end());
-	  wire.push_back(ge);
-	  GVertex *v1 = ge->getBeginVertex();
-	  GVertex *v2 = ge->getEndVertex();
-	  if (v1 == gv)return GEdgeSigned ( 1  , ge );   
-	  if (v2 == gv)return GEdgeSigned ( -1 , ge );   
-	  throw;
-	}
-      ++it;
+      wire.push_back(ge);
+      GVertex *v1 = ge->getBeginVertex();
+      GVertex *v2 = ge->getEndVertex();
+      if(v1 == gv) return GEdgeSigned(1, ge);   
+      if(v2 == gv) return GEdgeSigned(-1, ge);   
+      throw;
     }
+    ++it;
+  }
   it = possibleChoices.begin();
   ite = possibleChoices.end();
-  while (it != ite)
-    {
-      GEdge *ge = *it;
-      if (ge != thisOne->ge)
-	{
-	  wire.erase(std::remove_if(wire.begin(),wire.end() , std::bind2nd(std::equal_to<GEdge*>(), ge)) , 
-		     wire.end());
-	  GVertex *v1 = ge->getBeginVertex();
-	  GVertex *v2 = ge->getEndVertex();
-	  if (v1 == gv)return GEdgeSigned ( 1  , ge );   
-	  if (v2 == gv)return GEdgeSigned ( -1 , ge );
-	  throw;
-	}   
-      ++it;
-    }
+  while(it != ite){
+    GEdge *ge = *it;
+    if(ge != thisOne->ge){
+      wire.erase(std::remove_if(wire.begin(),wire.end(), 
+				std::bind2nd(std::equal_to<GEdge*>(), ge)), 
+		 wire.end());
+      GVertex *v1 = ge->getBeginVertex();
+      GVertex *v2 = ge->getEndVertex();
+      if(v1 == gv) return GEdgeSigned(1, ge);   
+      if(v2 == gv) return GEdgeSigned(-1, ge);
+      throw;
+    }   
+    ++it;
+  }
+  
+  // should never end up here
+  return GEdgeSigned(0, 0);
 }
 
-int  GEdgeLoop::count (GEdge* ge) const
+int GEdgeLoop::count(GEdge* ge) const
 {
   GEdgeLoop::citer it = begin();
   GEdgeLoop::citer ite = end();
   int count = 0;
-  while (it != ite)
-    {
-      if (it->ge == ge) count++; 
-      ++it;
-    }
+  while(it != ite){
+    if(it->ge == ge) count++; 
+    ++it;
+  }
   return count;
 }
 
-GEdgeLoop::GEdgeLoop ( const std::list<GEdge*> & cwire )
+GEdgeLoop::GEdgeLoop(const std::list<GEdge*> &cwire)
 {
-
-  std::list<GEdge*> wire (cwire);
+  std::list<GEdge*> wire(cwire);
 
   GEdgeSigned *prevOne = 0;
 
   Msg(INFO,"Building a wire");
   GEdgeSigned ges(0,0);
-  while (wire.size())
-    {
-      ges = nextOne ( prevOne , wire );
-      
-      prevOne = &ges;
-      ges.print();
-      loop.push_back(ges);
+  while(wire.size()){
+    ges = nextOne(prevOne, wire);
+    if(ges.getSign() == 0){ // oops
+      Msg(WARNING, "Something wrong in edge loop?");
+      break;
     }
-
+    prevOne = &ges;
+    ges.print();
+    loop.push_back(ges);
+  }
 }
diff --git a/Geo/GEdgeLoop.h b/Geo/GEdgeLoop.h
index 9ca28ebf64..35f7de8fb6 100644
--- a/Geo/GEdgeLoop.h
+++ b/Geo/GEdgeLoop.h
@@ -39,6 +39,7 @@ struct GEdgeSigned
     return (_sign!=1)?ge->getBeginVertex():ge->getEndVertex();
   }
   void print() const;
+  int getSign(){return _sign;}
 };
 
 class GEdgeLoop 
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 9ef0292634..25c2c953e3 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFace.cpp,v 1.51 2007-01-17 08:14:23 geuzaine Exp $
+// $Id: meshGFace.cpp,v 1.52 2007-01-19 15:34:05 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -1445,6 +1445,10 @@ void orientMeshGFace::operator()(GFace *gf)
 {
   if(gf->geomType() == GEntity::ProjectionSurface) return;
 
+  // orientation of opencascade surfaces are not consistent with
+  // orientation of bounding edges: should do something else
+  //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 == TRANSFINI) return;
diff --git a/benchmarks/3d/Torus.geo b/benchmarks/3d/Torus.geo
index f4b965cb73..e878d86047 100644
--- a/benchmarks/3d/Torus.geo
+++ b/benchmarks/3d/Torus.geo
@@ -13,7 +13,3 @@ Line Loop(5) = {4,1,2,3};
 Plane Surface(6) = {5};         
        
 Extrude Surface{6, {0.0,1,0}, {0,0.0,0.0}, 1*3.14159/2};         
-       
-Coherence;         
-Surface Loop(29) = {6,15,19,23,27,28};
-Volume(30) = {29};
diff --git a/doc/TODO b/doc/TODO
index 9e93ab9458..3f3fda17a8 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.37 2007-01-18 09:12:45 geuzaine Exp $
+$Id: TODO,v 1.38 2007-01-19 15:34:05 geuzaine Exp $
 
 ********************************************************************
 
@@ -6,6 +6,11 @@ introduce Right/Left/Alternate for extruded meshes
 
 ********************************************************************
 
+color edges depending on number of adjacent surfaces (to check face
+sewing w/ tolerance)
+
+********************************************************************
+
 fix second order mesh for periodic surfaces
 
 ********************************************************************
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 83b2257e4c..076da5c01c 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,16 +1,18 @@
-$Id: VERSIONS,v 1.371 2007-01-16 16:58:34 geuzaine Exp $
+$Id: VERSIONS,v 1.372 2007-01-19 15:34:05 geuzaine Exp $
 
 2.0: new geometry and mesh databases, with support for STEP and IGES
 input via OpenCascade; complete rewrite of geometry and mesh drawing
 code; complete rewrite of mesh I/O layer (with new native binary MSH
 format and support for import/export of I-deas UNV, Nastran BDF, STL,
 Medit MESH and VRML 1.0 files); added support for incomplete second
-order elements; new default 2D mesh algorithm; removed anisotropic
-algorithm (as well as attractors); removed explicit region number
-specification in extrusions; option changes in the graphical interface
-are now applied instantaneously; added support for offscreen rendering
-using OSMesa; added support for SVG output; added string labels for
-Physical entities; lots of other improvements all over the place.
+order elements; new default 2D and 3D meshing algorithms; improved
+integration of Netgen and TetGen algorithms; removed anisotropic
+meshing algorithm (as well as attractors); removed explicit region
+number specification in extrusions; option changes in the graphical
+interface are now applied instantaneously; added support for offscreen
+rendering using OSMesa; added support for SVG output; added string
+labels for Physical entities; lots of other improvements all over the
+place.
 
 1.65 (May 15, 2006): new Plugin(ExtractEdges); fixed compilation
 errors with gcc4.1; replaced Plugin(DisplacementRaise) and
@@ -486,4 +488,3 @@ in rotations; changed default window sizes for better match with
 
 0.982: lighting for mesh and post-processing; corrected 2nd order mesh
 on non plane surfaces; added example 13.
-
diff --git a/doc/gmsh.html b/doc/gmsh.html
index 2f7980a480..9ab71fd841 100644
--- a/doc/gmsh.html
+++ b/doc/gmsh.html
@@ -251,17 +251,17 @@ thumbnail"></a>
 
 <h2><a name="Links"></a>Links</h2>
 
-Gmsh can be linked
-with <a href="http://www.opencascade.org">OpenCascade</a> to provide
-support for STEP, IGES and BREP files. Gmsh can also be linked with several
-external mesh generators (currently 
-<!-- a href="http://www-2.cs.cmu.edu/~quake/triangle.html">Triangle</a> from Jonathan Shewchuk,--> 
+Gmsh can be linked with 
+<a href="http://www.opencascade.org">OpenCascade</a> to provide
+support for STEP, IGES and BREP files. Gmsh can also be linked with
+several external mesh generators (currently
+<a href="http://www-2.cs.cmu.edu/~quake/triangle.html">Triangle</a> from Jonathan Shewchuk, 
 <a href="http://www.hpfem.jku.at/netgen/">Netgen</a> from Joachim Sch&ouml;berl and 
 <a href="http://tetgen.berlios.de/index.html">TetGen</a> from Hang Si).
 
 <p>
-Gmsh's high quality vector PostScript and PDF output is produced by <a
-href="/gl2ps/">GL2PS</a>.
+Gmsh's high quality vector PostScript, PDF and SVG output is produced
+by <a href="/gl2ps/">GL2PS</a>.
 
 <p>
 Gmsh's cross-platform graphical user interface is based on <a
diff --git a/doc/texinfo/opt_general.texi b/doc/texinfo/opt_general.texi
index 36d765a124..d2b4ac9e7c 100644
--- a/doc/texinfo/opt_general.texi
+++ b/doc/texinfo/opt_general.texi
@@ -94,6 +94,11 @@ Enable alpha blending (transparency) in post-processing views@*
 Default value: @code{1}@*
 Saved in: @code{General.OptionsFileName}
 
+@item General.Antialiasing
+Use multisample antialiasing (will slow down rendering)@*
+Default value: @code{0}@*
+Saved in: @code{General.OptionsFileName}
+
 @item General.ArrowHeadRadius
 Relative radius of arrow head@*
 Default value: @code{0.12}@*
diff --git a/doc/texinfo/opt_geometry.texi b/doc/texinfo/opt_geometry.texi
index 9793269455..79b8cc95c4 100644
--- a/doc/texinfo/opt_geometry.texi
+++ b/doc/texinfo/opt_geometry.texi
@@ -54,6 +54,21 @@ Display size of normal vectors (in pixels)@*
 Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
+@item Geometry.OCCFixSmallEdges
+Fix small edges in OpenCascade models@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
+@item Geometry.OCCFixSmallFaces
+Fix small faces in OpenCascade models@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
+@item Geometry.OCCSewFaces
+Sew faces in OpenCascade models@*
+Default value: @code{0}@*
+Saved in: @code{General.OptionsFileName}
+
 @item Geometry.OldCircle
 Use old circle description (compatibility option for old Gmsh geometries)@*
 Default value: @code{0}@*
-- 
GitLab