Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/geom.git] / src / PARTITION / Partition_Inter2d.cxx
index e15bf24e3b6a73e4979080dd8743800860eceeba..4394e45a6e2475a6b4fc8d81be061b5fb12324c0 100644 (file)
@@ -1,23 +1,23 @@
 //  GEOM PARTITION : partition algorithm
 //
 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//  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
 //
 //
 //
@@ -31,30 +31,26 @@ using namespace std;
 
 #include "utilities.h"
 
-#include <TopExp.hxx>
-#include <TopExp_Explorer.hxx>
-
+#include <BRepAdaptor_Curve.hxx>
 #include <BRepAlgo_AsDes.hxx>
-
+#include <BRepLib_MakeVertex.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
-#include <BRepLib_MakeVertex.hxx>
-#include <BRepAdaptor_Curve.hxx>
-
-#include <gp_Pnt.hxx>
-#include <TopoDS.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
+#include <Geom_Surface.hxx>
+#include <Precision.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopOpeBRepDS_Transition.hxx>
 #include <TopOpeBRep_EdgesIntersector.hxx>
 #include <TopOpeBRep_Point2d.hxx>
-#include <TopOpeBRepDS_Transition.hxx>
-#include <TopTools_ListOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_MapOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
-
-#include <stdio.h>
-#include <Precision.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <gp_Pnt.hxx>
 
 #ifdef DEB
 static Standard_Boolean TestEdges = 0;
@@ -63,21 +59,110 @@ static Standard_Integer NbE2d = 0;
 #endif
 
 //=======================================================================
-//function : StorePart2d
-//purpose  : 
+//function : getOtherShape
+//purpose  :
+//=======================================================================
+
+static TopoDS_Shape getOtherShape(const TopoDS_Shape&         theS,
+                                  const TopTools_ListOfShape& theSList)
+{
+  TopTools_ListIteratorOfListOfShape anIt( theSList );
+  for ( ; anIt.More(); anIt.Next() )
+    if (!theS.IsSame( anIt.Value() ))
+      return anIt.Value();
+
+  return TopoDS_Shape();
+}
+
+//=======================================================================
+//function : findVOnE
+//purpose  : on theE, find a vertex close to theV, such that an edge
+//           passing through it is an itersection of theF1 and theF2.
+//           theE intersects theE2 at theV
+//=======================================================================
+
+static Standard_Boolean findVOnE(const TopoDS_Vertex &         theV,
+                                 const TopoDS_Edge&            theE,
+                                 const TopoDS_Edge&            theE2,
+                                 const TopoDS_Shape&           theF1,
+                                 const TopoDS_Shape&           theF2,
+                                 const Handle(BRepAlgo_AsDes)& theAsDes,
+                                 TopoDS_Vertex &               theFoundV)
+{
+  Standard_Real MinDist2 = ::RealLast();
+  gp_Pnt P;
+
+  // check all vertices on theE
+  const TopTools_ListOfShape& aVList = theAsDes->Descendant( theE );
+  TopTools_ListIteratorOfListOfShape anIt( aVList );
+  if (anIt.More())
+    P = BRep_Tool::Pnt( theV );
+  for ( ; anIt.More(); anIt.Next() )
+  {
+    // check by distance
+    TopoDS_Vertex & V = TopoDS::Vertex( anIt.Value() );
+    Standard_Real dist2 = P.SquareDistance( BRep_Tool::Pnt( V ));
+    if (dist2 < MinDist2)
+      MinDist2 = dist2;
+    else
+      continue;
+
+    // V is a candidate if among edges passing through V there is one
+    // which is an intersection of theF1 and theF2
+    TopTools_ListIteratorOfListOfShape anEIt( theAsDes->Ascendant( V ));
+    Standard_Boolean isOk = Standard_False;
+    for (  ; !isOk && anEIt.More(); anEIt.Next() )
+    {
+      const TopoDS_Shape & E2 = anEIt.Value();
+      if ( theE2.IsSame( E2 ))
+        continue;
+      const TopTools_ListOfShape & aFList = theAsDes->Ascendant( E2 );
+      if (aFList.IsEmpty())
+        continue;
+      if ( theF1.IsSame( aFList.First() ))
+        isOk = theF2.IsSame( aFList.Last() );
+      else
+        isOk = theF2.IsSame( aFList.First() ) && theF1.IsSame( aFList.Last() );
+    }
+    if (isOk)
+      theFoundV = V;
+  }
+
+  if (theFoundV.IsNull())
+    return Standard_False;
+
+  // check that MinDist2 is not too large
+  Standard_Real f, l;
+  TopLoc_Location L;
+  Handle(Geom_Curve) aCurve = BRep_Tool::Curve( theE, L, f, l );
+  gp_Pnt P1 = aCurve->Value( f );
+  gp_Pnt P2 = aCurve->Value( 0.3 * f + 0.7 * l );
+  //gp_Pnt P2 = aCurve->Value( 0.5 * ( f + l ));
+  if (MinDist2 > P1.SquareDistance( P2 ))
+    return Standard_False;
+
+#ifdef DEB
+  MESSAGE("findVOnE: found MinDist = " << sqrt (MinDist2));
+#endif
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : AddVonE
+//purpose  : Put V in AsDes as intersection of E1 and E2.
+//           Check that vertex equal to V already exists on one
+//           of edges, in  such  a  case,  V  is  not added but
+//           existing vertex is updated to  be on E1 and E2 and
+//           is returned insead of V.
 //=======================================================================
 
-// static void  StorePart2d (const TopoDS_Edge&       E1,
-//                       const TopoDS_Edge&       E2,
-//                       TopTools_ListOfShape&    LV1,
-//                       TopTools_ListOfShape&    LV2,
-//                       Handle(BRepAlgo_AsDes)   AsDes,
-//                       Standard_Real            Tol)
 TopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV,
-                                        const TopoDS_Edge&   E1,
-                                        const TopoDS_Edge&   E2,
-                                        const Handle(BRepAlgo_AsDes)& AsDes)
-                                        
+                                         const TopoDS_Edge&   E1,
+                                         const TopoDS_Edge&   E2,
+                                         const Handle(BRepAlgo_AsDes)& AsDes,
+                                         const TopoDS_Face&   theF)
+
 {
   //-------------------------------------------------------------
   // test if the points of intersection already exist. If not,
@@ -86,119 +171,131 @@ TopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV,
   //-------------------------------------------------------------
   const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1);
   const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2);
-  TopTools_ListOfShape        NewVOnE1;
-  TopTools_ListOfShape        NewVOnE2;
   gp_Pnt                      P1,P2;
   TopoDS_Vertex               V1,V2;
-  TopTools_ListIteratorOfListOfShape it, itLV1, itLV2;
+  TopTools_ListIteratorOfListOfShape it;
   BRep_Builder                       B;
   TopAbs_Orientation                 O1,O2;
   Standard_Real                      U1,U2;
   Standard_Real                      Tol,Tol1,Tol2;
   Standard_Boolean                   OnE1,OnE2;
 
-//   for (itLV1.Initialize(LV1),itLV2.Initialize(LV2);
-//        itLV1.More();
-//        itLV1.Next()  ,itLV2.Next()) {
-
-    TopoDS_Vertex V    = theV;
-//     TopoDS_Vertex V    = TopoDS::Vertex(itLV1.Value());
-
-    U1 = BRep_Tool::Parameter(V,E1);
-    U2 = BRep_Tool::Parameter(V,E2);
-    O1 = V.Orientation();
-    O2 = O1;///itLV2.Value().Orientation();
-    P1  = BRep_Tool::Pnt(V);
-    Tol = BRep_Tool::Tolerance( V );
-    OnE1 = OnE2 = Standard_False;
-    
+  TopoDS_Vertex V    = theV;
+
+  U1 = BRep_Tool::Parameter(V,E1);
+  U2 = BRep_Tool::Parameter(V,E2);
+  O1 = V.Orientation();
+  O2 = O1;
+  P1  = BRep_Tool::Pnt(V);
+  Tol = BRep_Tool::Tolerance( V );
+  OnE1 = OnE2 = Standard_False;
+
+  //-----------------------------------------------------------------
+  // Search if the point of intersection is a vertex of E1.
+  //-----------------------------------------------------------------
+  for (it.Initialize(VOnE1); it.More(); it.Next()) {
+    const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );
+    if (V.IsSame( CV )) {
+      V1   = V;
+      OnE1 = Standard_True;
+      break;
+    }
+    P2 = BRep_Tool::Pnt( CV );
+    Tol1 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));
+    if (P1.SquareDistance(P2) <= Tol1*Tol1) {
+      V    = CV;
+      V1   = V;
+      OnE1 = Standard_True;
+      break;
+    }
+  }
+  if (OnE1) {
     //-----------------------------------------------------------------
-    // Search if the point of intersection is a vertex of E1.
+    // Search if the vertex found is still on E2.
     //-----------------------------------------------------------------
-    for (it.Initialize(VOnE1); it.More(); it.Next()) {
-      const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );
-      if (V.IsSame( CV )) {
-       V1   = V;
-        OnE1 = Standard_True;
-        break;
-      }
-      P2 = BRep_Tool::Pnt( CV );
-      Tol1 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));
-      if (P1.SquareDistance(P2) <= Tol1*Tol1) {
-        V    = CV;
-        V1   = V;
-        OnE1 = Standard_True;
+    for (it.Initialize(VOnE2); it.More(); it.Next()) {
+      if (V.IsSame( it.Value() )) {
+        OnE2 = Standard_True;
+        V2   = V;
         break;
       }
     }
-    if (OnE1) {
+  }
+  if (!OnE2) {
+    for (it.Initialize(VOnE2); it.More(); it.Next()) {
       //-----------------------------------------------------------------
-      // Search if the vertex found is still on E2.
+      // Search if the point of intersection is a vertex of E2.
       //-----------------------------------------------------------------
-      for (it.Initialize(VOnE2); it.More(); it.Next()) {
-        if (V.IsSame( it.Value() )) {
-          OnE2 = Standard_True;
-          V2   = V;
-          break;
-        }
+      const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );
+      P2 = BRep_Tool::Pnt( CV );
+      Tol2 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));
+      if (P1.SquareDistance(P2) <= Tol2*Tol2) {
+        V  = CV;
+        V2 = V;
+        OnE2 = Standard_True;
+        break;
       }
     }
-    if (!OnE2) {
-      for (it.Initialize(VOnE2); it.More(); it.Next()) {
-        //-----------------------------------------------------------------
-        // Search if the point of intersection is a vertex of E2.
-        //-----------------------------------------------------------------
-        const TopoDS_Vertex& CV = TopoDS::Vertex( it.Value() );
-        P2 = BRep_Tool::Pnt( CV );
-        Tol2 = 1.1*(Tol + BRep_Tool::Tolerance( CV ));
-        if (P1.SquareDistance(P2) <= Tol2*Tol2) {
-          V  = CV;
-          V2 = V;
-          OnE2 = Standard_True;
-          break;
-        }
-      }
+  }
+
+
+  if (!OnE1 && !OnE2 && !theF.IsNull())
+  {
+    // if 3 faces intersects each others, 3 new edges on them must pass
+    // through one vertex but real intersection points of each
+    // pair of edges are sometimes more far than a tolerance.
+    // Try to analitically find vertices that E1 and E2 must pass trough
+
+    TopoDS_Shape F1 = getOtherShape( theF, AsDes->Ascendant( E1 ));
+    TopoDS_Shape F2 = getOtherShape( theF, AsDes->Ascendant( E2 ));
+    if (!F1.IsNull() && !F2.IsNull() && !F1.IsSame( F2 ))
+    {
+      OnE1 = findVOnE ( theV, E1, E2, F1, F2, AsDes, V1 );
+      OnE2 = findVOnE ( theV, E2, E1, F1, F2, AsDes, V2 );
+      if (OnE2) V = V2;
+      if (OnE1) V = V1;
     }
-    if (OnE1 && OnE2) {
-      if (!V1.IsSame(V2)) {
-       Standard_Real UV2;
-       TopoDS_Edge   EWE2;
-       TopoDS_Vertex VI;
-       const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
-
-       for (it.Initialize(EdgeWithV2); it.More(); it.Next()) {
-         EWE2  = TopoDS::Edge(it.Value());
-         VI = V2;
-         VI.Orientation(TopAbs_INTERNAL);
-         UV2 = BRep_Tool::Parameter(VI,EWE2);
-         VI = V1;
-         VI.Orientation(TopAbs_INTERNAL);
-         B.UpdateVertex(VI,UV2,EWE2, Max(Tol1,Tol2));
-       }
-       AsDes->Replace(V2,V1);
+  }
+
+  if (OnE1 && OnE2) {
+    if (!V1.IsSame(V2)) {
+      // replace V1 with V2 on all edges V1 is on
+      Standard_Real UV1;
+      TopoDS_Edge   EWE1;
+      TopoDS_Vertex VI;
+      const TopTools_ListOfShape& EdgeWithV1 = AsDes->Ascendant(V1);
+
+      for (it.Initialize(EdgeWithV1); it.More(); it.Next()) {
+        EWE1  = TopoDS::Edge(it.Value());
+        VI = V1;
+        VI.Orientation(TopAbs_INTERNAL);
+        UV1 = BRep_Tool::Parameter(VI,EWE1);
+        VI = V2;
+        VI.Orientation(TopAbs_INTERNAL);
+        B.UpdateVertex( VI, UV1, EWE1, GetTolerance( VI, UV1, EWE1, AsDes));
       }
+      AsDes->Replace(V1,V2);
+      V = V2;
     }
-    // add existing vertices instead of new ones
-    if (!OnE1) {
-      if (OnE2) {
-       V.Orientation(TopAbs_INTERNAL);
-       B.UpdateVertex(V,U1,E1, Tol2);
-      }
-      V.Orientation(O1);
-      NewVOnE1.Prepend(V);
+  }
+
+  // add existing vertices instead of new ones
+  if (!OnE1) {
+    if (OnE2) {
+      V.Orientation(TopAbs_INTERNAL);
+      B.UpdateVertex (V, U1, E1, GetTolerance( V, U1, E1, AsDes));
     }
-    if (!OnE2) {
-      if (OnE1) {
-       V.Orientation(TopAbs_INTERNAL);
-       B.UpdateVertex(V,U2,E2, Tol1);
-      }
-      V.Orientation(O2);
-      NewVOnE2.Prepend(V);
+    V.Orientation(O1);
+    AsDes->Add(E1,V);
+  }
+  if (!OnE2) {
+    if (OnE1) {
+      V.Orientation(TopAbs_INTERNAL);
+      B.UpdateVertex (V, U2, E2, GetTolerance( V, U2, E2, AsDes ));
     }
-//  }
-  
-  if (!NewVOnE1.IsEmpty()) AsDes->Add(E1,NewVOnE1);
-  if (!NewVOnE2.IsEmpty()) AsDes->Add(E2,NewVOnE2);
+    V.Orientation(O2);
+    AsDes->Add(E2,V);
+  }
 
   return V;
 }
@@ -212,11 +309,11 @@ TopoDS_Vertex Partition_Inter2d::AddVonE(const TopoDS_Vertex& theV,
 //=======================================================================
 
 TopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV,
-                                              const Standard_Real f,
-                                              const Standard_Real l,
-                                              const TopoDS_Edge&  E,
-                                              Standard_Boolean&   isFirst,
-                                              Standard_Real&      minDU)
+                                               const Standard_Real f,
+                                               const Standard_Real l,
+                                               const TopoDS_Edge&  E,
+                                               Standard_Boolean&   isFirst,
+                                               Standard_Real&      minDU)
 {
   TopoDS_Vertex endV;
   Standard_Real U, endU, min;
@@ -238,7 +335,7 @@ TopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV,
     isFirst = Standard_True;
   else
     isFirst = Standard_False;
-  
+
   return endV;
 }
 
@@ -248,10 +345,10 @@ TopoDS_Vertex Partition_Inter2d::FindEndVertex(const TopTools_ListOfShape& LV,
 //=======================================================================
 
 static void treatClosed (const TopoDS_Edge& E1,
-                         const Standard_Real f,
-                         const Standard_Real l,
-                         TopTools_ListOfShape& LV1,
-                         TopTools_ListOfShape& /*LV2*/)
+                          const Standard_Real f,
+                          const Standard_Real l,
+                          TopTools_ListOfShape& LV1,
+                          TopTools_ListOfShape& /*LV2*/)
 {
   Standard_Boolean isFirst=0;
   Standard_Real    minDU = 1.e10;
@@ -261,12 +358,12 @@ static void treatClosed (const TopoDS_Edge& E1,
   if (minDU > Precision::PConfusion())
     return; // not end point
 
-  Standard_Real newU; 
+  Standard_Real newU;
   if (isFirst)
     newU = f + (l - f);
   else
     newU = l - (l - f);
-  
+
   // update end parameter
   BRep_Builder B;
   endV.Orientation(TopAbs_INTERNAL);
@@ -275,21 +372,21 @@ static void treatClosed (const TopoDS_Edge& E1,
 
 //=======================================================================
 //function : EdgesPartition
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 static void EdgesPartition(const TopoDS_Face&            F,
-                          const TopoDS_Edge&            E1,
-                          const TopoDS_Edge&            E2,
-                          const Handle(BRepAlgo_AsDes)& AsDes,
-                          const TopTools_MapOfShape&    NewEdges,
-                          const Standard_Boolean        WithOri)
+                           const TopoDS_Edge&            E1,
+                           const TopoDS_Edge&            E2,
+                           const Handle(BRepAlgo_AsDes)& AsDes,
+                           const TopTools_MapOfShape&    NewEdges,
+                           const Standard_Boolean        WithOri)
 {
 
   Standard_Real f[3],l[3];
   Standard_Real MilTol2;
   Standard_Real Tol = Max (BRep_Tool::Tolerance(E1),
-                          BRep_Tool::Tolerance(E2));
+                           BRep_Tool::Tolerance(E2));
   MilTol2 = Tol * Tol * 10;
 
   BRep_Tool::Range(E1, f[1], l[1]);
@@ -319,10 +416,10 @@ static void EdgesPartition(const TopoDS_Face&            F,
       TopExp_Explorer exp(F2, TopAbs_EDGE);
       TopExp::MapShapes(F1, TopAbs_EDGE, ME);
       for (; exp.More(); exp.Next()) {
-       if (ME.Contains( exp.Current())) {
-         intersect = Standard_False;
-         break;
-       }
+        if (ME.Contains( exp.Current())) {
+          intersect = Standard_False;
+          break;
+        }
       }
     }
   }
@@ -341,7 +438,8 @@ static void EdgesPartition(const TopoDS_Face&            F,
 
     Standard_Boolean rejectreducedsegmentpoints = Standard_False;
     EInter.InitPoint(rejectreducedsegmentpoints);
-    for (;EInter.MorePoint();EInter.NextPoint()) {
+    for ( ; EInter.MorePoint(); EInter.NextPoint() )
+    {
       const TopOpeBRep_Point2d& P2D = EInter.Point();
       const gp_Pnt&    P    = P2D.Value();
       TopoDS_Vertex    V    = BRepLib_MakeVertex(P);
@@ -353,36 +451,25 @@ static void EdgesPartition(const TopoDS_Face&            F,
       gp_Pnt P2 = CE2.Value(P2D.Parameter(2));
       Standard_Real sqd1 = P1.SquareDistance(P);
       Standard_Real sqd2 = P2.SquareDistance(P);
-      if (sqd1 > MilTol2 || sqd2 > MilTol2  ) {
-       //MESSAGE ( "Inter2d : Solution rejected, dist: " << sqrt(Max(sqd1,sqd2)) )
-#ifdef DEB
-       if (TestEdges) {
-         MESSAGE ( " edges : E2d_"<<NbE2d-2<<" E2d_"<<NbE2d-1 ); }
-#endif
-       continue;
-      }
+      if (sqd1 > MilTol2 || sqd2 > MilTol2  )
+        continue;
 
       // add a new vertex to the both edges
-      Standard_Real toler = 1.5 * Max (Tol, sqrt(Max(sqd1,sqd2)) );
+      Standard_Real toler = Max( Tol, sqrt( Max( sqd1, sqd2 )));
       Standard_Integer i;
       for (i = 1; i <= 2; i++) {
-       Standard_Real U = P2D.Parameter(i);
-#ifdef DEB
-       if (U < f[i]-Tol  || U > l[i]+Tol) {
-         MESSAGE ( "out" );
-       }
-#endif
-       V.Orientation(TopAbs_INTERNAL);
-       B.UpdateVertex( V,U,EI[i], toler);
-       TopAbs_Orientation OO = TopAbs_REVERSED;
-       if (WithOri) {
-         if (P2D.IsVertex(i)) 
-           OO = P2D.Vertex(i).Orientation();
-         else if (P2D.Transition(i).Before() == TopAbs_OUT) {
-           OO = TopAbs_FORWARD;
-         }
-         V.Orientation(OO);
-         if (i == 1) LV1.Append(V);
+        Standard_Real U = P2D.Parameter(i);
+        V.Orientation(TopAbs_INTERNAL);
+        B.UpdateVertex( V,U,EI[i], toler);
+        TopAbs_Orientation OO = TopAbs_REVERSED;
+        if (WithOri) {
+          if (P2D.IsVertex(i))
+            OO = P2D.Vertex(i).Orientation();
+          else if (P2D.Transition(i).Before() == TopAbs_OUT) {
+            OO = TopAbs_FORWARD;
+          }
+          V.Orientation(OO);
+          if (i == 1) LV1.Append(V);
           else        LV2.Append(V);
         }
       }
@@ -410,7 +497,7 @@ static void EdgesPartition(const TopoDS_Face&            F,
       TolConf = Max (Tol, TolConf);
       TolConf2 = TolConf * TolConf;
       if (!intersect)
-       TolConf2 *= 100;
+        TolConf2 *= 100;
       Standard_Real SqDist = P1.SquareDistance(P2);
 
       if (SqDist <= TolConf2) {
@@ -442,27 +529,25 @@ static void EdgesPartition(const TopoDS_Face&            F,
     i = 1;
     Purge = Standard_False;
     for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2);
-         it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
+         it1LV1.More();
+         it1LV1.Next(),it1LV2.Next()) {
       j = 1;
       it2LV1.Initialize(LV1);
       while (j < i) {
-       const TopoDS_Vertex& VE1 = TopoDS::Vertex(it1LV1.Value());
-       const TopoDS_Vertex& VE2 = TopoDS::Vertex(it2LV1.Value());
-       Standard_Real Tol1 = BRep_Tool::Tolerance( VE1 );
-       Standard_Real Tol2 = BRep_Tool::Tolerance( VE2 );
+        const TopoDS_Vertex& VE1 = TopoDS::Vertex(it1LV1.Value());
+        const TopoDS_Vertex& VE2 = TopoDS::Vertex(it2LV1.Value());
+        Standard_Real Tol1 = BRep_Tool::Tolerance( VE1 );
+        Standard_Real Tol2 = BRep_Tool::Tolerance( VE2 );
         P1 = BRep_Tool::Pnt( VE1 );
         P2 = BRep_Tool::Pnt( VE2 );
         if (P1.IsEqual(P2, Tol1 + Tol2)) {
           LV1.Remove(it1LV1);
           LV2.Remove(it1LV2);
-          if (AffichPurge) {
-            MESSAGE ("Vertices confused purged in EdgeInter.")
-            }
-         Purge = Standard_True;
-         break;
-       }
-       j++;
-       it2LV1.Next();
+          Purge = Standard_True;
+          break;
+        }
+        j++;
+        it2LV1.Next();
       }
       if (Purge) break;
       i++;
@@ -471,17 +556,17 @@ static void EdgesPartition(const TopoDS_Face&            F,
 
   // care of new closed edges, they always intersect with seam at end
   if (V1[0].IsSame( V1[1] ) && NewEdges.Contains(E1) )
-    treatClosed (E1,f[1],l[1],LV1,LV2);
+    treatClosed (E1, f[1], l[1], LV1, LV2);
   if (V2[0].IsSame( V2[1] ) && NewEdges.Contains(E2) )
-    treatClosed (E2,f[2],l[2],LV2,LV1);
-  
-  //---------------------------------
-  // Stocking vertex .
-  //---------------------------------  
+    treatClosed (E2, f[2], l[2], LV2, LV1);
+
+  //----------------
+  // Stocking vertex
+  //----------------
 
-  //StorePart2d (E1,E2,LV1,LV2,AsDes,Tol);
   for ( it1LV1.Initialize( LV1 ); it1LV1.More(); it1LV1.Next())
-    Partition_Inter2d::AddVonE ( TopoDS::Vertex( it1LV1.Value()), E1,E2,AsDes);
+    Partition_Inter2d::AddVonE (TopoDS::Vertex( it1LV1.Value()),
+                                E1, E2, AsDes, F);
 }
 
 //=======================================================================
@@ -492,8 +577,8 @@ static void EdgesPartition(const TopoDS_Face&            F,
 //=======================================================================
 
 void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)&   AsDes,
-                                      const TopoDS_Face&              F,
-                                      const TopTools_MapOfShape&      NewEdges)
+                                       const TopoDS_Face&              F,
+                                       const TopTools_MapOfShape&      NewEdges)
 {
 
 #ifdef DEB
@@ -517,7 +602,7 @@ void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)&   AsDes,
   const TopTools_ListOfShape&        LE = AsDes->Descendant(F);
   TopoDS_Vertex                      V1,V2;
   Standard_Integer                   j, i = 1;
-  
+
   TopoDS_Face FF = F;
   FF.Orientation(TopAbs_FORWARD);
 
@@ -533,8 +618,8 @@ void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)&   AsDes,
       // between them and with the restrictions edges
       //----------------------------------------------------------
       if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) &&
-          (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {
-       EdgesPartition(FF,E1,E2,AsDes,NewEdges,Standard_True);
+           (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {
+        EdgesPartition(FF,E1,E2,AsDes,NewEdges,Standard_True);
       }
       it2LE.Next();
       j++;
@@ -543,3 +628,46 @@ void Partition_Inter2d::CompletPart2d (const Handle(BRepAlgo_AsDes)&   AsDes,
   }
 }
 
+//=======================================================================
+//function : GetTolerance
+//purpose  : Returns  tolerance  theV   must   have  atfer  its
+//           addition to theE with  theU parameter. theAsDes is
+//           used to find pcurves of theE
+//=======================================================================
+
+Standard_Real Partition_Inter2d::GetTolerance
+                         (const TopoDS_Vertex &         theV,
+                          const Standard_Real           theU,
+                          const TopoDS_Edge &           theE,
+                          const Handle(BRepAlgo_AsDes)& theAsDes)
+{
+  Standard_Real aTol = BRep_Tool::Tolerance( theV );
+  gp_Pnt aPnt = BRep_Tool::Pnt( theV );
+
+  // check point on 3D curve
+  Standard_Real f,l;
+  Handle(Geom_Curve) C = BRep_Tool::Curve( theE, f, l );
+  if (!C.IsNull())
+    aTol = Max ( aTol, aPnt.Distance( C->Value( theU )));
+
+  // check points on pcurves
+  const TopTools_ListOfShape& aFList = theAsDes->Ascendant( theE );
+  TopTools_ListIteratorOfListOfShape aFIt( aFList );
+  for (  ; aFIt.More(); aFIt.Next() )
+  {
+    const TopoDS_Face& F = TopoDS::Face( aFIt.Value() );
+    Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( theE, F, f, l );
+    if (!pcurve.IsNull())
+    {
+      gp_Pnt2d aPnt2d = pcurve->Value( theU );
+      TopLoc_Location L;
+      Handle(Geom_Surface) S = BRep_Tool::Surface( F, L );
+      gp_Pnt aPntOnS = S->Value( aPnt2d.X(), aPnt2d.Y() );
+      if (!L.IsIdentity())
+        aPntOnS.Transform( L.Transformation() );
+      aTol = Max ( aTol, aPnt.Distance( aPntOnS ));
+    }
+  }
+
+  return aTol;
+}