0030052: Data Exchange - STEP import missing surfaces
[occt.git] / src / ShapeFix / ShapeFix_Face.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 6349c01..32dede1
@@ -1,19 +1,15 @@
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 // pdn 10.12.98: tr9_r0501-ug
 // pdn 28.12.98: PRO10366 shifting pcurve between two singularities
 // abv 19.10.2001  FixAddNaturalBound improved and extracted as separate fix
 // skl,pdn 14.05.2002  OCC55 (correction precision for small faces)
 
-#include <ShapeFix_Face.ixx>
-
-#include <Standard_Failure.hxx>
-#include <Standard_ErrorHandler.hxx>
-
-#include <Precision.hxx>
-
+#include <Bnd_Box.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BndLib_Add2dCurve.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepGProp.hxx>
+#include <BRepTools.hxx>
+#include <BRepTopAdaptor_FClass2d.hxx>
+#include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_Curve.hxx>
 #include <Geom2d_Line.hxx>
 #include <Geom2dAdaptor_Curve.hxx>
-#include <Geom_Curve.hxx>
+#include <Geom2dInt_GInter.hxx>
 #include <Geom_BSplineSurface.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_ConicalSurface.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_Surface.hxx>
 #include <GeomAdaptor_HSurface.hxx>
-
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Shell.hxx>
-#include <TopoDS_Compound.hxx>
-#include <TopoDS_Iterator.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TopTools_SequenceOfShape.hxx>
-
-#include <BRep_Tool.hxx>
-#include <BRep_Builder.hxx>
-#include <BRepTopAdaptor_FClass2d.hxx>
-#include <BRepTools.hxx>
-#include <BRepTools_WireExplorer.hxx>
-#include <BRepBuilderAPI_MakeFace.hxx>
-#include <BRepBuilderAPI_MakeVertex.hxx>
-#include <BRepBuilderAPI_MakeWire.hxx>
-
-#include <Message_Msg.hxx>  
-#include <ShapeBuild_ReShape.hxx>
-#include <ShapeExtend_WireData.hxx>
+#include <GProp_GProps.hxx>
+#include <IntRes2d_Domain.hxx>
+#include <IntRes2d_IntersectionPoint.hxx>
+#include <IntRes2d_IntersectionSegment.hxx>
+#include <IntRes2d_Transition.hxx>
+#include <Message_Msg.hxx>
+#include <NCollection_Array1.hxx>
+#include <Precision.hxx>
 #include <ShapeAnalysis.hxx>
-#include <ShapeFix_Wire.hxx>
-#include <ShapeFix_Edge.hxx>
 #include <ShapeAnalysis_Edge.hxx>
-#include <Bnd_Box2d.hxx>
-#include <Geom_Circle.hxx>
-#include <Geom_SphericalSurface.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-#include <Geom_ConicalSurface.hxx>
-#include <ShapeAnalysis_Wire.hxx>
 #include <ShapeAnalysis_Surface.hxx>
-
+#include <ShapeAnalysis_Wire.hxx>
+#include <ShapeBuild_Edge.hxx>
+#include <ShapeBuild_ReShape.hxx>
+#include <ShapeExtend_BasicMsgRegistrator.hxx>
 #include <ShapeExtend_CompositeSurface.hxx>
+#include <ShapeExtend_WireData.hxx>
+#include <ShapeFix.hxx>
 #include <ShapeFix_ComposeShell.hxx>
+#include <ShapeFix_DataMapOfShapeBox2d.hxx>
+#include <ShapeFix_Edge.hxx>
+#include <ShapeFix_Face.hxx>
+#include <ShapeFix_IntersectionTool.hxx>
+#include <ShapeFix_SplitTool.hxx>
+#include <ShapeFix_Wire.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_Failure.hxx>
+#include <Standard_Type.hxx>
 #include <TColGeom_HArray2OfSurface.hxx>
-#include <ShapeBuild_Edge.hxx>
 #include <TColgp_SequenceOfPnt2d.hxx>
-#include <Bnd_Box.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
 #include <TopTools_DataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
-#include <TopoDS.hxx>
-#include <TopExp.hxx>
-
-#include <ShapeFix.hxx>
-#include <ShapeFix_DataMapOfShapeBox2d.hxx>
-#include <BndLib_Add2dCurve.hxx>
-#include <Geom2dAdaptor_Curve.hxx>
-#include <IntRes2d_Domain.hxx>
-#include <Geom2dInt_GInter.hxx>
-#include <IntRes2d_IntersectionPoint.hxx>
-#include <IntRes2d_Transition.hxx>
 #include <TopTools_SequenceOfShape.hxx>
-#include <IntRes2d_IntersectionSegment.hxx>
-#include <TopTools_DataMapOfShapeInteger.hxx>
 
-#include <ShapeFix_IntersectionTool.hxx>
-#include <ShapeFix_SplitTool.hxx>
-#include <TColStd_MapOfInteger.hxx>
-#include <TopTools_DataMapOfShapeShape.hxx>
+IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Face,ShapeFix_Root)
 
-#ifdef DEB
+#ifdef OCCT_DEBUG
 #define DEBUG
 #endif
 
+static Standard_Boolean IsSurfaceUVInfinite(const Handle(Geom_Surface)& theSurf)
+{
+  Standard_Real UMin,UMax,VMin,VMax;
+  theSurf->Bounds(UMin,UMax,VMin,VMax);
+
+  return (Precision::IsInfinite(UMin) ||
+          Precision::IsInfinite(UMax) ||
+          Precision::IsInfinite(VMin) ||
+          Precision::IsInfinite(VMax)   );
+}
+
+static Standard_Boolean IsSurfaceUVPeriodic(const Handle(Geom_Surface)& theSurf)
+{
+  return theSurf->IsUPeriodic() && theSurf->IsVPeriodic();
+}
+
 //=======================================================================
 //function : ShapeFix_Face
 //purpose  : 
@@ -152,6 +162,7 @@ void ShapeFix_Face::ClearModes()
   myFixAddNaturalBoundMode   = -1;
   myFixMissingSeamMode       = -1;
   myFixSmallAreaWireMode     = -1;
+  myRemoveSmallAreaFaceMode  = -1;
   myFixIntersectingWiresMode = -1;
   myFixLoopWiresMode         = -1;
   myFixSplitFaceMode         = -1;
@@ -336,8 +347,8 @@ static Standard_Boolean SplitWire(const TopoDS_Face &face, const TopoDS_Wire& wi
   }
 
   if(aResWires.Length()>1) {
-#ifdef DEBUG
-    cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< endl;
+#ifdef OCCT_DEBUG
+    std::cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< std::endl;
 #endif
   }
 
@@ -354,7 +365,7 @@ Standard_Boolean ShapeFix_Face::Perform()
 {
   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
   myFixWire->SetContext ( Context() );
-  Handle(ShapeFix_Wire) theAdvFixWire = Handle(ShapeFix_Wire)::DownCast(myFixWire);
+  Handle(ShapeFix_Wire) theAdvFixWire = myFixWire;
   if (theAdvFixWire.IsNull()) return Standard_False;
 
   BRep_Builder B;
@@ -371,10 +382,10 @@ Standard_Boolean ShapeFix_Face::Perform()
     theAdvFixWire->SetFace ( myFace );
     
     Standard_Integer usFixLackingMode = theAdvFixWire->FixLackingMode();
-    Standard_Integer usFixNotchedEdgesMode = theAdvFixWire->FixNotchedEdgesMode();
+    //Standard_Integer usFixNotchedEdgesMode = theAdvFixWire->FixNotchedEdgesMode(); // CR0024983
     Standard_Integer usFixSelfIntersectionMode = theAdvFixWire->FixSelfIntersectionMode();
     theAdvFixWire->FixLackingMode() = Standard_False;
-    theAdvFixWire->FixNotchedEdgesMode() = Standard_False;
+    //theAdvFixWire->FixNotchedEdgesMode() = Standard_False; // CR0024983
     theAdvFixWire->FixSelfIntersectionMode() = Standard_False;
     
     Standard_Boolean fixed = Standard_False; 
@@ -423,7 +434,7 @@ Standard_Boolean ShapeFix_Face::Perform()
         theAdvFixWire->SetPrecision(newpreci);    
       }
     }
-   
+
     isfixReorder = Standard_False;
     for ( TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) { 
       if(iter.Value().ShapeType() != TopAbs_WIRE) {
@@ -447,6 +458,8 @@ Standard_Boolean ShapeFix_Face::Perform()
         fixed = (theAdvFixWire->StatusSmall(ShapeExtend_DONE) || 
                theAdvFixWire->StatusConnected(ShapeExtend_DONE) ||
                theAdvFixWire->StatusEdgeCurves(ShapeExtend_DONE) ||
+               theAdvFixWire->StatusNotches(ShapeExtend_DONE) ||  // CR0024983
+               theAdvFixWire->StatusFixTails(ShapeExtend_DONE) ||
                theAdvFixWire->StatusDegenerated(ShapeExtend_DONE) ||
                theAdvFixWire->StatusClosed(ShapeExtend_DONE));
         TopoDS_Wire w = theAdvFixWire->Wire();
@@ -468,7 +481,7 @@ Standard_Boolean ShapeFix_Face::Perform()
     }
     
     theAdvFixWire->FixLackingMode() = usFixLackingMode;
-    theAdvFixWire->FixNotchedEdgesMode() = usFixNotchedEdgesMode;
+    //theAdvFixWire->FixNotchedEdgesMode() = usFixNotchedEdgesMode;  // CR0024983
     theAdvFixWire->FixSelfIntersectionMode() = usFixSelfIntersectionMode;
     if ( ! myFwd ) tmpFace.Orientation ( TopAbs_REVERSED );
     
@@ -501,7 +514,7 @@ Standard_Boolean ShapeFix_Face::Perform()
   }
 
   // cycle by all possible faces coming from FixMissingSeam
-  // each face is processed as if it was single 
+  // each face is processed as if it was single
   TopExp_Explorer exp(myResult,TopAbs_FACE);
   for ( ; exp.More(); exp.Next() ) {
     myFace = TopoDS::Face ( exp.Current() );
@@ -546,9 +559,10 @@ Standard_Boolean ShapeFix_Face::Perform()
         }
        if ( theAdvFixWire->Perform() ) {
           isfixReorder =  theAdvFixWire->StatusReorder(ShapeExtend_DONE);
-         fixed = (theAdvFixWire->StatusLacking(ShapeExtend_DONE) ||
-                   theAdvFixWire->StatusSelfIntersection(ShapeExtend_DONE) ||
-                   theAdvFixWire->StatusNotches(ShapeExtend_DONE));  //Standard_True; 
+          fixed = (theAdvFixWire->StatusLacking(ShapeExtend_DONE) ||
+            theAdvFixWire->StatusSelfIntersection(ShapeExtend_DONE) ||
+            theAdvFixWire->StatusNotches(ShapeExtend_DONE) ||
+            theAdvFixWire->StatusFixTails(ShapeExtend_DONE));
          TopoDS_Wire w = theAdvFixWire->Wire();
           if(fixed) {
             if ( ! Context().IsNull() ) Context()->Replace ( wire, w );
@@ -664,7 +678,7 @@ Standard_Boolean ShapeFix_Face::Perform()
   
   //return the original preci
   SetPrecision(aSavPreci);
-  theAdvFixWire->SetPrecision(aSavPreci);    
+  theAdvFixWire->SetPrecision(aSavPreci);
   
   // cycle by all possible faces coming from FixAddNaturalBound
   // each face is processed as if it was single 
@@ -672,13 +686,14 @@ Standard_Boolean ShapeFix_Face::Perform()
     myFace = TopoDS::Face ( exp.Current() );
 
     // fix small-area wires
-    if ( NeedFix ( myFixSmallAreaWireMode, Standard_False ) ) {
-      if ( FixSmallAreaWire() )
-       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
+    if ( NeedFix ( myFixSmallAreaWireMode, Standard_False ) )
+    {
+      const Standard_Boolean isRemoveFace = NeedFix( myRemoveSmallAreaFaceMode, Standard_False );
+      if ( FixSmallAreaWire( isRemoveFace ) )
+        myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
     }
   }
-  
-    
+
   if ( ! Context().IsNull() ) {
     if(Status ( ShapeExtend_DONE ) && !isReplaced && !aInitFace.IsSame(savShape))
     {
@@ -811,29 +826,36 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
       vs.Append(wi.Value());
   }
 
-  // deal with case of empty face: just create a new one by standard tool
-  if ( ws.Length() <=0 ) {
-    BRepBuilderAPI_MakeFace mf (mySurf->Surface(), Precision::Confusion());
-    if ( ! Context().IsNull() ) Context()->Replace ( myFace, mf.Face() );
-    myFace = mf.Face();
+  // deal with the case of an empty face: just create a new face by a standard tool
+  if (ws.IsEmpty() && !IsSurfaceUVInfinite (mySurf->Surface()))
+  {
+    BRepBuilderAPI_MakeFace aFaceBuilder (mySurf->Surface(), Precision::Confusion());
+
+    TopoDS_Face aNewFace = aFaceBuilder.Face();
+    aNewFace.Orientation (myFace.Orientation());
+
+    if ( ! Context().IsNull() )
+      Context()->Replace (myFace, aNewFace);
+
+    // taking into account orientation
+    myFace = aNewFace;
 
     //gka 11.01.99 file PRO7755.stp entity #2018 surface #1895: error BRepLib_MakeFace func IsDegenerated
     Handle(ShapeFix_Edge) sfe = myFixWire->FixEdgeTool();
     for (TopExp_Explorer Eed (myFace, TopAbs_EDGE); Eed.More(); Eed.Next()) {
       TopoDS_Edge edg = TopoDS::Edge (Eed.Current());
-      sfe->FixVertexTolerance(edg);
+      sfe->FixVertexTolerance(edg, myFace);
     }
 
 //    B.UpdateFace (myFace,myPrecision);
     SendWarning ( myFace, Message_Msg ( "FixAdvFace.FixOrientation.MSG0" ) );// Face created with natural bounds
     BRepTools::Update(myFace);
+    myResult = myFace;
     return Standard_True;
   }
-  
-  // check that surface is double-closed and fix is needed
-  if ( ( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
-         mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ||
-       ShapeAnalysis::IsOuterBound (myFace) ) 
+
+  // check if surface is double-closed and fix is needed
+  if ( !IsSurfaceUVPeriodic (mySurf->Surface()) || ShapeAnalysis::IsOuterBound (myFace) ) 
     return Standard_False;
 
   // Collect informations on free intervals in U and V
@@ -972,8 +994,8 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
   BRepTools::Update(myFace);
   
 /**/
-#ifdef DEBUG
-  cout<<"Natural bound on sphere or torus with holes added"<<endl; // mise au point !
+#ifdef OCCT_DEBUG
+  std::cout<<"Natural bound on sphere or torus with holes added"<<std::endl; // mise au point !
 #endif
   SendWarning ( myFace, Message_Msg ( "FixAdvFace.FixOrientation.MSG0" ) );// Face created with natural bounds
   return Standard_True;
@@ -1019,7 +1041,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
       continue;
     }
     
-    TopoDS_Iterator ei (wi.Value(),Standard_False); 
+    TopoDS_Iterator ei (wi.Value(),Standard_False);
     TopoDS_Edge anEdge;
     Standard_Real length = RealLast();
     if ( ei.More() ) {
@@ -1063,8 +1085,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
   if ( nb <= 0) return Standard_False;
   Standard_Integer nbInternal=0;
   Standard_Boolean isAddNaturalBounds = (NeedFix (myFixAddNaturalBoundMode) && 
-                                         ( mySurf->Adaptor3d()->GetType() == GeomAbs_Sphere || 
-                                          mySurf->Adaptor3d()->GetType() == GeomAbs_Torus ));
+                                         IsSurfaceUVPeriodic (mySurf->Surface()));
   TColStd_SequenceOfInteger aSeqReversed;
   // if wire is only one, check its orientation
   if ( nb == 1 ) {
@@ -1074,18 +1095,18 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
     TopoDS_Face af = TopoDS::Face ( dummy );
     af.Orientation ( TopAbs_FORWARD );
     B.Add (af,ws.Value(1));
-    if ( ( myFixAddNaturalBoundMode != Standard_True || //: abv 29.08.01: Spatial_firex_lofting.sat
-           ( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
-             mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ) &&
-         ! ShapeAnalysis::IsOuterBound (af)) {
+    if ((myFixAddNaturalBoundMode != 1 ||
+         !IsSurfaceUVPeriodic (mySurf->Surface())    ) &&
+        !ShapeAnalysis::IsOuterBound (af)                )
+    {
       Handle(ShapeExtend_WireData) sbdw = 
         new ShapeExtend_WireData (TopoDS::Wire(ws.Value(1)));
       sbdw->Reverse ( myFace );
       ws.SetValue ( 1, sbdw->Wire() );
       SendWarning ( sbdw->Wire(), Message_Msg ( "FixAdvFace.FixOrientation.MSG5" ) );// Wire on face was reversed
       done = Standard_True;
-#ifdef DEBUG
-      cout<<"Wire reversed"<<endl; // mise au point !
+#ifdef OCCT_DEBUG
+      std::cout<<"Wire reversed"<<std::endl; // mise au point !
 #endif
     }
   }
@@ -1110,6 +1131,8 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
     Standard_Boolean vclosed = mySurf->IsVClosed();
     Standard_Real SUF, SUL, SVF, SVL;
     mySurf->Bounds(SUF, SUL, SVF, SVL);
+    Standard_Real uRange = SUL - SUF;
+    Standard_Real vRange = SVL - SVF;
     
     TopTools_DataMapOfShapeListOfShape MW;
     TopTools_DataMapOfShapeInteger SI;
@@ -1119,10 +1142,58 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
     MapIntWires.Clear();
     Standard_Integer NbOuts=0;
     Standard_Integer i;
+
+    NCollection_Array1<Bnd_Box2d> aWireBoxes(1, nb);
+    Standard_Real uMiddle = 0, vMiddle = 0;
+    Standard_Boolean isFirst = Standard_True;
+    //create Bounding boxes for each wire
+    for ( i = 1; i <= nb; i ++) {
+      TopoDS_Shape aShape = ws.Value(i);
+      TopoDS_Wire aWire = TopoDS::Wire (aShape);
+      Bnd_Box2d aBox;
+      Standard_Real cf,cl;
+      TopoDS_Iterator ew (aWire);
+      for(;ew.More(); ew.Next()) {
+        TopoDS_Edge ed = TopoDS::Edge (ew.Value());
+        Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl);
+        if (cw.IsNull ())
+        {
+          continue;
+        }
+        Geom2dAdaptor_Curve gac;
+        Standard_Real aFirst = cw->FirstParameter();
+        Standard_Real aLast = cw->LastParameter();
+        if(cw->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) && (cf < aFirst || cl > aLast)) {
+          //avoiding problems with segment in Bnd_Box
+          gac.Load(cw);
+        }
+       else
+         gac.Load(cw,cf,cl);
+       BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),aBox);
+      }
+
+      Standard_Real aXMin, aXMax, aYMin, aYMax;
+      aBox.Get(aXMin, aYMin, aXMax, aYMax);
+      if (isFirst) {
+        isFirst = Standard_False;
+        uMiddle = (aXMin + aXMax) * 0.5;
+        vMiddle = (aYMin + aYMax) * 0.5;
+      }
+      else {
+        Standard_Real xShift = 0, yShift = 0;
+        if ( mySurf->IsUClosed() ) 
+          xShift = ShapeAnalysis::AdjustByPeriod ( 0.5*(aXMin + aXMax), uMiddle, uRange );
+        if ( mySurf->IsVClosed() ) 
+          yShift = ShapeAnalysis::AdjustByPeriod ( 0.5*(aYMin + aYMax), vMiddle, vRange ) ;
+        aBox.Update(aXMin + xShift, aYMin + yShift, aXMax + xShift, aYMax + yShift);
+      }
+      aWireBoxes.ChangeValue(i) = aBox;
+    }
     
     for ( i = 1; i <= nb; i ++) {
       TopoDS_Shape asw = ws.Value(i);
       TopoDS_Wire aw = TopoDS::Wire (asw);
+      Bnd_Box2d aBox1 = aWireBoxes.Value(i);
       TopoDS_Shape dummy = myFace.EmptyCopied();
       TopoDS_Face af = TopoDS::Face ( dummy );
 //      B.MakeFace (af,mySurf->Surface(),::Precision::Confusion());
@@ -1137,27 +1208,28 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
       TopAbs_State sta = TopAbs_OUT;
       TopAbs_State staout = clas.PerformInfinitePoint();
       TopTools_ListOfShape IntWires;
+      Standard_Integer aWireIt = 0;
       for ( Standard_Integer j = 1; j <= nbAll; j ++) {
+        aWireIt++;
         //if(i==j) continue;
         TopoDS_Shape aSh2 = allSubShapes.Value(j);
         if(aw == aSh2)
           continue;
         TopAbs_State stb = TopAbs_UNKNOWN;
         if(aSh2.ShapeType() == TopAbs_VERTEX) {
+          aWireIt--;
           gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2));
           gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion());
           stb = clas.Perform (p2d,Standard_False);
           if(stb == staout && (uclosed || vclosed)) {
             gp_Pnt2d p2d1;
             if(uclosed) {
-              Standard_Real period = SUL-SUF;
-              p2d1.SetCoord(p2d.X()+period, p2d.Y());
+              p2d1.SetCoord(p2d.X()+uRange, p2d.Y());
               stb = clas.Perform (p2d1,Standard_False);
               
             }
             if(stb == staout && vclosed) {
-              Standard_Real period = SVL-SVF;
-              p2d1.SetCoord(p2d.X(), p2d.Y()+ period);
+              p2d1.SetCoord(p2d.X(), p2d.Y()+ vRange);
               stb = clas.Perform (p2d1,Standard_False);
             }
           }
@@ -1165,7 +1237,11 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
         else if (aSh2.ShapeType() == TopAbs_WIRE) {
           CheckShift = Standard_True;
           TopoDS_Wire bw = TopoDS::Wire (aSh2);
-          //   Standard_Integer numin =0;
+          //Standard_Integer numin =0;
+          Bnd_Box2d aBox2 = aWireBoxes.Value(aWireIt);
+          if (aBox2.IsOut(aBox1))
+            continue;
+
           TopoDS_Iterator ew (bw);
           for(;ew.More(); ew.Next()) {
             TopoDS_Edge ed = TopoDS::Edge (ew.Value());
@@ -1193,23 +1269,31 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
             if( stb == staout && CheckShift ) {
               CheckShift = Standard_False;
               if(uclosed) {
-                Standard_Real period = SUL-SUF;
-                unp1.SetCoord(unp.X()+period, unp.Y());
+                unp1.SetCoord(unp.X()+uRange, unp.Y());
                 found = (staout != clas.Perform (unp1,Standard_False));
                 if(!found) {
-                  unp1.SetX(unp.X()-period);
+                  unp1.SetX(unp.X()-uRange);
                   found = (staout != clas.Perform (unp1,Standard_False));
                 }
               }
               if(vclosed&&!found) {
-                Standard_Real period = SVL-SVF;
-                unp1.SetCoord(unp.X(), unp.Y()+period);
+                unp1.SetCoord(unp.X(), unp.Y()+vRange);
                 found = (staout != clas.Perform (unp1,Standard_False));
                 if(!found) {
-                  unp1.SetY(unp.Y()-period);
+                  unp1.SetY(unp.Y()-vRange);
                   found = (staout != clas.Perform (unp1,Standard_False));
                 }
               }
+              // Additional check of diagonal steps for toroidal surfaces
+              if (!found && uclosed && vclosed)
+              {
+                for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0)
+                  for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0)
+                  {
+                    unp1.SetCoord(unp.X() + uRange * dX, unp.Y() + vRange * dY);
+                    found = (staout != clas.Perform(unp1, Standard_False));
+                  }
+              }
             }
             if(found) {
               if(stb==TopAbs_IN) stb = TopAbs_OUT;
@@ -1322,8 +1406,8 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
     Standard_Integer k =1;
     for( ; k <= aSeqReversed.Length(); k++ )
     {
-#ifdef DEBUG
-      cout<<"Wire no "<<aSeqReversed.Value(k)<<" of "<<nb<<" reversed"<<endl; // mise au point !
+#ifdef OCCT_DEBUG
+      std::cout<<"Wire no "<<aSeqReversed.Value(k)<<" of "<<nb<<" reversed"<<std::endl; // mise au point !
 #endif
     }
       
@@ -1350,6 +1434,8 @@ static Standard_Boolean CheckWire (const TopoDS_Wire &wire,
   vec.SetX(0);
   vec.SetY(0);
   ShapeAnalysis_Edge sae;
+
+  isuopen = isvopen = 0;
   isDeg = Standard_True;
   for ( TopoDS_Iterator ed(wire); ed.More(); ed.Next() ) {
     TopoDS_Edge edge = TopoDS::Edge ( ed.Value() );
@@ -1360,17 +1446,48 @@ static Standard_Boolean CheckWire (const TopoDS_Wire &wire,
       return Standard_False;
     vec += c2d->Value(l).XY() - c2d->Value(f).XY();
   }
-  isuopen = ( Abs ( Abs ( vec.X() ) - dU ) < 0.1 * dU ? ( vec.X() >0 ? 1 : -1 ) : 0 );
-  isvopen = ( Abs ( Abs ( vec.Y() ) - dV ) < 0.1 * dV ? ( vec.Y() >0 ? 1 : -1 ) : 0 );
+
+  Standard_Real aDelta = Abs(vec.X())-dU;
+  if(Abs(aDelta) < 0.1*dU)
+  {
+    if(vec.X() > 0.0)
+    {
+      isuopen = 1;
+    }
+    else
+    {
+      isuopen = -1;
+    }
+  }
+  else
+  {
+    isuopen = 0;
+  }
+
+  aDelta = Abs(vec.Y())-dV;
+  if(Abs(aDelta) < 0.1*dV)
+  {
+    if(vec.Y() > 0.0)
+    {
+      isvopen = 1;
+    }
+    else
+    {
+      isvopen = -1;
+    }
+  }
+  else
+  {
+    isvopen = 0;
+  }
+
   return isuopen || isvopen;
 }
 
-
 //=======================================================================
 //function : FixMissingSeam
 //purpose  : 
 //=======================================================================
-
 Standard_Boolean ShapeFix_Face::FixMissingSeam() 
 {
   Standard_Boolean uclosed = mySurf->IsUClosed();
@@ -1413,8 +1530,8 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
     }
   }
     
-  URange = Abs ( SUL - SUF );
-  VRange = Abs ( SVL - SVF );
+  URange = Min(Abs (SUL - SUF), Precision::Infinite());
+  VRange = Min(Abs(SVL - SVF), Precision::Infinite());
 //  Standard_Real UTol = 0.2 * URange, VTol = 0.2 * VRange;
   Standard_Integer ismodeu = 0, ismodev = 0; //szv#4:S4163:12Mar99 was Boolean
   Standard_Integer isdeg1=0, isdeg2=0;
@@ -1453,19 +1570,19 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
         }
         else {
           w2.Reverse();
-#ifdef DEB
-          if ( ! isdeg2 ) cout << "Warning: ShapeFix_Face::FixMissingSeam(): wire reversed" << endl;
+#ifdef OCCT_DEBUG
+          if ( ! isdeg2 ) std::cout << "Warning: ShapeFix_Face::FixMissingSeam(): wire reversed" << std::endl;
 #endif
         }
       }
-#ifdef DEB
-      else cout << "Warning: ShapeFix_Face::FixMissingSeam(): incompatible open wires" << endl;
+#ifdef OCCT_DEBUG
+      else std::cout << "Warning: ShapeFix_Face::FixMissingSeam(): incompatible open wires" << std::endl;
 #endif
     }
 //    else return Standard_False; //  abort
     else {
-#ifdef DEB
-      cout << "Warning: ShapeFix_Face::FixMissingSeam(): more than two open wires detected!" << endl;
+#ifdef OCCT_DEBUG
+      std::cout << "Warning: ShapeFix_Face::FixMissingSeam(): more than two open wires detected!" << std::endl;
 #endif
       //:abv 30.08.09: if more than one open wires and more than two of them are
       // completely degenerated, remove any of them
@@ -1474,8 +1591,8 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
         w1.Nullify();
         w2.Nullify();
         i = 0;
-#ifdef DEB
-        cout << "Warning: ShapeFix_Face::FixMissingSeam(): open degenerated wire removed" << endl;
+#ifdef OCCT_DEBUG
+        std::cout << "Warning: ShapeFix_Face::FixMissingSeam(): open degenerated wire removed" << std::endl;
 #endif
         continue;
       }
@@ -1484,79 +1601,132 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
 
   BRep_Builder B;
   if ( w1.IsNull() ) return Standard_False;
-  else if ( w2.IsNull() ) {
-    // WARNING!!! Temporarily for spheres only: 
-    // If only one of wires limiting face on sphere is open in 2d,
-    // this means that degenerated edge should be added to one of poles, and
+  else if ( w2.IsNull()) {
+    // For spheres and BSpline cone-like surfaces(bug 24055):
+    // If only one of wires limiting face on surface is open in 2d,
+    // this may means that degenerated edge should be added, and
     // then usual procedure applied
+    gp_Pnt2d p;
+    gp_Dir2d d;
+    Standard_Real aRange;
+
     if ( ismodeu && mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ) {
-      gp_Pnt2d p ( ( ismodeu < 0 ? 0. : 2.*M_PI ), ismodeu * 0.5 * M_PI );
-      gp_Dir2d d ( -ismodeu, 0. );
-      Handle(Geom2d_Line) line = new Geom2d_Line ( p, d );
-      TopoDS_Edge edge;
-      B.MakeEdge ( edge );
-      B.Degenerated ( edge, Standard_True );
-      B.UpdateEdge ( edge, line, myFace, ::Precision::Confusion() );
-      B.Range ( edge, myFace, 0., 2*M_PI );
-      TopoDS_Vertex V;
-      B.MakeVertex ( V, mySurf->Value ( p.X(), p.Y() ), ::Precision::Confusion() );
-      V.Orientation(TopAbs_FORWARD);
-      B.Add(edge,V);
-      V.Orientation(TopAbs_REVERSED);
-      B.Add(edge,V);
-      B.MakeWire ( w2 );
-      B.Add ( w2, edge );
-      ws.Append ( w2 );
+      p.SetCoord ( ( ismodeu < 0 ? 0. : 2.*M_PI ), ismodeu * 0.5 * M_PI );
+      Standard_Real aXCoord = -ismodeu;
+      d.SetCoord ( aXCoord, 0.);
+      aRange = 2.*M_PI;
+    }
+    else if ( ismodev && mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
+      Standard_Real uCoord;
+      if (mySurf->Value(SUF, SVF).Distance(mySurf->Value(SUF, (SVF + SVL) / 2)) < ::Precision::Confusion())
+        uCoord = SUF;
+      else if (mySurf->Value(SUL, SVF).Distance(mySurf->Value(SUL, (SVF + SVL) / 2)) < ::Precision::Confusion())
+        uCoord = SUL;
+      else return Standard_False;
+
+      p.SetCoord ( uCoord, ( ismodev < 0 ? 0. : VRange ) );
+      d.SetCoord ( 0., -ismodev);
+      aRange = VRange;
+    }
+    else if ( ismodeu && mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) {
+      Standard_Real vCoord;
+      if (mySurf->Value(SUF, SVF).Distance(mySurf->Value((SUF + SUL) / 2, SVF)) < ::Precision::Confusion())
+        vCoord = SVF;
+      else if (mySurf->Value(SUL, SVL).Distance(mySurf->Value((SUF + SUL) / 2, SVL)) < ::Precision::Confusion())
+        vCoord = SVL;
+      else return Standard_False;
+
+      p.SetCoord ( ( ismodeu < 0 ? 0. : URange ), vCoord );
+      Standard_Real aXCoord = -ismodeu;
+      d.SetCoord ( aXCoord, 0.);
+      aRange = URange;
     }
     else return Standard_False;
+
+    Handle(Geom2d_Line) line = new Geom2d_Line ( p, d );
+    TopoDS_Edge edge;
+    B.MakeEdge ( edge );
+    B.Degenerated ( edge, Standard_True );
+    B.UpdateEdge ( edge, line, myFace, ::Precision::Confusion() );
+    B.Range ( edge, myFace, 0., aRange );
+    TopoDS_Vertex V;
+    B.MakeVertex ( V, mySurf->Value ( p.X(), p.Y() ), ::Precision::Confusion() );
+    V.Orientation(TopAbs_FORWARD);
+    B.Add(edge,V);
+    V.Orientation(TopAbs_REVERSED);
+    B.Add(edge,V);
+    B.MakeWire ( w2 );
+    B.Add ( w2, edge );
+    ws.Append ( w2 );
   }
   
+  // Check consistency of orientations of the two wires that need to be connected by a seam
+  Standard_Real uf=SUF, vf=SVF;  
+  Standard_Integer coord = ( ismodeu ? 1 : 0 );
+  Standard_Integer isneg = ( ismodeu ? ismodeu : -ismodev );
+  Standard_Real period = ( ismodeu ? URange : VRange );
+  TopoDS_Shape S;
+  Standard_Real m1[2][2], m2[2][2];
+  S = myFace.EmptyCopied();
+  B.Add ( S, w1 );
+  ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m1[0][0], m1[0][1], m1[1][0], m1[1][1]);
+  S = myFace.EmptyCopied();
+  B.Add ( S, w2 );
+  ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m2[0][0], m2[0][1], m2[1][0], m2[1][1]);
+   
+  // For the case when surface is closed only in one direction it is necesary to check
+  // validity of orientation of the open wires in parametric space. 
+  // In case of U closed surface wire with minimal V coordinate should be directed in positive direction by U
+  // In case of V closed surface wire with minimal U coordinate should be directed in negative direction by V
+  if (!vclosed || !uclosed)
+  {
+    Standard_Real deltaOther = 0.5 * (m2[coord][0] + m2[coord][1]) - 0.5 * (m1[coord][0] + m1[coord][1]);
+    if (deltaOther  * isneg < 0)
+    {
+      w1.Reverse();
+      w2.Reverse();
+    }
+  }
+
   // sort original wires
   Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
   sfw->SetFace ( myFace );
   sfw->SetPrecision ( Precision() );
-
   Handle(ShapeExtend_WireData) wd1 = new ShapeExtend_WireData ( w1 );
   Handle(ShapeExtend_WireData) wd2 = new ShapeExtend_WireData ( w2 );
-
-  // sorting
-//  Standard_Boolean degenerated = ( secondDeg != firstDeg );
-//  if ( ! degenerated ) {
-    sfw->Load ( wd1 );
-    sfw->FixReorder();
-//  }
+  sfw->Load ( wd1 );
+  sfw->FixReorder();
   sfw->Load ( wd2 );
   sfw->FixReorder();
-
+  TopoDS_Wire w11 = wd1->Wire();
+  TopoDS_Wire w21 = wd2->Wire();
   //:abv 29.08.01: reconstruct face taking into account reversing
   TopoDS_Shape dummy = myFace.EmptyCopied();
   TopoDS_Face tmpF = TopoDS::Face ( dummy );
   tmpF.Orientation ( TopAbs_FORWARD );
   for ( i=1; i <= ws.Length(); i++ ) {
     TopoDS_Wire wire = TopoDS::Wire ( ws.Value(i) );
-    if ( wire.IsSame ( w1 ) ) wire = w1;
-    else if ( wire.IsSame ( w2 ) ) wire = w2;
+    if ( wire.IsSame ( w1 ) ) wire = w11;
+    else if ( wire.IsSame ( w2 ) ) wire = w21;
+    else
+    {
+      // other wires (not boundary) are considered as holes; make sure to have them oriented accordingly
+      TopoDS_Shape curface = tmpF.EmptyCopied();
+      B.Add(curface,wire);
+      curface.Orientation ( myFace.Orientation() );
+      if( ShapeAnalysis::IsOuterBound(TopoDS::Face(curface)))
+        wire.Reverse();
+    }
     B.Add ( tmpF, wire );
   }
   tmpF.Orientation ( myFace.Orientation() );
-  
-  Standard_Real uf=SUF, vf=SVF;
-  
+
   // A special kind of FixShifted is necessary for torus-like
   // surfaces to adjust wires by period ALONG the missing SEAM direction
   // tr9_r0501-ug.stp #187640
   if ( uclosed && vclosed ) {
-    Standard_Integer coord = ( ismodeu ? 1 : 0 );
-    Standard_Integer isneg = ( ismodeu ? ismodeu : -ismodev );
-    Standard_Real period = ( ismodeu ? URange : VRange );
-    TopoDS_Shape S;
-    Standard_Real m1[2][2], m2[2][2];
-    S = tmpF.EmptyCopied();
-    B.Add ( S, w1 );
-    ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m1[0][0], m1[0][1], m1[1][0], m1[1][1]);
-    S = tmpF.EmptyCopied();
-    B.Add ( S, w2 );
-    ShapeAnalysis::GetFaceUVBounds (TopoDS::Face(S), m2[0][0], m2[0][1], m2[1][0], m2[1][1]);
     Standard_Real shiftw2 = 
       ShapeAnalysis::AdjustByPeriod ( 0.5 * ( m2[coord][0] + m2[coord][1] ),
                                       0.5 * ( m1[coord][0] + m1[coord][1]  +
@@ -1568,9 +1738,10 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
       if(it.Value().ShapeType() != TopAbs_WIRE)
         continue;
       TopoDS_Wire w = TopoDS::Wire ( it.Value() );
-      if ( w == w1 ) continue;
+      if ( w == w11 ) continue;
       Standard_Real shift;
-      if ( w == w2 ) shift = shiftw2;
+      if ( w == w21 ) shift = shiftw2;
+
       else {
        S = tmpF.EmptyCopied();
        B.Add ( S, w );
@@ -1624,7 +1795,7 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
     }
     Standard_Boolean skipV = ! vclosed;
     if ( vclosed && ! ismodeu ) {
-      pos1.SetY ( pos1.Y() + ShapeAnalysis::AdjustByPeriod ( pos1.Y(), SVF, URange ) );
+      pos1.SetY ( pos1.Y() + ShapeAnalysis::AdjustByPeriod ( pos1.Y(), SVF, VRange ) );
       if ( foundV ==2 && Abs ( pos1.Y() ) > Abs(vf) ) skipV = Standard_True;
       else if ( ! foundV || ( foundV ==1 && Abs ( pos1.Y() ) < Abs(vf) ) ) {
        foundV = 1;
@@ -1692,13 +1863,56 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
   mySurf = new ShapeAnalysis_Surface ( RTS );
 
   myResult = CompShell.Result();
-//  if ( myFace.Orientation() == TopAbs_REVERSED ) res.Reverse();
   Context()->Replace ( myFace, myResult );
+
+  // Remove small wires and / or faces that can be generated by ComposeShell
+  // (see tests bugs step bug30052_4, de step_3 E6)
+  Standard_Integer nbFaces = 0;
+  TopExp_Explorer expF ( myResult, TopAbs_FACE );
+  for (; expF.More(); expF.Next() )
+  {
+    TopoDS_Face aFace = TopoDS::Face(expF.Value());
+    TopExp_Explorer aExpW(aFace, TopAbs_WIRE);
+    Standard_Integer nbWires = 0;
+    for( ;aExpW.More(); aExpW.Next() )
+    {
+      ShapeFix_Wire aSfw(TopoDS::Wire(aExpW.Value()), aFace, Precision());
+      aSfw.SetContext(Context());
+      if(aSfw.NbEdges())
+        aSfw.FixSmall (Standard_True, Precision());
+      if(!aSfw.NbEdges())
+      {
+        Context()->Remove(aExpW.Value());
+        continue;
+      }
+      nbWires++;
+    }
+    if(!nbWires)
+    {
+      Context()->Remove(aFace);
+      continue;
+    }
+    nbFaces++;
+  }
+   
+  myResult = Context()->Apply(myResult);
   for (TopExp_Explorer exp ( myResult, TopAbs_FACE ); exp.More(); exp.Next() ) {
-    myFace = TopoDS::Face ( exp.Current() );
+    myFace = TopoDS::Face ( Context()->Apply(exp.Current() ));
+    if( myFace.IsNull())
+      continue;
+    if(nbFaces > 1)
+    {
+      FixSmallAreaWire(Standard_True);
+      TopoDS_Shape aShape = Context()->Apply(myFace);
+      if(aShape.IsNull() )
+        continue;
+      myFace = TopoDS::Face(aShape);
+    }
     BRepTools::Update(myFace); //:p4
   }
-
+  myResult = Context()->Apply(myResult);
+  
   SendWarning ( Message_Msg ( "FixAdvFace.FixMissingSeam.MSG0" ) );// Missing seam-edge added
   return Standard_True;
 }
@@ -1707,51 +1921,69 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
 //function : FixSmallAreaWire
 //purpose  : 
 //=======================================================================
-
 //%14 pdn 24.02.99 PRO10109, USA60293 fix wire on face with small area.
-Standard_Boolean ShapeFix_Face::FixSmallAreaWire(
+Standard_Boolean ShapeFix_Face::FixSmallAreaWire(const Standard_Boolean theIsRemoveSmallFace)
 {
-  if ( ! Context().IsNull() ) {
-    TopoDS_Shape S = Context()->Apply ( myFace );
-    myFace = TopoDS::Face ( S );
+  if ( !Context().IsNull() )
+  {
+    TopoDS_Shape aShape = Context()->Apply(myFace);
+    myFace = TopoDS::Face(aShape);
   }
-  
-  //smh#8
-  TopoDS_Shape emptyCopied = myFace.EmptyCopied();
-  TopoDS_Face face = TopoDS::Face (emptyCopied);
+
+  BRep_Builder aBuilder;
   Standard_Integer nbRemoved = 0, nbWires = 0;
-  BRep_Builder B;
-  Standard_Real prec = ::Precision::PConfusion()*100;
-  for (TopoDS_Iterator wi (myFace, Standard_False); wi.More(); wi.Next()) {
-    if(wi.Value().ShapeType() != TopAbs_WIRE && 
-       (wi.Value().Orientation() != TopAbs_FORWARD && wi.Value().Orientation() != TopAbs_REVERSED))
-        continue;
-    TopoDS_Wire wire = TopoDS::Wire ( wi.Value() );
-    Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire(wire,myFace,prec);
-    if ( saw->CheckSmallArea(prec) )
+
+  TopoDS_Shape anEmptyCopy = myFace.EmptyCopied();
+  TopoDS_Face  aFace = TopoDS::Face(anEmptyCopy);
+  aFace.Orientation (TopAbs_FORWARD);
+
+  const Standard_Real aTolerance3d = ShapeFix_Root::Precision();
+  for (TopoDS_Iterator aWIt(myFace, Standard_False); aWIt.More(); aWIt.Next())
+  {
+    const TopoDS_Shape& aShape = aWIt.Value();
+    if ( aShape.ShapeType()   != TopAbs_WIRE    &&
+         aShape.Orientation() != TopAbs_FORWARD &&
+         aShape.Orientation() != TopAbs_REVERSED )
     {
-      SendWarning ( wire, Message_Msg ("FixAdvFace.FixSmallAreaWire.MSG0") );// Null area wire detected, wire skipped
-      nbRemoved++;
+      continue;
+    }
+
+    const TopoDS_Wire&         aWire       = TopoDS::Wire(aShape);
+    Handle(ShapeAnalysis_Wire) anAnalyzer  = new ShapeAnalysis_Wire(aWire, myFace, aTolerance3d);
+    if ( anAnalyzer->CheckSmallArea(aWire) )
+    {
+      // Null area wire detected, wire skipped
+      SendWarning(aWire, Message_Msg("FixAdvFace.FixSmallAreaWire.MSG0"));
+      ++nbRemoved;
     }
     else
     {
-      B.Add(face,wire);
-      nbWires++;
+      aBuilder.Add(aFace, aWire);
+      ++nbWires;
     }
   }
-  if ( nbRemoved <=0 ) return Standard_False;
-  
-  if ( nbWires <=0 ) {
-#ifdef DEB
-    cout << "Warning: ShapeFix_Face: All wires on a face have small area; left untouched" << endl;
+
+  if ( nbRemoved <= 0 )
+    return Standard_False;
+
+  if ( nbWires <= 0 )
+  {
+#ifdef OCCT_DEBUG
+    std::cout << "Warning: ShapeFix_Face: All wires on a face have small area; left untouched" << std::endl;
 #endif
+    if ( theIsRemoveSmallFace && !Context().IsNull() )
+      Context()->Remove(myFace);
+
     return Standard_False;
   }
-#ifdef DEB
-  cout << "Warning: ShapeFix_Face: " << nbRemoved << " small area wire(s) removed" << endl;
+#ifdef OCCT_DEBUG
+  std::cout << "Warning: ShapeFix_Face: " << nbRemoved << " small area wire(s) removed" << std::endl;
 #endif
-  if ( ! Context().IsNull() ) Context()->Replace ( myFace, face );
-  myFace = face;
+  aFace.Orientation (myFace.Orientation ());
+  if (!Context ().IsNull ())
+    Context ()->Replace (myFace, aFace);
+
+  myFace = aFace;
   return Standard_True;
 }
 //=======================================================================
@@ -1962,8 +2194,8 @@ Standard_Boolean ShapeFix_Face::FixLoopWire(TopTools_SequenceOfShape& aResWires)
   Standard_Boolean isDone =(aResWires.Length() && isClosed);
   if(isDone && aResWires.Length() >1)
   {
-#ifdef DEBUG
-    cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< endl;
+#ifdef OCCT_DEBUG
+    std::cout<<"Wire was splitted on "<<aResWires.Length()<<" wires"<< std::endl;
 #endif
   }
 
@@ -2237,7 +2469,9 @@ Standard_Boolean ShapeFix_Face::FixSplitFace(const TopTools_DataMapOfShapeListOf
       V1=sae.FirstVertex(E1);
       V2=sae.LastVertex(E2);
       if(!V1.IsSame(V2)) {
-        cout<<"wire not closed --> stop split"<<endl;
+#ifdef OCCT_DEBUG
+        std::cout<<"wire not closed --> stop split"<<std::endl;
+#endif
         return Standard_False;
       }
       // create face
@@ -2249,7 +2483,16 @@ Standard_Boolean ShapeFix_Face::FixSplitFace(const TopTools_DataMapOfShapeListOf
       const TopTools_ListOfShape& IntWires = MapWires.Find(wire);
       TopTools_ListIteratorOfListOfShape liter(IntWires);
       for( ; liter.More(); liter.Next()) {
-        B.Add(tmpFace,liter.Value());
+        TopoDS_Shape aShapeEmptyCopied = tmpFace.EmptyCopied();
+        TopoDS_Face aFace = TopoDS::Face ( aShapeEmptyCopied);
+        aFace.Orientation ( TopAbs_FORWARD );
+        B.Add (aFace,liter.Value());
+        BRepTopAdaptor_FClass2d clas (aFace,::Precision::PConfusion());
+        TopAbs_State staout = clas.PerformInfinitePoint();
+        if (staout == TopAbs_IN) 
+          B.Add(tmpFace,liter.Value());
+        else
+          B.Add(tmpFace,liter.Value().Reversed());                
         NbWiresNew++;
       }
       if(!myFwd) tmpFace.Orientation(TopAbs_REVERSED);
@@ -2265,7 +2508,12 @@ Standard_Boolean ShapeFix_Face::FixSplitFace(const TopTools_DataMapOfShapeListOf
     for(Standard_Integer i=1; i<=faces.Length(); i++ ) 
       B.Add(Comp,faces(i));
     myResult = Comp;
-    Context()->Replace ( myFace, myResult );
+
+    if(!Context().IsNull())
+    {
+      Context()->Replace ( myFace, myResult );
+    }
+
     for (TopExp_Explorer exp ( myResult, TopAbs_FACE ); exp.More(); exp.Next() ) {
       myFace = TopoDS::Face ( exp.Current() );
       BRepTools::Update(myFace);
@@ -2304,10 +2552,10 @@ static Standard_Boolean IsPeriodicConicalLoop(const Handle(Geom_ConicalSurface)&
   Standard_Real aMaxV = aMaxU;
 
   // Iterate over the edges to check whether the wire is periodic on conical surface
-  BRepTools_WireExplorer aWireExp(theWire);
-  for ( ; aWireExp.More(); aWireExp.Next() )
+  TopoDS_Iterator aWireIter(theWire, Standard_False);
+  for ( ; aWireIter.More(); aWireIter.Next() )
   {
-    const TopoDS_Edge& aCurrentEdge = aWireExp.Current();
+    const TopoDS_Edge& aCurrentEdge = TopoDS::Edge(aWireIter.Value());
     Handle(Geom2d_Curve) aC2d;
     Standard_Real aPFirst, aPLast;