0023367: New functionality restoring the middle path of pipe-like shape
authorjgv <jgv@opencascade.com>
Tue, 16 Oct 2012 09:12:36 +0000 (13:12 +0400)
committerjgv <jgv@opencascade.com>
Tue, 16 Oct 2012 09:12:36 +0000 (13:12 +0400)
Version 2
Small correction
Adding test cases

14 files changed:
src/BRepOffsetAPI/BRepOffsetAPI.cdl
src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cdl [new file with mode: 0644]
src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cxx [new file with mode: 0644]
src/BRepTest/BRepTest_SweepCommands.cxx
src/SWDRAW/SWDRAW_ShapeUpgrade.cxx
src/ShapeUpgrade/ShapeUpgrade.cdl
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cdl [new file with mode: 0644]
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx [new file with mode: 0644]
tests/bugs/modalg/bug23367_1 [new file with mode: 0755]
tests/bugs/modalg/bug23367_2 [new file with mode: 0755]
tests/bugs/modalg/bug23367_3 [new file with mode: 0755]
tests/bugs/modalg/bug23367_4 [new file with mode: 0755]
tests/bugs/modalg/bug23367_5 [new file with mode: 0755]
tests/bugs/modalg/bug23367_6 [new file with mode: 0755]

index 71e16c8..dbdadcd 100755 (executable)
@@ -98,6 +98,9 @@ is
     class ThruSections;              ---  inherits  MakeShape  from  BRepBuilderAPI
 
     class NormalProjection ;  ---  inherits  MakeShape  from  BRepBuilderAPI
+
+    class MiddlePath;        ---  inherits  MakeShape  from  BRepBuilderAPI
+    
     -- 
     --   Plate
     --     
diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cdl
new file mode 100644 (file)
index 0000000..ea0b74e
--- /dev/null
@@ -0,0 +1,53 @@
+-- File:      BRepOffsetAPI_MiddlePath.cdl
+-- Created:   06.08.12 15:56:30
+-- Author:    jgv@ROLEX
+---Copyright: Open CASCADE 2012
+
+class MiddlePath from BRepOffsetAPI inherits MakeShape from BRepBuilderAPI
+
+       ---Purpose: Describes functions to build a middle path of a
+       --          pipe-like shape
+
+uses
+
+    Shape from TopoDS,
+    Wire  from TopoDS,
+    Edge  from TopoDS,
+    Face  from TopoDS,
+    MapOfShape from TopTools,
+    SequenceOfSequenceOfShape from BRepOffsetAPI
+    
+is
+    --Create(aShape    : Shape from TopoDS;
+       --   StartWire : Wire from TopoDS)
+    --returns MiddlePath from BRepOffsetAPI;
+    
+    --Create(aShape    : Shape from TopoDS;
+       --   StartEdge : Edge from TopoDS)
+    --returns MiddlePath from BRepOffsetAPI;
+    
+    Create(aShape     : Shape from TopoDS;
+          StartShape : Shape from TopoDS;
+          EndShape   : Shape from TopoDS)
+    ---Purpose: General constructor.
+    --          StartShape and EndShape may be
+    --          a wire or a face
+    returns MiddlePath from BRepOffsetAPI;
+
+    Build(me: in out)
+    is redefined;
+
+fields
+    
+    myInitialShape : Shape from TopoDS;
+    myStartWire    : Wire  from TopoDS;
+    myEndWire      : Wire  from TopoDS;
+    myClosedSection  : Boolean from Standard;
+    myClosedRing     : Boolean from Standard;
+    
+    myStartWireEdges : MapOfShape from TopTools;
+    myEndWireEdges   : MapOfShape from TopTools;
+    
+    myPaths        : SequenceOfSequenceOfShape from BRepOffsetAPI;
+    
+end MiddlePath;
diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_MiddlePath.cxx
new file mode 100644 (file)
index 0000000..4df8ef5
--- /dev/null
@@ -0,0 +1,962 @@
+// File:      BRepOffsetAPI_MiddlePath.cxx
+// Created:   06.08.12 16:53:16
+// Author:    jgv@ROLEX
+// Copyright: Open CASCADE 2012
+
+#include <BRepOffsetAPI_MiddlePath.ixx>
+#include <BRepOffsetAPI_MiddlePath.hxx>
+
+#include <ShapeUpgrade_UnifySameDomain.hxx>
+
+#include <gp_Lin.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_BezierCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <BRep_Tool.hxx>
+#include <gce_MakeLin.hxx>
+
+#include <BRepLib_MakeWire.hxx>
+
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopExp.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopoDS.hxx>
+#include <BRepTools.hxx>
+#include <TopTools_SequenceOfShape.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <BRep_Builder.hxx>
+#include <Precision.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_Line.hxx>
+#include <GCE2d_MakeLine.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <BRepLib.hxx>
+#include <GeomAbs_CurveType.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <TopTools_Array1OfShape.hxx>
+#include <BRepLib_MakeFace.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColgp_HArray1OfPnt.hxx>
+#include <TColgp_Array1OfVec.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
+#include <GProp_GProps.hxx>
+#include <BRepGProp.hxx>
+#include <Geom_Circle.hxx>
+#include <gp_Circ.hxx>
+#include <GC_MakeCircle.hxx>
+#include <TColgp_SequenceOfPnt.hxx>
+#include <GeomLib.hxx>
+#include <GeomAPI_Interpolate.hxx>
+
+static Standard_Boolean IsClosed(const TopoDS_Wire& aWire)
+{
+  TopoDS_Vertex V1, V2;
+  TopExp::Vertices(aWire, V1, V2);
+  return (V1.IsSame(V2));
+}
+
+static Standard_Boolean IsLinear(const TopoDS_Edge& anEdge,
+                                 gp_Lin& aLine)
+{
+  Standard_Real fpar, lpar;
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+  if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
+    aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
+
+  gp_Pnt Pnt1, Pnt2;
+  if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)))
+  {
+    aLine = ((Handle(Geom_Line)&) aCurve)->Lin();
+    return Standard_True;
+  }
+  else if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
+  {
+    Handle(Geom_BezierCurve) theBezier = (Handle(Geom_BezierCurve)&) aCurve;
+    if (theBezier->NbPoles() == 2)
+    {
+      Pnt1 = theBezier->Pole(1);
+      Pnt2 = theBezier->Pole(2);
+      aLine = gce_MakeLin(Pnt1, Pnt2);
+      return Standard_True;
+    }
+  }
+  else if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
+  {
+    Handle(Geom_BSplineCurve) theBSpline = (Handle(Geom_BSplineCurve)&) aCurve;
+    if (theBSpline->NbPoles() == 2)
+    {
+      Pnt1 = theBSpline->Pole(1);
+      Pnt2 = theBSpline->Pole(2);
+      aLine = gce_MakeLin(Pnt1, Pnt2);
+      return Standard_True;
+    }
+  }
+
+  return Standard_False;
+}
+
+static GeomAbs_CurveType TypeOfEdge(const TopoDS_Edge& anEdge)
+{
+  gp_Lin aLin;
+  if (IsLinear(anEdge, aLin))
+    return GeomAbs_Line;
+
+  BRepAdaptor_Curve BAcurve(anEdge);
+  return BAcurve.GetType();
+}
+
+static gp_Vec TangentOfEdge(const TopoDS_Shape& aShape,
+                            const Standard_Boolean OnFirst)
+{
+  TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+  TopAbs_Orientation anOr = anEdge.Orientation();
+  
+  Standard_Real fpar, lpar;
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+  Standard_Real thePar;
+  if (OnFirst)
+    thePar = (anOr == TopAbs_FORWARD)? fpar : lpar;
+  else
+    thePar = (anOr == TopAbs_FORWARD)? lpar : fpar;
+
+  gp_Pnt thePoint;
+  gp_Vec theTangent;
+  aCurve->D1(thePar, thePoint, theTangent);
+  if (anOr == TopAbs_REVERSED)
+    theTangent.Reverse();
+
+  return theTangent;
+}
+
+
+static Standard_Boolean IsValidEdge(const TopoDS_Edge& theEdge,
+                                    const TopoDS_Face& theFace)
+{
+  TopoDS_Vertex V1, V2;
+  TopExp::Vertices(theEdge, V1, V2);
+
+  Standard_Real Tol = Precision::Confusion();
+  Standard_Integer i;
+  
+  TopExp_Explorer Explo(theFace, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    const TopoDS_Shape& anEdge = Explo.Current();
+    BRepExtrema_DistShapeShape DistMini(theEdge, anEdge);
+    if (DistMini.Value() <= Tol)
+    {
+      for (i = 1; i <= DistMini.NbSolution(); i++)
+      {
+        BRepExtrema_SupportType theType = DistMini.SupportTypeShape2(i);
+        if (theType == BRepExtrema_IsOnEdge)
+          return Standard_False;
+        //theType is "IsVertex"
+        TopoDS_Shape aVertex = DistMini.SupportOnShape2(i);
+        if (!(aVertex.IsSame(V1) || aVertex.IsSame(V2)))
+          return Standard_False;
+      }
+    }
+  }
+
+  return Standard_True;
+}
+
+/*
+//=======================================================================
+//function : BRepOffsetAPI_MiddlePath
+//purpose  : Constructor
+//=======================================================================
+
+BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
+                                                   const TopoDS_Wire&  StartWire)
+{
+  myInitialShape = aShape;
+  myStartWire    = StartWire;
+  myClosedSection = myStartWire.Closed();
+}
+
+//=======================================================================
+//function : BRepOffsetAPI_MiddlePath
+//purpose  : Constructor
+//=======================================================================
+
+BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
+                                                   const TopoDS_Edge&  StartEdge)
+{
+  myInitialShape = aShape;
+
+  BRepLib_MakeWire MW(StartEdge);
+  
+  //BB.Add(myStartWire, StartEdge);
+
+  TopTools_IndexedDataMapOfShapeListOfShape EFmap;
+  TopTools_IndexedDataMapOfShapeListOfShape VEmap;
+  TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE,   TopAbs_FACE, EFmap);
+  TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
+  
+  //Standard_Boolean Start = Standard_True;
+  //if (Start)
+  //{
+  //TopExp::Vertices(CurEdge, V1, V2);
+  //  StartVertex = V1;
+  //  CurVertex   = V2;
+  //  if (VEmap(CurVertex).Extent() == 2) //end: two free edges
+  //  {
+  //    StartVertex = V2;
+  //    CurVertex   = V1;
+  //    if (VEmap(CurVertex).Extent() == 2) //end: two free edges
+  //      break;
+  //  }
+  //  Start = Standard_False;
+  //  continue;
+  //}
+
+  TopoDS_Vertex StartVertex, CurVertex, V1, V2;
+  TopExp::Vertices(StartEdge, StartVertex, CurVertex);
+  TopoDS_Edge CurEdge = StartEdge;
+  Standard_Integer i;
+  for (i = 1; i <= 2; i++)
+  {
+    for (;;)
+    {
+      const TopTools_ListOfShape& LE = VEmap.FindFromKey(CurVertex);
+      if (LE.Extent() == 2) //end: two free edges or one closed free edge
+        break;
+      TopTools_ListIteratorOfListOfShape itl(LE);
+      TopoDS_Edge anEdge;
+      for (; itl.More(); itl.Next())
+      {
+        anEdge = TopoDS::Edge(itl.Value());
+        if (anEdge.IsSame(CurEdge))
+          continue;
+        if (EFmap.FindFromKey(anEdge).Extent() == 1) //another free edge found
+          break;
+      }
+      //BB.Add(myStartWire, anEdge);
+      MW.Add(anEdge);
+      TopExp::Vertices(anEdge, V1, V2);
+      CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
+      CurEdge = anEdge;
+      if (CurVertex.IsSame(StartVertex))
+        break;
+    }
+    if (CurVertex.IsSame(StartVertex))
+      break;
+    CurVertex = StartVertex;
+    CurEdge = StartEdge;
+  }
+  
+  myStartWire = MW.Wire();
+  myClosedSection = myStartWire.Closed();
+}
+*/
+
+//=======================================================================
+//function : BRepOffsetAPI_MiddlePath
+//purpose  : Constructor
+//=======================================================================
+
+BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
+                                                   const TopoDS_Shape& StartShape,
+                                                   const TopoDS_Shape& EndShape)
+{
+  ShapeUpgrade_UnifySameDomain Unifier(aShape);
+  Unifier.Build();
+  myInitialShape = Unifier.Shape();
+
+  TopoDS_Wire aStartWire, anEndWire;
+  if (StartShape.ShapeType() == TopAbs_FACE)
+  {
+    const TopoDS_Face& StartFace = TopoDS::Face(StartShape);
+    aStartWire = BRepTools::OuterWire(StartFace);
+  }
+  else
+    aStartWire = TopoDS::Wire(StartShape);
+  
+  if (EndShape.ShapeType() == TopAbs_FACE)
+  {
+    const TopoDS_Face& EndFace = TopoDS::Face(EndShape);
+    anEndWire = BRepTools::OuterWire(EndFace);
+  }
+  else
+    anEndWire = TopoDS::Wire(EndShape);
+
+  BRepLib_MakeWire MWstart;
+  //TopTools_MapOfShape MapEdges;
+  BRepTools_WireExplorer wexp(aStartWire);
+  for (; wexp.More(); wexp.Next())
+  {
+    TopoDS_Shape anEdge = wexp.Current();
+    TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
+    if (!NewEdge.IsNull())
+      MWstart.Add(TopoDS::Edge(NewEdge));
+  }
+  myStartWire = MWstart.Wire();
+
+  BRepLib_MakeWire MWend;
+  //MapEdges.Clear();
+  for (wexp.Init(anEndWire); wexp.More(); wexp.Next())
+  {
+    TopoDS_Shape anEdge = wexp.Current();
+    TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
+    if (!NewEdge.IsNull())
+      MWend.Add(TopoDS::Edge(NewEdge));
+  }
+  myEndWire = MWend.Wire();
+
+  myClosedSection = myStartWire.Closed();
+  myClosedRing    = myStartWire.IsSame(myEndWire);
+}
+
+//=======================================================================
+//function : Build
+//purpose  : 
+//=======================================================================
+
+void BRepOffsetAPI_MiddlePath::Build()
+{
+  TopTools_ListIteratorOfListOfShape itl;
+  
+  TopTools_SequenceOfShape StartVertices;
+  TopTools_MapOfShape EndVertices;
+  TopTools_MapOfShape EndEdges;
+  BRepOffsetAPI_SequenceOfSequenceOfShape SectionsEdges;
+  
+  BRepTools_WireExplorer wexp(myStartWire);
+  TopTools_SequenceOfShape EdgeSeq;
+  for (; wexp.More(); wexp.Next())
+  {
+    StartVertices.Append(wexp.CurrentVertex());
+    EdgeSeq.Append(wexp.Current());
+  }
+  if (!myClosedSection)
+    StartVertices.Append(wexp.CurrentVertex());
+  SectionsEdges.Append(EdgeSeq);
+  
+  for (wexp.Init(myEndWire); wexp.More(); wexp.Next())
+  {
+    EndVertices.Add(wexp.CurrentVertex());
+    EndEdges.Add(wexp.Current());
+  }
+  if (!myClosedSection)
+    EndVertices.Add(wexp.CurrentVertex());
+  
+
+  TopoDS_Iterator itw(myStartWire);
+  for (; itw.More(); itw.Next())
+    myStartWireEdges.Add(itw.Value());
+  for (itw.Initialize(myEndWire); itw.More(); itw.Next())
+    myEndWireEdges.Add(itw.Value());
+
+  TopTools_IndexedDataMapOfShapeListOfShape VEmap;
+  TopTools_IndexedDataMapOfShapeListOfShape EFmap;
+  TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
+  TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE,   TopAbs_FACE, EFmap);
+
+  TopTools_MapOfShape CurVertices;
+  
+  Standard_Integer i, j, k;
+  TopoDS_Edge anEdge, theEdge;
+  TopoDS_Vertex V1, V2, NextVertex;
+  //Initialization of <myPaths>
+  for (i = 1; i <= StartVertices.Length(); i++)
+  {
+    TopTools_SequenceOfShape Edges;
+    const TopTools_ListOfShape& LE = VEmap.FindFromKey(StartVertices(i));
+    for (itl.Initialize(LE); itl.More(); itl.Next())
+    {
+      anEdge = TopoDS::Edge(itl.Value());
+      if (!myStartWireEdges.Contains(anEdge))
+      {
+        TopExp::Vertices(anEdge, V1, V2, Standard_True);
+        if (V1.IsSame(StartVertices(i)))
+          CurVertices.Add(V2);
+        else
+        {
+          anEdge.Reverse();
+          CurVertices.Add(V1);
+        }
+        Edges.Append(anEdge);
+        break;
+      }
+    }
+    myPaths.Append(Edges);
+  }
+
+  //Filling of "myPaths"
+  //TopTools_MapOfShape StartFacesMap;
+  TopTools_ListOfShape NextVertices;
+  for (;;)
+  {
+    /*
+    StartFacesMap.Clear();
+    for (i = 1; i <= myPaths.Length(); i++)
+    {
+      const TopoDS_Shape& LastEdge = myPaths(i).Last();
+      const TopTools_ListOfShape& LF = EFmap(LastEdge);
+      for (itl.Initialize(LF); itl.More(); itl.Next())
+        StartFacesMap.Add(itl.Value();
+    }
+    */
+    //TopTools_SequenceOfShape NewEdges;
+    for (i = 1; i <= myPaths.Length(); i++)
+    {
+      theEdge = TopoDS::Edge(myPaths(i).Last());
+      TopoDS_Vertex theVertex = TopExp::LastVertex(theEdge, Standard_True);
+      if (EndVertices.Contains(theVertex))
+        continue;
+      const TopTools_ListOfShape& LE = VEmap.FindFromKey(theVertex);
+      Standard_Boolean NextEdgeFound = Standard_False;
+      for (itl.Initialize(LE); itl.More(); itl.Next())
+      {
+        anEdge = TopoDS::Edge(itl.Value());
+        if (anEdge.IsSame(theEdge))
+          continue;
+        TopExp::Vertices(anEdge, V1, V2, Standard_True);
+        if (V1.IsSame(theVertex))
+          NextVertex = V2;
+        else
+        {
+          anEdge.Reverse();
+          NextVertex = V1;
+        }
+        if (!CurVertices.Contains(NextVertex))
+        {
+          NextEdgeFound = Standard_True;
+          break;
+        }
+      }
+      if (NextEdgeFound)
+      {
+        myPaths(i).Append(anEdge);
+        NextVertices.Append(NextVertex);
+      }
+    }
+    if (NextVertices.IsEmpty())
+      break;
+    for (itl.Initialize(NextVertices); itl.More(); itl.Next())
+      CurVertices.Add(itl.Value());
+    NextVertices.Clear();
+  }
+
+  //Building of set of sections
+  Standard_Integer NbE = EdgeSeq.Length();
+  Standard_Integer NbVer = myPaths.Length();
+  if (myClosedSection)
+    NbVer++;
+  i = 1;
+  for (;;)
+  {
+    for (j = 1; j <= EdgeSeq.Length(); j++)
+      EdgeSeq(j).Nullify();
+
+    Standard_Boolean ToInsertVertex = Standard_False;
+    
+    for (j = 2; j <= NbVer; j++)
+    {
+      if (!EdgeSeq(j-1).IsNull())
+        continue;
+      
+      if (ToInsertVertex)
+      {
+        if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
+        {
+          TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i));
+          TopoDS_Shape fver = TopExp::FirstVertex(aE1, Standard_True);
+          myPaths(j-1).InsertBefore(i, fver);
+        }
+        if (myPaths((j<=NbE)? j : 1)(i).ShapeType() == TopAbs_EDGE)
+        {
+          TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i));
+          TopoDS_Shape fver = TopExp::FirstVertex(aE2, Standard_True);
+          myPaths((j<=NbE)? j : 1).InsertBefore(i, fver);
+        }
+        ToInsertVertex = Standard_False;
+      }
+      
+      TopoDS_Edge E1, E2;
+      if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
+        E1 = TopoDS::Edge(myPaths(j-1)(i));
+      if (myPaths((j<=NbE)? j : 1)(i).ShapeType() == TopAbs_EDGE)
+        E2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i));
+      TopoDS_Edge E12 = TopoDS::Edge(SectionsEdges(i)(j-1));
+      
+      //TopoDS_Vertex PrevVertex = TopoDS::Vertex(VerSeq(j-1));
+      //TopoDS_Vertex CurVertex  = TopoDS::Vertex(VerSeq(j));
+      TopoDS_Vertex PrevVertex = (E1.IsNull())? TopoDS::Vertex(myPaths(j-1)(i))
+        : TopExp::LastVertex(E1, Standard_True);
+      TopoDS_Vertex CurVertex = (E2.IsNull())? TopoDS::Vertex(myPaths((j<=NbE)? j : 1)(i))
+        : TopExp::LastVertex(E2, Standard_True);
+      
+      TopoDS_Edge ProperEdge;
+      const TopTools_ListOfShape& LE = VEmap.FindFromKey(PrevVertex);
+      //Temporary
+      Standard_Integer LenList = LE.Extent();
+      ///////////
+      for (itl.Initialize(LE); itl.More(); itl.Next())
+      {
+        anEdge = TopoDS::Edge(itl.Value());
+        TopExp::Vertices(anEdge, V1, V2);
+        if ((V1.IsSame(PrevVertex) && V2.IsSame(CurVertex) ||
+             V1.IsSame(CurVertex) && V2.IsSame(PrevVertex)) &&
+            !anEdge.IsSame(E1))
+        {
+          ProperEdge = anEdge;
+          break;
+        }
+      }
+      
+      if ((myPaths(j-1)(i)).ShapeType() == TopAbs_VERTEX &&
+          (myPaths((j<=NbE)? j : 1)(i)).ShapeType() == TopAbs_VERTEX)
+      {
+        EdgeSeq(j-1) = ProperEdge;
+        continue;
+      }
+
+      TopoDS_Vertex PrevPrevVer = (E1.IsNull())? PrevVertex
+        : TopExp::FirstVertex(E1, Standard_True);
+      TopoDS_Vertex PrevCurVer  = (E2.IsNull())? CurVertex
+        : TopExp::FirstVertex(E2, Standard_True);
+      if (ProperEdge.IsNull()) //no connection between these two vertices
+      {
+        //ToInsertVertex = Standard_False;
+        const TopoDS_Shape& EE1 = (E1.IsNull())?
+          myPaths(j-1)(i-1) : E1;
+        const TopoDS_Shape& EE2 = (E2.IsNull())?
+          myPaths((j<=NbE)? j : 1)(i-1) : E2;
+        const TopTools_ListOfShape& LF = EFmap.FindFromKey(EE1);
+        TopoDS_Face theFace;
+        for (itl.Initialize(LF); itl.More(); itl.Next())
+        {
+          const TopoDS_Shape& aFace = itl.Value();
+          TopExp_Explorer Explo(aFace, TopAbs_EDGE);
+          for (; Explo.More(); Explo.Next())
+          {
+            if (EE2.IsSame(Explo.Current()))
+            {
+              const TopTools_ListOfShape& LFsec = EFmap.FindFromKey(E12);
+              TopTools_ListIteratorOfListOfShape itlsec(LFsec);
+              for (; itlsec.More(); itlsec.Next())
+                if (aFace.IsSame(itlsec.Value()))
+                {
+                  theFace = TopoDS::Face(aFace);
+                  break;
+                }
+              if (!theFace.IsNull())
+                break;
+            }
+          }
+          if (!theFace.IsNull())
+            break;
+        }
+        TopTools_ListOfShape ListOneFace;
+        ListOneFace.Append(theFace);
+
+        if (E1.IsNull() || E2.IsNull())
+        {
+          if (E1.IsNull())
+            E1 = TopoDS::Edge(myPaths(j-1)(i-1));
+          if (E2.IsNull())
+            E2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i-1));
+          Standard_Real fpar1, lpar1, fpar2, lpar2;
+          Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
+          Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
+          Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
+          if (E1.Orientation() == TopAbs_FORWARD)
+          { FirstPar1 = fpar1; LastPar1 = lpar1; }
+          else
+          { FirstPar1 = lpar1; LastPar1 = fpar1; }
+          if (E2.Orientation() == TopAbs_FORWARD)
+          { FirstPar2 = fpar2; LastPar2 = lpar2; }
+          else
+          { FirstPar2 = lpar2; LastPar2 = fpar2; }
+          gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
+          gp_Pnt2d LastPnt2d  = PCurve2->Value(LastPar2);
+          Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
+          Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
+          Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
+          TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
+                                                 PrevVertex, CurVertex,
+                                                 0., len_ne);
+          BRepLib::BuildCurve3d(NewEdge);
+          EdgeSeq(j-1) = NewEdge;
+          EFmap.Add(NewEdge, ListOneFace);
+        }
+        else //E1 is edge
+        {
+          //Extract points 2d
+          Standard_Real fpar1, lpar1, fpar2, lpar2;
+          Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
+          Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
+          Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
+          if (E1.Orientation() == TopAbs_FORWARD)
+          { FirstPar1 = fpar1; LastPar1 = lpar1; }
+          else
+          { FirstPar1 = lpar1; LastPar1 = fpar1; }
+          if (E2.Orientation() == TopAbs_FORWARD)
+          { FirstPar2 = fpar2; LastPar2 = lpar2; }
+          else
+          { FirstPar2 = lpar2; LastPar2 = fpar2; }
+          gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
+          gp_Pnt2d LastPnt2d  = PCurve2->Value(LastPar2);
+          Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
+          Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
+          Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
+          TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
+                                                 PrevVertex, CurVertex,
+                                                 0., len_ne);
+          BRepLib::BuildCurve3d(NewEdge);
+          gp_Pnt2d PrevFirstPnt2d = PCurve1->Value(FirstPar1);
+          gp_Pnt2d PrevLastPnt2d  = PCurve2->Value(FirstPar2);
+          Handle(Geom2d_Line) Line1 = GCE2d_MakeLine(PrevFirstPnt2d, LastPnt2d);
+          Handle(Geom2d_Line) Line2 = GCE2d_MakeLine(FirstPnt2d, PrevLastPnt2d);
+          Standard_Real len_ne1 = PrevFirstPnt2d.Distance(LastPnt2d);
+          TopoDS_Edge NewEdge1 = BRepLib_MakeEdge(Line1, theSurf,
+                                                  PrevPrevVer, CurVertex,
+                                                  0., len_ne1);
+          BRepLib::BuildCurve3d(NewEdge1);
+          Standard_Real len_ne2 = FirstPnt2d.Distance(PrevLastPnt2d);
+          TopoDS_Edge NewEdge2 = BRepLib_MakeEdge(Line2, theSurf,
+                                                  PrevVertex, PrevCurVer,
+                                                  0., len_ne2);
+          BRepLib::BuildCurve3d(NewEdge2);
+          Standard_Boolean good_ne  = IsValidEdge(NewEdge, theFace);
+          Standard_Boolean good_ne1 = IsValidEdge(NewEdge1, theFace);
+          Standard_Boolean good_ne2 = IsValidEdge(NewEdge2, theFace);
+
+          GeomAbs_CurveType type_E1 = TypeOfEdge(E1);
+          GeomAbs_CurveType type_E2 = TypeOfEdge(E2);
+
+          Standard_Integer ChooseEdge = 0;
+          
+          if (!good_ne || type_E1 != type_E2)
+          {
+            if (type_E1 == type_E2) //!good_ne
+            {
+              if (good_ne1)
+                ChooseEdge = 1;
+              else
+                ChooseEdge = 2;
+            }
+            else //types are different
+            {
+              if (type_E1 == GeomAbs_Line)
+                ChooseEdge = 1;
+              else if (type_E2 == GeomAbs_Line)
+                ChooseEdge = 2;
+              else //to be developed later...
+              {}
+            }
+          }
+          
+          if (ChooseEdge == 0)
+          {
+            EdgeSeq(j-1) = NewEdge;
+            EFmap.Add(NewEdge, ListOneFace);
+          }
+          else if (ChooseEdge == 1)
+          {
+            EdgeSeq(j-1) = NewEdge1;
+            EFmap.Add(NewEdge1, ListOneFace);
+            for (k = 1; k < j-1; k++)
+              EdgeSeq(k).Nullify();
+            for (k = 1; k <= j-1; k++)
+            {
+              TopoDS_Edge aLastEdge = TopoDS::Edge(myPaths(k)(i));
+              TopoDS_Shape VertexAsEdge = TopExp::FirstVertex(aLastEdge, Standard_True);
+              myPaths(k).InsertBefore(i, VertexAsEdge);
+            }
+            j = 1;
+          }
+          else if (ChooseEdge == 2)
+          {
+            EdgeSeq(j-1) = NewEdge2;
+            EFmap.Add(NewEdge2, ListOneFace);
+            ToInsertVertex = Standard_True;
+          }
+        } //else //E1 is edge
+      } //if (ProperEdge.IsNull())
+      else //connecting edge exists
+      {
+        /*
+        if (ToInsertVertex)
+        {
+          myPaths(j-1).InsertBefore(i, PrevPrevVer);
+          myPaths((j<=NbE)? j : 1).InsertBefore(i, PrevCurVer);
+          EdgeSeq(j-1) = E12;
+        }
+        else
+        */
+          EdgeSeq(j-1) = ProperEdge;
+      }
+    } //for (j = 2; j <= NbVer; j++)
+    SectionsEdges.Append(EdgeSeq);
+
+    //check for exit from for(;;)
+    Standard_Integer NbEndEdges = 0;
+    for (j = 1; j <= EdgeSeq.Length(); j++)
+      if (EndEdges.Contains(EdgeSeq(j)))
+        NbEndEdges++;
+    if (NbEndEdges == NbE)
+      break;
+    
+    i++;
+  } //for (;;)
+  
+
+  //final phase: building of middle path
+  Standard_Integer NbSecFaces = SectionsEdges.Length();
+  TopTools_Array1OfShape SecFaces(1, NbSecFaces);
+  for (i = 1; i <= NbSecFaces; i++)
+  {
+    BRepLib_MakeWire MW;
+    for (j = 1; j <= NbE; j++)
+    {
+      anEdge = TopoDS::Edge(SectionsEdges(i)(j));
+      MW.Add(anEdge);
+    }
+    if (!myClosedSection)
+    {
+      TopExp::Vertices(MW.Wire(), V1, V2);
+      anEdge = BRepLib_MakeEdge(V2, V1);
+      MW.Add(anEdge);
+    }
+    TopoDS_Wire aWire = MW.Wire();
+    BRepLib_MakeFace MF(aWire, Standard_True); //Only plane
+    if (MF.IsDone())
+      SecFaces(i) = MF.Face();
+    else
+      SecFaces(i) = aWire;
+  }
+
+  TColgp_Array1OfPnt Centers(1, NbSecFaces);
+  for (i = 1; i <= NbSecFaces; i++)
+  {
+    GProp_GProps Properties;
+    if (SecFaces(i).ShapeType() == TopAbs_FACE)
+      BRepGProp::SurfaceProperties(SecFaces(i), Properties);
+    else //wire
+      BRepGProp::LinearProperties(SecFaces(i), Properties);
+      
+    Centers(i) = Properties.CentreOfMass();
+  }
+
+  TopTools_Array1OfShape MidEdges(1, NbSecFaces-1);
+  Standard_Real LinTol = 1.e-5;
+  Standard_Real AngTol = 1.e-7;
+  gp_Pnt Pnt1, Pnt2;
+  for (i = 1; i < NbSecFaces; i++)
+  {
+    GeomAbs_CurveType TypeOfMidEdge = GeomAbs_OtherCurve;
+    for (j = 1; j <= myPaths.Length(); j++)
+    {
+      const TopoDS_Shape& aShape = myPaths(j)(i);
+      if (aShape.ShapeType() == TopAbs_VERTEX)
+      {
+        TypeOfMidEdge = GeomAbs_OtherCurve;
+        break;
+      }
+      anEdge = TopoDS::Edge(aShape);
+      GeomAbs_CurveType aType = TypeOfEdge(anEdge);
+      if (j == 1)
+        TypeOfMidEdge = aType;
+      else
+      {
+        if (aType != TypeOfMidEdge)
+        {
+          TypeOfMidEdge = GeomAbs_OtherCurve;
+          break;
+        }
+      }
+    }
+    if (TypeOfMidEdge == GeomAbs_Line)
+      MidEdges(i) = BRepLib_MakeEdge(Centers(i), Centers(i+1));
+    else if (TypeOfMidEdge == GeomAbs_Circle)
+    {
+      gp_Ax1 theAxis;
+      gp_Dir theDir1, theDir2;
+      Standard_Real theAngle;
+      Standard_Boolean SimilarArcs = Standard_True;
+      for (j = 1; j <= myPaths.Length(); j++)
+      {
+        anEdge = TopoDS::Edge(myPaths(j)(i));
+        Standard_Real fpar, lpar;
+        Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+        if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
+          aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
+        Pnt1 = aCurve->Value(fpar);
+        Pnt2 = aCurve->Value(lpar);
+        Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve);
+        gp_Circ aCirc = aCircle->Circ();
+        if (j == 1)
+        {
+          theAxis = aCirc.Axis();
+          theDir1 = gp_Vec(aCirc.Location(), Pnt1);
+          theDir2 = gp_Vec(aCirc.Location(), Pnt2);
+          theAngle = lpar - fpar;
+        }
+        else
+        {
+          gp_Ax1 anAxis = aCirc.Axis();
+          gp_Lin aLin(anAxis);
+          if (!aLin.Contains(theAxis.Location(), LinTol) ||
+              !anAxis.IsParallel(theAxis, AngTol))
+          {
+            SimilarArcs = Standard_False;
+            break;
+          }
+          gp_Dir aDir1 = gp_Vec(aCirc.Location(), Pnt1);
+          gp_Dir aDir2 = gp_Vec(aCirc.Location(), Pnt2);
+          if (!(aDir1.IsEqual(theDir1, AngTol) && aDir2.IsEqual(theDir2, AngTol) ||
+                aDir1.IsEqual(theDir2, AngTol) && aDir2.IsEqual(theDir1, AngTol)))
+          {
+            SimilarArcs = Standard_False;
+            break;
+          }
+        }
+      }
+      if (SimilarArcs)
+      {
+        gp_XYZ AxisLoc = theAxis.Location().XYZ();
+        gp_XYZ AxisDir = theAxis.Direction().XYZ();
+        Standard_Real Parameter = (Centers(i).XYZ() - AxisLoc) * AxisDir;
+        gp_Pnt theCenterOfCirc(AxisLoc + Parameter*AxisDir);
+        
+        gp_Vec Vec1(theCenterOfCirc, Centers(i));
+        gp_Vec Vec2(theCenterOfCirc, Centers(i+1));
+        /*
+        gp_Dir VecProd = Vec1 ^ Vec2;
+        if (theAxis.Direction() * VecProd < 0.)
+          theAxis.Reverse();
+        */
+        
+        Standard_Real anAngle = Vec1.AngleWithRef(Vec2, theAxis.Direction());
+        if (anAngle < 0.)
+          anAngle += 2.*M_PI;
+        if (Abs(anAngle - theAngle) > AngTol)
+          theAxis.Reverse();
+        gp_Ax2 theAx2(theCenterOfCirc, theAxis.Direction(), Vec1);
+        Handle(Geom_Circle) theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
+        MidEdges(i) = BRepLib_MakeEdge(theCircle, 0., theAngle);
+      }
+    }
+  }
+
+  //Build missed edges
+  for (i = 1; i < NbSecFaces; i++)
+  {
+    if (MidEdges(i).IsNull())
+    {
+      for (j = i+1; j < NbSecFaces; j++)
+      {
+        if (!MidEdges(j).IsNull())
+          break;
+      }
+      //from i to j-1 all edges are null
+      Handle(TColgp_HArray1OfPnt) thePoints = new TColgp_HArray1OfPnt(1, j-i+1);
+      TColgp_Array1OfVec theTangents(1, j-i+1);
+      Handle(TColStd_HArray1OfBoolean) theFlags = new TColStd_HArray1OfBoolean(1, j-i+1);
+      for (k = i; k <= j; k++)
+        thePoints->SetValue(k-i+1, Centers(k));
+      for (k = i; k <= j; k++)
+      {
+        TColgp_SequenceOfPnt PntSeq;
+        for (Standard_Integer indp = 1; indp <= myPaths.Length(); indp++)
+        {
+          gp_Vec aTangent;
+          if (k == i)
+          {
+            if (myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
+              continue;
+            aTangent = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
+          }
+          else if (k == j)
+          {
+            if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX)
+              continue;
+            aTangent = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
+          }
+          else
+          {
+            if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX ||
+                myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
+              continue;
+            gp_Vec Tangent1 = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
+            gp_Vec Tangent2 = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
+            aTangent = Tangent1 + Tangent2;
+          }
+          aTangent.Normalize();
+          gp_Pnt aPnt(aTangent.XYZ());
+          PntSeq.Append(aPnt);
+        }
+        TColgp_Array1OfPnt PntArray(1, PntSeq.Length());
+        for (Standard_Integer ip = 1; ip <= PntSeq.Length(); ip++)
+          PntArray(ip) = PntSeq(ip);
+        gp_Pnt theBary;
+        gp_Dir xdir, ydir;
+        Standard_Real xgap, ygap, zgap;
+        GeomLib::Inertia(PntArray, theBary, xdir, ydir, xgap, ygap, zgap);
+        gp_Vec theTangent(theBary.XYZ());
+        theTangents(k-i+1) = theTangent;
+      }
+      theFlags->Init(Standard_True);
+
+      GeomAPI_Interpolate Interpol(thePoints, Standard_False, LinTol);
+      Interpol.Load(theTangents, theFlags);
+      Interpol.Perform();
+      if (!Interpol.IsDone())
+      {
+        cout<<endl<<"Interpolation failed"<<endl;
+      }
+      Handle(Geom_Curve) InterCurve = Interpol.Curve();
+      MidEdges(i) = BRepLib_MakeEdge(InterCurve);
+      i = j;
+    }
+  }  
+
+  BRepLib_MakeWire MakeFinalWire;
+  for (i = 1; i < NbSecFaces; i++)
+    if (!MidEdges(i).IsNull())
+      MakeFinalWire.Add(TopoDS::Edge(MidEdges(i)));
+
+  TopoDS_Wire FinalWire = MakeFinalWire.Wire();
+  myShape = MakeFinalWire.Wire();
+  
+  //Temporary
+  /*
+  TopoDS_Compound aCompound, aCmp1, aCmp2;
+  BRep_Builder BB;
+  BB.MakeCompound(aCompound);
+  BB.MakeCompound(aCmp1);
+  BB.MakeCompound(aCmp2);
+  for (i = 1; i <= myPaths.Length(); i++)
+  {
+    TopoDS_Compound aCmp;
+    BB.MakeCompound(aCmp);
+    for (j = 1; j <= myPaths(i).Length(); j++)
+      BB.Add(aCmp, myPaths(i)(j));
+    BB.Add(aCmp1, aCmp);
+  }
+  for (i = 1; i <= SectionsEdges.Length(); i++)
+  {
+    TopoDS_Wire aWire;
+    BB.MakeWire(aWire);
+    for (j = 1; j <= SectionsEdges(i).Length(); j++)
+      BB.Add(aWire, SectionsEdges(i)(j));
+    BB.Add(aCmp2, aWire);
+  }
+  BB.Add(aCompound, aCmp1);
+  BB.Add(aCompound, aCmp2);
+  BB.Add(aCompound, FinalWire);
+         
+  myShape = aCompound;
+  */
+  ////////////
+
+  Done();
+}
index 755ebbe..dc75ab1 100755 (executable)
@@ -35,6 +35,7 @@
 #include <BRepOffsetAPI_MakeEvolved.hxx>
 #include <BRepOffsetAPI_ThruSections.hxx>
 #include <BRepOffsetAPI_MakePipeShell.hxx>
+#include <BRepOffsetAPI_MiddlePath.hxx>
 
 #include <BRepLib_MakeWire.hxx>
 #include <TopoDS.hxx>
@@ -772,6 +773,32 @@ static Standard_Integer simulsweep(Draw_Interpretor& di,
   return 0;
 }
 
+//=======================================================================
+//  middlepath
+//=======================================================================
+static Standard_Integer middlepath(Draw_Interpretor& di,
+                                  Standard_Integer n, const char** a)
+{
+  if (n < 5) return 1;
+
+  TopoDS_Shape aShape = DBRep::Get(a[2]);
+  if (aShape.IsNull()) return 1;
+
+  TopoDS_Shape StartShape = DBRep::Get(a[3]);
+  if (StartShape.IsNull()) return 1;
+  
+  TopoDS_Shape EndShape   = DBRep::Get(a[4]);
+  if (EndShape.IsNull()) return 1;
+
+  BRepOffsetAPI_MiddlePath Builder(aShape, StartShape, EndShape);
+  Builder.Build();
+
+  TopoDS_Shape Result = Builder.Shape();
+  DBRep::Set(a[1], Result);
+
+  return 0;
+}
+
 //=======================================================================
 //function : SweepCommands
 //purpose  : 
@@ -839,5 +866,8 @@ void  BRepTest::SweepCommands(Draw_Interpretor& theCommands)
                  __FILE__,simulsweep,g);
   theCommands.Add("geompipe", "geompipe r spineedge profileedge radius [byACR [byrotate]]"
                  __FILE__,geompipe,g);
+  
+  theCommands.Add("middlepath", "middlepath res shape startshape endshape",
+                 __FILE__,middlepath,g);
 }
 
index 81d0a4c..fc9f019 100755 (executable)
@@ -23,6 +23,7 @@
 //pdn,gka 10.06.99 S4189: command DT_ShapeConvertRev added
 
 #include <SWDRAW_ShapeUpgrade.ixx>
+//#include <SWDRAW_ShapeUpgrade.hxx>
 
 #include <DBRep.hxx>
 #include <ShapeUpgrade.hxx>
@@ -82,6 +83,7 @@
 #include <ShapeUpgrade_ShapeDivideClosed.hxx>
 #include <ShapeUpgrade_RemoveInternalWires.hxx>
 #include <ShapeUpgrade_RemoveLocations.hxx>
+#include <ShapeUpgrade_UnifySameDomain.hxx>
 #include <BRepBuilderAPI_Transform.hxx>
 
 // the plane (equation z=0) shared by PlaneDividedFaceContinuity and PlaneGridShell
@@ -1441,6 +1443,27 @@ static Standard_Integer removeloc (Draw_Interpretor& di,
   DBRep::Set(argv[1],aNewShape);
   return 0;
 }
+
+//=======================================================================
+// unifysamedom
+//=======================================================================
+static Standard_Integer unifysamedom(Draw_Interpretor& , Standard_Integer n, const char** a)
+{
+  if (n < 3)
+    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();
+
+  DBRep::Set(a[1], Result);
+  return 0;
+}
+
 static Standard_Integer copytranslate(Draw_Interpretor& di, 
                                    Standard_Integer argc, 
                                    const char** argv)
@@ -1561,5 +1584,9 @@ static Standard_Integer copytranslate(Draw_Interpretor& di,
                    __FILE__,removeinternalwires,g);
   
   theCommands.Add ("removeloc","result shape",__FILE__,removeloc,g);
+  
+  theCommands.Add ("unifysamedom",
+                   "unifysamedom result shape",__FILE__,unifysamedom,g);
+  
   theCommands.Add ("copytranslate","result shape dx dy dz",__FILE__,copytranslate,g);
 }
index bb0e87f..a914fdb 100755 (executable)
@@ -115,6 +115,9 @@ is
     class RemoveInternalWires;
     ---Purpose: Removes all internal wires having area less than specified min area
     
+    class UnifySameDomain;
+    ---Purpose: Unifies same domain faces and edges of specified shape
+    
     C0BSplineToSequenceOfC1BSplineCurve (BS   : BSplineCurve from Geom;
                                         seqBS: out HSequenceOfBoundedCurve from TColGeom)
     returns Boolean;
diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cdl b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cdl
new file mode 100644 (file)
index 0000000..df0e9e4
--- /dev/null
@@ -0,0 +1,63 @@
+-- File:      ShapeUpgrade_UnifySameDomain.cdl
+-- Created:   09.06.12 13:48:36
+-- Author:    jgv@ROLEX
+---Copyright: Open CASCADE 2012
+
+class UnifySameDomain from ShapeUpgrade inherits TShared from MMgt
+
+       ---Purpose: Unifies same domain faces and edges of specified shape
+
+uses
+    Shape from TopoDS,
+    ListOfShape from TopTools,
+    ReShape from ShapeBuild
+
+is
+    Create returns UnifySameDomain from ShapeUpgrade;
+    ---Purpose: empty constructor
+
+    Create(aShape: Shape from TopoDS;
+          UnifyEdges: Boolean from Standard = Standard_True;
+          UnifyFaces: Boolean from Standard = Standard_True;
+          ConcatBSplines: Boolean from Standard = Standard_False)
+    returns UnifySameDomain from ShapeUpgrade;
+    
+    Initialize(me: mutable; aShape: Shape from TopoDS;
+              UnifyEdges: Boolean from Standard = Standard_True;
+              UnifyFaces: Boolean from Standard = Standard_True;
+              ConcatBSplines: Boolean from Standard = Standard_False);
+    
+    Build( me : mutable );
+       ---Purpose: Builds the resulting shape
+    
+    Shape(me) returns Shape from TopoDS;
+       ---C++: return const &
+       ---Purpose: Gives the resulting shape
+    
+    Generated (me; aShape : Shape from TopoDS)
+    returns Shape from TopoDS;
+    
+    UnifyFaces(me: mutable);
+    ---Purpose: this method makes if possible a common face from each
+    --          group of faces lying on coincident surfaces
+
+    UnifyEdges(me: mutable);
+    ---Purpose: this method makes if possible a common edge from each
+    --          group of edges connecting common couple of faces
+
+    UnifyFacesAndEdges(me: mutable);
+    ---Purpose: this method unifies same domain faces and edges
+
+fields
+    
+    myInitShape : Shape from TopoDS;
+    myUnifyFaces : Boolean from Standard;
+    myUnifyEdges : Boolean from Standard;
+    myConcatBSplines : Boolean from Standard;
+    
+    myShape : Shape from TopoDS;
+    
+    myContext   : ReShape from ShapeBuild;
+    --myOldNewMap : DataMapOfShapeShape  from TopTools;
+    
+end UnifySameDomain;
diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
new file mode 100644 (file)
index 0000000..fb50b3a
--- /dev/null
@@ -0,0 +1,1397 @@
+// File:      ShapeUpgrade_UnifySameDomain.cxx
+// Created:   09.06.12 14:35:07
+// Author:    jgv@ROLEX
+// Copyright: Open CASCADE 2012
+
+#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_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 <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 <ShapeAnalysis_WireOrder.hxx>
+#include <ShapeBuild_Edge.hxx>
+#include <Geom2d_Line.hxx>
+#include <ShapeFix_Face.hxx>
+#include <TColGeom_HArray2OfSurface.hxx>
+#include <ShapeExtend_CompositeSurface.hxx>
+#include <ShapeFix_ComposeShell.hxx>
+#include <ShapeFix_SequenceOfWireSegment.hxx>
+#include <ShapeFix_WireSegment.hxx>
+#include <ShapeFix_Edge.hxx>
+#include <ShapeFix_Shell.hxx>
+#include <ShapeUpgrade_RemoveLocations.hxx>
+
+
+//=======================================================================
+//function : AddOrdinaryEdges
+//purpose  : auxilary
+//=======================================================================
+// adds edges from the shape to the sequence
+// seams and equal edges are dropped
+// Returns true if one of original edges dropped
+static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges,
+                                         const TopoDS_Shape aShape,
+                                         Standard_Integer& anIndex)
+{
+  //map of edges
+  TopTools_IndexedMapOfShape aNewEdges;
+  //add edges without seams
+  for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) {
+    TopoDS_Shape edge = exp.Current();
+    if(aNewEdges.Contains(edge))
+    {
+      //aNewEdges.Remove(edge);
+      TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
+      aNewEdges.RemoveLast();
+      if (aNewEdges.FindIndex(edge) != 0)
+        aNewEdges.Substitute(aNewEdges.FindIndex(edge), LastEdge);
+      /////////////////////////
+    }
+    else
+      aNewEdges.Add(edge);
+  }
+
+  Standard_Boolean isDropped = Standard_False;
+  //merge edges and drop seams
+  Standard_Integer i;
+  for (i = 1; i <= edges.Length(); i++) {
+    TopoDS_Shape current = edges(i);
+    if(aNewEdges.Contains(current)) {
+
+      //aNewEdges.Remove(current);
+      TopoDS_Shape LastEdge = aNewEdges(aNewEdges.Extent());
+      aNewEdges.RemoveLast();
+      if (aNewEdges.FindIndex(current) != 0)
+        aNewEdges.Substitute(aNewEdges.FindIndex(current), LastEdge);
+      /////////////////////////
+      edges.Remove(i);
+      i--;
+
+      if(!isDropped) {
+        isDropped = Standard_True;
+        anIndex = i;
+      }
+    }
+  }
+
+  //add edges to the sequemce
+  for (i = 1; i <= aNewEdges.Extent(); i++)
+    edges.Append(aNewEdges(i));
+
+  return isDropped;
+}
+
+//=======================================================================
+//function : getCylinder
+//purpose  : auxilary
+//=======================================================================
+static Standard_Boolean getCylinder(Handle(Geom_Surface)& theInSurface,
+                                    gp_Cylinder& theOutCylinder)
+{
+  Standard_Boolean isCylinder = Standard_False;
+
+  if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
+    Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface);
+
+    theOutCylinder = aGC->Cylinder();
+    isCylinder = Standard_True;
+  }
+  else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
+    Handle(Geom_SurfaceOfRevolution) aRS =
+      Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface);
+    Handle(Geom_Curve) aBasis = aRS->BasisCurve();
+    if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) {
+      Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis);
+      gp_Dir aDir = aRS->Direction();
+      gp_Dir aBasisDir = aBasisLine->Position().Direction();
+      if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
+        // basis line is parallel to the revolution axis: it is a cylinder
+        gp_Pnt aLoc = aRS->Location();
+        Standard_Real aR = aBasisLine->Lin().Distance(aLoc);
+        gp_Ax3 aCylAx (aLoc, aDir);
+
+        theOutCylinder = gp_Cylinder(aCylAx, aR);
+        isCylinder = Standard_True;
+      }
+    }
+  }
+  else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
+    Handle(Geom_SurfaceOfLinearExtrusion) aLES =
+      Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface);
+    Handle(Geom_Curve) aBasis = aLES->BasisCurve();
+    if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) {
+      Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis);
+      gp_Dir aDir = aLES->Direction();
+      gp_Dir aBasisDir = aBasisCircle->Position().Direction();
+      if (aBasisDir.IsParallel(aDir, Precision::Angular())) {
+        // basis circle is normal to the extrusion axis: it is a cylinder
+        gp_Pnt aLoc = aBasisCircle->Location();
+        Standard_Real aR = aBasisCircle->Radius();
+        gp_Ax3 aCylAx (aLoc, aDir);
+
+        theOutCylinder = gp_Cylinder(aCylAx, aR);
+        isCylinder = Standard_True;
+      }
+    }
+  }
+  else {
+  }
+
+  return isCylinder;
+}
+
+//=======================================================================
+//function : ClearRts
+//purpose  : auxilary
+//=======================================================================
+static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
+{
+  if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
+    Handle(Geom_RectangularTrimmedSurface) rts =
+      Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+    return rts->BasisSurface();
+  }
+  return aSurface;
+}
+
+//=======================================================================
+//function : IsSameDomain
+//purpose  : 
+//=======================================================================
+static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
+                                     const TopoDS_Face& aCheckedFace)
+{
+  //checking the same handles
+  TopLoc_Location L1, L2;
+  Handle(Geom_Surface) S1, S2;
+
+  S1 = BRep_Tool::Surface(aFace,L1);
+  S2 = BRep_Tool::Surface(aCheckedFace,L2);
+
+  if (S1 == S2 && L1 == L2)
+    return Standard_True;
+
+  // planar and cylindrical cases (IMP 20052)
+  Standard_Real aPrec = Precision::Confusion();
+
+  S1 = BRep_Tool::Surface(aFace);
+  S2 = BRep_Tool::Surface(aCheckedFace);
+
+  S1 = ClearRts(S1);
+  S2 = ClearRts(S2);
+
+  //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2;
+  //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1);
+  //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2);
+  //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
+  //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
+
+  // case of two elementary surfaces: use OCCT tool
+  // elementary surfaces: ConicalSurface, CylindricalSurface,
+  //                      Plane, SphericalSurface and ToroidalSurface
+  if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) &&
+      S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
+  {
+    Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1);
+    Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2);
+
+    Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool();
+    Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
+
+    try {
+      IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
+      if (!anIIInt.IsDone() || anIIInt.IsEmpty())
+        return Standard_False;
+
+      return anIIInt.TangentFaces();
+    }
+    catch (Standard_Failure) {
+      return Standard_False;
+    }
+  }
+
+  // case of two planar surfaces:
+  // all kinds of surfaces checked, including b-spline and bezier
+  GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
+  if (aPlanarityChecker1.IsPlanar()) {
+    GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
+    if (aPlanarityChecker2.IsPlanar()) {
+      gp_Pln aPln1 = aPlanarityChecker1.Plan();
+      gp_Pln aPln2 = aPlanarityChecker2.Plan();
+
+      if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(),Precision::Angular()) &&
+          aPln1.Distance(aPln2) < aPrec) {
+        return Standard_True;
+      }
+    }
+  }
+
+  // case of two cylindrical surfaces, at least one of which is a swept surface
+  // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
+  if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
+       S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) &&
+      (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
+       S2->IsKind(STANDARD_TYPE(Geom_SweptSurface))))
+  {
+    gp_Cylinder aCyl1, aCyl2;
+    if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
+      if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
+        gp_Dir aDir1 = aCyl1.Position().Direction();
+        gp_Dir aDir2 = aCyl2.Position().Direction();
+        if (aDir1.IsParallel(aDir2, Precision::Angular())) {
+          gp_Pnt aLoc1 = aCyl1.Location();
+          gp_Pnt aLoc2 = aCyl2.Location();
+          gp_Vec aVec12 (aLoc1, aLoc2);
+          if (aVec12.SquareMagnitude() < aPrec*aPrec ||
+              aVec12.IsParallel(aDir1, Precision::Angular())) {
+            return Standard_True;
+          }
+        }
+      }
+    }
+  }
+
+  return Standard_False;
+}
+
+//=======================================================================
+//function : MovePCurves
+//purpose  :
+//=======================================================================
+static void MovePCurves(TopoDS_Face& aTarget,
+                        const TopoDS_Face& aSource)
+{
+  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());
+    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
+//           and glues their 3d curves
+//=======================================================================
+static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain,
+                                        const TopoDS_Vertex& FirstVertex,
+                                        const TopoDS_Vertex& LastVertex)
+{
+  Standard_Integer i, j;
+
+  TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1));
+  //TColGeom2d_SequenceOfCurve PCurveSeq;
+  TColGeom_SequenceOfSurface SurfSeq;
+  //TopTools_SequenceOfShape LocSeq;
+  
+  BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(FirstEdge.TShape()))->Curves() );
+  for (; itr.More(); itr.Next())
+  {
+    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);
+      */
+    }
+  }
+
+  Standard_Real fpar, lpar;
+  BRep_Tool::Range(FirstEdge, fpar, lpar);
+  TopoDS_Edge PrevEdge = FirstEdge;
+  TopoDS_Vertex CV;
+  Standard_Real MaxTol = 0.;
+  
+  TopoDS_Edge ResEdge;
+  BRep_Builder BB;
+
+  Standard_Integer nb_curve = aChain.Length();   //number of curves
+  TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1);                    //array of the curves
+  TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
+    
+  TopoDS_Vertex PrevVertex = FirstVertex;
+  for (i = 1; i <= nb_curve; i++)
+  {
+    TopoDS_Edge anEdge = TopoDS::Edge(aChain(i));
+    TopoDS_Vertex VF, VL;
+    TopExp::Vertices(anEdge, VF, VL);
+    Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex));
+    
+    Standard_Real Tol1 = BRep_Tool::Tolerance(VF);
+    Standard_Real Tol2 = BRep_Tool::Tolerance(VL);
+    if (Tol1 > MaxTol)
+      MaxTol = Tol1;
+    if (Tol2 > MaxTol)
+      MaxTol = Tol2;
+    
+    if (i > 1)
+    {
+      TopExp::CommonVertex(PrevEdge, anEdge, CV);
+      Standard_Real Tol = BRep_Tool::Tolerance(CV);
+      tabtolvertex(i-2) = Tol;
+    }
+    
+    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+    Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar);
+    tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
+    GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion());
+    if (ToReverse)
+      tab_c3d(i-1)->Reverse();
+    PrevVertex = (ToReverse)? VF : VL;
+    PrevEdge = anEdge;
+  }
+  Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
+  Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
+  GeomConvert::ConcatC1(tab_c3d,
+                        tabtolvertex,
+                        ArrayOfIndices,
+                        concatcurve,
+                        Standard_False,
+                        Precision::Confusion());   //C1 concatenation
+  
+  if (concatcurve->Length() > 1)
+  {
+    GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
+    
+    for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
+      Concat.Add( concatcurve->Value(i), MaxTol, Standard_True );
+    
+    concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
+  }
+  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));
+      TopoDS_Vertex VF, VL;
+      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);
+      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());
+      if (ToReverse)
+        tab_c2d(i-1)->Reverse();
+      PrevVertex = (ToReverse)? VF : VL;
+      PrevEdge = anEdge;
+    }
+    Handle(TColGeom2d_HArray1OfBSplineCurve)  concatc2d;     //array of the concatenated curves
+    Handle(TColStd_HArray1OfInteger)        ArrayOfInd2d;  //array of the remining Vertex
+    Geom2dConvert::ConcatC1(tab_c2d,
+                            tabtolvertex,
+                            ArrayOfInd2d,
+                            concatc2d,
+                            Standard_False,
+                            Precision::Confusion());   //C1 concatenation
+    
+    if (concatc2d->Length() > 1)
+    {
+      Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower()));
+      
+      for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++)
+        Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True );
+      
+      concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve());
+    }
+    Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower());
+    ResPCurves.Append(aResPCurve);
+  }
+  
+  ResEdge = BRepLib_MakeEdge(ResCurve,
+                             FirstVertex, LastVertex,
+                             ResCurve->FirstParameter(), ResCurve->LastParameter());
+  BB.SameRange(ResEdge, Standard_False);
+  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());
+  }
+
+  BRepLib::SameParameter(ResEdge, MaxTol, Standard_True);
+  
+  return ResEdge;
+}
+
+//=======================================================================
+//function : MergeEdges
+//purpose  : auxilary
+//=======================================================================
+static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges,
+                                   const TopoDS_Face& aFace,
+                                   const Standard_Real Tol,
+                                   const Standard_Boolean ConcatBSplines,
+                                   TopoDS_Edge& anEdge)
+{
+  // 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 DEB
+    cout<<"can not create correct chain..."<<endl;
+#endif
+    return Standard_False;
+  }
+  // union edges in chain
+  // first step: union lines and circles
+  TopLoc_Location Loc;
+  Standard_Real fp1,lp1,fp2,lp2;
+  for(j=1; j<aChain.Length(); j++) {
+    TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j));
+    Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1);
+    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,Loc,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)) { 
+        continue;
+      }
+      // 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( 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()) continue;
+      // 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);
+      Handle(Geom_Circle) C = MC.Value();
+      TopoDS_Edge E;
+      if (!MC.IsDone() || C.IsNull()) {
+        // jfa for Mantis issue 0020228
+        if (PV1.Distance(PV2) > Precision::Confusion()) continue;
+        // closed chain
+        C = C1;
+        B.MakeEdge (E,C,Precision::Confusion());
+        B.Add(E,V1);
+        B.Add(E,V2);
+      }
+      else {
+        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;
+          }
+        }
+        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 (j < aChain.Length()) {
+#ifdef DEB
+    cout<<"null curve3d in edge..."<<endl;
+#endif
+    return Standard_False;
+  }
+  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;
+    for(j=1; j<=aChain.Length(); j++) {
+      TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
+      Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1);
+      if(c3d.IsNull()) continue;
+      while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
+        Handle(Geom_TrimmedCurve) tc =
+          Handle(Geom_TrimmedCurve)::DownCast(c3d);
+        c3d = tc->BasisCurve();
+      }
+      if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) ||
+            c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue;
+      NeedUnion = false;
+      break;
+    }
+    if(NeedUnion) {
+#ifdef DEB
+      cout<<"can not make analitical union => make approximation"<<endl;
+#endif
+      TopoDS_Edge E = GlueEdgesWithPCurves(aChain, VF, VL);
+      /*
+      TopoDS_Wire W;
+      B.MakeWire(W);
+      for(j=1; j<=aChain.Length(); j++) {
+        TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j));
+        B.Add(W,edge);
+      }
+      Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W);
+      Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000);
+      Handle(Geom_BSplineCurve) bc = Conv.Curve();
+      TopoDS_Edge E;
+      B.MakeEdge (E,bc,Precision::Confusion());
+      B.Add (E,VF);
+      B.Add (E,VL);
+      */
+      aChain.SetValue(1,E);
+    }
+    else {
+#ifdef DEB
+      cout<<"can not make approximation for such types of curves"<<endl;
+#endif
+      return Standard_False;
+    }
+  }
+
+  anEdge = TopoDS::Edge(aChain.Value(1));
+  return Standard_True;
+}
+
+//=======================================================================
+//function : ShapeUpgrade_UnifySameDomain
+//purpose  : Constructor
+//=======================================================================
+
+ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
+{
+  myUnifyEdges = Standard_True;
+  myUnifyFaces = Standard_True;
+  myConcatBSplines = Standard_False;
+
+  myContext = new ShapeBuild_ReShape;
+}
+
+//=======================================================================
+//function : ShapeUpgrade_UnifySameDomain
+//purpose  : Constructor
+//=======================================================================
+
+ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape,
+                                                           const Standard_Boolean UnifyEdges,
+                                                           const Standard_Boolean UnifyFaces,
+                                                           const Standard_Boolean ConcatBSplines)
+{
+  myInitShape = aShape;
+  myShape = aShape;
+  myUnifyEdges = UnifyEdges;
+  myUnifyFaces = UnifyFaces;
+  myConcatBSplines = ConcatBSplines;
+
+  myContext = new ShapeBuild_ReShape;
+}
+
+//=======================================================================
+//function : Initialize
+//purpose  : 
+//=======================================================================
+
+void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
+                                              const Standard_Boolean UnifyEdges,
+                                              const Standard_Boolean UnifyFaces,
+                                              const Standard_Boolean ConcatBSplines)
+{
+  myInitShape = aShape;
+  myShape = aShape;
+  myUnifyEdges = UnifyEdges;
+  myUnifyFaces = UnifyFaces;
+  myConcatBSplines = ConcatBSplines;
+
+  myContext->Clear();
+  //myOldNewMap.Clear();
+  //myGenerated.Clear();
+}
+
+//=======================================================================
+//function : UnifyFaces
+//purpose  : 
+//=======================================================================
+
+void ShapeUpgrade_UnifySameDomain::UnifyFaces()
+{
+  //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;
+
+    //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
+
+    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(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
+      if (mapF.Add(exp.Current()))
+        nbf++;
+    }
+
+    // processing each face
+    mapF.Clear();
+    for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) {
+      TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD));
+
+      if (aProcessed.Contains(aFace))
+        continue;
+
+      Standard_Integer dummy;
+      TopTools_SequenceOfShape edges;
+      AddOrdinaryEdges(edges,aFace,dummy);
+
+      TopTools_SequenceOfShape faces;
+      faces.Append(aFace);
+
+      //surface and location to construct result
+      TopLoc_Location aBaseLocation;
+      Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation);
+      aBaseSurface = ClearRts(aBaseSurface);
+
+      // find adjacent faces to union
+      Standard_Integer i;
+      for (i = 1; i <= edges.Length(); i++) {
+        TopoDS_Edge edge = TopoDS::Edge(edges(i));
+        if (BRep_Tool::Degenerated(edge))
+          continue;
+
+        const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
+        TopTools_ListIteratorOfListOfShape anIter(aList);
+        for (; anIter.More(); anIter.Next()) {
+          TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD));
+          if (anCheckedFace.IsSame(aFace))
+            continue;
+
+          if (aProcessed.Contains(anCheckedFace))
+            continue;
+
+          if (IsSameDomain(aFace,anCheckedFace)) {
+
+            if (aList.Extent() != 2) {
+              // non mainfold case is not processed
+              continue;
+            }
+
+            // replacing pcurves
+            TopoDS_Face aMockUpFace;
+            BRep_Builder B;
+            B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.);
+            MovePCurves(aMockUpFace,anCheckedFace);
+
+            if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) {
+              // sequence edges is modified
+              i = dummy;
+            }
+
+            faces.Append(anCheckedFace);
+            aProcessed.Add(anCheckedFace);
+            break;
+          }
+        }
+      }
+
+      // 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;
+
+        // connecting wires
+        while (edges.Length()>0) {
+
+          Standard_Boolean isEdge3d = Standard_False;
+          nbWires++;
+          TopTools_MapOfShape aVertices;
+          TopoDS_Wire aWire;
+          B.MakeWire(aWire);
+
+          TopoDS_Edge anEdge = TopoDS::Edge(edges(1));
+          edges.Remove(1);
+
+          isEdge3d |= !BRep_Tool::Degenerated(anEdge);
+          B.Add(aWire,anEdge);
+          TopoDS_Vertex V1,V2;
+          TopExp::Vertices(anEdge,V1,V2);
+          aVertices.Add(V1);
+          aVertices.Add(V2);
+
+          Standard_Boolean isNewFound = Standard_False;
+          do {
+            isNewFound = Standard_False;
+            for(Standard_Integer j = 1; j <= edges.Length(); j++) {
+              anEdge = TopoDS::Edge(edges(j));
+              TopExp::Vertices(anEdge,V1,V2);
+              if(aVertices.Contains(V1) || aVertices.Contains(V2)) {
+                isEdge3d |= !BRep_Tool::Degenerated(anEdge);
+                aVertices.Add(V1);
+                aVertices.Add(V2);
+                B.Add(aWire,anEdge);
+                edges.Remove(j);
+                j--;
+                isNewFound = Standard_True;
+              }
+            }
+          } while (isNewFound);
+
+          // sorting any type of edges
+          //aWire = TopoDS::Wire(aContext->Apply(aWire));
+          aWire = TopoDS::Wire(myContext->Apply(aWire));
+
+          //TopoDS_Face tmpF = TopoDS::Face(aContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
+          TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
+          Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
+          sfw->FixReorder();
+          Standard_Boolean isDegRemoved = Standard_False;
+          if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
+            // clear degenerated edges if at least one with 3d curve exist
+            if(isEdge3d) {
+              Handle(ShapeExtend_WireData) sewd = sfw->WireData();
+              for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) {
+                TopoDS_Edge E = sewd->Edge(j);
+                if(BRep_Tool::Degenerated(E)) {
+                  sewd->Remove(j);
+                  isDegRemoved = Standard_True;
+                  j--;
+                }
+              }
+            }
+            sfw->FixShifted();
+            if(isDegRemoved)
+              sfw->FixDegenerated();
+          }
+          TopoDS_Wire aWireFixed = sfw->Wire();
+          //aContext->Replace(aWire,aWireFixed);
+          myContext->Replace(aWire,aWireFixed);
+          //for history
+          /*
+          if (!myOldNewMap.IsBound(aWire))
+          {
+            TopTools_ListOfShape EmptyList;
+            myOldNewMap.Bind(aWire, EmptyList);
+          }
+          myOldNewMap(aWire).Clear();
+          myOldNewMap(aWire).Append(aWireFixed);
+          */
+          /////////////
+          
+          // add resulting wire
+          if(isEdge3d) {
+            B.Add(aResult,aWireFixed);
+          }
+          else  {
+            // sorting edges
+            Handle(ShapeExtend_WireData) sbwd = sfw->WireData();
+            Standard_Integer nbEdges = sbwd->NbEdges();
+            // sort degenerated edges and create one edge instead of several ones
+            ShapeAnalysis_WireOrder sawo(Standard_False, 0);
+            ShapeAnalysis_Edge sae;
+            Standard_Integer aLastEdge = nbEdges;
+            for(Standard_Integer j = 1; j <= nbEdges; j++) {
+              Standard_Real f,l;
+              //smh protection on NULL pcurve
+              Handle(Geom2d_Curve) c2d;
+              if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) {
+                aLastEdge--;
+                continue;
+              }
+              sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY());
+            }
+            sawo.Perform();
+
+            // constructind one degenerative edge
+            gp_XY aStart, anEnd, tmp;
+            Standard_Integer nbFirst = sawo.Ordered(1);
+            TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD));
+            ShapeBuild_Edge sbe;
+            TopoDS_Vertex aDummyV;
+            TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV);
+            sawo.XY(nbFirst,aStart,tmp);
+            sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd);
+
+            gp_XY aVec = anEnd-aStart;
+            Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart));
+
+            B.UpdateEdge(E,aLine,tmpF,0.);
+            B.Range(E,tmpF,0.,aVec.Modulus());
+            Handle(Geom_Curve) C3d;
+            B.UpdateEdge(E,C3d,0.);
+            B.Degenerated(E,Standard_True);
+            TopoDS_Wire aW;
+            B.MakeWire(aW);
+            B.Add(aW,E);
+            B.Add(aResult,aW);
+          }
+        }
+
+        // perform substitution of face
+        //aContext->Replace(aContext->Apply(aFace),aResult);
+        myContext->Replace(myContext->Apply(aFace),aResult);
+        //for history
+        /*
+        if (!myOldNewMap.IsBound(aFace))
+        {
+          TopTools_ListOfShape EmptyList;
+          myOldNewMap.Bind(aFace, EmptyList);
+        }
+        myOldNewMap(aFace).Clear();
+        myOldNewMap(aFace).Append(aResult);
+        */
+        /////////////
+
+        ShapeFix_Face sff (aResult);
+        //Intializing by tolerances
+        sff.SetPrecision(Precision::Confusion());
+        sff.SetMinTolerance(tol);
+        sff.SetMaxTolerance(1.);
+        //Setting modes
+        sff.FixOrientationMode() = 0;
+        //sff.FixWireMode() = 0;
+        //sff.SetContext(aContext);
+        sff.SetContext(myContext);
+        // Applying the fixes
+        sff.Perform();
+        if(sff.Status(ShapeExtend_FAIL))
+        hasFailed = Standard_True;
+
+        // breaking down to several faces
+        //TopoDS_Shape theResult = aContext->Apply(aResult);
+        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( aContext );
+          CompShell.SetContext( myContext );
+
+          TopTools_SequenceOfShape parts;
+          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);
+          }
+
+          CompShell.DispatchWires ( parts,wires );
+          for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
+            ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
+            //aFixOrient.SetContext(aContext);
+            aFixOrient.SetContext(myContext);
+            aFixOrient.FixOrientation();
+          }
+
+          TopoDS_Shape CompRes;
+          if ( faces.Length() !=1 ) {
+            TopoDS_Shell S;
+            B.MakeShell ( S );
+            for ( i=1; i <= parts.Length(); i++ )
+              B.Add ( S, parts(i) );
+            CompRes = S;
+          }
+          else CompRes = parts(1);
+
+          //aContext->Replace(aCurrent,CompRes);
+          myContext->Replace(aCurrent,CompRes);
+          //for history
+          /*
+          if (!myOldNewMap.IsBound(aCurrent))
+          {
+            TopTools_ListOfShape EmptyList;
+            myOldNewMap.Bind(aCurrent, EmptyList);
+          }
+          myOldNewMap(aCurrent).Clear();
+          myOldNewMap(aCurrent).Append(CompRes);
+          */
+          /////////////
+        }
+
+        // remove the remaining faces
+        for(i = 2; i <= faces.Length(); i++)
+          //aContext->Remove(faces(i));
+          myContext->Remove(faces(i));
+      }
+    } // end processing each face
+
+    //TopoDS_Shape aResult = Shape;
+    if (NbModif > 0 && !hasFailed) {
+      //TopoDS_Shape aResult = aContext->Apply(aShell);
+      TopoDS_Shape aResult = myContext->Apply(aShell);
+
+      ShapeFix_Edge sfe;
+      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(aShell, aResult);
+      //for history
+      /*
+      if (!myOldNewMap.IsBound(aShell))
+      {
+        TopTools_ListOfShape EmptyList;
+        myOldNewMap.Bind(aShell, EmptyList);
+      }
+      myOldNewMap(aShell).Clear();
+      myOldNewMap(aShell).Append(aResult);
+      */
+      /////////////
+    }
+    //else
+    {
+      for (exp.Init(aShell, 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();
+        }
+      }
+    }
+  } // end processing each shell
+
+  myShape = myContext->Apply(myShape);
+}
+
+//=======================================================================
+//function : UnifyEdges
+//purpose  : 
+//=======================================================================
+
+void ShapeUpgrade_UnifySameDomain::UnifyEdges()
+{
+  Standard_Real Tol = Precision::Confusion();
+  
+  //Handle(ShapeBuild_ReShape) myContext = new ShapeBuild_ReShape;
+  Standard_Real myTolerance = Precision::Confusion();
+  TopoDS_Shape aResult = myContext->Apply(myShape);
+
+  // processing each solid
+  TopAbs_ShapeEnum aType = TopAbs_SOLID;
+  TopExp_Explorer exps (myShape, aType);
+  if (!exps.More()) {
+    aType = TopAbs_SHELL;
+    exps.Init(myShape, aType);
+  }
+  for (; exps.More(); exps.Next()) {
+    //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
+    TopoDS_Shape aSolid = exps.Current();
+
+    TopTools_IndexedMapOfShape ChangedFaces;
+
+    // creating map of edge faces
+    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
+    TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
+
+    //Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
+    TopoDS_Shape aRes = aSolid;
+    //aRes = aContext->Apply(aSolid);
+    aRes = myContext->Apply(aSolid);
+
+    // processing each face
+    TopExp_Explorer exp;
+    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;
+
+      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);
+        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);
+          }
+        }
+      }
+
+      for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
+        const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
+        TopTools_SequenceOfShape SeqEdges;
+        TopTools_ListIteratorOfListOfShape anIter(ListEdges);
+        for ( ; anIter.More(); anIter.Next()) {
+          SeqEdges.Append(anIter.Value());
+        }
+        if (SeqEdges.Length()==1) 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++)
+          {
+            if (!myOldNewMap.IsBound(SeqEdges(j)))
+            {
+              TopTools_ListOfShape EmptyList;
+              myOldNewMap.Bind(SeqEdges(j), EmptyList);
+            }
+            myOldNewMap(SeqEdges(j)).Clear();
+            myOldNewMap(SeqEdges(j)).Append(E);
+          }
+          */
+          /////////////
+          
+          TopoDS_Face tmpF = TopoDS::Face(exp.Current());
+          if ( !ChangedFaces.Contains(tmpF) )
+            ChangedFaces.Add(tmpF);
+          tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
+          if ( !ChangedFaces.Contains(tmpF) )
+            ChangedFaces.Add(tmpF);
+        }
+      }
+
+    } // end processing each face
+
+    // fix changed faces and replace them in the local context
+    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)));
+      Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
+      sff->SetContext(myContext);
+      sff->SetPrecision(myTolerance);
+      sff->SetMinTolerance(myTolerance);
+      sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
+      sff->Perform();
+      TopoDS_Shape aNewFace = sff->Face();
+      //aContext->Replace(aFace,aNewFace);
+      myContext->Replace(aFace,aNewFace);
+      //for history
+      /*
+      if (!myOldNewMap.IsBound(aFace))
+      {
+        TopTools_ListOfShape EmptyList;
+        myOldNewMap.Bind(aFace, EmptyList);
+      }
+      myOldNewMap(aFace).Clear();
+      myOldNewMap(aFace).Append(aNewFace);
+      */
+      /////////////
+    }
+
+    if (ChangedFaces.Extent() > 0) {
+      // fix changed shell and replace it in the local context
+      //TopoDS_Shape aRes1 = aContext->Apply(aRes);
+      TopoDS_Shape aRes1 = myContext->Apply(aRes);
+      TopExp_Explorer expsh;
+      for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
+        TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
+        Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
+        sfsh->FixFaceOrientation(aShell);
+        TopoDS_Shape aNewShell = sfsh->Shell();
+        //aContext->Replace(aShell,aNewShell);
+        myContext->Replace(aShell,aNewShell);
+        //for history
+        /*
+        if (!myOldNewMap.IsBound(aShell))
+        {
+          TopTools_ListOfShape EmptyList;
+          myOldNewMap.Bind(aShell, EmptyList);
+        }
+        myOldNewMap(aShell).Clear();
+        myOldNewMap(aShell).Append(aNewShell);
+        */
+        /////////////
+      }
+      //TopoDS_Shape aRes2 = aContext->Apply(aRes1);
+      TopoDS_Shape aRes2 = myContext->Apply(aRes1);
+      // put new solid into global context
+      myContext->Replace(aSolid,aRes2);
+      //for history
+      /*
+      if (!myOldNewMap.IsBound(aSolid))
+      {
+        TopTools_ListOfShape EmptyList;
+        myOldNewMap.Bind(aSolid, EmptyList);
+      }
+      myOldNewMap(aSolid).Clear();
+      myOldNewMap(aSolid).Append(aRes2);
+      */
+      /////////////
+    }
+
+  } // end processing each solid
+
+  myShape = myContext->Apply(myShape);
+}
+
+//=======================================================================
+//function : UnifyFacesAndEdges
+//purpose  : 
+//=======================================================================
+
+void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
+{
+  UnifyFaces();
+  
+  /*
+  ShapeUpgrade_RemoveLocations RemLoc;
+  RemLoc.Remove(myShape);
+  myShape = RemLoc.GetResult();
+  */
+
+  UnifyEdges();
+}
+
+//=======================================================================
+//function : Build
+//purpose  : builds the resulting shape
+//======================================================================
+void ShapeUpgrade_UnifySameDomain::Build() 
+{
+  if (myUnifyFaces && myUnifyEdges)
+    UnifyFacesAndEdges();
+
+  else if (myUnifyEdges)
+    UnifyEdges();
+  else if (myUnifyFaces)
+    UnifyFaces();
+
+  //Done();
+}
+
+//=======================================================================
+//function : Shape
+//purpose  : give the resulting shape
+//=======================================================================
+const TopoDS_Shape& ShapeUpgrade_UnifySameDomain::Shape() const
+{
+  return myShape;
+}
+
+//=======================================================================
+//function : Generated
+//purpose  : returns the new shape from the old one
+//=======================================================================
+TopoDS_Shape ShapeUpgrade_UnifySameDomain::Generated(const TopoDS_Shape& aShape) const
+{
+  TopoDS_Shape aNewShape = myContext->Apply(aShape);
+  /*
+  if (aNewShape.IsNull())
+    aNewShape = myOldNewMap(aShape);
+  */
+  
+  return aNewShape;
+}
diff --git a/tests/bugs/modalg/bug23367_1 b/tests/bugs/modalg/bug23367_1
new file mode 100755 (executable)
index 0000000..21bf887
--- /dev/null
@@ -0,0 +1,18 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+box b 10 100 10
+explode b f
+donly b b_3 b_4
+fit
+
+middlepath result b b_3 b_4
+
+set length 100.
+
+set 2dviewer 1
diff --git a/tests/bugs/modalg/bug23367_2 b/tests/bugs/modalg/bug23367_2
new file mode 100755 (executable)
index 0000000..35864df
--- /dev/null
@@ -0,0 +1,20 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+pcylinder a 10 30 180
+explode a f
+donly a a_2 a_3
+fit
+middlepath result a a_2 a_3
+
+set length 30.0036
+
+set 2dviewer 1
+
+
+
diff --git a/tests/bugs/modalg/bug23367_3 b/tests/bugs/modalg/bug23367_3
new file mode 100755 (executable)
index 0000000..63b5c6d
--- /dev/null
@@ -0,0 +1,22 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+polyline pp 0 0 0 5 0 0 10 0 0 10 10 0 0 10 0 0 0 0
+mkplane ff pp
+prism a ff 0 0 50
+explode a f
+donly a a_6 a_7
+fit
+middlepath result a a_6 a_7
+
+set length 50.
+
+set 2dviewer 1
+
+
+
diff --git a/tests/bugs/modalg/bug23367_4 b/tests/bugs/modalg/bug23367_4
new file mode 100755 (executable)
index 0000000..91f3840
--- /dev/null
@@ -0,0 +1,21 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+ptorus a 50 10
+explode a e
+wire ww a_2
+donly a ww
+fit
+middlepath result a ww ww
+
+set length 314.159
+
+set 2dviewer 1
+
+
+
diff --git a/tests/bugs/modalg/bug23367_5 b/tests/bugs/modalg/bug23367_5
new file mode 100755 (executable)
index 0000000..f02c1b7
--- /dev/null
@@ -0,0 +1,21 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+pcylinder a 10 50
+explode a f
+donly a a_2 a_3
+fit
+middlepath result a a_2 a_3
+
+set length 50.
+
+set 2dviewer 1
+
+
+
+
diff --git a/tests/bugs/modalg/bug23367_6 b/tests/bugs/modalg/bug23367_6
new file mode 100755 (executable)
index 0000000..24f19e6
--- /dev/null
@@ -0,0 +1,22 @@
+puts "============"
+puts "CR23367"
+puts "============"
+puts ""
+##########################################################################################################
+# New functionality restoring the middle path of pipe-like shape
+##########################################################################################################
+
+restore [locate_data_file bug23367_pipe1.brep] a
+explode a e
+wire w1 a_2
+wire w2 a_6
+donly a w1 w2
+fit
+middlepath result a w1 w2
+
+set length 1386.13
+
+set 2dviewer 1
+
+
+