Salome HOME
Merge from BR_Dev_For_4_0 branch (from tag mergeto_BR_QT4_Dev_17Jan08)
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Gluer.cxx
index ad1a7c79c3572cd94cbfc23f056ad4579b97a8aa..e2f2c9a6953713998e7f77d31f634332fc4b2494 100755 (executable)
@@ -1,3 +1,22 @@
+// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 // File:       GEOMAlgo_Gluer.cxx
 // Created:    Sat Dec 04 12:45:53 2004
 // Author:     Peter KURNEV
 
 #include <GEOMAlgo_Gluer.ixx>
 
+#include <NMTDS_BoxBndTree.hxx>
+#include <NCollection_UBTreeFiller.hxx>
+
+#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
 #include <TColStd_ListOfInteger.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
 
 #include <gp_Pnt.hxx>
 #include <gp_Dir.hxx>
+#include <gp_XYZ.hxx>
 
 #include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
@@ -18,7 +43,6 @@
 #include <Bnd_Box.hxx>
 #include <Bnd_HArray1OfBox.hxx>
 #include <Bnd_BoundSortBox.hxx>
-#include <BRepBndLib.hxx>
 
 #include <TopLoc_Location.hxx>
 #include <TopAbs_ShapeEnum.hxx>
@@ -32,6 +56,7 @@
 #include <TopoDS_Wire.hxx>
 #include <TopoDS_Shell.hxx>
 #include <TopoDS_Solid.hxx>
+#include <TopoDS_Iterator.hxx>
 
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
 
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
+#include <BRepLib.hxx>
+#include <BRepTools.hxx>
+#include <BRepBndLib.hxx>
 
 #include <IntTools_Context.hxx>
 #include <BOPTools_Tools.hxx>
 #include <BOPTools_Tools3D.hxx>
 #include <BOPTools_Tools2D.hxx>
+#include <BOP_CorrectTolerances.hxx>
 
 #include <GEOMAlgo_IndexedDataMapOfIntegerShape.hxx>
 #include <GEOMAlgo_IndexedDataMapOfShapeBox.hxx>
-#include <GEOMAlgo_IndexedDataMapOfPassKeyListOfShape.hxx>
-#include <GEOMAlgo_PassKey.hxx>
+#include <GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape.hxx> 
+#include <GEOMAlgo_PassKeyShape.hxx>
 #include <GEOMAlgo_Tools.hxx>
+//
+
+static 
+  void GetSubShapes(const TopoDS_Shape& aS,
+                   TopTools_IndexedMapOfShape& aMSS);
 
 //=======================================================================
 //function : GEOMAlgo_Gluer
@@ -68,7 +102,8 @@ GEOMAlgo_Gluer::GEOMAlgo_Gluer()
   myTolerance=0.0001;
   myTol=myTolerance;
   myCheckGeometry=Standard_True;
-  myTypeResult=TopAbs_SOLID;
+  myKeepNonSolids=Standard_False;
+  myNbAlone=0;
 }
 //=======================================================================
 //function : ~GEOMAlgo_Gluer
@@ -93,7 +128,22 @@ Standard_Boolean GEOMAlgo_Gluer::CheckGeometry() const
 {
   return myCheckGeometry;
 }
-
+//=======================================================================
+//function : SetKeepNonSolids
+//purpose  : 
+//=======================================================================
+void GEOMAlgo_Gluer::SetKeepNonSolids(const Standard_Boolean aFlag)
+{
+  myKeepNonSolids=aFlag;
+}
+//=======================================================================
+//function : AloneShapes
+//purpose  : 
+//=======================================================================
+Standard_Integer GEOMAlgo_Gluer::AloneShapes()const
+{
+  return myNbAlone;
+}
 //=======================================================================
 //function : Images
 //purpose  : 
@@ -120,155 +170,334 @@ void GEOMAlgo_Gluer::Perform()
   myWarningStatus=0;
   //
   Standard_Integer i;
-  const Standard_Integer aNb=9;
+  const Standard_Integer aNb=8;
   void (GEOMAlgo_Gluer::* pF[aNb])()={
     &GEOMAlgo_Gluer::CheckData,       &GEOMAlgo_Gluer::InnerTolerance,
     &GEOMAlgo_Gluer::MakeVertices,    &GEOMAlgo_Gluer::MakeEdges,
     &GEOMAlgo_Gluer::MakeFaces,       &GEOMAlgo_Gluer::MakeShells,
-    &GEOMAlgo_Gluer::MakeSolids,      &GEOMAlgo_Gluer::BuildResult,
-    &GEOMAlgo_Gluer::CheckResult
+    &GEOMAlgo_Gluer::MakeSolids,      &GEOMAlgo_Gluer::CheckResult
   };
   //
-  //TimeReset(); 
-  //StartChrono();
-  //
   for (i=0; i<aNb; ++i) {
     (this->*pF[i])();
     if (myErrorStatus) {
       return;
     }
   }
-  //
-  //StopChrono(); 
-  //TimeShow(); 
 }
 //=======================================================================
-//function : CheckResult
+//function : MakeVertices
 //purpose  : 
 //=======================================================================
-void GEOMAlgo_Gluer::CheckResult()
+void GEOMAlgo_Gluer::MakeVertices()
 {
   myErrorStatus=0;
   //
-  if (myResult.IsNull()) {
-    myErrorStatus=6;
-    return; 
+  Standard_Integer j, i, aNbV, aNbVSD;
+  TColStd_ListIteratorOfListOfInteger aIt;
+  TopoDS_Shape aVF;
+  TopoDS_Vertex aVnew;
+  TopTools_IndexedMapOfShape aMV, aMVProcessed;
+  TopTools_ListIteratorOfListOfShape aItS;
+  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
+  TopTools_DataMapOfShapeListOfShape aMVV;
+  GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
+  GEOMAlgo_IndexedDataMapOfShapeBox aMSB;
+  //
+  NMTDS_BoxBndTreeSelector aSelector;
+  NMTDS_BoxBndTree aBBTree;
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
+  //
+  //
+  TopExp::MapShapes(myShape, TopAbs_VERTEX, aMV);
+  aNbV=aMV.Extent();
+  if (!aNbV) {
+    myErrorStatus=2; // no vertices in source shape
+    return;
   }
-  // 
-  Standard_Boolean bFound;
-  Standard_Integer i, j, aNbS, aNbFS, aNbSx;
-  TopTools_IndexedMapOfShape aMS, aMFS;
-  TopTools_IndexedDataMapOfShapeListOfShape aMFR;
   //
-  TopExp::MapShapesAndAncestors(myResult, TopAbs_FACE, myTypeResult, aMFR);
-  TopExp::MapShapes(myResult, myTypeResult, aMS);
+  for (i=1; i<=aNbV; ++i) {
+    const TopoDS_Shape& aV=aMV(i);
+    Bnd_Box aBox;
+    //
+    aBox.SetGap(myTol); 
+    BRepBndLib::Add(aV, aBox);
+    //
+    aTreeFiller.Add(i, aBox);
+    //
+    aMIS.Add(i, aV);
+    aMSB.Add(aV, aBox); 
+  }
   //
-  aNbS=aMS.Extent();
-  for (i=1; i<=aNbS; ++i) {
-    const TopoDS_Shape& aSolid=aMS(i);
+  aTreeFiller.Fill();
+  //
+  //------------------------------
+  // Chains
+  for (i=1; i<=aNbV; ++i) {
+    const TopoDS_Shape& aV=aMV(i);
     //
-    aMFS.Clear();
-    TopExp::MapShapes(aSolid, TopAbs_FACE, aMFS);
+    if (aMVProcessed.Contains(aV)) {
+      continue;
+    }
     //
-    bFound=Standard_False;
-    aNbFS=aMFS.Extent();
-    for (j=1; j<=aNbFS; ++j) {
-      const TopoDS_Shape& aFS=aMFS(j);
-      if (aMFR.Contains(aFS)) {
-       const TopTools_ListOfShape& aLSx=aMFR.FindFromKey(aFS);
-       aNbSx=aLSx.Extent();
-       if (aNbSx==2) {
-         bFound=!bFound;
-         break;
+    Standard_Integer aNbIP, aIP, aNbIP1, aIP1;
+    TopTools_ListOfShape aLVSD;
+    TColStd_MapOfInteger aMIP, aMIP1, aMIPC;
+    TColStd_MapIteratorOfMapOfInteger aIt1;
+    //
+    aMIP.Add(i);
+    while(1) {
+      aNbIP=aMIP.Extent();
+      aIt1.Initialize(aMIP);
+      for(; aIt1.More(); aIt1.Next()) {
+       aIP=aIt1.Key();
+       if (aMIPC.Contains(aIP)) {
+         continue;
        }
+       //
+       const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
+       const Bnd_Box& aBoxVP=aMSB.FindFromKey(aVP);
+       //
+       aSelector.Clear();
+       aSelector.SetBox(aBoxVP);
+       //
+       aNbVSD=aBBTree.Select(aSelector);
+       if (!aNbVSD) {
+         continue;  // it must not be 
+       }
+       //
+       const TColStd_ListOfInteger& aLI=aSelector.Indices();
+       aIt.Initialize(aLI);
+       for (; aIt.More(); aIt.Next()) {
+         aIP1=aIt.Value();
+         if (aMIP.Contains(aIP1)) {
+           continue;
+         }
+         aMIP1.Add(aIP1);
+       } //for (; aIt.More(); aIt.Next()) {
+      }//for(; aIt1.More(); aIt1.Next()) {
+      //
+      aNbIP1=aMIP1.Extent();
+      if (!aNbIP1) {
+       break;
       }
-    }
+      //
+      aIt1.Initialize(aMIP);
+      for(; aIt1.More(); aIt1.Next()) {
+       aIP=aIt1.Key();
+       aMIPC.Add(aIP);
+      }
+      //
+      aMIP.Clear();
+      aIt1.Initialize(aMIP1);
+      for(; aIt1.More(); aIt1.Next()) {
+       aIP=aIt1.Key();
+       aMIP.Add(aIP);
+      }
+      aMIP1.Clear();
+    }// while(1)
     //
-    if (!bFound) {
-      myWarningStatus=1;
-      break;
+    // Fill myImages
+    aNbIP=aMIPC.Extent();
+    //
+    if (!aNbIP) {// no SD vertices founded
+      aVF=aV;
+      aLVSD.Append(aV);
+      aMVProcessed.Add(aV);
     }
-  }
-}
-//=======================================================================
-//function : CheckData
-//purpose  : 
-//=======================================================================
-void GEOMAlgo_Gluer::CheckData()
-{
-  myErrorStatus=0;
+    else { // SD vertices founded [ aMIPC ]
+      aIt1.Initialize(aMIPC);
+      for(j=0; aIt1.More(); aIt1.Next(), ++j) {
+       aIP=aIt1.Key();
+       const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
+       if (!j) {
+         aVF=aVP;
+       }
+       aLVSD.Append(aVP);
+       aMVProcessed.Add(aVP);
+      }
+    }
+    myImages.Bind(aVF, aLVSD);
+  }// for (i=1; i<=aNbV; ++i) {
+  //------------------------------
   //
-  if (myShape.IsNull()) {
-    myErrorStatus=5;
-    return; 
+  // Make new vertices
+  aMV.Clear();
+  aItIm.Initialize(myImages);
+  for (; aItIm.More(); aItIm.Next()) {
+    const TopoDS_Shape& aV=aItIm.Key();
+    const TopTools_ListOfShape& aLVSD=aItIm.Value();
+    aNbVSD=aLVSD.Extent();
+    if (aNbVSD>1) {
+      aMV.Add(aV);
+      MakeVertex(aLVSD, aVnew);
+      aMVV.Bind(aVnew, aLVSD);
+    }
   }
-  
-}
-//=======================================================================
-//function : InnerTolerance
-//purpose  : 
-//=======================================================================
-void GEOMAlgo_Gluer::InnerTolerance()
-{
-  myErrorStatus=0;
-  //
-  Standard_Integer i;
-  Standard_Real aX[3][2], dH, dHmin, aCoef, aTolTresh;
-  Bnd_Box aBox;
   //
-  BRepBndLib::Add(myShape, aBox);
-  aBox.Get(aX[0][0], aX[1][0], aX[2][0], aX[0][1], aX[1][1], aX[2][1]);
+  // UnBind old vertices
+  aNbV=aMV.Extent();
+  for (i=1; i<=aNbV; ++i) {
+    const TopoDS_Shape& aV=aMV(i);
+    myImages.UnBind(aV);
+  }
   //
-  dHmin=aX[0][1]-aX[0][0];
-  for (i=1; i<3; ++i) {
-    dH=aX[i][1]-aX[i][0];
-    if (dH<dHmin) {
-      dHmin=dH;
-    }
+  // Bind new vertices
+  aItIm.Initialize(aMVV);
+  for (; aItIm.More(); aItIm.Next()) {
+    const TopoDS_Shape& aV=aItIm.Key();
+    const TopTools_ListOfShape& aLVSD=aItIm.Value();
+    myImages.Bind(aV, aLVSD);
   }
   //
-  myTol=myTolerance;
-  aCoef=0.01;
-  aTolTresh=aCoef*dHmin;
-  if (myTol>aTolTresh) {
-    myTol=aTolTresh;
+  // Origins
+  aItIm.Initialize(myImages);
+  for (; aItIm.More(); aItIm.Next()) {
+    const TopoDS_Shape& aV=aItIm.Key();
+    const TopTools_ListOfShape& aLVSD=aItIm.Value();
+    aItS.Initialize(aLVSD);
+    for (; aItS.More(); aItS.Next()) {
+      const TopoDS_Shape& aVSD=aItS.Value();
+      if (!myOrigins.IsBound(aVSD)) {
+       myOrigins.Bind(aVSD, aV);
+      }
+    }
   }
 }
 //=======================================================================
-//function : MakeSolids
+//function : MakeSubShapes
 //purpose  : 
 //=======================================================================
-void GEOMAlgo_Gluer::MakeSolids()
+void GEOMAlgo_Gluer::MakeSubShapes (const TopoDS_Shape&  theShape,
+                                    TopTools_MapOfShape& theMS,
+                                    TopoDS_Compound&     theResult)
 {
-  myErrorStatus=0;
+  if (theMS.Contains(theShape))
+    return;
   //
-  Standard_Integer i, aNbS;
-  TopAbs_Orientation anOr;
-  TopoDS_Solid aNewSolid;
-  TopTools_IndexedMapOfShape aMS;
-  TopExp_Explorer aExp;
   BRep_Builder aBB;
   //
-  TopExp::MapShapes(myShape, TopAbs_SOLID, aMS);
-  aNbS=aMS.Extent();
-  for (i=1; i<=aNbS; ++i) {
-    const TopoDS_Solid& aSolid=TopoDS::Solid(aMS(i));
-    anOr=aSolid.Orientation();
+  theMS.Add(theShape);
+  //
+  if (theShape.ShapeType() == TopAbs_COMPOUND ||
+      theShape.ShapeType() == TopAbs_COMPSOLID)
+  {
+    TopoDS_Iterator It (theShape, Standard_True, Standard_True);
+    for (; It.More(); It.Next())
+    {
+      MakeSubShapes(It.Value(), theMS, theResult);
+    }
+  }
+  else if (theShape.ShapeType() == TopAbs_SOLID)
+  {
+    // build a solid
+    TopoDS_Solid aNewSolid;
+    TopExp_Explorer aExpS, aExp;
+    //
+    const TopoDS_Solid& aSolid = TopoDS::Solid(theShape);
+    //
+    TopAbs_Orientation anOr = aSolid.Orientation();
     //
     aBB.MakeSolid(aNewSolid);
     aNewSolid.Orientation(anOr);
     //
     aExp.Init(aSolid, TopAbs_SHELL);
-    for (; aExp.More(); aExp.Next()) {
+    for (; aExp.More(); aExp.Next())
+    {
       const TopoDS_Shape& aShell=aExp.Current();
       const TopoDS_Shape& aShellR=myOrigins.Find(aShell);
       aBB.Add(aNewSolid, aShellR);
     }
+    //
     TopTools_ListOfShape aLS;
     //
     aLS.Append(aSolid);
     myImages.Bind(aNewSolid, aLS);
     myOrigins.Bind(aSolid, aNewSolid);
+    //
+    aBB.Add(theResult, aNewSolid);
+  }
+  else if (theShape.ShapeType() == TopAbs_WIRE)
+  {
+    if (myKeepNonSolids)
+    {
+      // just add image
+      if (!myOrigins.IsBound(theShape))
+      {
+        // build wire
+        const TopoDS_Wire& aW=TopoDS::Wire(theShape);
+        //
+        TopoDS_Wire newWire;
+        aBB.MakeWire(newWire);
+        //
+        TopExp_Explorer aExpE (aW, TopAbs_EDGE);
+        for (; aExpE.More(); aExpE.Next()) {
+          const TopoDS_Edge& aE=TopoDS::Edge(aExpE.Current());
+          TopoDS_Edge aER=TopoDS::Edge(myOrigins.Find(aE));
+          //
+          aER.Orientation(TopAbs_FORWARD);
+          if (!BRep_Tool::Degenerated(aER)) {
+            // build p-curve
+            //if (bIsUPeriodic) {
+            //  GEOMAlgo_Tools::RefinePCurveForEdgeOnFace(aER, aFFWD, aUMin, aUMax);
+            //}
+            //BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aER, aFFWD);
+            //
+            // orient image
+            Standard_Boolean bIsToReverse=BOPTools_Tools3D::IsSplitToReverse1(aER, aE, myContext);
+            if (bIsToReverse) {
+              aER.Reverse();
+            }
+          }
+          else {
+            aER.Orientation(aE.Orientation());
+          }
+          //
+          aBB.Add(newWire, aER);
+        }
+        // xf
+        TopTools_ListOfShape aLW;
+        //
+        aLW.Append(aW);
+        myImages.Bind(newWire, aLW);
+        myOrigins.Bind(aW, newWire);
+      }
+      const TopoDS_Shape& aShapeR = myOrigins.Find(theShape);
+      aBB.Add(theResult, aShapeR);
+    }
+  }
+  else
+  {
+    if (myKeepNonSolids)
+    {
+      // just add image
+      const TopoDS_Shape& aShapeR = myOrigins.Find(theShape);
+      aBB.Add(theResult, aShapeR);
+    }
+  }
+}
+//=======================================================================
+//function : MakeSolids
+//purpose  : 
+//=======================================================================
+void GEOMAlgo_Gluer::MakeSolids()
+{
+  myErrorStatus=0;
+  //
+  BRep_Builder aBB;
+  TopoDS_Compound aCmp;
+  TopTools_MapOfShape aMS;
+  //
+  aBB.MakeCompound(aCmp);
+  //
+  // Add images of all initial sub-shapes in the result.
+  // If myKeepNonSolids==false, add only solids images.
+  MakeSubShapes(myShape, aMS, aCmp);
+  //
+  myResult=aCmp;
+  //
+  if (aMS.Extent()) {
+    BOP_CorrectTolerances::CorrectCurveOnSurface(myResult);
   }
 }
 //=======================================================================
@@ -343,12 +572,13 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
 {
   myErrorStatus=0;
   //
+  Standard_Boolean bHasNewSubShape;
   Standard_Integer i, aNbF, aNbSDF, iErr;
   TopoDS_Shape aNewShape;
   TopTools_IndexedMapOfShape aMF;
   TopTools_ListIteratorOfListOfShape aItS;
-  GEOMAlgo_PassKey aPKF;
-  GEOMAlgo_IndexedDataMapOfPassKeyListOfShape aMPKLF;
+  GEOMAlgo_PassKeyShape aPKF;
+  GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
   //
   TopExp::MapShapes(myShape, aType, aMF);
   //
@@ -356,7 +586,6 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
   for (i=1; i<=aNbF; ++i) {
     const TopoDS_Shape& aS=aMF(i);
     // 
-    aPKF.Clear();
     if (aType==TopAbs_FACE) {
       const TopoDS_Face& aF=TopoDS::Face(aS);
       FacePassKey(aF, aPKF);
@@ -383,7 +612,7 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
   }
   // check geometric coincidence
   if (myCheckGeometry) {
-    iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTol, myContext); //XX
+    iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTol, myContext); 
     if (iErr) {
       myErrorStatus=200;
       return;
@@ -391,6 +620,7 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
   }
   //
   // Images/Origins
+  //
   aNbF=aMPKLF.Extent();
   for (i=1; i<=aNbF; ++i) {
     const TopTools_ListOfShape& aLSDF=aMPKLF(i);
@@ -400,19 +630,33 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
     }
     //
     const TopoDS_Shape& aS1=aLSDF.First();
-    if (aType==TopAbs_FACE) {
-      TopoDS_Face aNewFace;
-      //
-      const TopoDS_Face& aF1=TopoDS::Face(aS1);
-      MakeFace(aF1, aNewFace);
-      aNewShape=aNewFace;
+    //
+    bHasNewSubShape=Standard_True;
+    // prevent creation of a new shape if there are not
+    // new subshapes of aSS among the originals
+    if (aNbSDF==1) {
+      bHasNewSubShape=HasNewSubShape(aS1);
+      if (!bHasNewSubShape) {
+       aNewShape=aS1;
+       aNewShape.Orientation(TopAbs_FORWARD);
+      }
     }
-    else if (aType==TopAbs_EDGE) {
-      TopoDS_Edge aNewEdge;
-      //
-      const TopoDS_Edge& aE1=TopoDS::Edge(aS1);
-      MakeEdge(aE1, aNewEdge);
-      aNewShape=aNewEdge;
+    //
+    if (bHasNewSubShape) { 
+      if (aType==TopAbs_FACE) {
+       TopoDS_Face aNewFace;
+       //
+       const TopoDS_Face& aF1=TopoDS::Face(aS1);
+       MakeFace(aF1, aNewFace);
+       aNewShape=aNewFace;
+      }
+      else if (aType==TopAbs_EDGE) {
+       TopoDS_Edge aNewEdge;
+       //
+       const TopoDS_Edge& aE1=TopoDS::Edge(aS1);
+       MakeEdge(aE1, aNewEdge);
+       aNewShape=aNewEdge;
+      }
     }
     //
     myImages.Bind(aNewShape, aLSDF);
@@ -427,135 +671,115 @@ void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
   }
 }
 //=======================================================================
-//function : MakeVertices
+//function : CheckResult
 //purpose  : 
 //=======================================================================
-void GEOMAlgo_Gluer::MakeVertices()
+void GEOMAlgo_Gluer::CheckResult()
 {
   myErrorStatus=0;
   //
-  Standard_Boolean bFound; 
-  Standard_Integer i, aNbV, aIndex, aNbVSD;
-  TColStd_ListIteratorOfListOfInteger aIt;
-  Handle(Bnd_HArray1OfBox) aHAB;
-  Bnd_BoundSortBox aBSB;
-  TopoDS_Shape aSTmp;
-  TopTools_IndexedMapOfShape aMV;
-  TopTools_ListIteratorOfListOfShape aItS;
-  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
-  GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
-  GEOMAlgo_IndexedDataMapOfShapeBox aMSB;
-  //
-  TopExp::MapShapes(myShape, TopAbs_VERTEX, aMV);
-  aNbV=aMV.Extent();
-  if (!aNbV) {
-    myErrorStatus=2; // no vertices in source shape
-    return;
-  }
-  //
-  aHAB=new Bnd_HArray1OfBox(1, aNbV);
-  //
-  for (i=1; i<=aNbV; ++i) {
-    const TopoDS_Shape& aV=aMV(i);
-    Bnd_Box aBox;
-    //
-    aBox.SetGap(myTol);//XX 
-    BRepBndLib::Add(aV, aBox);
-    aHAB->SetValue(i, aBox);
-    aMIS.Add(i, aV);
-    aMSB.Add(aV, aBox); 
+  if (myResult.IsNull()) {
+    myErrorStatus=6;
+    return; 
   }
+  // 
+  Standard_Boolean bFound;
+  Standard_Integer i, j, aNbS, aNbFS, aNbSx;
+  TopTools_IndexedMapOfShape aMS, aMFS;
+  TopTools_IndexedDataMapOfShapeListOfShape aMFR;
   //
-  aBSB.Initialize(aHAB);
+  TopExp::MapShapesAndAncestors(myResult, TopAbs_FACE, TopAbs_SOLID, aMFR);
+  TopExp::MapShapes(myResult, TopAbs_SOLID, aMS);
   //
-  for (i=1; i<=aNbV; ++i) {
-    const TopoDS_Shape& aV=aMV(i);
-    const Bnd_Box& aBoxV=aMSB.FindFromKey(aV);
-    const TColStd_ListOfInteger& aLI=aBSB.Compare(aBoxV);
-    aNbVSD=aLI.Extent();
-    if (!aNbVSD) {
-      myErrorStatus=3; // it must not be 
-      return;
-    }
+  
+  myNbAlone=0;
+  aNbS=aMS.Extent();
+  for (i=1; i<=aNbS; ++i) {
+    const TopoDS_Shape& aSolid=aMS(i);
     //
-    // Images
-    TopTools_ListOfShape aLVSD;
-    TopoDS_Shape aVF;
+    aMFS.Clear();
+    TopExp::MapShapes(aSolid, TopAbs_FACE, aMFS);
     //
     bFound=Standard_False;
-    aIt.Initialize(aLI);
-    for (; aIt.More(); aIt.Next()) {
-      aIndex=aIt.Value();
-      const TopoDS_Shape& aVx=aMIS.FindFromKey(aIndex);
-      if (myImages.IsBound(aVx)) {
-       bFound=Standard_True;
-       aVF=aVx;
+    aNbFS=aMFS.Extent();
+    for (j=1; j<=aNbFS; ++j) {
+      const TopoDS_Shape& aFS=aMFS(j);
+      if (aMFR.Contains(aFS)) {
+       const TopTools_ListOfShape& aLSx=aMFR.FindFromKey(aFS);
+       aNbSx=aLSx.Extent();
+       if (aNbSx==2) {
+         bFound=!bFound;
+         break;
+       }
       }
-      aLVSD.Append(aVx);
-    }
-    if (bFound) {
-      TopTools_ListOfShape& aLVI=myImages.ChangeFind(aVF);
-      aLVI.Append(aLVSD);
     }
-    else {
-      myImages.Bind(aV, aLVSD);
+    //
+    if (!bFound) {
+      myWarningStatus=1;
+      ++myNbAlone;
+      //break;
     }
   }
+}
+//=======================================================================
+//function : CheckData
+//purpose  : 
+//=======================================================================
+void GEOMAlgo_Gluer::CheckData()
+{
+  myErrorStatus=0;
   //
-  // Refine Images
-  aItIm.Initialize(myImages);
-  for (; aItIm.More(); aItIm.Next()) {
-    TopTools_ListOfShape aLVSDNew;
-    TopTools_MapOfShape aM;
-    //
-    const TopoDS_Shape& aV=aItIm.Key();
-    const TopTools_ListOfShape& aLVSD=aItIm.Value();
-    aItS.Initialize(aLVSD);
-    for (; aItS.More(); aItS.Next()) {
-      const TopoDS_Shape& aVSD=aItS.Value();
-      if (aM.Add(aVSD)) {
-       aLVSDNew.Append(aVSD);
-      }
-    }
-    TopTools_ListOfShape& aLVI=myImages.ChangeFind(aV);
-    aLVI.Clear();
-    aLVI.Append(aLVSDNew);
+  if (myShape.IsNull()) {
+    myErrorStatus=5;
+    return; 
   }
+}
+//=======================================================================
+//function : InnerTolerance
+//purpose  : 
+//=======================================================================
+void GEOMAlgo_Gluer::InnerTolerance()
+{
+  myErrorStatus=0;
   //
-  // Origins
-  aItIm.Initialize(myImages);
-  for (; aItIm.More(); aItIm.Next()) {
-    const TopoDS_Shape& aV=aItIm.Key();
-    //
-    const TopTools_ListOfShape& aLVSD=myImages.Find(aV);
-    aItS.Initialize(aLVSD);
-    for (; aItS.More(); aItS.Next()) {
-      const TopoDS_Shape& aVSD=aItS.Value();
-      if (!myOrigins.IsBound(aVSD)) {
-       myOrigins.Bind(aVSD, aV);
-      }
+  /*
+  Standard_Integer i;
+  Standard_Real aX[3][2], dH, dHmin, aCoef, aTolTresh;
+  Bnd_Box aBox;
+  //
+  BRepBndLib::Add(myShape, aBox);
+  aBox.Get(aX[0][0], aX[1][0], aX[2][0], aX[0][1], aX[1][1], aX[2][1]);
+  //
+  dHmin=aX[0][1]-aX[0][0];
+  for (i=1; i<3; ++i) {
+    dH=aX[i][1]-aX[i][0];
+    if (dH<dHmin) {
+      dHmin=dH;
     }
   }
   //
+  myTol=myTolerance;
+  aCoef=0.01;
+  aTolTresh=aCoef*dHmin;
+  if (myTol>aTolTresh) {
+    myTol=aTolTresh;
+  }
+  */
+  myTol=myTolerance;
 }
 //=======================================================================
 //function : FacePassKey
 //purpose  : 
 //=======================================================================
 void GEOMAlgo_Gluer::FacePassKey(const TopoDS_Face& aF, 
-                                GEOMAlgo_PassKey& aPK)
+                                GEOMAlgo_PassKeyShape& aPK)
 {
-  Standard_Integer i, aNbE, aNbMax;
+  Standard_Integer i, aNbE;
   TopTools_ListOfShape aLE;
   TopTools_IndexedMapOfShape aME;
   //
   TopExp::MapShapes(aF, TopAbs_EDGE, aME);
   aNbE=aME.Extent();
-  aNbMax=aPK.NbMax();
-  if (!aNbE || aNbE>aNbMax) {
-     myErrorStatus=101; // temprorary
-     return;
-  }
   //
   for (i=1; i<=aNbE; ++i) {
     const TopoDS_Shape& aE=aME(i);
@@ -566,14 +790,14 @@ void GEOMAlgo_Gluer::FacePassKey(const TopoDS_Face& aF,
     const TopoDS_Shape& aER=myOrigins.Find(aE);
     aLE.Append(aER);
   }
-  aPK.SetIds(aLE);
+  aPK.SetShapes(aLE);
 }
 //=======================================================================
 //function : EdgePassKey
 //purpose  : 
 //=======================================================================
 void GEOMAlgo_Gluer::EdgePassKey(const TopoDS_Edge& aE, 
-                                GEOMAlgo_PassKey& aPK)
+                                GEOMAlgo_PassKeyShape& aPK)
 {
   TopoDS_Vertex aV1, aV2;
   //
@@ -585,7 +809,53 @@ void GEOMAlgo_Gluer::EdgePassKey(const TopoDS_Edge& aE,
   }
   const TopoDS_Shape& aVR1=myOrigins.Find(aV1);
   const TopoDS_Shape& aVR2=myOrigins.Find(aV2);
-  aPK.SetIds(aVR1, aVR2);
+  aPK.SetShapes(aVR1, aVR2);
+}
+//=======================================================================
+//function : MakeVertex
+//purpose  : 
+//=======================================================================
+void GEOMAlgo_Gluer::MakeVertex(const TopTools_ListOfShape& aLV, 
+                               TopoDS_Vertex& aNewVertex)
+{
+  Standard_Integer aNbV;
+  Standard_Real aTolV, aD, aDmax;
+  gp_XYZ aGC;
+  gp_Pnt aP3D, aPGC;
+  TopoDS_Vertex aVx;
+  BRep_Builder aBB;
+  TopTools_ListIteratorOfListOfShape aIt;
+  //
+  aNbV=aLV.Extent();
+  if (!aNbV) {
+    return;
+  }
+  //
+  // center of gravity
+  aGC.SetCoord(0.,0.,0.);
+  aIt.Initialize(aLV);
+  for (; aIt.More(); aIt.Next()) {
+    aVx=TopoDS::Vertex(aIt.Value());
+    aP3D=BRep_Tool::Pnt(aVx);
+    aGC+=aP3D.XYZ();
+  }
+  aGC/=(Standard_Real)aNbV;
+  aPGC.SetXYZ(aGC);
+  //
+  // tolerance value
+  aDmax=-1.;
+  aIt.Initialize(aLV);
+  for (; aIt.More(); aIt.Next()) {
+    aVx=TopoDS::Vertex(aIt.Value());
+    aP3D=BRep_Tool::Pnt(aVx);
+    aTolV=BRep_Tool::Tolerance(aVx);
+    aD=aPGC.Distance(aP3D)+aTolV;
+    if (aD>aDmax) {
+      aDmax=aD;
+    }
+  }
+  //
+  aBB.MakeVertex (aNewVertex, aPGC, aDmax);
 }
 //=======================================================================
 //function : MakeEdge
@@ -596,10 +866,13 @@ void GEOMAlgo_Gluer::MakeEdge(const TopoDS_Edge& aE,
 {
   myErrorStatus=0;
   //
+  Standard_Boolean bIsDE;
   Standard_Real aT1, aT2;
   TopoDS_Vertex aV1, aV2, aVR1, aVR2;
   TopoDS_Edge aEx;
   //
+  bIsDE=BRep_Tool::Degenerated(aE);
+  //
   aEx=aE;
   aEx.Orientation(TopAbs_FORWARD);
   //
@@ -613,9 +886,31 @@ void GEOMAlgo_Gluer::MakeEdge(const TopoDS_Edge& aE,
   aVR2=TopoDS::Vertex(myOrigins.Find(aV2));
   aVR2.Orientation(TopAbs_REVERSED);
   //
-  BOPTools_Tools::MakeSplitEdge(aEx, aVR1, aT1, aVR2, aT2, aNewEdge); 
+  if (bIsDE) {
+    Standard_Real aTol;
+    BRep_Builder aBB;
+    TopoDS_Edge E;
+    TopAbs_Orientation anOrE;
+    //
+    anOrE=aE.Orientation();
+    aTol=BRep_Tool::Tolerance(aE);
+    //
+    E=aEx;
+    E.EmptyCopy();
+    //
+    aBB.Add  (E, aVR1);
+    aBB.Add  (E, aVR2);
+    aBB.Range(E, aT1, aT2);
+    aBB.Degenerated(E, Standard_True);
+    aBB.UpdateEdge(E, aTol);
+    //
+    aNewEdge=E;
+  }
+  //
+  else {
+    BOPTools_Tools::MakeSplitEdge(aEx, aVR1, aT1, aVR2, aT2, aNewEdge); 
+  }
 }
-//
 //=======================================================================
 //function : MakeFace
 //purpose  : 
@@ -625,13 +920,14 @@ void GEOMAlgo_Gluer::MakeFace(const TopoDS_Face& aF,
 {
   myErrorStatus=0;
   //
-  Standard_Boolean bIsToReverse;
-  Standard_Real aTol;
+  Standard_Boolean bIsToReverse, bIsUPeriodic;
+  Standard_Real aTol, aUMin, aUMax, aVMin, aVMax;
   TopoDS_Edge aER;
   TopoDS_Wire newWire;
   TopoDS_Face aFFWD, newFace;
   TopLoc_Location aLoc;
   Handle(Geom_Surface) aS;
+  Handle(Geom2d_Curve) aC2D;
   TopExp_Explorer aExpW, aExpE;
   BRep_Builder aBB;
   //
@@ -639,7 +935,9 @@ void GEOMAlgo_Gluer::MakeFace(const TopoDS_Face& aF,
   aFFWD.Orientation(TopAbs_FORWARD);
   //
   aS=BRep_Tool::Surface(aFFWD, aLoc);
+  bIsUPeriodic=GEOMAlgo_Tools::IsUPeriodic(aS);
   aTol=BRep_Tool::Tolerance(aFFWD);
+  BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
   //
   aBB.MakeFace (newFace, aS, aLoc, aTol);
   //
@@ -651,17 +949,34 @@ void GEOMAlgo_Gluer::MakeFace(const TopoDS_Face& aF,
     for (; aExpE.More(); aExpE.Next()) {
       const TopoDS_Edge& aE=TopoDS::Edge(aExpE.Current());
       aER=TopoDS::Edge(myOrigins.Find(aE));
+      //
       aER.Orientation(TopAbs_FORWARD);
-      // build p-curve
-      BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aER, aFFWD);
-      // orient image 
-      bIsToReverse=BOPTools_Tools3D::IsSplitToReverse1(aER, aE, myContext);
-      if (bIsToReverse) {
-       aER.Reverse();
+      if (!BRep_Tool::Degenerated(aER)) {
+       // build p-curve
+       if (bIsUPeriodic) {
+         GEOMAlgo_Tools::RefinePCurveForEdgeOnFace(aER, aFFWD, aUMin, aUMax);
+       }
+       BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aER, aFFWD);
+       
+       // orient image 
+       bIsToReverse=BOPTools_Tools3D::IsSplitToReverse1(aER, aE, myContext);
+       if (bIsToReverse) {
+         aER.Reverse();
+       }
+      }
+      else {
+       aER.Orientation(aE.Orientation());
       }
       //
       aBB.Add(newWire, aER);
     }
+    // xf
+    TopTools_ListOfShape aLW;
+    //
+    aLW.Append(aW);
+    myImages.Bind(newWire, aLW);
+    myOrigins.Bind(aW, newWire);
+    // xt
     aBB.Add(newFace, newWire);
   }
   aNewFace=newFace;
@@ -683,53 +998,140 @@ Standard_Boolean GEOMAlgo_Gluer::IsToReverse(const TopoDS_Face& aFR,
   bRet=Standard_False;
   //
   aExp.Init(aF, TopAbs_EDGE);
-  if (!aExp.More()) {
-    return bRet;
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
+    //
+    if (BRep_Tool::Degenerated(aE)) {
+      continue;
+    }
+    //
+    const TopoDS_Edge& aER=TopoDS::Edge(myOrigins.Find(aE));
+    //
+    aC3D=BRep_Tool::Curve(aE, aT1, aT2);
+    aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
+    aC3D->D0(aT, aP);
+    myContext.ProjectPointOnEdge(aP, aER, aTR);
+    //
+    BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
+    if (aF.Orientation()==TopAbs_REVERSED) {
+      aDNF.Reverse();
+    }
+    //
+    BOPTools_Tools3D::GetNormalToFaceOnEdge (aER, aFR, aTR, aDNFR);
+    if (aFR.Orientation()==TopAbs_REVERSED) {
+      aDNFR.Reverse();
+    }
+    //
+    aScPr=aDNF*aDNFR;
+    return (aScPr<0.);
   }
-  const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
-  const TopoDS_Edge& aER=TopoDS::Edge(myOrigins.Find(aE));
+  return bRet;
+}
+//=======================================================================
+//function : HasNewSubShape
+//purpose  : 
+//=======================================================================
+Standard_Boolean GEOMAlgo_Gluer::HasNewSubShape(const TopoDS_Shape& aS)const
+{
+  Standard_Boolean bRet;
+  Standard_Integer i, aNbSS;
+  TopTools_IndexedMapOfShape aMSS;
   //
-  aC3D=BRep_Tool::Curve(aE, aT1, aT2);
-  aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
-  aC3D->D0(aT, aP);
-  myContext.ProjectPointOnEdge(aP, aER, aTR);
+  GetSubShapes(aS, aMSS);
   //
-  BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
-  if (aF.Orientation()==TopAbs_REVERSED) {
-    aDNF.Reverse();
+  bRet=Standard_False;
+  aNbSS=aMSS.Extent();
+  for (i=1; i<=aNbSS; ++i) {
+    const TopoDS_Shape& aSS=aMSS(i);
+    if (aSS.ShapeType()==TopAbs_WIRE) {
+      continue;
+    }
+    //
+    bRet=!myOrigins.IsBound(aSS);
+    if (bRet) {
+      return bRet;
+    }
+    //
+    const TopoDS_Shape& aSSIm=myOrigins.Find(aSS);
+    bRet=!aSSIm.IsSame(aSS);
+    if (bRet) {
+      return bRet;
+    }
   }
+  return bRet;
+}
+//=======================================================================
+//function : GetSubShapes
+//purpose  : 
+//=======================================================================
+void GetSubShapes(const TopoDS_Shape& aS,
+                 TopTools_IndexedMapOfShape& aMSS)
+{
+  Standard_Integer aR;
+  TopAbs_ShapeEnum aType;
+  TopoDS_Iterator aIt;
   //
-  BOPTools_Tools3D::GetNormalToFaceOnEdge (aER, aFR, aTR, aDNFR);
-  if (aFR.Orientation()==TopAbs_REVERSED) {
-    aDNFR.Reverse();
+  aType=aS.ShapeType();
+  aR=(Standard_Integer)aType+1;
+  if (aR>TopAbs_VERTEX) {
+    return;
   }
   //
-  aScPr=aDNF*aDNFR;
-  return (aScPr<0.);
+  aIt.Initialize(aS);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aSS=aIt.Value();
+    aMSS.Add(aSS);
+    GetSubShapes(aSS, aMSS);
+  }
 }
-//
 //=======================================================================
-//function : BuildResult
+//function : Modified
 //purpose  : 
 //=======================================================================
-void GEOMAlgo_Gluer::BuildResult()
+const TopTools_ListOfShape& GEOMAlgo_Gluer::Modified (const TopoDS_Shape& aS) 
 {
-  TopoDS_Compound aCmp;
-  BRep_Builder aBB;
   TopAbs_ShapeEnum aType;
-  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
   //
-  aBB.MakeCompound(aCmp);
+  myGenerated.Clear();
   //
-  aItIm.Initialize(myImages);
-  for (; aItIm.More(); aItIm.Next()) {
-    const TopoDS_Shape& aIm=aItIm.Key();
-    aType=aIm.ShapeType();
-    if(aType==myTypeResult) {
-      aBB.Add(aCmp, aIm);
+  aType=aS.ShapeType();
+  if (aType==TopAbs_VERTEX ||
+      aType==TopAbs_EDGE   || 
+      aType==TopAbs_WIRE   || 
+      aType==TopAbs_FACE   || 
+      aType==TopAbs_SHELL  || 
+      aType==TopAbs_SOLID) {  
+    if(myOrigins.IsBound(aS)) {
+      const TopoDS_Shape& aSnew=myOrigins.Find(aS);
+      if (!aSnew.IsSame(aS)) {
+       myGenerated.Append(aSnew);
+      }
     }
   }
-  myResult=aCmp;
+  //
+  return myGenerated;
+}
+//=======================================================================
+//function : Generated
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& GEOMAlgo_Gluer::Generated(const TopoDS_Shape& )
+{
+  myGenerated.Clear();
+  return myGenerated;
+}
+//=======================================================================
+//function : IsDeleted
+//purpose  : 
+//=======================================================================
+Standard_Boolean GEOMAlgo_Gluer::IsDeleted (const TopoDS_Shape& aS)
+{
+  Standard_Boolean bRet=Standard_False;
+  //
+  const TopTools_ListOfShape& aL=Modified(aS);
+  bRet=!aL.IsEmpty();
+  //
+  return bRet;
 }
 //
 // ErrorStatus
@@ -748,81 +1150,3 @@ void GEOMAlgo_Gluer::BuildResult()
 //
 // 1   - some shapes can not be glued by faces
 //
-     
-/*
-//
-// CHRONOMETER
-//
-#include <Standard_Static.hxx>
-#include <OSD_Chronometer.hxx>
-
-static Standard_Real S_ChronoTime;
-Standard_STATIC(OSD_Chronometer, S_Chrono);
-
-static void StartChrono();
-static void StopChrono(); 
-static void TimeShow(); 
-static void TimeReset(); 
-static int HasChrono();
-
-//=======================================================================
-//function : StartChrono
-//purpose  : 
-//=======================================================================
-void StartChrono() 
-{
-  if (HasChrono()){
-    S_Chrono().Reset();
-    S_Chrono().Start();
-  }
-}
-
-//=======================================================================
-//function : StopChrono
-//purpose  : 
-//=======================================================================
-void StopChrono() 
-{ 
-  if (HasChrono()) {
-    Standard_Real Chrono;
-    S_Chrono().Stop();
-    S_Chrono().Show(Chrono);
-    //
-    S_ChronoTime+=Chrono;
-  }
-}
-//=======================================================================
-//function : TimeReset
-//purpose  : 
-//=======================================================================
-void TimeReset() 
-{
-  if (HasChrono()){
-    S_ChronoTime=0;
-  }
-}
-//=======================================================================
-//function : TimeShow
-//purpose  : 
-//=======================================================================
-void TimeShow() 
-{ 
-  if (HasChrono()){
-    cout << "Tps: " << S_ChronoTime << endl;
-  }
-}
-//=======================================================================
-//function : HasChrono
-//purpose  : 
-//=======================================================================
-int HasChrono() 
-{ 
-  char *xr=getenv ("XCHRONO");
-  if (xr!=NULL){
-    if (!strcmp (xr, "yes")) {
-      return 1;
-    }
-  }
-  return 0;
-}
-*/