0028681: UnifySameDomain distorts face boundary when merges a chain of small linear...
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_UnifySameDomain.cxx
index 7468368..667f419 100644 (file)
@@ -15,9 +15,6 @@
 
 
 #include <BRep_Builder.hxx>
-#include <BRep_CurveRepresentation.hxx>
-#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
-#include <BRep_TEdge.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepLib.hxx>
 #include <BRepLib_MakeEdge.hxx>
@@ -34,6 +31,7 @@
 #include <Geom_ElementarySurface.hxx>
 #include <Geom_Line.hxx>
 #include <Geom_OffsetSurface.hxx>
+#include <Geom_Plane.hxx>
 #include <Geom_RectangularTrimmedSurface.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_SurfaceOfLinearExtrusion.hxx>
 #include <ShapeAnalysis_WireOrder.hxx>
 #include <ShapeBuild_Edge.hxx>
 #include <ShapeBuild_ReShape.hxx>
-#include <ShapeExtend_CompositeSurface.hxx>
-#include <ShapeFix_ComposeShell.hxx>
 #include <ShapeFix_Edge.hxx>
 #include <ShapeFix_Face.hxx>
-#include <ShapeFix_SequenceOfWireSegment.hxx>
 #include <ShapeFix_Shell.hxx>
 #include <ShapeFix_Wire.hxx>
-#include <ShapeFix_WireSegment.hxx>
-#include <ShapeUpgrade_RemoveLocations.hxx>
 #include <ShapeUpgrade_UnifySameDomain.hxx>
 #include <Standard_Type.hxx>
 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
@@ -68,7 +61,6 @@
 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
 #include <TColGeom_Array1OfBSplineCurve.hxx>
 #include <TColGeom_HArray1OfBSplineCurve.hxx>
-#include <TColGeom_HArray2OfSurface.hxx>
 #include <TColGeom_SequenceOfSurface.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TColStd_MapOfInteger.hxx>
@@ -85,7 +77,6 @@
 #include <TopTools_SequenceOfShape.hxx>
 #include <gp_Circ.hxx>
 #include <BRepAdaptor_Curve.hxx>
-#include <BRepClass_FaceClassifier.hxx>
 #include <BRepAdaptor_Curve2d.hxx>
 #include <gp_Vec2d.hxx>
 
@@ -134,41 +125,6 @@ static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge,
   return Standard_False;
 }
 
-static Standard_Boolean CheckSharedEdgeOri(const TopoDS_Face& theF1,
-                                           const TopoDS_Face& theF2,
-                                           const TopoDS_Edge& theE)
-{
-  TopAbs_Orientation anEOri = theE.Orientation();
-  if (anEOri == TopAbs_EXTERNAL || anEOri == TopAbs_INTERNAL)
-    return Standard_False;
-
-  TopExp_Explorer Exp(theF1, TopAbs_EDGE);
-  for (;Exp.More();Exp.Next())
-  {
-    const TopoDS_Shape& aCE = Exp.Current();
-    if (aCE.IsSame(theE))
-    {
-      anEOri = aCE.Orientation(); 
-      break;
-    }
-  }
-
-  for (Exp.Init(theF2, TopAbs_EDGE);Exp.More();Exp.Next())
-  {
-    const TopoDS_Shape& aCE = Exp.Current();
-    if (aCE.IsSame(theE))
-    {
-      if (aCE.Orientation() == TopAbs::Reverse(anEOri))
-        return Standard_True;
-      else
-        return Standard_False;
-    }
-  }
-
-  return Standard_False;
-
-}
-
 //=======================================================================
 //function : AddOrdinaryEdges
 //purpose  : auxilary
@@ -431,28 +387,6 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
   return Standard_False;
 }
 
-//=======================================================================
-//function : UpdateMapEdgeFaces
-//purpose  :
-//=======================================================================
-static void UpdateMapEdgeFaces(const TopoDS_Face& theFace,
-                               Handle(ShapeBuild_ReShape)& theContext,
-                               TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgeFaces)
-{  
-  for (TopExp_Explorer anExp(theFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
-    TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
-    TopoDS_Edge aContextEdge = TopoDS::Edge(theContext->Apply(anEdge));
-    if (aContextEdge == anEdge) 
-      continue;
-    Standard_Integer anIndex = theMapEdgeFaces.FindIndex(aContextEdge);
-    if (anIndex == 0)
-      theMapEdgeFaces.Add(aContextEdge,
-                          theMapEdgeFaces.FindFromKey(anEdge));
-    else
-      theMapEdgeFaces.ChangeFromIndex(anIndex).Append(theFace);
-  }
-}
-
 //=======================================================================
 //function : UpdateMapOfShapes
 //purpose  :
@@ -468,46 +402,6 @@ static void UpdateMapOfShapes(TopTools_MapOfShape& theMapOfShapes,
   }
 }
 
-//=======================================================================
-//function : MovePCurves
-//purpose  :
-//=======================================================================
-static void MovePCurves(TopoDS_Face& aTarget,
-                        const TopoDS_Face& aSource,
-                        Standard_Boolean isSafeInputMode,
-                        Handle(ShapeBuild_ReShape)& theContext)
-{
-  BRep_Builder B;
-  for(TopExp_Explorer wexp(aSource,TopAbs_WIRE);wexp.More();wexp.Next()) {
-    Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(TopoDS::Wire(wexp.Current()),
-                                                  aTarget, Precision::Confusion());
-    if (isSafeInputMode)
-      sfw->SetContext(theContext);
-    sfw->FixReorder();
-    Standard_Boolean isReoredFailed = sfw->StatusReorder ( ShapeExtend_FAIL );
-    sfw->FixEdgeCurves();
-    if(isReoredFailed)
-      continue;
-
-    sfw->FixShifted();
-    sfw->FixDegenerated();
-
-    // remove degenerated edges from not degenerated points
-    ShapeAnalysis_Edge sae;
-    Handle(ShapeExtend_WireData) sewd = sfw->WireData();
-    for(Standard_Integer i = 1; i<=sewd->NbEdges();i++) {
-      TopoDS_Edge E = sewd->Edge(i);
-      if(BRep_Tool::Degenerated(E)&&!sae.HasPCurve(E,aTarget)) {
-        sewd->Remove(i);
-        i--;
-      }
-    }
-
-    TopoDS_Wire ResWire = sfw->Wire();
-    B.Add(aTarget,ResWire);
-  }
-}
-
 //=======================================================================
 //function : GlueEdgesWithPCurves
 //purpose  : Glues the pcurves of the sequence of edges
@@ -520,24 +414,21 @@ static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
   Standard_Integer i, j;
 
   TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
-  //TColGeom2d_SequenceOfCurve PCurveSeq;
   TColGeom_SequenceOfSurface SurfSeq;
-  //TopTools_SequenceOfShape LocSeq;
+  NCollection_Sequence<TopLoc_Location> LocSeq;
   
-  BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() );
-  for (; itr.More(); itr.Next())
+  for (int aCurveIndex = 0;; aCurveIndex++)
   {
-    Handle(BRep_CurveRepresentation) CurveRep = itr.Value();
-    if (CurveRep->IsCurveOnSurface())
-    {
-      //PCurveSeq.Append(CurveRep->PCurve());
-      SurfSeq.Append(CurveRep->Surface());
-      /*
-      TopoDS_Shape aLocShape;
-      aLocShape.Location(CurveRep->Location());
-      LocSeq.Append(aLocShape);
-      */
-    }
+    Handle(Geom2d_Curve) aCurve;
+    Handle(Geom_Surface) aSurface;
+    TopLoc_Location aLocation;
+    Standard_Real aFirst, aLast;
+    BRep_Tool::CurveOnSurface (FirstEdge, aCurve, aSurface, aLocation, aFirst, aLast, aCurveIndex);
+    if (aCurve.IsNull())
+      break;
+
+    SurfSeq.Append(aSurface);
+    LocSeq.Append(aLocation);
   }
 
   Standard_Real fpar, lpar;
@@ -605,14 +496,12 @@ static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
   Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower());
   
   TColGeom2d_SequenceOfBoundedCurve ResPCurves;
-  TopLoc_Location aLoc;
   for (j = 1; j <= SurfSeq.Length(); j++)
   {
     TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves
     
     PrevVertex = FirstVertex;
     PrevEdge = FirstEdge;
-    //TopLoc_Location theLoc = LocSeq(j).Location();
     for (i = 1; i <= nb_curve; i++)
     {
       TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
@@ -620,12 +509,10 @@ static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
       TopExp::Vertices(anEdge, VF, VL);
       Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
 
-      /*
-      Handle(Geom2d_Curve) aPCurve =
-        BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), anEdge.Location()*theLoc, fpar, lpar);
-      */
       Handle(Geom2d_Curve) aPCurve =
-        BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), aLoc, fpar, lpar);
+        BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), LocSeq(j), fpar, lpar);
+      if (aPCurve.IsNull())
+        continue;
       Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar);
       tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve);
       Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion());
@@ -663,8 +550,8 @@ static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
   BB.SameParameter(ResEdge, Standard_False);
   for (j = 1; j <= ResPCurves.Length(); j++)
   {
-    BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), aLoc, MaxTol);
-    BB.Range(ResEdge, SurfSeq(j), aLoc, ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
+    BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), LocSeq(j), MaxTol);
+    BB.Range(ResEdge, SurfSeq(j), LocSeq(j), ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter());
   }
 
   BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
@@ -915,7 +802,9 @@ static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& aChain,
 //=======================================================================
 
 static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, 
-                                          double theAngTol, const TopTools_MapOfShape& AvoidEdgeVrt)
+                                          double theAngTol, double theLinTol, 
+                                          const TopTools_MapOfShape& AvoidEdgeVrt, const bool theLineDirectionOk,
+                                          const gp_Pnt& theFirstPoint, const gp_Vec& theDirectionVec)
 {
   TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True);
   if (CV.IsNull() || AvoidEdgeVrt.Contains(CV))
@@ -958,6 +847,39 @@ static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS
   if (Diff1.Angle(Diff2) > theAngTol)
     return Standard_False;
 
+  if (theLineDirectionOk && t2 == GeomAbs_Line)
+  {
+    gp_Vec aCurV(theFirstPoint, BRep_Tool::Pnt(TopExp::LastVertex(edge2, Standard_True)));
+    Standard_Real aDD = theDirectionVec.CrossSquareMagnitude(aCurV);
+    if (aDD > theLinTol*theLinTol)
+      return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : GetLineEdgePoints
+//purpose  : 
+//=======================================================================
+static Standard_Boolean GetLineEdgePoints(const TopoDS_Edge& theInpEdge, gp_Pnt& theFirstPoint, gp_Vec& theDirectionVec)
+{
+  double f, l;
+  Handle(Geom_Curve) aCur = BRep_Tool::Curve(theInpEdge, f, l);
+  if(aCur.IsNull()) 
+    return Standard_False;
+
+  Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur);
+  if (!aTC.IsNull())
+    aCur = aTC->BasisCurve();
+
+  if (aCur->DynamicType() != STANDARD_TYPE(Geom_Line))
+    return Standard_False;
+
+  theFirstPoint = BRep_Tool::Pnt(TopExp::FirstVertex(theInpEdge, Standard_True));
+  gp_Pnt aLP = BRep_Tool::Pnt(TopExp::LastVertex(theInpEdge, Standard_True));
+  theDirectionVec = aLP.XYZ().Subtracted(theFirstPoint.XYZ());
+  theDirectionVec.Normalize();
   return Standard_True;
 }
 
@@ -969,25 +891,32 @@ static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS
 
 static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
                             NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
-                            Standard_Boolean IsClosed, double theAngTol, const TopTools_MapOfShape& AvoidEdgeVrt)
+                            Standard_Boolean IsClosed, double theAngTol, double theLinTol, 
+                            const TopTools_MapOfShape& AvoidEdgeVrt)
 {
   Standard_Boolean isOk = Standard_False;
   TopoDS_Edge edge1, edge2;
 
   SubSequenceOfEdges SubSeq;
-  SubSeq.SeqsEdges.Append(TopoDS::Edge(anInpEdgeSeq(1)));
+  TopoDS_Edge RefEdge = TopoDS::Edge(anInpEdgeSeq(1));
+  SubSeq.SeqsEdges.Append(RefEdge);
   SeqOfSubSeqOfEdges.Append(SubSeq);
 
+  gp_Pnt aFirstPoint;
+  gp_Vec aDirectionVec;
+  Standard_Boolean isLineDirectionOk = GetLineEdgePoints(RefEdge, aFirstPoint, aDirectionVec);  
+  
   for (int i = 1; i < anInpEdgeSeq.Length(); i++)
   {
     edge1 = TopoDS::Edge(anInpEdgeSeq(i));
     edge2 = TopoDS::Edge(anInpEdgeSeq(i+1));
-    isOk = IsMergingPossible(edge1, edge2, theAngTol, AvoidEdgeVrt);
+    isOk = IsMergingPossible(edge1, edge2, theAngTol, theLinTol, AvoidEdgeVrt, isLineDirectionOk, aFirstPoint, aDirectionVec);
     if (!isOk)
     {
       SubSequenceOfEdges aSubSeq;
       aSubSeq.SeqsEdges.Append(edge2);
       SeqOfSubSeqOfEdges.Append(aSubSeq);
+      isLineDirectionOk = GetLineEdgePoints(edge2, aFirstPoint, aDirectionVec);
     }
     else
       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(edge2);
@@ -997,7 +926,7 @@ static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
   {
     edge1 = TopoDS::Edge(anInpEdgeSeq.Last());
     edge2 = TopoDS::Edge(anInpEdgeSeq.First());
-    if (IsMergingPossible(edge1, edge2, theAngTol, AvoidEdgeVrt))
+    if (IsMergingPossible(edge1, edge2, theAngTol, theLinTol, AvoidEdgeVrt, Standard_False, aFirstPoint, aDirectionVec))
     {
       SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges);
       SeqOfSubSeqOfEdges.Remove(1);
@@ -1011,6 +940,7 @@ static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
 //=======================================================================
 static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges,
                                    const Standard_Real theAngTol,
+                                   const Standard_Real theLinTol,
                                    const Standard_Boolean ConcatBSplines,
                                    const Standard_Boolean isSafeInputMode,
                                    Handle(ShapeBuild_ReShape)& theContext,
@@ -1113,7 +1043,7 @@ static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges,
 
     // split chain by vertices at which merging is not possible
     NCollection_Sequence<SubSequenceOfEdges> aOneSeq;
-    GenerateSubSeq(aChain, aOneSeq, IsClosed, theAngTol, VerticesToAvoid);
+    GenerateSubSeq(aChain, aOneSeq, IsClosed, theAngTol, theLinTol, VerticesToAvoid);
 
     // put sub-chains in the result
     SeqOfSubSeqOfEdges.Append(aOneSeq);
@@ -1133,20 +1063,19 @@ static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges,
 
 //=======================================================================
 //function : MergeSeq
-//purpose  : Tries to unify the sequence of edges with the set of another edges 
-//which lies on the same geometry
+//purpose  : Tries to unify the sequence of edges with the set of
+//           another edges which lies on the same geometry
 //=======================================================================
-
 static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges,
                                   const Standard_Real theAngTol,
+                                  const Standard_Real theLinTol,
                                   const Standard_Boolean ConcatBSplines,
                                   const Standard_Boolean isSafeInputMode,
                                   Handle(ShapeBuild_ReShape)& theContext,
-                                  const TopTools_MapOfShape& nonMergVert,
-                                  TopTools_MapOfShape& theRemovedVertices)
-{ 
+                                  const TopTools_MapOfShape& nonMergVert)
+{
   NCollection_Sequence<SubSequenceOfEdges> SeqOfSubsSeqOfEdges;
-  if (MergeEdges(SeqEdges, theAngTol, ConcatBSplines, isSafeInputMode,
+  if (MergeEdges(SeqEdges, theAngTol, theLinTol, ConcatBSplines, isSafeInputMode,
                  theContext, SeqOfSubsSeqOfEdges, nonMergVert))
   {
     for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ )
@@ -1156,29 +1085,10 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges,
 
       theContext->Merge(SeqOfSubsSeqOfEdges(i).SeqsEdges,
         SeqOfSubsSeqOfEdges(i).UnionEdges);
-
-      ShapeAnalysis_Edge sae;
-      TopoDS_Vertex VF = sae.FirstVertex(SeqOfSubsSeqOfEdges(i).UnionEdges);
-      TopoDS_Vertex VL = sae.LastVertex(SeqOfSubsSeqOfEdges(i).UnionEdges);
-      for (Standard_Integer j = 1; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++)
-      {
-        const TopoDS_Shape& anOldEdge = SeqOfSubsSeqOfEdges(i).SeqsEdges(j);
-        TopoDS_Vertex V[2];
-        TopExp::Vertices(TopoDS::Edge(anOldEdge), V[0], V[1]);
-        for (int k = 0; k < 2; k++)
-        {
-          TopoDS_Vertex aV = V[k];
-          if (isSafeInputMode)  // vertex might be changed and replaced
-            aV = TopoDS::Vertex(theContext->Apply(aV));
-          if (!aV.IsEqual(VF) && !aV.IsEqual(VL))
-            theRemovedVertices.Add(V[k]);
-        }
-      }
     }
     return Standard_True;
   }
-  else
-    return Standard_False;
+  return Standard_False;
 }
 
 //=======================================================================
@@ -1271,8 +1181,8 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
   myConcatBSplines = ConcatBSplines;
 
   myContext->Clear();
-  myRemoved.Clear();
   myKeepShapes.Clear();
+  myHistory->Clear();
 }
 
 //=======================================================================
@@ -1319,37 +1229,6 @@ void ShapeUpgrade_UnifySameDomain::KeepShapes(const TopTools_MapOfShape& theShap
   }
 }
 
-//=======================================================================
-//function : putIntWires
-//purpose  : Add internal wires that are classified inside the face as a subshape,
-//           and remove them from the sequence
-//=======================================================================
-static void putIntWires(TopoDS_Shape& theFace, TopTools_SequenceOfShape& theWires)
-{
-  TopoDS_Face& aFace = TopoDS::Face(theFace);
-  for (Standard_Integer i=1; i <= theWires.Length(); i++)
-  {
-    TopoDS_Shape aWire = theWires(i);
-    gp_Pnt2d aP2d;
-    Standard_Boolean isP2d = Standard_False;
-    for (TopoDS_Iterator it(aWire); it.More() && !isP2d; it.Next())
-    {
-      const TopoDS_Edge& anEdge = TopoDS::Edge(it.Value());
-      Standard_Real aFirst, aLast;
-      Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aFace, aFirst, aLast);
-      aC2d->D0((aFirst + aLast) * 0.5, aP2d);
-      isP2d = Standard_True;
-    }
-    BRepClass_FaceClassifier aClass(aFace, aP2d, Precision::PConfusion());
-    if (aClass.State() == TopAbs_IN)
-    {
-      BRep_Builder().Add(aFace, aWire);
-      theWires.Remove(i);
-      i--;
-    }
-  }
-}
-
 //=======================================================================
 //function : UnifyFaces
 //purpose  : 
@@ -1364,7 +1243,7 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
   // unify faces in each shell separately
   TopExp_Explorer exps;
   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next())
-    IntUnifyFaces(exps.Current(), aGMapEdgeFaces, Standard_False);
+    IntUnifyFaces(exps.Current(), aGMapEdgeFaces);
 
   // gather all faces out of shells in one compound and unify them at once
   BRep_Builder aBB;
@@ -1375,19 +1254,36 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
     aBB.Add(aCmp, exps.Current());
 
   if (nbf > 0)
-    IntUnifyFaces(aCmp, aGMapEdgeFaces, Standard_True);
+    IntUnifyFaces(aCmp, aGMapEdgeFaces);
   
   myShape = myContext->Apply(myShape);
 }
 
+//=======================================================================
+//function : SetFixWireModes
+//purpose  : 
+//=======================================================================
+
+static void SetFixWireModes(ShapeFix_Face& theSff)
+{
+  Handle(ShapeFix_Wire) aFixWire = theSff.FixWireTool();
+  aFixWire->FixSelfIntersectionMode() = 0;
+  aFixWire->FixNonAdjacentIntersectingEdgesMode() = 0;
+  aFixWire->FixLackingMode() = 0;
+  aFixWire->FixNotchedEdgesMode() = 0;
+  aFixWire->ModifyTopologyMode() = Standard_False;
+  aFixWire->ModifyRemoveLoopMode() = 0;
+  aFixWire->FixGapsByRangesMode() = Standard_False;
+  aFixWire->FixSmallMode() = 0;
+}
+
 //=======================================================================
 //function : IntUnifyFaces
 //purpose  : 
 //=======================================================================
 
 void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape,
-   TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces,
-   Standard_Boolean IsCheckSharedEdgeOri)
+   TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces)
 {
   // creating map of edge faces for the shape
   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
@@ -1396,21 +1292,8 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
   // map of processed shapes
   TopTools_MapOfShape aProcessed;
 
-  Standard_Integer NbModif = 0;
-  Standard_Boolean hasFailed = Standard_False;
-  Standard_Real tol = Precision::Confusion();
-
-  // count faces
-  Standard_Integer nbf = 0;
-  TopExp_Explorer exp;
-  TopTools_MapOfShape mapF;
-  for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
-    if (mapF.Add(exp.Current()))
-      nbf++;
-  }
-
   // processing each face
-  mapF.Clear();
+  TopExp_Explorer exp;
   for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
     const TopoDS_Face& aFaceOriginal = TopoDS::Face(exp.Current());
     TopoDS_Face aFace = TopoDS::Face(aFaceOriginal.Oriented(TopAbs_FORWARD));
@@ -1418,14 +1301,19 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
     if (aProcessed.Contains(aFace))
       continue;
 
-    Standard_Integer dummy;
+    // Boundary edges for the new face
     TopTools_SequenceOfShape edges;
-    AddOrdinaryEdges(edges,aFace,dummy);
 
+    Standard_Integer dummy;
+    AddOrdinaryEdges(edges, aFace, dummy);
+
+    // Faces to get unified with the current faces
     TopTools_SequenceOfShape faces;
+
+    // Add the current face for unification
     faces.Append(aFace);
 
-    //surface and location to construct result
+    // surface and location to construct result
     TopLoc_Location aBaseLocation;
     Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
     aBaseSurface = ClearRts(aBaseSurface);
@@ -1440,10 +1328,21 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
       // get connectivity of the edge in the global shape
       const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge);
       if (!myAllowInternal && (aGList.Extent() != 2 || myKeepShapes.Contains(edge))) {
-        // non mainfold case is not processed unless myAllowInternal
+        // non manifold case is not processed unless myAllowInternal
         continue;
       }
       //
+      // Get the faces connected through the edge in the current shape
+      const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
+      if (aList.Extent() < 2) {
+        continue;
+      }
+
+      // for a planar face create and store pcurve of edge on face
+      // to speed up all operations
+      if (!mySafeInputMode && aBaseSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
+        BRepLib::BuildPCurveForEdgeOnPlane(edge, aFace);
+
       // get normal of the face to compare it with normals of other faces
       gp_Dir aDN1;
       //
@@ -1454,8 +1353,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
       //
       Standard_Boolean bCheckNormals = GetNormalToSurface(aFaceOriginal, edge, aTMid, aDN1);
       //
-      // process faces connected through the edge in the current shape
-      const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
+      // Process the faces
       TopTools_ListIteratorOfListOfShape anIter(aList);
       for (; anIter.More(); anIter.Next()) {
         const TopoDS_Face& aCheckedFaceOriginal = TopoDS::Face(anIter.Value());
@@ -1466,9 +1364,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
         if (aProcessed.Contains(anCheckedFace))
           continue;
 
-        if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) )
-          continue;
-
         if (bCheckNormals) {
           // get normal of checked face using the same parameter on edge
           gp_Dir aDN2;
@@ -1487,19 +1382,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
           if (IsLikeSeam(edge, anCheckedFace, aBaseSurface))
             continue;
 
-          // replacing pcurves
-          TopoDS_Face aMockUpFace;
-          BRep_Builder B;
-          B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
-          MovePCurves(aMockUpFace, anCheckedFace, mySafeInputMode, 
-                      myContext);
-          
-          if (mySafeInputMode) {
-            UpdateMapEdgeFaces(anCheckedFace, myContext, theGMapEdgeFaces);
-            UpdateMapEdgeFaces(anCheckedFace, myContext, aMapEdgeFaces);
-          }
-
-          if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
+          if (AddOrdinaryEdges(edges,anCheckedFace,dummy)) {
             // sequence edges is modified
             i = dummy;
           }
@@ -1517,9 +1400,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
       for (i = 1; i <= faces.Length(); i++) {
         TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
       }
-      if (mySafeInputMode)
-        UpdateMapOfShapes(myKeepShapes, myContext);
-      // Collect keep edges and multiconnected edges, i.e. edges that are internal to
+      // Collect keep edges and multi-connected edges, i.e. edges that are internal to
       // the set of selected faces and have connections to other faces.
       TopTools_ListOfShape aKeepEdges;
       for (i = 1; i <= aMapEF.Extent(); i++) {
@@ -1535,7 +1416,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
       if (!aKeepEdges.IsEmpty()) {
         if  (!myAllowInternal) {
           // Remove from the selection the faces which have no other connect edges 
-          // and contain multiconnected edges and/or keep edges.
+          // and contain multi-connected edges and/or keep edges.
           TopTools_MapOfShape anAvoidFaces;
           TopTools_ListIteratorOfListOfShape it(aKeepEdges);
           for (; it.More(); it.Next()) {
@@ -1595,7 +1476,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
           }
         }
         else {
-          // add multiconnected and keep edges as internal in new face
+          // add multi-connected and keep edges as internal in new face
           TopTools_ListIteratorOfListOfShape it(aKeepEdges);
           for (; it.More(); it.Next()) {
             const TopoDS_Shape& aE = it.Value();
@@ -1607,41 +1488,12 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
 
     // all faces collected in the sequence. Perform union of faces
     if (faces.Length() > 1) {
-      NbModif++;
       TopoDS_Face aResult;
       BRep_Builder B;
       B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
       Standard_Integer nbWires = 0;
 
-      TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
-
-      TopTools_IndexedMapOfShape anOldEdges;
-      for (int j = 1; j <= faces.Length(); j++) {
-        TopExp::MapShapes(faces(j), TopAbs_EDGE, anOldEdges);
-      }
-      TopTools_IndexedMapOfShape aMapEdgesAndVertexes;
-      for (int j = 1; j <= edges.Length(); j++) {
-        TopExp::MapShapes(edges(j), aMapEdgesAndVertexes);
-      }
-
-      for (int j = 1; j <= anOldEdges.Extent(); j++)
-      {
-        const TopoDS_Edge& anEdge = TopoDS::Edge(anOldEdges(j));
-        if (!aMapEdgesAndVertexes.Contains(anEdge))
-        {
-          myRemoved.Add(anEdge);
-
-          TopoDS_Vertex V[2];
-          TopExp::Vertices(anEdge, V[0], V[1]);
-          for (int k = 0; k < 2; k++)
-          {
-            if (!aMapEdgesAndVertexes.Contains(V[k]))
-            {
-              myRemoved.Add(V[k]);
-            }
-          }
-        }
-      }
+      TopoDS_Face tmpF = TopoDS::Face(faces(1).Oriented(TopAbs_FORWARD));
 
       // connecting wires
       while (edges.Length()>0) {
@@ -1688,7 +1540,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
 
         // sorting any type of edges
         aWire.Closed (BRep_Tool::IsClosed (aWire));
-        aWire = TopoDS::Wire(myContext->Apply(aWire));
 
         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
         if (mySafeInputMode)
@@ -1704,7 +1555,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
               if(BRep_Tool::Degenerated(E)) {
                 sewd->Remove(j);
                 isDegRemoved = Standard_True;
-                myRemoved.Add(E);
                 j--;
               }
             }
@@ -1713,12 +1563,11 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
           if(isDegRemoved)
             sfw->FixDegenerated();
         }
-        TopoDS_Wire aWireFixed = sfw->Wire();
-        myContext->Replace(aWire,aWireFixed);
+        aWire = sfw->Wire();
 
         // add resulting wire
         if(isEdge3d) {
-          B.Add(aResult,aWireFixed);
+          B.Add(aResult,aWire);
         }
         else  {
           // sorting edges
@@ -1768,118 +1617,25 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
         }
       }
 
-      // perform substitution of face
-      myContext->Replace(myContext->Apply(aFace),aResult);
-
       ShapeFix_Face sff (aResult);
-      //Intializing by tolerances
+      //Initializing by tolerances
       sff.SetPrecision(Precision::Confusion());
-      sff.SetMinTolerance(tol);
+      sff.SetMinTolerance(Precision::Confusion());
       sff.SetMaxTolerance(1.);
       //Setting modes
-      sff.FixOrientationMode() = 0;
-      //sff.FixWireMode() = 0;
-      sff.SetContext(myContext);
+      SetFixWireModes(sff);
+      if (mySafeInputMode)
+        sff.SetContext(myContext);
       // Applying the fixes
       sff.Perform();
-      if(sff.Status(ShapeExtend_FAIL))
-        hasFailed = Standard_True;
-
-      // breaking down to several faces
-      TopoDS_Shape theResult = myContext->Apply(aResult);
-      for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
-        TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
-        Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
-        grid->SetValue ( 1, 1, aBaseSurface );
-        Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
-        ShapeFix_ComposeShell CompShell;
-        CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
-        CompShell.SetContext( myContext );
-
-        TopTools_SequenceOfShape parts, anIntWires;
-        ShapeFix_SequenceOfWireSegment wires;
-        for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
-          const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current());
-          // check if the wire is ordinary (contains non-internal edges)
-          Standard_Boolean isInternal = Standard_True;
-          for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next())
-            isInternal = (it.Value().Orientation() == TopAbs_INTERNAL);
-          if (isInternal)
-          {
-            // place internal wire separately
-            anIntWires.Append(aWire);
-          }
-          else
-          {
-            Handle(ShapeExtend_WireData) sbwd =
-              new ShapeExtend_WireData (aWire);
-            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
-            wires.Append(seg);
-          }
-        }
-
-        CompShell.DispatchWires( parts, wires );
-        for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
-          ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
-          aFixOrient.SetContext(myContext);
-          aFixOrient.FixOrientation();
-          // put internal wires to faces
-          putIntWires(parts(j), anIntWires);
-        }
-
-        TopoDS_Shape CompRes;
-        if ( parts.Length() !=1 ) {
-          TopoDS_Shell S;
-          B.MakeShell ( S );
-          for ( i=1; i <= parts.Length(); i++ )
-            B.Add ( S, parts(i) );
-          S.Closed (BRep_Tool::IsClosed (S));
-          CompRes = S;
-        }
-        else CompRes = parts(1);
-
-        myContext->Replace(aCurrent,CompRes);
+      if(!sff.Status(ShapeExtend_FAIL))
+      {
+        // perform substitution of faces
+        aResult = sff.Face();
+        myContext->Merge(faces, aResult);
       }
-
-      const TopoDS_Shape aResult3 = myContext->Apply(theResult);
-      myContext->Merge(faces, aResult3);
     }
   } // end processing each face
-
-  //TopoDS_Shape aResult = Shape;
-  if (NbModif > 0 && !hasFailed) {
-    TopoDS_Shape aResult = myContext->Apply(theInpShape);
-
-    ShapeFix_Edge sfe;
-    if (!myContext.IsNull()) sfe.SetContext(myContext);
-    for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
-      TopoDS_Edge E = TopoDS::Edge(exp.Current());
-      sfe.FixVertexTolerance (E);
-      // ptv add fix same parameter
-      sfe.FixSameParameter(E, Precision::Confusion());
-    }
-
-    myContext->Replace(theInpShape, aResult);
-  }
-  //else
-  {
-    for (exp.Init(theInpShape, 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(Precision::Confusion());
-      sfw->SetMinTolerance(Precision::Confusion());
-      sfw->SetMaxTolerance(1.);
-      sfw->SetFace(aFace);
-      for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) {
-        TopoDS_Wire wire = TopoDS::Wire(iter.Value());
-        sfw->Load(wire);
-        sfw->FixReorder();
-        sfw->FixShifted();
-      }
-    }
-  }
-
 }
 
 //=======================================================================
@@ -1927,8 +1683,8 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
       SeqEdges.Append(expE.Current());
     SharedVert.Clear();
     CheckSharedVertices(SeqEdges, aMapEdgesVertex, myKeepShapes, SharedVert); 
-    MergeSeq(SeqEdges, myAngTol, myConcatBSplines, mySafeInputMode, myContext,
-      SharedVert, myRemoved);
+    MergeSeq(SeqEdges, myAngTol, myLinTol, myConcatBSplines, mySafeInputMode, myContext,
+      SharedVert);
   }
 
   // processing each face
@@ -1974,8 +1730,8 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
 
       SharedVert.Clear();
       CheckSharedVertices(SeqEdges, aMapEdgesVertex, myKeepShapes, SharedVert);
-      if (MergeSeq(SeqEdges, myAngTol, myConcatBSplines, mySafeInputMode,
-        myContext, SharedVert, myRemoved))
+      if (MergeSeq(SeqEdges, myAngTol, myLinTol, myConcatBSplines, mySafeInputMode,
+        myContext, SharedVert))
       {
         TopoDS_Face tmpF = TopoDS::Face(exp.Current());
         if ( !ChangedFaces.Contains(tmpF) )
@@ -1990,8 +1746,8 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
     {
       SharedVert.Clear();
       CheckSharedVertices(aNonSharedEdges, aMapEdgesVertex, myKeepShapes, SharedVert);
-      if (MergeSeq(aNonSharedEdges, myAngTol, myConcatBSplines, mySafeInputMode,
-        myContext, SharedVert, myRemoved))
+      if (MergeSeq(aNonSharedEdges, myAngTol, myLinTol, myConcatBSplines, mySafeInputMode,
+        myContext, SharedVert))
       {
         TopoDS_Face tmpF = TopoDS::Face(exp.Current());
         if ( !ChangedFaces.Contains(tmpF) )
@@ -2007,13 +1763,38 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(ChangedFaces.FindKey(i)));
     if (aFace.IsNull())
       continue;
-    Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
-    sff->SetContext(myContext);
-    sff->SetPrecision(aPrec);
-    sff->SetMinTolerance(aPrec);
-    sff->SetMaxTolerance(Max(1., aPrec*1000.));
-    sff->Perform();
-    TopoDS_Shape aNewFace = sff->Face();
+
+    // for a planar face create and store pcurve of edge on face
+    // to speed up all operations; but this is allowed only when non-safe mode in force
+    if (!mySafeInputMode)
+    {
+      TopLoc_Location aLoc;
+      Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace, aLoc);
+      aSurface = ClearRts(aSurface);
+      if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
+      {
+        TopTools_ListOfShape aLE;
+        for (TopExp_Explorer anEx(aFace, TopAbs_EDGE); anEx.More(); anEx.Next())
+          aLE.Append(anEx.Current());
+        BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFace);
+      }
+    }
+
+    ShapeFix_Face sff(aFace);
+    if (mySafeInputMode)
+      sff.SetContext(myContext);
+    sff.SetPrecision(aPrec);
+    sff.SetMinTolerance(aPrec);
+    sff.SetMaxTolerance(Max(1., aPrec*1000.));
+    sff.FixOrientationMode() = 0;
+    sff.FixAddNaturalBoundMode() = 0;
+    sff.FixIntersectingWiresMode() = 0;
+    sff.FixLoopWiresMode() = 0;
+    sff.FixSplitFaceMode() = 0;
+    sff.FixPeriodicDegeneratedMode() = 0;
+    SetFixWireModes(sff);
+    sff.Perform();
+    TopoDS_Shape aNewFace = sff.Face();
     myContext->Replace(aFace,aNewFace);
   }
 
@@ -2041,46 +1822,97 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
 }
 
 //=======================================================================
-//function : UnifyFacesAndEdges
-//purpose  : 
+//function : Build
+//purpose  : builds the resulting shape
 //=======================================================================
-
-void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
+void ShapeUpgrade_UnifySameDomain::Build() 
 {
-  UnifyFaces();
-  
-  /*
-  ShapeUpgrade_RemoveLocations RemLoc;
-  RemLoc.Remove(myShape);
-  myShape = RemLoc.GetResult();
-  */
+  if (myUnifyFaces)
+    UnifyFaces();
+  if (myUnifyEdges)
+    UnifyEdges();
 
-  UnifyEdges();
+  // Fill the history of modifications during the operation
+  FillHistory();
 }
 
 //=======================================================================
-//function : Build
-//purpose  : builds the resulting shape
-//======================================================================
-void ShapeUpgrade_UnifySameDomain::Build() 
+//function : FillHistory
+//purpose  : Fill the history of modifications during the operation
+//=======================================================================
+void ShapeUpgrade_UnifySameDomain::FillHistory()
 {
-  if (myUnifyFaces && myUnifyEdges)
-    UnifyFacesAndEdges();
+  if (myHistory.IsNull())
+    // History is not requested
+    return;
+
+  // Only Vertices, Edges and Faces can be modified during unification.
+  // Thus, only these kind of shapes should be checked.
+
+  // Get history from the context.
+  // It contains all modifications of the operation. Some of these
+  // modifications become not relevant and should be filtered.
+  Handle(BRepTools_History) aCtxHistory = myContext->History();
+
+  // Explore the history of the context and fill
+  // the history of UnifySameDomain algorithm
+  Handle(BRepTools_History) aUSDHistory = new BRepTools_History();
+
+  // Map all Vertices, Edges and Faces in the input shape
+  TopTools_IndexedMapOfShape aMapInputShape;
+  TopExp::MapShapes(myInitShape, TopAbs_VERTEX, aMapInputShape);
+  TopExp::MapShapes(myInitShape, TopAbs_EDGE  , aMapInputShape);
+  TopExp::MapShapes(myInitShape, TopAbs_FACE  , aMapInputShape);
+
+  // Map all Vertices, Edges and Faces in the result shape
+  TopTools_IndexedMapOfShape aMapResultShapes;
+  TopExp::MapShapes(myShape, TopAbs_VERTEX, aMapResultShapes);
+  TopExp::MapShapes(myShape, TopAbs_EDGE  , aMapResultShapes);
+  TopExp::MapShapes(myShape, TopAbs_FACE  , aMapResultShapes);
+
+  // Iterate on all input shapes and get their modifications
+  Standard_Integer i, aNb = aMapInputShape.Extent();
+  for (i = 1; i <= aNb; ++i)
+  {
+    const TopoDS_Shape& aS = aMapInputShape(i);
 
-  else if (myUnifyEdges)
-    UnifyEdges();
-  else if (myUnifyFaces)
-    UnifyFaces();
+    // Check the shape itself to be present in the result
+    if (aMapResultShapes.Contains(aS))
+    {
+      // The shape is present in the result as is, thus has not been modified
+      continue;
+    }
 
-  if (!myHistory.IsNull())
-  {
-    myHistory->Merge(myContext->History());
-    for (TopTools_MapOfShape::Iterator aIt(myRemoved);
-      aIt.More(); aIt.Next())
+    // Check if the shape has been modified during the operation
+    const TopTools_ListOfShape& aLSImages = aCtxHistory->Modified(aS);
+    if (aLSImages.IsEmpty())
+    {
+      // The shape has not been modified and not present in the result,
+      // thus it has been removed
+      aUSDHistory->Remove(aS);
+      continue;
+    }
+
+    // Check the images of the shape to be present in the result
+    Standard_Boolean bRemoved = Standard_True;
+    TopTools_ListIteratorOfListOfShape aItLSIm(aLSImages);
+    for (; aItLSIm.More(); aItLSIm.Next())
+    {
+      if (aMapResultShapes.Contains(aItLSIm.Value()))
+      {
+        // Image is found in the result, thus the shape has been modified
+        aUSDHistory->AddModified(aS, aItLSIm.Value());
+        bRemoved = Standard_False;
+      }
+    }
+
+    if (bRemoved)
     {
-      myHistory->Remove(aIt.Value());
+      // No images are found in the result, thus the shape has been removed
+      aUSDHistory->Remove(aS);
     }
   }
 
-  //Done();
+  // Merge the history of the operation into global history
+  myHistory->Merge(aUSDHistory);
 }