]> OCCT Git - occt-copy.git/commitdiff
0027000: Invalid result of ShapeUpgrade_UnifySameDomain CR0-CMR-OCCT690
authorakz <akz@opencascade.com>
Thu, 17 Dec 2015 13:56:09 +0000 (16:56 +0300)
committerakz <akz@opencascade.com>
Thu, 17 Dec 2015 13:56:09 +0000 (16:56 +0300)
This commit is a cherry-pick of commits from master related to ShapeUpgrade_UnifySameDomain that fix bug 27000.
Note that picked commits was backported from 7.0.0 to 6.9.0 so changes in header file moved to CDL.

Here is a set of picked commits:
1)SHA-1: f7d7054
0026489: The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
1)SHA-1: f2d685a
0026572: Error in ShapeUpgrade_UnifySameDomain algorithm: can not merge two edges in customer's shape
2)SHA-1: dd2f1b7
0026244: Destructive results of simplification with DRAW command 'unifysamedom' after intersection of two complex models
3)SHA-1: 6a0c0b1
0026635: UnifySameDomain loses internal edges
4)SHA-1: cef6867
0026488: The class ShapeUpgrade_UnifySameDomain is not documented.

13 files changed:
dox/user_guides/shape_healing/shape_healing.md
src/SWDRAW/SWDRAW_ShapeUpgrade.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cdl
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
tests/bugs/heal/bug26244 [new file with mode: 0644]
tests/bugs/heal/bug26489_1 [new file with mode: 0755]
tests/bugs/heal/bug26489_2 [new file with mode: 0755]
tests/bugs/heal/bug26489_3 [new file with mode: 0755]
tests/bugs/heal/bug26489_4 [new file with mode: 0755]
tests/bugs/heal/bug26489_5 [new file with mode: 0755]
tests/bugs/heal/bug26489_6 [new file with mode: 0755]
tests/bugs/heal/bug26572 [new file with mode: 0644]
tests/bugs/heal/bug26635 [new file with mode: 0644]

index 8b3ccea8d1998f1e7ba09912ae463a9965573cec..e70aaf952b527a726d1b137f24c8aed3db5b0048 100644 (file)
@@ -1447,11 +1447,42 @@ Handle(Geom_Surface) newSurf  = ConvSurf.ConvertToPeriodic(Standard_False);
 Standard_Real maxdist = ConvSurf.Gap(); 
 ~~~~~
 
+@subsubsection occt_shg_4_4_9 Unify Same Domain
+
+*ShapeUpgrade_UnifySameDomain* tool allows unifying all possible faces and edges of a shape, which lies on the same geometry. Faces/edges are considered as 'same-domain' if the neighboring faces/edges lie on coincident surfaces/curves.  Such faces/edges can be unified into one face/edge.
+This tool takes an input shape and returns a new one. All modifications of the initial shape are recorded during the operation.
+The following options are available:
+
+  * If the flag *UnifyFaces* is set to TRUE, *UnifySameDomain* tries to unify all possible faces;
+  * If the flag *UnifyEdges* is set to TRUE, *UnifySameDomain* tries to unify all possible edges;
+  * if the flag *ConcatBSplines* is set to TRUE, all neighboring edges, which lie on the BSpline or Bezier curves with C1 continuity on their common vertices will be merged into one common edge. 
+
+By default, *UnifyFaces* and *UnifyEdges* are set to TRUE; *ConcatBSplines* is set to FALSE.
+
+The common methods of this tool are as follows:
+  * Method *Build()* is used to unify.
+  * Method *Shape()* is used to get the resulting shape.
+  * Method *Generated()* is used to get a new common shape from the old shape. If a group of edges has been unified into one common edge then method *Generated()* called on any edge from this group will return the common edge. The same goes for the faces.
+
+The example of the usage is given below:
+~~~~~
+ // 'Sh' is the initial shape
+ ShapeUpgrade_UnifySameDomain USD(Sh, true, true, true); // UnifyFaces mode on, UnifyEdges mode on, ConcatBSplines mode on.
+ USD.Build();
+ //get the result
+ TopoDS_Shape Result = USD.Shape(); 
+ //Let Sh1 as a part of Sh
+ //get the new (probably unified) shape form the Sh1
+ TopoDS_Shape ResSh1 = USD.Generated(Sh1);
+~~~~~ 
+
 @section occt_shg_5_ Auxiliary tools for repairing, analysis and upgrading
 
 @subsection occt_shg_5_1 Tool for rebuilding shapes
 
-  Class *ShapeBuild_ReShape* rebuilds a shape by making pre-defined substitutions on some of its components. During the first phase, it records requests to replace or remove some individual shapes. For each shape, the last given request is recorded. Requests may be applied as *Oriented* (i.e. only to an item with the same orientation) or not (the orientation of the replacing shape corresponds to that of the original one). Then these requests may be applied to any shape, which may contain one or more of these individual shapes. 
+  Class *ShapeBuild_ReShape* rebuilds a shape by making predefined substitutions on some of its components. During the first phase, it records requests to replace or remove some individual shapes. For each shape, the last given request is recorded. Requests may be applied as *Oriented* (i.e. only to an item with the same orientation) or not (the orientation of the replacing shape corresponds to that of the original one). Then these requests may be applied to any shape, which may contain one or more of these individual shapes. 
 
 This tool has a flag for taking the location of shapes into account (for keeping the structure of assemblies) (*ModeConsiderLocation*). If this mode is equal to Standard_True, the shared shapes with locations will be kept. If this mode is equal to Standard_False, some different shapes will be produced from one shape with different locations after rebuilding. By default, this mode is equal to Standard_False. 
 
index fc9074212b4bedca7f2a914513651d47f19fa53e..4cbd542c057cf140db4bd35446cf8db4ea449183 100644 (file)
@@ -1282,26 +1282,80 @@ static Standard_Integer removeloc (Draw_Interpretor& di,
   return 0;
 }
 
+static ShapeUpgrade_UnifySameDomain& Unifier() {
+  static ShapeUpgrade_UnifySameDomain sUnifier;
+  return sUnifier;
+}
+
 //=======================================================================
 // unifysamedom
 //=======================================================================
-static Standard_Integer unifysamedom(Draw_Interpretor& , Standard_Integer n, const char** a)
+static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, const char** a)
 {
-  if (n < 3)
+  if (n < 3 || n > 6)
+  {
+    di << "Use unifysamedom result shape [-f] [-e] [+b]\n";
+    di << "where [-f]. [-e], [+b] is available options\n";
+    di << "[-f] to switch off 'unify-faces' mode \n";
+    di << "[-e] to switch off 'unify-edges' mode\n";
+    di << "[+b] to switch on a 'concat bspline' mode\n";
+    di << "'unify-faces' and 'unify-edges' modes are switched on by default";
     return 1;
+  }
 
   TopoDS_Shape aShape = DBRep::Get(a[2]);
   if (aShape.IsNull())
     return 1;
 
-  ShapeUpgrade_UnifySameDomain Unifier(aShape);
-  Unifier.Build();
-  TopoDS_Shape Result = Unifier.Shape();
+  // default values
+  Standard_Boolean anUFaces = Standard_True;
+  Standard_Boolean anUEdges = Standard_True;
+  Standard_Boolean anConBS = Standard_False;
+
+  if (n > 3)
+    for ( int i = 3; i < n; i++ ) 
+    {
+      if ( !strcmp(a[i], "-f")) 
+        anUFaces = Standard_False;
+      else if (!strcmp(a[i], "-e"))
+        anUEdges = Standard_False;
+      else if (!strcmp(a[i], "+b"))
+        anConBS = Standard_True;
+    }
+
+  Unifier().Initialize(aShape, anUEdges, anUFaces, anConBS);
+  Unifier().Build();
+  TopoDS_Shape Result = Unifier().Shape();
 
   DBRep::Set(a[1], Result);
   return 0;
 }
 
+Standard_Integer unifysamedomgen (Draw_Interpretor& di, 
+                                  Standard_Integer n, 
+                                  const char** a)
+{
+  if (n!=3) {
+    di << "use unifysamedomgen newshape oldshape";
+    return 0;
+  }
+  TopoDS_Shape aShape;
+  aShape=DBRep::Get(a[2]);
+  if (aShape.IsNull()) {
+    di<<" null shape is not allowed here\n";
+    return 1;
+  }
+  TopoDS_Shape ResShape = Unifier().Generated(aShape);
+  if (ResShape.IsNull()) {
+    di << " null shape\n";
+  }
+  else {
+    DBRep::Set(a[1], ResShape);
+  }
+  return 0;
+}
+
+
 static Standard_Integer copytranslate(Draw_Interpretor& di, 
                                    Standard_Integer argc, 
                                    const char** argv)
@@ -1424,7 +1478,12 @@ static Standard_Integer copytranslate(Draw_Interpretor& di,
   theCommands.Add ("removeloc","result shape",__FILE__,removeloc,g);
   
   theCommands.Add ("unifysamedom",
-                   "unifysamedom result shape",__FILE__,unifysamedom,g);
+                   "unifysamedom result shape [-f] [-e] [+b]", __FILE__,unifysamedom,g);
+
+  theCommands.Add ("unifysamedomgen",
+                   "unifysamedomgen newshape oldshape : get new shape generated "
+                   "by unifysamedom command from the old one",
+                   __FILE__,unifysamedomgen,g);
   
   theCommands.Add ("copytranslate","result shape dx dy dz",__FILE__,copytranslate,g);
 }
index 8cd1d0376c440c84d602e25b9f3dea07fcab3840..f27584cffcedc04f4979bff4584f233b4cdfdbca 100644 (file)
@@ -21,6 +21,7 @@ class UnifySameDomain from ShapeUpgrade inherits TShared from MMgt
 uses
     Shape from TopoDS,
     ListOfShape from TopTools,
+    DataMapOfShapeShape from TopTools,
     ReShape from ShapeBuild
 
 is
@@ -69,6 +70,6 @@ fields
     myShape : Shape from TopoDS;
     
     myContext   : ReShape from ShapeBuild;
-    --myOldNewMap : DataMapOfShapeShape  from TopTools;
+    myOldShapes : DataMapOfShapeShape from TopTools;
     
 end UnifySameDomain;
index b2f5f77b107f1f0d807b8975e26d0b0e1775b54e..a842f42e0207b3e214e43515b8112eb4f36850bc 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <ShapeUpgrade_UnifySameDomain.ixx>
-#include <ShapeUpgrade_UnifySameDomain.hxx>
-#include <TopTools_SequenceOfShape.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
-#include <TopExp_Explorer.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_Line.hxx>
-#include <gp_Dir.hxx>
-#include <Geom_CylindricalSurface.hxx>
-#include <gp_Cylinder.hxx>
-#include <Geom_SurfaceOfRevolution.hxx>
-#include <Geom_SurfaceOfLinearExtrusion.hxx>
-#include <gp_Lin.hxx>
-#include <Geom_Circle.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-#include <TopoDS_Face.hxx>
-#include <BRep_Tool.hxx>
-#include <GeomAdaptor_HSurface.hxx>
-#include <BRepTopAdaptor_TopolTool.hxx>
-#include <IntPatch_ImpImpIntersection.hxx>
-#include <GeomLib_IsPlanarSurface.hxx>
+
 #include <BRep_Builder.hxx>
-#include <ShapeFix_Wire.hxx>
-#include <TopoDS.hxx>
-#include <ShapeAnalysis_Edge.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TColGeom_SequenceOfSurface.hxx>
+#include <BRep_CurveRepresentation.hxx>
 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
 #include <BRep_TEdge.hxx>
-#include <BRep_CurveRepresentation.hxx>
-#include <TColGeom_Array1OfBSplineCurve.hxx>
-#include <TColGeom_HArray1OfBSplineCurve.hxx>
-#include <TColGeom2d_Array1OfBSplineCurve.hxx>
-#include <TColGeom2d_HArray1OfBSplineCurve.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TopExp.hxx>
-#include <Geom_TrimmedCurve.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepLib.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <BRepTopAdaptor_TopolTool.hxx>
+#include <GC_MakeCircle.hxx>
+#include <Geom2d_Line.hxx>
 #include <Geom2d_TrimmedCurve.hxx>
-#include <GeomConvert.hxx>
 #include <Geom2dConvert.hxx>
-#include <GeomConvert_CompCurveToBSplineCurve.hxx>
 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
-#include <TColGeom2d_SequenceOfBoundedCurve.hxx>
-#include <BRepLib_MakeEdge.hxx>
-#include <TColStd_MapOfInteger.hxx>
-#include <BRepLib.hxx>
-#include <GC_MakeCircle.hxx>
 #include <Geom_BezierCurve.hxx>
-#include <ShapeBuild_ReShape.hxx>
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_ElementarySurface.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_OffsetSurface.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_SurfaceOfLinearExtrusion.hxx>
+#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_SweptSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <GeomConvert.hxx>
+#include <GeomConvert_CompCurveToBSplineCurve.hxx>
+#include <GeomLib_IsPlanarSurface.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Lin.hxx>
+#include <IntPatch_ImpImpIntersection.hxx>
+#include <ShapeAnalysis_Edge.hxx>
 #include <ShapeAnalysis_WireOrder.hxx>
 #include <ShapeBuild_Edge.hxx>
-#include <Geom2d_Line.hxx>
-#include <ShapeFix_Face.hxx>
-#include <TColGeom_HArray2OfSurface.hxx>
+#include <ShapeBuild_ReShape.hxx>
 #include <ShapeExtend_CompositeSurface.hxx>
 #include <ShapeFix_ComposeShell.hxx>
-#include <ShapeFix_SequenceOfWireSegment.hxx>
-#include <ShapeFix_WireSegment.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.ixx>
+#include <ShapeUpgrade_UnifySameDomain.hxx>
+#include <Standard_Type.hxx>
+#include <TColGeom2d_Array1OfBSplineCurve.hxx>
+#include <TColGeom2d_HArray1OfBSplineCurve.hxx>
+#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>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <TopTools_SequenceOfShape.hxx>
+#include <gp_Circ.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepClass_FaceClassifier.hxx>
+#include <NCollection_Sequence.hxx>
+#include <TopTools_MapIteratorOfMapOfShape.hxx>
+
+struct SubSequenceOfEdges
+{
+  TopTools_SequenceOfShape SeqsEdges;
+  TopoDS_Edge UnionEdges;
+};
 
 
 //=======================================================================
@@ -513,184 +530,180 @@ static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
 }
 
 //=======================================================================
-//function : MergeEdges
-//purpose  : auxilary
+//function : MergeSubSeq
+//purpose  : Merges a sequence of edges into one edge if possible
 //=======================================================================
-static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
-                                   const TopoDS_Face& /*aFace*/,
-                                   const Standard_Real Tol,
-                                   const Standard_Boolean ConcatBSplines,
-                                   TopoDS_Edge& anEdge)
+
+static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& aChain, TopoDS_Edge& OutEdge, double Tol, Standard_Boolean ConcatBSplines) 
 {
-  // make chain for union
-  BRep_Builder B;
   ShapeAnalysis_Edge sae;
-  TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1));
-  TopoDS_Edge LastE = FirstE;
-  TopoDS_Vertex VF = sae.FirstVertex(FirstE);
-  TopoDS_Vertex VL = sae.LastVertex(LastE);
-  TopTools_SequenceOfShape aChain;
-  aChain.Append(FirstE);
-  TColStd_MapOfInteger IndUsedEdges;
-  IndUsedEdges.Add(1);
-  Standard_Integer j;
-  for (j = 1; j <= SeqEdges.Length(); j++)
-  {
-    TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j));
-    if (BRep_Tool::Degenerated(anEdge))
-      return Standard_False;
-  }
-  
-  for(j=2; j<=SeqEdges.Length(); j++) {
-    for(Standard_Integer k=2; k<=SeqEdges.Length(); k++) {
-      if(IndUsedEdges.Contains(k)) continue;
-      TopoDS_Edge edge = TopoDS::Edge(SeqEdges.Value(k));
-      TopoDS_Vertex VF2 = sae.FirstVertex(edge);
-      TopoDS_Vertex VL2 = sae.LastVertex(edge);
-      if(sae.FirstVertex(edge).IsSame(VL)) {
-        aChain.Append(edge);
-        LastE = edge;
-        VL = sae.LastVertex(LastE);
-        IndUsedEdges.Add(k);
-      }
-      else if(sae.LastVertex(edge).IsSame(VF)) {
-        aChain.Prepend(edge);
-        FirstE = edge;
-        VF = sae.FirstVertex(FirstE);
-        IndUsedEdges.Add(k);
-      }
-    }
-  }
-  if(aChain.Length()<SeqEdges.Length()) {
-#ifdef OCCT_DEBUG
-    cout<<"can not create correct chain..."<<endl;
-#endif
-    return Standard_False;
-  }
+  BRep_Builder B;
   // union edges in chain
-  // first step: union lines and circles
+  int j;
   Standard_Real fp1,lp1,fp2,lp2;
-  for(j=1; j<aChain.Length(); j++) {
+  Standard_Boolean IsUnionOfLinesPossible = Standard_True;
+  Standard_Boolean IsUnionOfCirclesPossible = Standard_True;
+  Handle(Geom_Curve) c3d1, c3d2;
+  for(j=1; j<aChain.Length(); j++) 
+  {
     TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
-    Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,fp1,lp1);
+    c3d1 = BRep_Tool::Curve(edge1,fp1,lp1);
+
+    TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
+    c3d2 = BRep_Tool::Curve(edge2,fp2,lp2);
+
+    if(c3d1.IsNull() || c3d2.IsNull()) 
+      return Standard_False;
 
-    if(c3d1.IsNull()) break;
     while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
       Handle(Geom_TrimmedCurve) tc =
         Handle(Geom_TrimmedCurve)::DownCast(c3d1);
       c3d1 = tc->BasisCurve();
     }
-    TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1));
-    Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,fp2,lp2);
-    if(c3d2.IsNull()) break;
     while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
       Handle(Geom_TrimmedCurve) tc =
         Handle(Geom_TrimmedCurve)::DownCast(c3d2);
       c3d2 = tc->BasisCurve();
     }
     if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) {
-      // union lines
       Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1);
       Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2);
       gp_Dir Dir1 = L1->Position().Direction();
       gp_Dir Dir2 = L2->Position().Direction();
-      //if(!Dir1.IsEqual(Dir2,Precision::Angular())) { 
-      //if(!Dir1.IsParallel(Dir2,Precision::Angular())) { 
-      if(!Dir1.IsParallel(Dir2,Tol)) { 
-        return Standard_False;
-      }
-      // can union lines => create new edge
-      TopoDS_Vertex V1 = sae.FirstVertex(edge1);
-      gp_Pnt PV1 = BRep_Tool::Pnt(V1);
-      TopoDS_Vertex V2 = sae.LastVertex(edge2);
-      gp_Pnt PV2 = BRep_Tool::Pnt(V2);
-      gp_Vec Vec(PV1,PV2);
-      Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
-      Standard_Real dist = PV1.Distance(PV2);
-      Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
-      TopoDS_Edge E;
-      B.MakeEdge (E,tc,Precision::Confusion());
-      B.Add (E,V1);  B.Add (E,V2);
-      B.UpdateVertex(V1, 0., E, 0.);
-      B.UpdateVertex(V2, dist, E, 0.);
-      //ShapeFix_Edge sfe;
-      //sfe.FixAddPCurve(E,aFace,Standard_False);
-      //sfe.FixSameParameter(E);
-      aChain.Remove(j);
-      aChain.SetValue(j,E);
-      j--;
+      if(!Dir1.IsParallel(Dir2,Tol))  
+        IsUnionOfLinesPossible = Standard_False;
     }
+    else
+      IsUnionOfLinesPossible = Standard_False;
     if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) {
-      // union circles
       Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1);
       Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2);
       gp_Pnt P01 = C1->Location();
       gp_Pnt P02 = C2->Location();
       if (P01.Distance(P02) > Precision::Confusion())
-        return Standard_False;
-      // can union circles => create new edge
-      TopoDS_Vertex V1 = sae.FirstVertex(edge1);
-      gp_Pnt PV1 = BRep_Tool::Pnt(V1);
-      TopoDS_Vertex V2 = sae.LastVertex(edge2);
-      gp_Pnt PV2 = BRep_Tool::Pnt(V2);
-      TopoDS_Vertex VM = sae.LastVertex(edge1);
-      gp_Pnt PVM = BRep_Tool::Pnt(VM);
-      GC_MakeCircle MC (PV1,PVM,PV2);
-      TopoDS_Edge E;
-      if (!MC.IsDone() || MC.Value().IsNull()) {
-        // jfa for Mantis issue 0020228
-        if (PV1.Distance(PV2) > Precision::Confusion())
+        IsUnionOfCirclesPossible = Standard_False;
+    }
+    else
+      IsUnionOfCirclesPossible = Standard_False;
+  }
+  if (IsUnionOfLinesPossible && IsUnionOfCirclesPossible)
+    return Standard_False;
+
+  //union of lines is possible
+  if (IsUnionOfLinesPossible)
+  {
+    TopoDS_Vertex V1 = sae.FirstVertex(TopoDS::Edge(aChain.First()));
+    gp_Pnt PV1 = BRep_Tool::Pnt(V1);
+    TopoDS_Vertex V2 = sae.LastVertex(TopoDS::Edge(aChain.Last()));
+    gp_Pnt PV2 = BRep_Tool::Pnt(V2);
+    gp_Vec Vec(PV1, PV2);
+    Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec));
+    Standard_Real dist = PV1.Distance(PV2);
+    Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist);
+    TopoDS_Edge E;
+    B.MakeEdge (E, tc ,Precision::Confusion());
+    B.Add (E,V1);  B.Add (E,V2);
+    B.UpdateVertex(V1, 0., E, 0.);
+    B.UpdateVertex(V2, dist, E, 0.);
+    OutEdge = E;
+    return Standard_True;
+  }
+
+  if (IsUnionOfCirclesPossible)
+  {
+    double f,l;
+    TopoDS_Edge FE = TopoDS::Edge(aChain.First());
+    Handle(Geom_Curve) c3d = BRep_Tool::Curve(FE,f,l);
+
+    while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
+      Handle(Geom_TrimmedCurve) tc =
+        Handle(Geom_TrimmedCurve)::DownCast(c3d);
+      c3d = tc->BasisCurve();
+    }
+    Handle(Geom_Circle) Cir = Handle(Geom_Circle)::DownCast(c3d);
+
+    TopoDS_Vertex V1 = sae.FirstVertex(FE);
+    TopoDS_Vertex V2 = sae.LastVertex(TopoDS::Edge(aChain.Last()));
+    TopoDS_Edge E;
+    if (V1.IsSame(V2)) {
+      // closed chain
+      BRepAdaptor_Curve adef(FE);
+      Handle(Geom_Circle) Cir1;
+      double FP, LP;
+      if ( FE.Orientation() == TopAbs_FORWARD)
+      {
+        FP = adef.FirstParameter();
+        LP = adef.LastParameter();
+      }
+      else
+      {
+        FP = adef.LastParameter();
+        LP = adef.FirstParameter();
+      }
+      if (Abs(FP) < Precision::PConfusion())
+      {
+        B.MakeEdge (E,Cir, Precision::Confusion());
+        B.Add(E,V1);
+        B.Add(E,V2);
+        E.Orientation(FE.Orientation());
+      }
+      else
+      {
+        GC_MakeCircle MC1 (adef.Value(FP), adef.Value((FP + LP) * 0.5), adef.Value(LP));
+        if (MC1.IsDone())
+          Cir1 = MC1.Value();
+        else
           return Standard_False;
-        // closed chain
-        B.MakeEdge (E,C1,Precision::Confusion());
+        B.MakeEdge (E, Cir1, Precision::Confusion());
         B.Add(E,V1);
         B.Add(E,V2);
       }
-      else {
-        Handle(Geom_Circle) C = MC.Value();
-        gp_Pnt P0 = C->Location();
-        gp_Dir D1(gp_Vec(P0,PV1));
-        gp_Dir D2(gp_Vec(P0,PV2));
-        Standard_Real fpar = C->XAxis().Direction().Angle(D1);
-        if(fabs(fpar)>Precision::Confusion()) {
-          // check orientation
-          gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
-          if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
-            fpar = -fpar;
-          }
+    }
+    else {
+      gp_Pnt PV1 = BRep_Tool::Pnt(V1);
+      gp_Pnt PV2 = BRep_Tool::Pnt(V2);
+      TopoDS_Vertex VM = sae.LastVertex(FE);
+      gp_Pnt PVM = BRep_Tool::Pnt(VM);
+      GC_MakeCircle MC (PV1,PVM,PV2);
+      Handle(Geom_Circle) C = MC.Value();
+      gp_Pnt P0 = C->Location();
+      gp_Dir D1(gp_Vec(P0,PV1));
+      gp_Dir D2(gp_Vec(P0,PV2));
+      Standard_Real fpar = C->XAxis().Direction().Angle(D1);
+      if(fabs(fpar)>Precision::Confusion()) {
+        // check orientation
+        gp_Dir ND =  C->XAxis().Direction().Crossed(D1);
+        if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
+          fpar = -fpar;
         }
-        Standard_Real lpar = C->XAxis().Direction().Angle(D2);
-        if(fabs(lpar)>Precision::Confusion()) {
-          // check orientation
-          gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
-          if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
-            lpar = -lpar;
-          }
+      }
+      Standard_Real lpar = C->XAxis().Direction().Angle(D2);
+      if(fabs(lpar)>Precision::Confusion()) {
+        // check orientation
+        gp_Dir ND =  C->XAxis().Direction().Crossed(D2);
+        if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) {
+          lpar = -lpar;
         }
-        if (lpar < fpar) lpar += 2*M_PI;
-        Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
-        B.MakeEdge (E,tc,Precision::Confusion());
-        B.Add(E,V1);
-        B.Add(E,V2);
-        B.UpdateVertex(V1, fpar, E, 0.);
-        B.UpdateVertex(V2, lpar, E, 0.);
       }
-      aChain.Remove(j);
-      aChain.SetValue(j,E);
-      j--;
+      if (lpar < fpar) lpar += 2*M_PI;
+      Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar);
+      B.MakeEdge (E,tc,Precision::Confusion());
+      B.Add(E,V1);
+      B.Add(E,V2);
+      B.UpdateVertex(V1, fpar, E, 0.);
+      B.UpdateVertex(V2, lpar, E, 0.);
     }
-  }
-  if (j < aChain.Length()) {
-#ifdef OCCT_DEBUG
-    cout<<"null curve3d in edge..."<<endl;
-#endif
-    return Standard_False;
+    OutEdge = E;
+    return Standard_True;
   }
   if (aChain.Length() > 1 && ConcatBSplines) {
     // second step: union edges with various curves
     // skl for bug 0020052 from Mantis: perform such unions
     // only if curves are bspline or bezier
-    bool NeedUnion = true;
+
+    TopoDS_Vertex VF = sae.FirstVertex(TopoDS::Edge(aChain.First()));
+    TopoDS_Vertex VL = sae.LastVertex(TopoDS::Edge(aChain.Last()));
+    Standard_Boolean NeedUnion = Standard_True;
     for(j=1; j<=aChain.Length(); j++) {
       TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
       TopLoc_Location Loc;
@@ -703,7 +716,7 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
       }
       if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
             c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
-      NeedUnion = false;
+      NeedUnion = Standard_False;
       break;
     }
     if(NeedUnion) {
@@ -711,7 +724,8 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
       cout<<"can not make analitical union => make approximation"<<endl;
 #endif
       TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
-      aChain.SetValue(1,E);
+      OutEdge = E;
+      return Standard_True;
     }
     else {
 #ifdef OCCT_DEBUG
@@ -720,11 +734,258 @@ static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
       return Standard_False;
     }
   }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : IsMergingPossible
+//purpose  : Checks if merging of two edges is possible
+//=======================================================================
+
+static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, 
+                                          double Tol, const TopTools_MapOfShape& DegEdgeVrt)
+{
+  TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True);
+  if (CV.IsNull() || DegEdgeVrt.Contains(CV))
+    return Standard_False;
+
+  BRepAdaptor_Curve ade1(edge1);
+  BRepAdaptor_Curve ade2(edge2);
+
+  GeomAbs_CurveType t1 = ade1.GetType();
+  GeomAbs_CurveType t2 = ade2.GetType();
+
+  if( t1 == GeomAbs_Circle && t2 == GeomAbs_Circle)
+  {
+    if (ade1.Circle().Location().Distance(ade2.Circle().Location()) > Precision::Confusion())
+      return Standard_False;
+  }
+
+  if( ( (t1 != GeomAbs_BezierCurve && t1 != GeomAbs_BSplineCurve) ||
+      (t2 != GeomAbs_BezierCurve && t2 != GeomAbs_BSplineCurve)) && t1 != t2)
+    return Standard_False;
+
+  gp_Vec Diff1, Diff2;
+  gp_Pnt P1, P2;
+  if (edge1.Orientation() == TopAbs_FORWARD)
+    ade1.D1(ade1.LastParameter(), P1, Diff1);
+  else
+  {
+    ade1.D1(ade1.FirstParameter(), P1, Diff1);
+    Diff1 = -Diff1;
+  }
+
+  if (edge2.Orientation() == TopAbs_FORWARD)
+    ade2.D1(ade2.FirstParameter(), P2, Diff2);
+  else
+  {
+    ade2.D1(ade2.LastParameter(), P2, Diff2);
+    Diff2 = -Diff2;
+  }
+
+  if (Diff1.Angle(Diff2) > Tol)
+    return Standard_False;
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : GenerateSubSeq
+//purpose  : Generates sub-sequences of edges from sequence of edges
+//Edges from each subsequences can be merged into the one edge  
+//=======================================================================
+
+static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq,
+                            NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
+                            Standard_Boolean IsClosed, double Tol, const TopTools_MapOfShape& DegEdgeVrt )
+{
+  Standard_Boolean isOk = Standard_False;
+  TopoDS_Edge edge1, edge2;
+
+  SubSequenceOfEdges SubSeq;
+  SubSeq.SeqsEdges.Append(TopoDS::Edge(anInpEdgeSeq(1)));
+  SeqOfSubSeqOfEdges.Append(SubSeq);
+
+  for (int i = 1; i < anInpEdgeSeq.Length(); i++)
+  {
+    edge1 = TopoDS::Edge(anInpEdgeSeq(i));
+    edge2 = TopoDS::Edge(anInpEdgeSeq(i+1));
+    isOk = IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt);
+    if (!isOk)
+    {
+      SubSequenceOfEdges SubSeq;
+      SubSeq.SeqsEdges.Append(edge2);
+      SeqOfSubSeqOfEdges.Append(SubSeq);
+    }
+    else
+      SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(edge2);
+  }
+  /// check first and last chain segments
+  if (IsClosed && SeqOfSubSeqOfEdges.Length() > 1)
+  {
+    edge1 = TopoDS::Edge(anInpEdgeSeq.Last());
+    edge2 = TopoDS::Edge(anInpEdgeSeq.First());
+    if (IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt))
+    {
+      SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges);
+      SeqOfSubSeqOfEdges.Remove(1);
+    }
+  }
+}
+
+
+//=======================================================================
+//function : MergeEdges
+//purpose  : auxilary
+//=======================================================================
+static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
+                                   const Standard_Real Tol,
+                                   const Standard_Boolean ConcatBSplines,
+                                   NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges,
+                                   const TopTools_MapOfShape& NonMergVrt )
+{
+  // make chain for union
+  //BRep_Builder B;
+  ShapeAnalysis_Edge sae;
+  TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1));
+  TopoDS_Edge LastE = FirstE;
+  TopoDS_Vertex VF = sae.FirstVertex(FirstE);
+  TopoDS_Vertex VL = sae.LastVertex(LastE);
+  TopTools_SequenceOfShape aChain;
+  aChain.Append(FirstE);
+  TColStd_MapOfInteger IndUsedEdges;
+  IndUsedEdges.Add(1);
+  Standard_Integer j;
+  TopTools_MapOfShape VerticesToAvoid;
+  TopTools_SequenceOfShape SeqEdges1;
+  for (j = 1; j <= SeqEdges.Length(); j++)
+  {
+    TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j));
+    if (BRep_Tool::Degenerated(anEdge))
+    {
+      TopoDS_Vertex V1, V2;
+      TopExp::Vertices(anEdge, V1, V2);
+      VerticesToAvoid.Add(V1);
+      VerticesToAvoid.Add(V2);
+      continue;
+    }
+    SeqEdges1.Append(anEdge);
+  }
+
+  for(j=2; j<=SeqEdges1.Length(); j++) {
+    for(Standard_Integer k=2; k<=SeqEdges1.Length(); k++) {
+      if(IndUsedEdges.Contains(k)) continue;
+      TopoDS_Edge edge = TopoDS::Edge(SeqEdges1.Value(k));
+      TopoDS_Vertex VF2 = sae.FirstVertex(edge);
+      TopoDS_Vertex VL2 = sae.LastVertex(edge);
+      if(VF2.IsSame(VL)) {
+        aChain.Append(edge);
+        LastE = edge;
+        VL = sae.LastVertex(LastE);
+        IndUsedEdges.Add(k);
+      }
+      else if(VL2.IsSame(VF)) {
+        aChain.Prepend(edge);
+        FirstE = edge;
+        VF = sae.FirstVertex(FirstE);
+        IndUsedEdges.Add(k);
+      }
+    }
+  }
+
+  Standard_Boolean IsClosed = Standard_False;
+  if (VF.IsSame ( VL ))
+    IsClosed = Standard_True;
 
-  anEdge = TopoDS::Edge(aChain.Value(1));
+  for (TopTools_MapIteratorOfMapOfShape it(NonMergVrt); it.More(); it.Next())
+  {
+    VerticesToAvoid.Add(it.Key());
+  }
+  GenerateSubSeq(aChain, SeqOfSubSeqOfEdges, IsClosed, Tol, VerticesToAvoid);
+
+  for (int i = 1; i <= SeqOfSubSeqOfEdges.Length(); i++)
+  {
+    TopoDS_Edge UE;
+    if (SeqOfSubSeqOfEdges(i).SeqsEdges.Length() < 2)
+      continue;
+    if (MergeSubSeq(SeqOfSubSeqOfEdges(i).SeqsEdges, UE, Tol, ConcatBSplines))
+      SeqOfSubSeqOfEdges(i).UnionEdges = UE;
+  }
   return Standard_True;
 }
 
+//=======================================================================
+//function : MergeSeq
+//purpose  : Tries to unify the sequence of edges with the set of another edges 
+//which lies on the same geometry
+//=======================================================================
+
+static Standard_Boolean MergeSeq (const TopTools_SequenceOfShape& SeqEdges,
+                                  const Standard_Real Tol,
+                                  const Standard_Boolean ConcatBSplines,
+                                  Handle(ShapeBuild_ReShape)& theContext,
+                                  TopTools_DataMapOfShapeShape& theOldShapes,
+                                  const TopTools_MapOfShape& nonMergVert,
+                                  const TopTools_DataMapOfShapeShape& NewEdges2OldEdges)
+{ 
+  NCollection_Sequence<SubSequenceOfEdges> SeqOfSubsSeqOfEdges;
+  int k = 1;
+  if ( MergeEdges(SeqEdges, Tol, ConcatBSplines, SeqOfSubsSeqOfEdges, nonMergVert) )
+  {
+    for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ )
+    {
+      if (SeqOfSubsSeqOfEdges(i).UnionEdges.IsNull())
+        continue;
+      theContext->Replace(SeqOfSubsSeqOfEdges(i).SeqsEdges(1), SeqOfSubsSeqOfEdges(i).UnionEdges);
+      k++;
+      for (Standard_Integer j = 2; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++)
+      {
+        TopoDS_Shape OldEdge = NewEdges2OldEdges(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
+        theOldShapes.Bind(OldEdge, SeqOfSubsSeqOfEdges(i).UnionEdges);
+        theContext->Remove(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
+      }
+    }
+    return Standard_True;
+  }
+  else
+    return Standard_False;
+}
+
+//=======================================================================
+//function : CheckSharedVertices
+//purpose  : Checks the sequence of edges on the presence of shared vertex 
+//=======================================================================
+
+static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, 
+                                const TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgesVertex,
+                                TopTools_MapOfShape& theShareVertMap)
+{
+  ShapeAnalysis_Edge sae;
+  TopTools_SequenceOfShape SeqVertexes;
+  TopTools_MapOfShape MapVertexes;
+  for (Standard_Integer k = 1; k <= theSeqEdges.Length(); k++ )
+  {
+    TopoDS_Vertex aV1 = sae.FirstVertex(TopoDS::Edge(theSeqEdges(k)));
+    TopoDS_Vertex aV2 = sae.LastVertex(TopoDS::Edge(theSeqEdges(k)));
+    if (!MapVertexes.Add(aV1))
+      SeqVertexes.Append(aV1);
+    if (!MapVertexes.Add(aV2))
+      SeqVertexes.Append(aV2);
+  }
+
+  for (Standard_Integer k = 1; k <= SeqVertexes.Length()/* && !IsSharedVertexPresent*/; k++ )
+  {
+    const TopTools_ListOfShape& ListEdgesV1 = theMapEdgesVertex.FindFromKey(SeqVertexes(k));
+    TopTools_MapOfShape aMapOfEdges;
+    TopTools_ListIteratorOfListOfShape iter(ListEdgesV1);
+    for (; iter.More(); iter.Next())
+      aMapOfEdges.Add(iter.Value());
+    if (aMapOfEdges.Extent() > 2)
+      theShareVertMap.Add(SeqVertexes(k));
+  }
+  //return theShareVertMap.IsEmpty() ? false : true;
+}
+
 //=======================================================================
 //function : ShapeUpgrade_UnifySameDomain
 //purpose  : Constructor
@@ -775,10 +1036,41 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
   myConcatBSplines = ConcatBSplines;
 
   myContext->Clear();
-  //myOldNewMap.Clear();
+  myOldShapes.Clear();
   //myGenerated.Clear();
 }
 
+//=======================================================================
+//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  : 
@@ -786,14 +1078,18 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
 
 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 {
-  // creating map of edge faces
-  TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
-  TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
+  //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
+  TopoDS_Shape aResShape = myContext->Apply(myShape);
+
   // processing each shell
   TopExp_Explorer exps;
   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
     TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
-    
+
+    // creating map of edge faces
+    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
+    TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
+
     // map of processed shapes
     TopTools_MapOfShape aProcessed;
 
@@ -893,6 +1189,8 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 
           TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
           edges.Remove(1);
+          // collect internal edges in separate wires
+          Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
 
           isEdge3d |= !BRep_Tool::Degenerated(anEdge);
           B.Add(aWire,anEdge);
@@ -906,6 +1204,10 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
             isNewFound = Standard_False;
             for(Standard_Integer j = 1; j <= edges.Length(); j++) {
               anEdge = TopoDS::Edge(edges(j));
+              // check if the current edge orientation corresponds to the first one
+              Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL);
+              if (isCurrInternal != isInternal)
+                continue;
               TopExp::Vertices(anEdge,V1,V2);
               if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
                 isEdge3d |= !BRep_Tool::Degenerated(anEdge);
@@ -1052,13 +1354,26 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
           //CompShell.SetContext( aContext );
           CompShell.SetContext( myContext );
 
-          TopTools_SequenceOfShape parts;
+          TopTools_SequenceOfShape parts, anIntWires;
           ShapeFix_SequenceOfWireSegment wires;
           for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
-            Handle(ShapeExtend_WireData) sbwd =
-              new ShapeExtend_WireData ( TopoDS::Wire(W_Exp.Current() ));
-            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
-            wires.Append(seg);
+            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 );
@@ -1067,10 +1382,12 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
             //aFixOrient.SetContext(aContext);
             aFixOrient.SetContext(myContext);
             aFixOrient.FixOrientation();
+            // put internal wires to faces
+            putIntWires(parts(j), anIntWires);
           }
 
           TopoDS_Shape CompRes;
-          if ( faces.Length() !=1 ) {
+          if ( parts.Length() !=1 ) {
             TopoDS_Shell S;
             B.MakeShell ( S );
             for ( i=1; i <= parts.Length(); i++ )
@@ -1097,8 +1414,10 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 
         // remove the remaining faces
         for(i = 2; i <= faces.Length(); i++)
-          //aContext->Remove(faces(i));
+        { 
+          myOldShapes.Bind(faces(i), theResult);
           myContext->Remove(faces(i));
+        }
       }
     } // end processing each face
 
@@ -1155,7 +1474,6 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 //function : UnifyEdges
 //purpose  : 
 //=======================================================================
-
 void ShapeUpgrade_UnifySameDomain::UnifyEdges()
 {
   Standard_Real Tol = Precision::Confusion();
@@ -1178,82 +1496,84 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
   TopoDS_Shape aRes = myShape;
   //aRes = aContext->Apply(aSolid);
   aRes = myContext->Apply(myShape);
+  
+  TopTools_MapOfShape SharedVert;
+
+  
+  TopTools_IndexedMapOfShape anOldEdges;
+  TopExp::MapShapes(myInitShape, TopAbs_EDGE, anOldEdges);
+
+  TopTools_DataMapOfShapeShape NewEdges2OldEdges;
+  for (int i = 1; i <= anOldEdges.Extent(); i++)
+  {
+    TopoDS_Shape NewEdge = myContext->Apply(anOldEdges(i));
+    if (!NewEdge.IsNull())
+      NewEdges2OldEdges.Bind(NewEdge, anOldEdges(i));
+  }
 
-  // processing each face
   TopExp_Explorer exp;
+  // processing separate wires
+  for (exp.Init(aRes, TopAbs_WIRE, TopAbs_FACE); exp.More(); exp.Next()) 
+  {
+    TopTools_SequenceOfShape SeqEdges;
+    TopExp_Explorer expE(exp.Current(), TopAbs_EDGE);
+    for (; expE.More(); expE.Next())
+      SeqEdges.Append(expE.Current());
+    SharedVert.Clear();
+    CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert); 
+    MergeSeq(SeqEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges);
+  }
+
+  // processing each face
   for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
     //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
     TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;
-
+    TopTools_SequenceOfShape aNonSharedEdges;
     for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
       TopoDS_Edge edge = TopoDS::Edge(expe.Current());
       if (!aMapEdgeFaces.Contains(edge)) continue;
       const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
       TopTools_ListIteratorOfListOfShape anIter(aList);
+      Standard_Integer NbFacesPerEdge = aList.Extent();
       for ( ; anIter.More(); anIter.Next()) {
         TopoDS_Face face = TopoDS::Face(anIter.Value());
-        //TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
         TopoDS_Face face1 = TopoDS::Face(myContext->Apply(anIter.Value()));
-        if (face1.IsSame(aFace)) continue;
-        if (aMapFacesEdges.Contains(face)) {
-          aMapFacesEdges.ChangeFromKey(face).Append(edge);
-        }
-        else {
-          TopTools_ListOfShape ListEdges;
-          ListEdges.Append(edge);
-          aMapFacesEdges.Add(face,ListEdges);
+        if (face1.IsSame(aFace) && NbFacesPerEdge != 1)
+          continue;
+        if (NbFacesPerEdge == 1)
+          //store non-shared edges separately 
+          aNonSharedEdges.Append(edge);
+        else 
+        {
+          if (aMapFacesEdges.Contains(face))
+            aMapFacesEdges.ChangeFromKey(face).Append(edge);
+          else 
+          {
+            TopTools_ListOfShape ListEdges;
+            ListEdges.Append(edge);
+            aMapFacesEdges.Add(face,ListEdges);
+          }
         }
       }
     }
-
-    for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
+      
+    for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++)
+    {
       const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
       TopTools_SequenceOfShape SeqEdges;
-      ShapeAnalysis_Edge sae;
       TopTools_ListIteratorOfListOfShape anIter(ListEdges);
-      Standard_Boolean IsSharedVertexPresent = Standard_False;
       for ( ; anIter.More(); anIter.Next())
         SeqEdges.Append(anIter.Value());
       if (SeqEdges.Length()==1) 
         continue;  
-      TopTools_SequenceOfShape SeqVertexes;
-      TopTools_MapOfShape  MapVertexes;
-      for (int k = 1; k <= SeqEdges.Length(); k++ )
-      {
-        TopoDS_Vertex aV1 = sae.FirstVertex(TopoDS::Edge(SeqEdges(k)));
-        TopoDS_Vertex aV2 = sae.LastVertex(TopoDS::Edge(SeqEdges(k)));
-        if (!MapVertexes.Add(aV1))
-          SeqVertexes.Append(aV1);
-        if (!MapVertexes.Add(aV2))
-          SeqVertexes.Append(aV2);
-      }
 
-      for (Standard_Integer k = 1; k <= SeqVertexes.Length() && !IsSharedVertexPresent; k++ )
+      SharedVert.Clear();
+      CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert);
+      //if (!SharedVert.IsEmpty()) 
+      //  continue;
+      if ( MergeSeq(SeqEdges,Tol,myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) )
       {
-        const TopTools_ListOfShape& ListEdgesV1 = aMapEdgesVertex.FindFromKey(SeqVertexes(k));
-        TopTools_MapOfShape aMapOfEdges;
-        TopTools_ListIteratorOfListOfShape iter(ListEdgesV1);
-        for (; iter.More(); iter.Next())
-          aMapOfEdges.Add(iter.Value());
-        if (aMapOfEdges.Extent() > 2)
-          IsSharedVertexPresent = Standard_True;
-      }
-
-      if (IsSharedVertexPresent)
-        continue;
-      TopoDS_Edge E;
-      if ( MergeEdges(SeqEdges,aFace,Tol,myConcatBSplines,E) ) {
-        // now we have only one edge - aChain.Value(1)
-        // we have to replace old ListEdges with this new edge
-        //aContext->Replace(SeqEdges(1),E);
-        myContext->Replace(SeqEdges(1),E);
-        Standard_Integer j;
-        for (j = 2; j <= SeqEdges.Length(); j++) {
-          //aContext->Remove(SeqEdges(j));
-          myContext->Remove(SeqEdges(j));
-          //myOldNewMap.Bind(SeqEdges(j), E);
-        }
         //for history
         /*
         for (j = 1; j <= SeqEdges.Length(); j++)
@@ -1277,6 +1597,18 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
           ChangedFaces.Add(tmpF);
       }
     }
+    
+    if ( aNonSharedEdges.Length() > 1 )
+    {
+      SharedVert.Clear();
+      CheckSharedVertices(aNonSharedEdges, aMapEdgesVertex, SharedVert); 
+      if ( MergeSeq(aNonSharedEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) )
+      {
+        TopoDS_Face tmpF = TopoDS::Face(exp.Current());
+        if ( !ChangedFaces.Contains(tmpF) )
+          ChangedFaces.Add(tmpF);
+      }
+    }
 
   } // end processing each face
 
@@ -1284,6 +1616,8 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
   for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
     //TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
     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(myTolerance);
@@ -1400,10 +1734,9 @@ const TopoDS_Shape& ShapeUpgrade_UnifySameDomain::Shape() const
 TopoDS_Shape ShapeUpgrade_UnifySameDomain::Generated(const TopoDS_Shape& aShape) const
 {
   TopoDS_Shape aNewShape = myContext->Apply(aShape);
-  /*
+
   if (aNewShape.IsNull())
-    aNewShape = myOldNewMap(aShape);
-  */
+    aNewShape = myContext->Apply(myOldShapes(aShape));
   
   return aNewShape;
 }
diff --git a/tests/bugs/heal/bug26244 b/tests/bugs/heal/bug26244
new file mode 100644 (file)
index 0000000..2d8385e
--- /dev/null
@@ -0,0 +1,286 @@
+puts "=========="
+puts "OCC26244"
+puts "=========="
+puts ""
+###########################################
+# Destructive results of simplification with DRAW command 'unifysamedom' after intersection of two complex models
+###########################################
+
+set my_pi 3.1415926535897931
+set aModelHeight 178.25
+set aPlatformLength 426.25
+set aPlatformWidth 201.5
+set aPlatformHeight 58.9
+set aPrismLength 279
+set aPrismWidth 155
+set aPrismHeight [expr $aModelHeight - $aPlatformHeight]
+set aPrismXOffset [expr $aPlatformLength - $aPrismLength - 69.75]
+set aPrismYOffset [expr ($aPlatformWidth - $aPrismWidth)/2]
+
+#================================================================================
+# A base of the model
+box _platform $aPlatformLength $aPlatformWidth $aPlatformHeight
+
+# Make screw holes on the platform
+set aScrewHoleRadius [expr 26.2/2]
+set aScrewHoleOffset 31
+pcylinder _screwhole $aScrewHoleRadius $aPlatformHeight
+ttranslate _screwhole $aScrewHoleOffset $aScrewHoleOffset 0
+bcut _platform _platform _screwhole
+reset _screwhole
+ttranslate _screwhole [expr $aPlatformLength - $aScrewHoleOffset] $aScrewHoleOffset 0
+bcut _platform _platform _screwhole
+reset _screwhole
+ttranslate _screwhole [expr $aPlatformLength - $aScrewHoleOffset] [expr $aPlatformWidth - $aScrewHoleOffset] 0
+bcut _platform _platform _screwhole
+reset _screwhole
+ttranslate _screwhole $aScrewHoleOffset [expr $aPlatformWidth - $aScrewHoleOffset] 0
+bcut _platform _platform _screwhole
+reset _screwhole
+
+# Back side cave
+set aCaveLength 81.38
+set aCaveDepth 10
+set aCaveWidth 19.38
+set aBottomLevel [expr $aPlatformHeight/2 - $aCaveWidth/2]
+set aTopLevel [expr $aPlatformHeight/2 + $aCaveWidth/2]
+beziercurve t_bcurve 4  0 $aCaveLength $aBottomLevel  3  0 [expr $aCaveLength + $aCaveWidth/2] $aBottomLevel 6  0 [expr $aCaveLength + $aCaveWidth/2] $aTopLevel 6  0 $aCaveLength $aTopLevel 3
+vertex t_v1 0 $aCaveLength $aBottomLevel
+vertex t_v2 0 $aCaveLength $aTopLevel
+mkedge t_e1 t_bcurve
+edge t_e2 t_v1 t_v2
+wire t_w t_e1 t_e2
+mkplane t_f1 t_w
+prism t_s1 t_f1 $aCaveDepth 0 0
+box t_s2 0 0 $aBottomLevel $aCaveDepth $aCaveLength $aCaveWidth
+bfuse _backcave t_s1 t_s2
+bcut _platform _platform _backcave
+
+# Right side cave
+set aRCaveRadius 26.2
+set aRCaveDistToSection 15.5
+set aCurveParam [expr ($my_pi - acos($aRCaveDistToSection/$aRCaveRadius))]
+set aRCaveCenterX [expr $aPlatformLength - 162.75]
+set aRCaveCenterZ [expr $aPlatformHeight/2]
+circle t_circle $aRCaveCenterX 0 $aRCaveCenterZ 0 1 0 1 0 0 $aRCaveRadius
+trim t_curve t_circle -$aCurveParam $aCurveParam
+mkedge t_e1 t_curve
+cvalue t_curve -$aCurveParam t_x t_y t_z
+vertex t_v1 t_x t_y t_z
+cvalue t_curve $aCurveParam t_x t_y t_z
+vertex t_v2 t_x t_y t_z
+edge t_e2 t_v1 t_v2
+wire t_w t_e1 t_e2
+mkplane t_f t_w
+prism t_s t_f 0 $aCaveDepth 0
+bcut _platform _platform t_s
+
+# Caves on front side
+set aFCaveCirclesRadius 4.65
+set aFCaveBottomWidth 37.8
+set aFCaveHeight 38.75
+set aFCaveTopWidth 27
+set aFCaveSmallCircleRadius 9.3
+circle t_circle1 [expr $aFCaveTopWidth/2] [expr $aFCaveHeight/2] $aFCaveCirclesRadius
+circle t_circle2 [expr -$aFCaveTopWidth/2] [expr $aFCaveHeight/2] $aFCaveCirclesRadius
+circle t_circle3 [expr -$aFCaveBottomWidth/2] [expr -$aFCaveHeight/2] $aFCaveCirclesRadius
+circle t_circle4 [expr $aFCaveBottomWidth/2] [expr -$aFCaveHeight/2] $aFCaveCirclesRadius
+
+lintan t_l t_circle1 t_circle2
+trim t_side1 t_l_1 0 $aFCaveTopWidth
+
+lintan t_l t_circle2 t_circle3
+trim t_side2 t_l_1 0 39.058577803089555
+
+lintan t_l t_circle3 t_circle4
+trim t_side3 t_l_1 0 $aFCaveBottomWidth
+
+lintan t_l t_circle4 t_circle1
+trim t_side4 t_l_1 0 39.196587861700415
+
+trim t_circle1 t_circle1 0.15109758878146562 1.5707963267948966 
+trim t_circle2 t_circle2 1.5707963267948966 3.0158086349284448
+trim t_circle3 t_circle3 3.0158086349284448 4.7123889803846897 
+trim t_circle4 t_circle4 4.7123889803846897 0.15109758878146562 
+
+plane t_plane 0 0 0 1 0 0 0 1 0
+
+to3d t_circle1 t_circle1 t_plane
+to3d t_circle2 t_circle2 t_plane
+to3d t_circle3 t_circle3 t_plane
+to3d t_circle4 t_circle4 t_plane
+to3d t_side1 t_side1 t_plane
+to3d t_side2 t_side2 t_plane
+to3d t_side3 t_side3 t_plane
+to3d t_side4 t_side4 t_plane
+
+mkedge t_e1 t_circle1
+mkedge t_e2 t_side1
+mkedge t_e3 t_circle2
+mkedge t_e4 t_side2
+mkedge t_e5 t_circle3
+mkedge t_e6 t_side3
+mkedge t_e7 t_circle4
+mkedge t_e8 t_side4
+
+wire t_w t_e1 t_e2 t_e3 t_e4 t_e5 t_e6 t_e7 t_e8
+mkplane t_f t_w
+prism t_s1 t_f -$aCaveDepth 0 0
+
+circle t_circle 0 [expr $aFCaveTopWidth/2 + $aFCaveBottomWidth/2] 0 1 0 0 $aFCaveSmallCircleRadius
+mkedge t_e t_circle
+wire t_w t_e
+mkplane t_f t_w
+prism t_s2 t_f [expr -$aCaveDepth/2] 0 0
+
+box t_s3 0 0 -$aFCaveSmallCircleRadius  [expr -$aCaveDepth/2] [expr $aFCaveTopWidth/2 + $aFCaveBottomWidth/2] [expr $aFCaveSmallCircleRadius*2]
+
+# Compile elements
+bfuse t_s2 t_s2 t_s3
+bfuse _frontcave t_s1 t_s2
+unifysamedom _frontcave _frontcave
+
+# Cut this cave from the platform
+ttranslate _frontcave $aPlatformLength [expr $aPlatformWidth*2/3] [expr $aPlatformHeight/2]
+bcut _platform _platform _frontcave
+
+tmirror _frontcave $aPlatformLength [expr $aPlatformWidth/2] [expr $aPlatformHeight/2] 0 1 0
+bcut _platform _platform _frontcave
+
+#================================================================================
+# A wedge on the platform
+box t_box  $aPrismXOffset $aPrismYOffset $aPlatformHeight $aPrismLength $aPrismWidth $aPrismHeight
+
+set aCutwedgeLength [expr $aPrismHeight/0.57735]
+wedge _cutwedge $aPlatformLength [expr $aPrismYOffset + $aPrismWidth] $aModelHeight 0 -1 0 -1 0 0 $aCutwedgeLength $aPrismHeight $aPrismWidth 0
+
+bcut _prism t_box _cutwedge
+
+# Make 9 small holes on a top side
+set aWedgeSmallHolesRadius 7.68
+set aWedgeSmallHolesOrbit 67.81
+set aWedgeHoleXPos [expr $aPrismXOffset + 77.5]
+set aWedgeHoleYPos [expr $aPrismYOffset + 77.5]
+
+plane t_plane $aWedgeHoleXPos $aWedgeHoleYPos [expr $aPlatformHeight + $aPrismHeight/2] 0 0 1 1 0 0
+pcylinder t_cyl t_plane $aWedgeSmallHolesRadius [expr $aPrismHeight/2]
+
+set i 2
+while {$i <= 10} {ttranslate t_cyl [expr $aWedgeSmallHolesOrbit*cos($i*$my_pi/6)] [expr $aWedgeSmallHolesOrbit*sin($i*$my_pi/6)] 0; bcut _prism _prism t_cyl; reset t_cyl; incr i}
+
+# Make a cylinder on a canted side
+set aWedgeCylinderRadius 38.75
+set aWedgeCylinderHeight 38.75
+set aWedgeCantedHeight [expr tan($my_pi/6)*($aCutwedgeLength - 69.75)]
+set aWedgeCylinderZPos [expr $aModelHeight - $aWedgeCantedHeight/2]
+plane t_plane [expr $aPrismXOffset + $aPrismLength*3/4] [expr $aPrismYOffset + $aPrismWidth/2] $aWedgeCylinderZPos cos($my_pi/3) 0 sin($my_pi/3) 0 1 0
+pcylinder t_cyl t_plane $aWedgeCylinderRadius $aWedgeCylinderHeight
+explode t_cyl e
+blend t_cyl t_cyl 3 t_cyl_1
+bfuse _prism _prism t_cyl
+unifysamedom _prism _prism
+
+# Make a hole in the cylinder on the wedge
+pcylinder t_cyl t_plane [expr $aWedgeCylinderRadius/2] 100
+ttranslate t_cyl [expr -60*cos($my_pi/3)] 0 [expr -60*sin($my_pi/3)]
+bcut _prism _prism t_cyl
+
+# Make a hole on a right side of the wedge
+plane t_plane [expr $aPlatformLength - 162.75] $aPrismYOffset [expr $aModelHeight - $aWedgeCantedHeight] 0 1 0 1 0 0
+pcylinder t_cyl t_plane 13.1 [expr $aPrismWidth/2]
+bcut _prism _prism t_cyl
+
+# Fuse the platform and the prism
+bfuse _model _platform _prism
+
+# Make a pass-through hole
+set aWedgeHoleInnerRadius 38.77
+set aWedgeHoleOuterRadius 58.13
+set aWedgeHoleBottomInnerRadius 50.38
+
+# Cylinders from bottom to top
+plane t_plane $aWedgeHoleXPos $aWedgeHoleYPos 0
+pcylinder t_cyl1 t_plane $aWedgeHoleOuterRadius 10
+pcylinder t_cyl2 t_plane $aWedgeHoleBottomInnerRadius 10
+pcylinder t_cyl3 t_plane $aWedgeHoleInnerRadius [expr $aModelHeight - 30]
+pcylinder t_cyl4 t_plane $aWedgeHoleOuterRadius 10
+
+ttranslate t_cyl2 0 0 10
+ttranslate t_cyl3 0 0 20
+ttranslate t_cyl4 0 0 [expr $aModelHeight - 10]
+
+bfuse _cutCylindricShape t_cyl1 t_cyl2
+bfuse _cutCylindricShape _cutCylindricShape t_cyl3
+bfuse _cutCylindricShape _cutCylindricShape t_cyl4
+
+bcut _model _model _cutCylindricShape
+
+# Add a block on left side
+circle t_circle1 0 0 38.75
+circle t_circle2 [expr 38.75 + 9.3] [expr -57.35 + 9.3] 9.3
+circle t_circle3 [expr -38.75 - 9.3] [expr -57.35 + 9.3] 9.3
+
+lintan t_l t_circle1 t_circle2
+trim t_line12 t_l_2 0 48.050000000000004
+
+lintan t_l t_circle2 t_circle3
+trim t_line23 t_l_3 0 96.099999999999994
+
+lintan t_l t_circle3 t_circle1
+trim t_line31 t_l_4 0 48.050000000000004
+
+trim t_circle1 t_circle1 0 $my_pi
+trim t_circle2 t_circle2 $my_pi 4.7123889803846897
+trim t_circle3 t_circle3 4.7123889803846897 6.2831853071795862
+
+reverse t_circle1
+
+plane t_plane [expr $aPrismXOffset + 77.5] [expr $aPrismYOffset + $aPrismWidth] [expr $aPlatformHeight + 57.35] 0 1 0 -1 0 0
+
+to3d t_circle1 t_circle1 t_plane
+to3d t_circle2 t_circle2 t_plane
+to3d t_circle3 t_circle3 t_plane
+to3d t_line12 t_line12 t_plane
+to3d t_line23 t_line23 t_plane
+to3d t_line31 t_line31 t_plane
+
+mkedge t_e1 t_circle1
+mkedge t_e2 t_line31
+mkedge t_e3 t_circle3
+mkedge t_e4 t_line23
+mkedge t_e5 t_circle2
+mkedge t_e6 t_line12
+
+wire t_w t_e1 t_e2 t_e3 t_e4 t_e5 t_e6
+mkplane t_f t_w
+prism t_s t_f 0 $aCaveDepth 0
+
+bfuse _model _model t_s
+
+############# Analyse #############
+
+tcopy _model _copy
+trotate _copy $aWedgeHoleXPos $aWedgeHoleYPos 0 0 0 1 90
+bcommon res _model _copy
+checkshape res
+
+unifysamedom r res
+incmesh r 0.1
+trinfo r
+
+set info [trinfo r]
+regexp { +([-0-9.+eE]+) +triangles} $info full tr
+regexp { +([-0-9.+eE]+) +nodes} $info full nd
+regexp { +([-0-9.+eE]+) +nodes} $info full nd
+regexp {Maximal deflection +([-0-9.+eE]+)} $info full defl
+
+set expected_defl 0.04
+set tol_abs_defl 0.01
+set tol_rel_defl 0.01
+checkreal "Maximal deflection" ${defl} ${expected_defl} ${tol_abs_defl} ${tol_rel_defl}
+
+vinit
+vsetdispmode 1
+vdisplay r
+vfit
+set only_screen 1
diff --git a/tests/bugs/heal/bug26489_1 b/tests/bugs/heal/bug26489_1
new file mode 100755 (executable)
index 0000000..2f60af6
--- /dev/null
@@ -0,0 +1,33 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_p01usd.brep] poly
+
+mkplane ff poly
+unifysamedom result ff
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 4
+ EDGE      : 4
+ WIRE      : 1
+ FACE      : 1
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 0
+ SHAPE     : 10
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "result provided by the class ShapeUpgrade_UnifySameDomain"
+
+vinit
+vsetdispmode 1
+vclear
+vdisplay result
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/heal/bug26489_2 b/tests/bugs/heal/bug26489_2
new file mode 100755 (executable)
index 0000000..440392f
--- /dev/null
@@ -0,0 +1,32 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_p01usd.brep] poly
+
+unifysamedom result poly
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 4
+ EDGE      : 4
+ WIRE      : 1
+ FACE      : 0
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 0
+ SHAPE     : 9
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "result provided by the class ShapeUpgrade_UnifySameDomain"
+
+vinit
+vsetdispmode 1
+vclear
+vdisplay result
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/heal/bug26489_3 b/tests/bugs/heal/bug26489_3
new file mode 100755 (executable)
index 0000000..a50b143
--- /dev/null
@@ -0,0 +1,32 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_3cir.brep] ff
+
+unifysamedom result ff
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 1
+ EDGE      : 1
+ WIRE      : 1
+ FACE      : 1
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 0
+ SHAPE     : 4
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "result provided by the class ShapeUpgrade_UnifySameDomain"
+
+vinit
+vsetdispmode 1
+vclear
+vdisplay result
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/heal/bug26489_4 b/tests/bugs/heal/bug26489_4
new file mode 100755 (executable)
index 0000000..5d3af85
--- /dev/null
@@ -0,0 +1,50 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_r002.brep] b1
+
+unifysamedom result b1
+
+explode b1 f
+
+vinit
+vsetdispmode 1
+
+unifysamedomgen x1 b1_1
+vclear
+vdisplay x1
+vfit
+vdump ${imagedir}/${casename}_1.png
+
+unifysamedomgen x2 b1_2
+vclear
+vdisplay x2
+vfit
+vdump ${imagedir}/${casename}_2.png
+
+unifysamedomgen x3 b1_3
+vclear
+vdisplay x3
+vfit
+vdump ${imagedir}/${casename}_3.png
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 4
+ EDGE      : 4
+ WIRE      : 1
+ FACE      : 1
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 0
+ SHAPE     : 10
+"
+checknbshapes x1 -ref ${nbshapes_expected} -t -m "x1 result provided by the class ShapeUpgrade_UnifySameDomain"
+checknbshapes x2 -ref ${nbshapes_expected} -t -m "x2 result provided by the class ShapeUpgrade_UnifySameDomain"
+checknbshapes x3 -ref ${nbshapes_expected} -t -m "x3 result provided by the class ShapeUpgrade_UnifySameDomain"
diff --git a/tests/bugs/heal/bug26489_5 b/tests/bugs/heal/bug26489_5
new file mode 100755 (executable)
index 0000000..b7ae704
--- /dev/null
@@ -0,0 +1,34 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_r003.brep] b1
+
+explode b1 w
+
+unifysamedom result b1_1
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 4
+ EDGE      : 4
+ WIRE      : 1
+ FACE      : 0
+ SHELL     : 0
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 0
+ SHAPE     : 9
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "result provided by the class ShapeUpgrade_UnifySameDomain"
+
+vinit
+vsetdispmode 1
+vclear
+vdisplay result
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/heal/bug26489_6 b/tests/bugs/heal/bug26489_6
new file mode 100755 (executable)
index 0000000..8aaa65e
--- /dev/null
@@ -0,0 +1,32 @@
+puts "============"
+puts "OCC26489"
+puts "============"
+puts ""
+######################################################
+# The class ShapeUpgrade_UnifySameDomain provides the results that are wrong or difficult to explain.
+######################################################
+
+restore [locate_data_file bug26489_r002.brep] b1
+
+unifysamedom result b1
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 4
+ EDGE      : 4
+ WIRE      : 1
+ FACE      : 1
+ SHELL     : 1
+ SOLID     : 0
+ COMPSOLID : 0
+ COMPOUND  : 1
+ SHAPE     : 12
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "result provided by the class ShapeUpgrade_UnifySameDomain"
+
+vinit
+vsetdispmode 1
+vclear
+vdisplay result
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/heal/bug26572 b/tests/bugs/heal/bug26572
new file mode 100644 (file)
index 0000000..65d21dd
--- /dev/null
@@ -0,0 +1,36 @@
+puts "========"
+puts "OCC26572"
+puts "========"
+puts ""
+#######################################################################
+# Error in ShapeUpgrade_UnifySameDomain algorithm: can not merge two edges in customer's shape
+#######################################################################
+
+restore [locate_data_file bug26572_issue_12_new_input.brep] s
+
+nbshapes s -t
+
+smallview
+donly s
+fit
+xwd ${imagedir}/${casename}_1.png
+
+unifysamedom res s
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 48
+ EDGE      : 72
+ WIRE      : 28
+ FACE      : 27
+ SHELL     : 1
+ SOLID     : 1
+ COMPSOLID : 0
+ COMPOUND  : 1
+ SHAPE     : 178
+"
+checknbshapes res -ref ${nbshapes_expected} -t -m "Shape Upgrade"
+
+donly res
+
+xwd ${imagedir}/${casename}_2.png
diff --git a/tests/bugs/heal/bug26635 b/tests/bugs/heal/bug26635
new file mode 100644 (file)
index 0000000..a4db759
--- /dev/null
@@ -0,0 +1,25 @@
+puts "========"
+puts "OCC26635"
+puts "========"
+puts ""
+########################################
+# UnifySameDomain loses internal edges
+########################################
+
+restore [locate_data_file OCC26635_t0.brep] t0
+restore [locate_data_file OCC26635_t1.brep] t1
+restore [locate_data_file OCC26635_t2.brep] t2
+
+bclear
+baddobjects t0 t1
+baddtools t2
+bfillds
+bbop r 1
+
+unifysamedom ru r
+set bug_info [bopargcheck ru #F]
+
+if {$bug_info != "Shape(s) seem(s) to be valid for BOP.\n"} {
+  puts "ERROR: OCC26635 is reproduced."
+}
+