From b1ee3b8a3b23214615a9b1621ae0d7d918299090 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 5 Oct 2011 06:27:58 +0000
Subject: [PATCH] don't try to remove degenerated edges by default: it fails on
 some geometries

---
 Common/Context.h        |   3 +-
 Common/DefaultOptions.h |   2 +
 Common/Options.cpp      |  13 ++++
 Common/Options.h        |   1 +
 Fltk/onelabWindow.cpp   |   2 +-
 Fltk/optionWindow.cpp   |  16 +++--
 Fltk/optionWindow.h     |   2 -
 Geo/GModelIO_OCC.cpp    | 132 +++++++++++++++++++++-------------------
 Geo/GModelIO_OCC.h      |   7 ++-
 9 files changed, 104 insertions(+), 74 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index ed2f660b18..e21dfda744 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -49,7 +49,8 @@ struct contextGeometryOptions {
   double normals, tangents, scalingFactor;
   int autoCoherence, highlightOrphans, clip, useTransform;
   double tolerance, snap[3], transform[3][3], offset[3];
-  int occFixSmallEdges, occFixSmallFaces, occSewFaces, occConnectFaces;
+  int occFixDegenerated, occFixSmallEdges, occFixSmallFaces;
+  int occSewFaces, occConnectFaces;
   int copyMeshingMethod, exactExtrusion;
   int matchGeomAndMesh;
 };
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index f7d827326d..caf185bfb3 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -920,6 +920,8 @@ StringXNumber GeometryOptions_Number[] = {
   { F|O, "NumSubEdges" , opt_geometry_num_sub_edges , 20. ,
     "Number of edge subdivisions between control points when displaying curves" }, 
 
+  { F|O, "OCCFixDegenerated" , opt_geometry_occ_fix_degenerated , 0. , 
+    "Fix degenerated edges/faces in STEP, IGES and BRep models" },
   { F|O, "OCCFixSmallEdges" , opt_geometry_occ_fix_small_edges , 0. , 
     "Fix small edges in STEP, IGES and BRep models" },
   { F|O, "OCCFixSmallFaces" , opt_geometry_occ_fix_small_faces , 0. , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 877d39fbac..257af24d08 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -4680,6 +4680,19 @@ double opt_geometry_light_two_side(OPT_ARGS_NUM)
   return CTX::instance()->geom.lightTwoSide;
 }
 
+double opt_geometry_occ_fix_degenerated(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX::instance()->geom.occFixDegenerated = val ? 1 : 0;
+#if defined(HAVE_FLTK)
+  if(FlGui::available() && (action & GMSH_GUI)) {
+    FlGui::instance()->options->geo.butt[16]->value
+      (CTX::instance()->geom.occFixDegenerated);
+  }
+#endif
+  return CTX::instance()->geom.occFixSmallEdges;
+}
+
 double opt_geometry_occ_fix_small_edges(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index e80389fc05..fe5cb6cfd6 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -443,6 +443,7 @@ double opt_geometry_line_type(OPT_ARGS_NUM);
 double opt_geometry_surface_type(OPT_ARGS_NUM);
 double opt_geometry_light(OPT_ARGS_NUM);
 double opt_geometry_light_two_side(OPT_ARGS_NUM);
+double opt_geometry_occ_fix_degenerated(OPT_ARGS_NUM);
 double opt_geometry_occ_fix_small_edges(OPT_ARGS_NUM);
 double opt_geometry_occ_fix_small_faces(OPT_ARGS_NUM);
 double opt_geometry_occ_sew_faces(OPT_ARGS_NUM);
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index a610052754..ac5c15f860 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -187,7 +187,7 @@ bool onelab::localNetworkClient::run(const std::string &what)
     default:
       Msg::Warning("Received unknown message type (%d)", type);
       break;
-    }
+    } 
 
     FlGui::instance()->check();
   }
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index 93c1111885..d224d43ad2 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -378,7 +378,7 @@ static void geometry_options_ok_cb(Fl_Widget *w, void *data)
   opt_geometry_auto_coherence(0, GMSH_SET, o->geo.butt[8]->value());
   opt_geometry_light(0, GMSH_SET, o->geo.butt[9]->value());
   opt_geometry_highlight_orphans(0, GMSH_SET, o->geo.butt[10]->value());
-  opt_geometry_occ_fix_small_edges(0, GMSH_SET, o->geo.butt[11]->value());
+  opt_geometry_occ_fix_degenerated(0, GMSH_SET, o->geo.butt[16]->value());
   opt_geometry_occ_fix_small_faces(0, GMSH_SET, o->geo.butt[12]->value());
   opt_geometry_occ_sew_faces(0, GMSH_SET, o->geo.butt[13]->value());
   opt_geometry_light_two_side(0, GMSH_SET, o->geo.butt[14]->value());
@@ -1796,28 +1796,34 @@ optionWindow::optionWindow(int deltaFontSize)
         (FL_NO_BOX, L + 2 * WB, 2 * WB + 3 * BH + 1, IW, BH, "Open CASCADE model healing options (experimental):");
       b2->align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
 
+      geo.butt[16] = new Fl_Check_Button
+        (L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Remove degenerated edges and faces");
+      geo.butt[16]->type(FL_TOGGLE_BUTTON);
+      geo.butt[16]->callback(geometry_options_ok_cb);
+
       geo.butt[11] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Remove small edges");
+        (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Remove small edges");
       geo.butt[11]->type(FL_TOGGLE_BUTTON);
       geo.butt[11]->callback(geometry_options_ok_cb);
 
       geo.butt[12] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Remove small faces");
+        (L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Remove small faces");
       geo.butt[12]->type(FL_TOGGLE_BUTTON);
       geo.butt[12]->callback(geometry_options_ok_cb);
 
       geo.butt[13] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Sew faces");
+        (L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Sew faces");
       geo.butt[13]->type(FL_TOGGLE_BUTTON);
       geo.butt[13]->callback(geometry_options_ok_cb);
 
       geo.butt[15] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Cut and merge faces");
+        (L + 2 * WB, 2 * WB + 8 * BH, BW, BH, "Cut and merge faces");
       geo.butt[15]->type(FL_TOGGLE_BUTTON);
       geo.butt[15]->callback(geometry_options_ok_cb);
 
 #if !defined(HAVE_OCC)
       b2->deactivate();
+      geo.butt[16]->deactivate();
       geo.butt[11]->deactivate();
       geo.butt[12]->deactivate();
       geo.butt[13]->deactivate();
diff --git a/Fltk/optionWindow.h b/Fltk/optionWindow.h
index ddf67bde7e..048fc8ac61 100644
--- a/Fltk/optionWindow.h
+++ b/Fltk/optionWindow.h
@@ -21,8 +21,6 @@
 #include "spherePositionWidget.h"
 #include "colorbarWindow.h"
 
-
-
 #define NUM_FONTS 14
 extern Fl_Menu_Item menu_font_names[];
 
diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index 88969c506e..4d80c00183 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -207,10 +207,15 @@ void OCC_Internals::addShapeToLists(TopoDS_Shape _shape)
   
 }
 
-void OCC_Internals::healGeometry(double tolerance, bool fixsmalledges, 
-                                 bool fixspotstripfaces, bool sewfaces, 
-                                 bool makesolids, bool connect)
+void OCC_Internals::healGeometry(double tolerance, bool fixdegenerated,
+                                 bool fixsmalledges, bool fixspotstripfaces, 
+                                 bool sewfaces, bool makesolids, bool connect)
 {
+  if(!fixdegenerated && !fixsmalledges && !fixspotstripfaces &&
+     !sewfaces && !makesolids && !connect) return;
+
+  Msg::Info("Starting geometry healing procedure (tolerance: %g)", tolerance);
+
   buildLists();
   TopExp_Explorer exp0, exp1;
   int nrc = 0, nrcs = 0;
@@ -218,21 +223,7 @@ void OCC_Internals::healGeometry(double tolerance, bool fixsmalledges,
   int nrw = wmap.Extent(), nre = emap.Extent(), nrv = vmap.Extent();
   for (exp0.Init(shape, TopAbs_COMPOUND); exp0.More(); exp0.Next()) nrc++;
   for (exp0.Init(shape, TopAbs_COMPSOLID); exp0.More(); exp0.Next()) nrcs++;
-
-  Msg::Info("Starting geometry healing procedure (tolerance: %g)", tolerance);
-
-  {
-    Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
-    rebuild->Apply(shape);
-    for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){
-      TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
-      if(BRep_Tool::Degenerated(edge))
-        rebuild->Remove(edge, false);
-    }
-    shape = rebuild->Apply(shape);
-  }
-  buildLists();
-
+ 
   double surfacecont = 0;
   for (exp0.Init(shape, TopAbs_FACE); exp0.More(); exp0.Next()){
     TopoDS_Face face = TopoDS::Face(exp0.Current());
@@ -241,55 +232,69 @@ void OCC_Internals::healGeometry(double tolerance, bool fixsmalledges,
     surfacecont += system.Mass();
   }
 
-  {
-    Msg::Info("- repairing faces");
-
-    Handle(ShapeFix_Face) sff;
-    Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
-    rebuild->Apply(shape);
+  if (fixdegenerated){
+    Msg::Info("- fix degenerated edges and faces");
 
-    for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){
-      TopoDS_Face face = TopoDS::Face(exp0.Current());
+    {
+      Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
+      rebuild->Apply(shape);
+      for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){
+        TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
+        if(BRep_Tool::Degenerated(edge))
+          rebuild->Remove(edge, false);
+      }
+      shape = rebuild->Apply(shape);
+    }
+    buildLists();
 
-      sff = new ShapeFix_Face (face);
-      sff->FixAddNaturalBoundMode() = Standard_True;
-      sff->FixSmallAreaWireMode() = Standard_True;
-      sff->Perform();
+    {
+      Handle(ShapeFix_Face) sff;
+      Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
+      rebuild->Apply(shape);
       
-      if(sff->Status(ShapeExtend_DONE1) ||
-         sff->Status(ShapeExtend_DONE2) ||
-         sff->Status(ShapeExtend_DONE3) ||
-         sff->Status(ShapeExtend_DONE4) ||
-         sff->Status(ShapeExtend_DONE5))
-        {
-          Msg::Info("  repaired face %d", fmap.FindIndex(face));
-          if(sff->Status(ShapeExtend_DONE1))
-            Msg::Info("  (some wires are fixed)");
-          else if(sff->Status(ShapeExtend_DONE2))
-            Msg::Info("  (orientation of wires fixed)");
-          else if(sff->Status(ShapeExtend_DONE3))
-            Msg::Info("  (missing seam added)");
-          else if(sff->Status(ShapeExtend_DONE4))
-            Msg::Info("  (small area wire removed)");
-          else if(sff->Status(ShapeExtend_DONE5))
-            Msg::Info("  (natural bounds added)");
-          TopoDS_Face newface = sff->Face();
-          
-          rebuild->Replace(face, newface, Standard_False);
-        }
+      for (exp0.Init (shape, TopAbs_FACE); exp0.More(); exp0.Next()){
+        TopoDS_Face face = TopoDS::Face(exp0.Current());
+
+        sff = new ShapeFix_Face (face);
+        sff->FixAddNaturalBoundMode() = Standard_True;
+        sff->FixSmallAreaWireMode() = Standard_True;
+        sff->Perform();
+        
+        if(sff->Status(ShapeExtend_DONE1) ||
+           sff->Status(ShapeExtend_DONE2) ||
+           sff->Status(ShapeExtend_DONE3) ||
+           sff->Status(ShapeExtend_DONE4) ||
+           sff->Status(ShapeExtend_DONE5))
+          {
+            Msg::Info("  repaired face %d", fmap.FindIndex(face));
+            if(sff->Status(ShapeExtend_DONE1))
+              Msg::Info("  (some wires are fixed)");
+            else if(sff->Status(ShapeExtend_DONE2))
+              Msg::Info("  (orientation of wires fixed)");
+            else if(sff->Status(ShapeExtend_DONE3))
+              Msg::Info("  (missing seam added)");
+            else if(sff->Status(ShapeExtend_DONE4))
+              Msg::Info("  (small area wire removed)");
+            else if(sff->Status(ShapeExtend_DONE5))
+              Msg::Info("  (natural bounds added)");
+            TopoDS_Face newface = sff->Face();
+            
+            rebuild->Replace(face, newface, Standard_False);
+          }
+      }
+      shape = rebuild->Apply(shape);
     }
-    shape = rebuild->Apply(shape);
-  }
-  
-  {
-    Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
-    rebuild->Apply(shape);
-    for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){
-      TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
-      if ( BRep_Tool::Degenerated(edge) )
-        rebuild->Remove(edge, false);
+    
+    {
+      Handle_ShapeBuild_ReShape rebuild = new ShapeBuild_ReShape;
+      rebuild->Apply(shape);
+      for (exp1.Init (shape, TopAbs_EDGE); exp1.More(); exp1.Next()){
+        TopoDS_Edge edge = TopoDS::Edge(exp1.Current());
+        if (BRep_Tool::Degenerated(edge))
+          rebuild->Remove(edge, false);
+      }
+      shape = rebuild->Apply(shape);
     }
-    shape = rebuild->Apply(shape);
   }
   
   if (fixsmalledges){
@@ -549,6 +554,7 @@ void OCC_Internals::loadBREP(const char *fn)
   BRepTools::Read(shape, (char*)fn, aBuilder);
   BRepTools::Clean(shape);
   healGeometry(CTX::instance()->geom.tolerance, 
+               CTX::instance()->geom.occFixDegenerated,
                CTX::instance()->geom.occFixSmallEdges,
                CTX::instance()->geom.occFixSmallFaces,
                CTX::instance()->geom.occSewFaces,
@@ -580,6 +586,7 @@ void OCC_Internals::loadSTEP(const char *fn)
   shape = reader.OneShape();  
   BRepTools::Clean(shape);
   healGeometry(CTX::instance()->geom.tolerance, 
+               CTX::instance()->geom.occFixDegenerated,
                CTX::instance()->geom.occFixSmallEdges,
                CTX::instance()->geom.occFixSmallFaces,
                CTX::instance()->geom.occSewFaces,
@@ -606,6 +613,7 @@ void OCC_Internals::loadIGES(const char *fn)
   shape = reader.OneShape();  
   BRepTools::Clean(shape);
   healGeometry(CTX::instance()->geom.tolerance, 
+               CTX::instance()->geom.occFixDegenerated,
                CTX::instance()->geom.occFixSmallEdges,
                CTX::instance()->geom.occFixSmallFaces,
                CTX::instance()->geom.occSewFaces,
diff --git a/Geo/GModelIO_OCC.h b/Geo/GModelIO_OCC.h
index 487d0a061e..f3142057eb 100644
--- a/Geo/GModelIO_OCC.h
+++ b/Geo/GModelIO_OCC.h
@@ -32,9 +32,10 @@ class OCC_Internals {
   void buildLists();
   void buildShapeFromLists(TopoDS_Shape _shape);
   void addShapeToLists(TopoDS_Shape shape);
-  void healGeometry(double tolerance, bool fixsmalledges, 
-                    bool fixspotstripfaces, bool sewfaces, 
-                    bool makesolids=false, bool connect=false);
+  void healGeometry(double tolerance, bool fixdegenerated,
+                    bool fixsmalledges, bool fixspotstripfaces,
+                    bool sewfaces, bool makesolids=false, 
+                    bool connect=false);
   void loadBREP(const char *);  
   void writeBREP(const char *);  
   void loadSTEP(const char *);
-- 
GitLab