Salome HOME
[bos #26723] EDF 24464 - Problem of extra-edges
[modules/geom.git] / src / BlockFix / BlockFix_UnionFaces.cxx
index b3f615ed5f5c422cced0da4fe54ab2e538f90f30..caa78198c70bf39226120261b936e43ab8db674d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <ShapeFix_Wire.hxx>
 #include <ShapeFix_Edge.hxx>
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
 #include <IntPatch_ImpImpIntersection.hxx>
-#else
-#include <IntPatch_TheIIIntOfIntersection.hxx>
-#endif
 
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
 #include <Geom_SurfaceOfRevolution.hxx>
 #include <Geom_SurfaceOfLinearExtrusion.hxx>
 #include <Geom_RectangularTrimmedSurface.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepAdaptor_HSurface.hxx>
+#include <LocalAnalysis_SurfaceContinuity.hxx>
+#include <GeomConvert_ApproxSurface.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
 
 #include <Geom_Curve.hxx>
 #include <Geom_Line.hxx>
@@ -131,7 +133,7 @@ Standard_Integer& BlockFix_UnionFaces::GetOptimumNbFaces()
 
 //=======================================================================
 //function : AddOrdinaryEdges
-//purpose  : auxilary
+//purpose  : auxiliary
 //           adds edges from the shape to the sequence
 //           seams and equal edges are dropped
 //           Returns true if one of original edges dropped
@@ -142,8 +144,9 @@ static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
 {
   //map of edges
   TopTools_MapOfShape aNewEdges;
+  TopExp_Explorer exp(aShape,TopAbs_EDGE);
   //add edges without seams
-  for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
+  for(; exp.More(); exp.Next()) {
     TopoDS_Shape edge = exp.Current();
     if(aNewEdges.Contains(edge))
       aNewEdges.Remove(edge);
@@ -168,16 +171,21 @@ static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
     }
   }
 
-  //add edges to the sequemce
-  for(TopTools_MapIteratorOfMapOfShape anIter(aNewEdges); anIter.More(); anIter.Next())
-    edges.Append(anIter.Key());
+  //add edges to the sequence
+  for(exp.ReInit(); exp.More(); exp.Next()) {
+    const TopoDS_Shape &anEdge = exp.Current();
+
+    if (aNewEdges.Contains(anEdge)) {
+      edges.Append(anEdge);
+    }
+  }
 
   return isDropped;
 }
 
 //=======================================================================
 //function : ClearRts
-//purpose  : auxilary
+//purpose  : auxiliary
 //=======================================================================
 static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
 {
@@ -191,7 +199,7 @@ static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
 
 //=======================================================================
 //function : IsFacesOfSameSolids
-//purpose  : auxilary
+//purpose  : auxiliary
 //=======================================================================
 static Standard_Boolean IsFacesOfSameSolids
        (const TopoDS_Face                               &theFace1,
@@ -233,17 +241,137 @@ static Standard_Boolean IsFacesOfSameSolids
   return isSame;
 }
 
+//=======================================================================
+//function : DefineMaxTolerance
+//purpose  : calculates maximum possible tolerance on edges of shape
+//=======================================================================
+static Standard_Real DefineMaxTolerance(const TopoDS_Shape& theShape)
+{
+  Standard_Real aTol = Precision::Confusion();
+
+  Standard_Real MinSize = RealLast();
+  TopExp_Explorer Explo(theShape, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
+    Bnd_Box aBox;
+    BRepBndLib::Add(anEdge, aBox);
+    Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+    aBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+    Standard_Real MaxSize = Max(Xmax - Xmin, Max(Ymax - Ymin, Zmax - Zmin));
+    if (MaxSize < MinSize)
+      MinSize = MaxSize;
+  }
+
+  if (!Precision::IsInfinite(MinSize))
+    aTol = 0.1 * MinSize;
+
+  return aTol;
+}
+
+//=======================================================================
+//function : IsTangentFaces
+//purpose  : decides: is edge on closed surface tangent or not
+//=======================================================================
+static Standard_Boolean IsTangentFaces(const TopoDS_Edge& theEdge,
+                                       const TopoDS_Face& theFace)
+{
+  Standard_Real TolC0 = Max(0.001, 1.5*BRep_Tool::Tolerance(theEdge));
+
+  Standard_Real aFirst;
+  Standard_Real aLast;
+    
+// Obtaining of pcurves of edge on two faces.
+  const Handle(Geom2d_Curve) aC2d1 = BRep_Tool::CurveOnSurface
+                                                (theEdge, theFace, aFirst, aLast);
+  TopoDS_Edge ReversedEdge = theEdge;
+  ReversedEdge.Reverse();
+  const Handle(Geom2d_Curve) aC2d2 = BRep_Tool::CurveOnSurface
+                                                (ReversedEdge, theFace, aFirst, aLast);
+  if (aC2d1.IsNull() || aC2d2.IsNull())
+    return Standard_False;
+
+// Obtaining of two surfaces from adjacent faces.
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
+
+  if (aSurf.IsNull())
+    return Standard_False;
+
+// Computation of the number of samples on the edge.
+  BRepAdaptor_Surface              aBAS(theFace);
+  Handle(BRepAdaptor_HSurface)     aBAHS      = new BRepAdaptor_HSurface(aBAS);
+  Handle(BRepTopAdaptor_TopolTool) aTool      = new BRepTopAdaptor_TopolTool(aBAHS);
+  Standard_Integer                 aNbSamples =     aTool->NbSamples();
+  const Standard_Integer           aNbSamplesMax =   23;
+  aNbSamples = Min(aNbSamplesMax, aNbSamples);
+  const Standard_Real              aTolAngle   =     M_PI/18;
+
+
+// Computation of the continuity.
+  Standard_Real    aPar;
+  Standard_Real    aDelta = (aLast - aFirst)/(aNbSamples - 1);
+  Standard_Integer i, nbNotDone = 0;
+
+  for (i = 1, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) {
+    if (i == aNbSamples) aPar = aLast;
+
+    LocalAnalysis_SurfaceContinuity aCont(aC2d1,  aC2d2,  aPar,
+                                          aSurf, aSurf, GeomAbs_G1,
+                                          0.001, TolC0, aTolAngle, 0.1, 0.1);
+    if (!aCont.IsDone()) 
+    {
+      nbNotDone++;
+      continue;
+    }
+
+    if (!aCont.IsG1())
+      return Standard_False;
+  }
+  
+  if (nbNotDone == aNbSamples)
+    return Standard_False;
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : HasSeamEdge
+//purpose  : Detects if a face contains a seam edge
+//=======================================================================
+static Standard_Boolean HasSeamEdge(const TopoDS_Face& theFace)
+{
+  TopExp_Explorer Explo(theFace, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
+    if (BRepTools::IsReallyClosed(anEdge, theFace))
+      return Standard_True;
+  }
+
+  return Standard_False;
+}
+
+
 //=======================================================================
 //function : IsEdgeValidToMerge
 //purpose  : Edge is valid if it is not seam or if it is a seam and the face
 //           has another seam edge.
 //=======================================================================
-static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge &theEdge,
-                                           const TopoDS_Face &theFace)
+static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge& theEdge,
+                                           const TopoDS_Face& theFace,
+                                           const Handle(Geom_Surface)& theSurface,
+                                           Standard_Boolean& theIsEdgeOnSeam,
+                                           Standard_Boolean& theToMakeUPeriodic,
+                                           Standard_Boolean& theToMakeVPeriodic)
 {
   Standard_Boolean isValid = Standard_True;
 
-  if (BRep_Tool::IsClosed(theEdge, theFace)) {
+  theIsEdgeOnSeam |= BRep_Tool::IsClosed(theEdge, theFace);
+  
+  if (BRepTools::IsReallyClosed(theEdge, theFace)) {
+    // Mantis issue 0023451, now code corresponds to the comment to this method
+    isValid = Standard_False;
+
     // This is a seam edge. Check if there are another seam edges on the face.
     TopExp_Explorer anExp(theFace, TopAbs_EDGE);
 
@@ -259,11 +387,38 @@ static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge &theEdge,
       TopoDS_Edge anEdge = TopoDS::Edge(aShEdge);
 
       if (BRep_Tool::IsClosed(anEdge, theFace)) {
-        isValid = Standard_False;
+        // Mantis issue 0023451, now code corresponds to the comment to this method
+        //isValid = Standard_False;
+        isValid = Standard_True;
         break;
       }
     }
   }
+  else if (theIsEdgeOnSeam)
+  {
+    Standard_Real fpar, lpar;
+    Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, fpar, lpar);
+    gp_Pnt2d P2d1 = aPCurve->Value(fpar);
+    gp_Pnt2d P2d2 = aPCurve->Value(lpar);
+    if (!theSurface->IsUPeriodic() &&
+        theSurface->IsUClosed() &&
+        Abs(P2d1.X() - P2d2.X()) < Abs(P2d1.Y() - P2d2.Y()))
+    {
+      if (IsTangentFaces(theEdge, theFace))
+        theToMakeUPeriodic = Standard_True;
+      else
+        isValid = Standard_False;
+    }
+    if (!theSurface->IsVPeriodic() &&
+        theSurface->IsVClosed() &&
+        Abs(P2d1.Y() - P2d2.Y()) < Abs(P2d1.X() - P2d2.X()))
+    {
+      if (IsTangentFaces(theEdge, theFace))
+        theToMakeVPeriodic = Standard_True;
+      else
+        isValid = Standard_False;
+    }
+  }
 
   return isValid;
 }
@@ -274,28 +429,28 @@ static Standard_Boolean IsEdgeValidToMerge(const TopoDS_Edge &theEdge,
 //=======================================================================
 TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
 {
-  Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
-  TopoDS_Shape aResShape = myContext->Apply(Shape);
+  // Fill Map of faces as keys and list of solids or shells as items.
+  TopTools_IndexedDataMapOfShapeListOfShape aMapFaceSoOrSh;
+
+  TopAbs_ShapeEnum aType = Shape.ShapeType();
 
-  // Fill Map of faces as keys and list of solids as items.
-  TopTools_IndexedDataMapOfShapeListOfShape aMapFaceSolids;
+  if (aType != TopAbs_SHELL) {
+    aType = TopAbs_SOLID;
+  }
 
   TopExp::MapShapesAndAncestors
-    (Shape, TopAbs_FACE, TopAbs_SOLID, aMapFaceSolids);
+    (Shape, TopAbs_FACE, aType, aMapFaceSoOrSh);
 
   // processing each solid
+  Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
+  TopTools_MapOfShape aProcessed;
   TopExp_Explorer exps;
-  for (exps.Init(Shape, TopAbs_SOLID); exps.More(); exps.Next()) {
-    TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
+  for (exps.Init(Shape, aType); exps.More(); exps.Next()) {
+    TopoDS_Shape aSoOrSh = exps.Current();
 
     // creating map of edge faces
     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
-    TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
-
-    // map of processed shapes
-    TopTools_MapOfShape aProcessed;
-
-    Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
+    TopExp::MapShapesAndAncestors(aSoOrSh, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
 
     Standard_Integer NbModif = 0;
     Standard_Boolean hasFailed = Standard_False;
@@ -305,7 +460,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
     int nbf = 0;
     TopExp_Explorer exp;
     TopTools_MapOfShape mapF;
-    for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
+    for (exp.Init(aSoOrSh, TopAbs_FACE); exp.More(); exp.Next()) {
       if (mapF.Add(exp.Current()))
         nbf++;
     }
@@ -315,11 +470,12 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
 
     // processing each face
     mapF.Clear();
-    for (exp.Init(aSolid, TopAbs_FACE); exp.More() && doUnion; exp.Next()) {
+    for (exp.Init(aSoOrSh, TopAbs_FACE); exp.More() && doUnion; exp.Next()) {
       TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
 
-      if (aProcessed.Contains(aFace))
+      if (aProcessed.Contains(aFace)) {
         continue;
+      }
 
       Standard_Integer dummy;
       TopTools_SequenceOfShape edges;
@@ -332,12 +488,17 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
       TopLoc_Location aBaseLocation;
       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
       aBaseSurface = ClearRts(aBaseSurface);
+      aBaseSurface = Handle(Geom_Surface)::DownCast(aBaseSurface->Copy());
+      Standard_Boolean ToMakeUPeriodic = Standard_False, ToMakeVPeriodic = Standard_False;
 
       // find adjacent faces to union
       Standard_Integer i;
       for (i = 1; i <= edges.Length(); i++) {
         TopoDS_Edge edge = TopoDS::Edge(edges(i));
-        if (BRep_Tool::Degenerated(edge) || !IsEdgeValidToMerge(edge, aFace))
+        Standard_Boolean IsEdgeOnSeam = Standard_False;
+        if (BRep_Tool::Degenerated(edge) ||
+            !IsEdgeValidToMerge(edge, aFace, aBaseSurface,
+                                IsEdgeOnSeam, ToMakeUPeriodic, ToMakeVPeriodic))
           continue;
 
         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
@@ -350,13 +511,14 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
           if (aProcessed.Contains(anCheckedFace))
             continue;
 
-          if (!IsEdgeValidToMerge(edge, anCheckedFace)) {
+          if (!IsEdgeValidToMerge(edge, anCheckedFace, aBaseSurface,
+                                  IsEdgeOnSeam, ToMakeUPeriodic, ToMakeVPeriodic)) {
             // Skip seam edge.
             continue;
           }
 
           // Check if faces belong to same solids.
-          if (!IsFacesOfSameSolids(aFace, anCheckedFace, aMapFaceSolids)) {
+          if (!IsFacesOfSameSolids(aFace, anCheckedFace, aMapFaceSoOrSh)) {
             continue;
           }
 
@@ -367,6 +529,11 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
               continue;
             }
 
+            //Prevent creating a face with parametric range more than period
+            if (IsEdgeOnSeam &&
+                (HasSeamEdge(aFace) || HasSeamEdge(anCheckedFace)))
+              continue;
+
             // replacing pcurves
             TopoDS_Face aMockUpFace;
             BRep_Builder B;
@@ -390,6 +557,27 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
         NbModif++;
         TopoDS_Face aResult;
         BRep_Builder B;
+        if (ToMakeUPeriodic || ToMakeVPeriodic)
+        {
+          Handle(Geom_BSplineSurface) aBSplineSurface = Handle(Geom_BSplineSurface)::DownCast(aBaseSurface);
+          if (aBSplineSurface.IsNull())
+          {
+            Standard_Real aTol = 1.e-4;
+            GeomAbs_Shape aUCont = GeomAbs_C1, aVCont = GeomAbs_C1;
+            Standard_Integer degU = 14, degV = 14;
+            Standard_Integer nmax = 16;
+            Standard_Integer aPrec = 1;  
+            GeomConvert_ApproxSurface Approximator(aBaseSurface,aTol,aUCont,aVCont,degU,degV,nmax,aPrec);
+            aBSplineSurface = Approximator.Surface();
+          }
+          
+          if (ToMakeUPeriodic)
+            aBSplineSurface->SetUPeriodic();
+          if (ToMakeVPeriodic)
+            aBSplineSurface->SetVPeriodic();
+          
+          aBaseSurface = aBSplineSurface;
+        }
         B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
         Standard_Integer nbWires = 0;
 
@@ -433,8 +621,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
           // sorting any type of edges
           aWire = TopoDS::Wire(aContext->Apply(aWire));
 
-          TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
-          Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
+          Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,aResult,Precision::Confusion());
           sfw->FixReorder();
           Standard_Boolean isDegRemoved = Standard_False;
           if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
@@ -457,7 +644,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
           TopoDS_Wire aWireFixed = sfw->Wire();
           aContext->Replace(aWire,aWireFixed);
           // add resulting wire
-          if(isEdge3d) {
+          if (isEdge3d) {
             B.Add(aResult,aWireFixed);
           }
           else  {
@@ -468,40 +655,42 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
             ShapeAnalysis_WireOrder sawo(Standard_False, 0);
             ShapeAnalysis_Edge sae;
             Standard_Integer aLastEdge = nbEdges;
-            for(Standard_Integer j = 1; j <= nbEdges; j++) {
+            for (Standard_Integer j = 1; j <= nbEdges; j++) {
               Standard_Real f,l;
               //smh protection on NULL pcurve
               Handle(Geom2d_Curve) c2d;
-              if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
+              if (!sae.PCurve(sbwd->Edge(j),aResult,c2d,f,l)) {
                 aLastEdge--;
                 continue;
               }
               sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
             }
-            sawo.Perform();
-
-            // constructind one degenerative edge
-            gp_XY aStart, anEnd, tmp;
-            Standard_Integer nbFirst = sawo.Ordered(1);
-            TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
-            ShapeBuild_Edge sbe;
-            TopoDS_Vertex aDummyV;
-            TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
-            sawo.XY(nbFirst,aStart,tmp);
-            sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
-
-            gp_XY aVec = anEnd-aStart;
-            Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
-
-            B.UpdateEdge(E,aLine,tmpF,0.);
-            B.Range(E,tmpF,0.,aVec.Modulus());
-            Handle(Geom_Curve) C3d;
-            B.UpdateEdge(E,C3d,0.);
-            B.Degenerated(E,Standard_True);
-            TopoDS_Wire aW;
-            B.MakeWire(aW);
-            B.Add(aW,E);
-            B.Add(aResult,aW);
+            if (aLastEdge > 0) {
+              sawo.Perform();
+
+              // constructing one degenerative edge
+              gp_XY aStart, anEnd, tmp;
+              Standard_Integer nbFirst = sawo.Ordered(1);
+              TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
+              ShapeBuild_Edge sbe;
+              TopoDS_Vertex aDummyV;
+              TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
+              sawo.XY(nbFirst,aStart,tmp);
+              sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
+
+              gp_XY aVec = anEnd-aStart;
+              Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
+
+              B.UpdateEdge(E,aLine,aResult,0.);
+              B.Range(E,aResult,0.,aVec.Modulus());
+              Handle(Geom_Curve) C3d;
+              B.UpdateEdge(E,C3d,0.);
+              B.Degenerated(E,Standard_True);
+              TopoDS_Wire aW;
+              B.MakeWire(aW);
+              B.Add(aW,E);
+              B.Add(aResult,aW);
+            }
           }
         }
 
@@ -509,10 +698,11 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
         aContext->Replace(aContext->Apply(aFace),aResult);
 
         ShapeFix_Face sff (aResult);
-        //Intializing by tolerances
+        //Initializing by tolerances
         sff.SetPrecision(myTolerance);
         sff.SetMinTolerance(tol);
-        sff.SetMaxTolerance(Max(1.,myTolerance*1000.));
+        Standard_Real MaxTol = DefineMaxTolerance(aResult);
+        sff.SetMaxTolerance(MaxTol);
         //Setting modes
         sff.FixOrientationMode() = 0;
         //sff.FixWireMode() = 0;
@@ -570,7 +760,7 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
 
     //TopoDS_Shape aResult = Shape;
     if (NbModif > 0 && !hasFailed) {
-      TopoDS_Shape aResult = aContext->Apply(aSolid);
+      TopoDS_Shape aResult = aContext->Apply(aSoOrSh);
 
       ShapeFix_Edge sfe;
       for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
@@ -579,20 +769,19 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
         // ptv add fix same parameter
         sfe.FixSameParameter(E, myTolerance);
       }
-
-      myContext->Replace(aSolid, aResult);
     }
-    //else
-    {
-      for (exp.Init(aSolid, TopAbs_FACE); exp.More(); exp.Next()) {
-        TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
-        Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
-        sfw->SetContext(myContext);
-        sfw->SetPrecision(myTolerance);
-        sfw->SetMinTolerance(myTolerance);
-        sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
-        sfw->SetFace(aFace);
-        for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
+
+    for (exp.Init(aSoOrSh, TopAbs_FACE); exp.More(); exp.Next()) {
+      TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
+      Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
+      sfw->SetContext(aContext);
+      sfw->SetPrecision(myTolerance);
+      sfw->SetMinTolerance(myTolerance);
+      sfw->SetMaxTolerance(Max(1.,myTolerance*1000.));
+      sfw->SetFace(aFace);
+      for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
+        TopoDS_Shape aFaceCont = iter.Value();
+        if (!aFaceCont.IsNull() && aFaceCont.ShapeType() == TopAbs_WIRE) {
           TopoDS_Wire wire = TopoDS::Wire(iter.Value());
           sfw->Load(wire);
           sfw->FixReorder();
@@ -602,7 +791,8 @@ TopoDS_Shape BlockFix_UnionFaces::Perform(const TopoDS_Shape& Shape)
     }
   } // end processing each solid
 
-  aResShape = myContext->Apply(Shape);
+  const TopoDS_Shape aResShape = aContext->Apply(Shape);
+
   return aResShape;
 }
 
@@ -705,21 +895,16 @@ Standard_Boolean BlockFix_UnionFaces::IsSameDomain(const TopoDS_Face& aFace,
     Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
 
     try {
-#if OCC_VERSION_LARGE > 0x06010000
       OCC_CATCH_SIGNALS;
-#endif
 
-#if OCC_VERSION_LARGE > 0x06040000 // Porting to OCCT6.5.1
       IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
-#else
-      IntPatch_TheIIIntOfIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
-#endif
+
       if (!anIIInt.IsDone() || anIIInt.IsEmpty())
         return false;
 
       return anIIInt.TangentFaces();
     }
-    catch (Standard_Failure) {
+    catch (Standard_Failure&) {
       return false;
     }
   }