0022746: Progress indicator in ShapeHealing
[occt.git] / src / ShapeFix / ShapeFix_Solid.cxx
index 3a269a7..ad5ee8b 100755 (executable)
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
 #include <Message_Msg.hxx>
+#include <Message_ProgressSentry.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 
 #include <TopTools_DataMapOfShapeInteger.hxx>
 #include <Geom_Curve.hxx>
 #include <ShapeAnalysis_FreeBounds.hxx>
-
   
 //======================================================
 //function : ShapeFix_Solid
@@ -341,36 +341,55 @@ static Standard_Boolean CreateSolids(const TopoDS_Shape aShape,TopTools_IndexedM
 //purpose  : 
 //=======================================================================
 
-Standard_Boolean ShapeFix_Solid::Perform() 
+Standard_Boolean ShapeFix_Solid::Perform(const Handle(Message_ProgressIndicator)& theProgress) 
 {
 
   Standard_Boolean status = Standard_False;
-  if(Context().IsNull())
+  if ( Context().IsNull() )
     SetContext ( new ShapeBuild_ReShape );
   myFixShell->SetContext(Context());
-  Standard_Integer NbShells =0;
+
+  Standard_Integer NbShells = 0;
   TopoDS_Shape S = Context()->Apply ( myShape );
-  if (  NeedFix ( myFixShellMode ) ) {
-    
-    // call FixShell
-    for( TopoDS_Iterator iter(S); iter.More(); iter.Next()) { 
-      TopoDS_Shape sh = iter.Value();
-      if(sh.ShapeType() != TopAbs_SHELL)
-       continue;
-      myFixShell->Init(TopoDS::Shell(sh));
-      if(myFixShell->Perform()) {
-        //    Context()->Replace(sh,myFixShell->Shell());
+
+  // Calculate number of underlying shells
+  Standard_Integer aNbShells = 0;
+  for ( TopExp_Explorer aExpSh(S, TopAbs_SHELL); aExpSh.More(); aExpSh.Next() )
+    aNbShells++;
+
+  // Start progress scope (no need to check if progress exists -- it is safe)
+  Message_ProgressSentry aPSentry(theProgress, "Fixing solid stage", 0, 2, 1);
+
+  if ( NeedFix(myFixShellMode) )
+  {
+    // Start progress scope (no need to check if progress exists -- it is safe)
+    Message_ProgressSentry aPSentry(theProgress, "Fixing shell", 0, aNbShells, 1);
+
+    // Fix shell by shell using ShapeFix_Shell tool
+    for ( TopExp_Explorer aExpSh(S, TopAbs_SHELL); aExpSh.More() && aPSentry.More(); aExpSh.Next(), aPSentry.Next() )
+    { 
+      TopoDS_Shape sh = aExpSh.Current();
+
+      myFixShell->Init( TopoDS::Shell(sh) );
+      if ( myFixShell->Perform(theProgress) )
+      {
         status = Standard_True;
         myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
       }
       NbShells+= myFixShell->NbShells();
     }
+
+    // Halt algorithm in case of user's abort
+    if ( !aPSentry.More() )
+      return Standard_False;
   }
-  else {
-    for(TopExp_Explorer aExpSh(myShape,TopAbs_SHELL); aExpSh.More(); aExpSh.Next())
-      NbShells++;
+  else 
+  {
+    NbShells = aNbShells;
   }
-  //if(!status) return status;
+
+  // Switch to the second stage
+  aPSentry.Next();
     
   if(NbShells ==1) {
     TopoDS_Shape tmpShape = Context()->Apply(myShape);
@@ -441,7 +460,11 @@ Standard_Boolean ShapeFix_Solid::Perform()
         BRep_Builder aB;
         TopoDS_Compound aComp;
         aB.MakeCompound(aComp);
-        for(Standard_Integer i =1; i <= aMapSolids.Extent(); i++) {
+        Message_ProgressSentry aPSentry(theProgress, "Creating solid",
+                                        0, aMapSolids.Extent(), 1);
+        for(Standard_Integer i =1; (i <= aMapSolids.Extent()) && (aPSentry.More()); 
+            i++, aPSentry.Next()) 
+        {
           TopoDS_Shape aResSh =aMapSolids.FindKey(i);
           if(aResShape.ShapeType() == TopAbs_SHELL && myCreateOpenSolidMode) {
             aResSh.Closed(Standard_False);
@@ -456,6 +479,8 @@ Standard_Boolean ShapeFix_Solid::Perform()
           aB.Add(aComp,aResSh);
           
         }
+        if ( !aPSentry.More() )
+          return Standard_False; // aborted execution
         Context()->Replace(aResShape,aComp);
       }
     }