0027679: Wrong offset: overlapping edges
[occt.git] / src / BRepFill / BRepFill_OffsetWire.cxx
index d26c261..5cc63bd 100644 (file)
 
 //  Modified by skv - Fri Jul  8 11:21:38 2005 OCC9145
 
-#include <stdio.h>
-
-#include <BRepFill_OffsetWire.ixx>
-
+#include <Adaptor3d_Curve.hxx>
+#include <Adaptor2d_OffsetCurve.hxx>
+#include <Bisector_Bisec.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_CurveRepresentation.hxx>
+#include <BRep_GCurve.hxx>
+#include <BRep_TEdge.hxx>
+#include <BRep_Tool.hxx>
+#include <BRep_TVertex.hxx>
 #include <BRepAdaptor_Curve.hxx>
 #include <BRepAdaptor_Surface.hxx>
-
 #include <BRepFill_DataMapOfNodeShape.hxx>
+#include <BRepFill_DataMapOfOrientedShapeListOfShape.hxx>
 #include <BRepFill_DataMapOfShapeSequenceOfPnt.hxx>
-#include <BRepFill_DataMapOfShapeSequenceOfReal.hxx> 
-#include <BRepFill_DataMapOfOrientedShapeListOfShape.hxx> 
+#include <BRepFill_DataMapOfShapeSequenceOfReal.hxx>
+#include <BRepFill_OffsetWire.hxx>
 #include <BRepFill_TrimEdgeTool.hxx>
 #include <BRepLib.hxx>
-#include <BRepLib_MakeVertex.hxx>
+#include <BRepLib_MakeEdge.hxx>
 #include <BRepLib_MakeFace.hxx>
+#include <BRepLib_MakeVertex.hxx>
 #include <BRepLib_MakeWire.hxx>
-#include <BRepLib_MakeEdge.hxx>
+#include <BRepMAT2d_BisectingLocus.hxx>
+#include <BRepMAT2d_Explorer.hxx>
+#include <BRepMAT2d_LinkTopoBilo.hxx>
 #include <BRepTools.hxx>
-#include <BRep_Builder.hxx>
-#include <BRep_Tool.hxx>
-#include <BRep_TEdge.hxx>
-#include <BRep_CurveRepresentation.hxx>
-#include <BRep_GCurve.hxx>
+#include <BRepTools_Substitution.hxx>
 #include <BRepTools_WireExplorer.hxx>
-#include <BRepMAT2d_Explorer.hxx>
-#include <Geom2dAdaptor_Curve.hxx>
-#include <Geom2dAdaptor_HCurve.hxx>
-#include <Adaptor3d_OffsetCurve.hxx>
-#include <Adaptor3d_Curve.hxx>
-#include <Geom_Surface.hxx>
-#include <Geom_Plane.hxx>
-#include <Geom2d_Curve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_Circle.hxx>
+#include <Geom2d_Curve.hxx>
 #include <Geom2d_Line.hxx>
-#include <Geom2d_TrimmedCurve.hxx>
 #include <Geom2d_OffsetCurve.hxx>
-#include <GeomAPI.hxx>
-#include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
+#include <Geom2dLProp_CLProps2d.hxx>
 #include <Geom_Circle.hxx>
 #include <Geom_Line.hxx>
 #include <Geom_OffsetCurve.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAPI.hxx>
+#include <gp.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Dir2d.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Vec.hxx>
+#include <MAT2d_CutCurve.hxx>
 #include <MAT_Arc.hxx>
-#include <MAT_Node.hxx>
 #include <MAT_Graph.hxx>
-#include <MAT2d_CutCurve.hxx>
+#include <MAT_Node.hxx>
 #include <Precision.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_NoSuchObject.hxx>
 #include <Standard_NotImplemented.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
 #include <TColgp_SequenceOfPnt.hxx>
-#include <TColStd_SequenceOfReal.hxx> 
-#include <TopAbs.hxx> 
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_SequenceOfReal.hxx>
+#include <TopAbs.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Wire.hxx>
 #include <TopoDS_Compound.hxx>
+#include <TopoDS_Face.hxx>
 #include <TopoDS_Iterator.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_MapIteratorOfMapOfShape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <TopTools_DataMapOfShapeListOfShape.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Wire.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
-#include <TopTools_SequenceOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>    
-#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>    
+#include <TopTools_DataMapOfShapeListOfShape.hxx>
 #include <TopTools_DataMapOfShapeSequenceOfShape.hxx>
-
-#include <gp.hxx>
-#include <gp_Vec.hxx>
-#include <gp_Ax2.hxx>
-#include <gp_Pln.hxx>
-#include <gp_Dir2d.hxx>
-
-#include <BRep_TVertex.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
-#include <Geom2d_BSplineCurve.hxx>
-#include <TColgp_Array1OfPnt2d.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <BRepTools_Substitution.hxx>
-#include <BRepLib_MakeVertex.hxx>
-#include <Geom2dLProp_CLProps2d.hxx>
-#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
-#include <Standard_ErrorHandler.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapIteratorOfMapOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_SequenceOfShape.hxx>
+
+#include <stdio.h>
 #ifdef OCCT_DEBUG
 //#define DRAW
 #ifdef DRAW
 #include <DrawTrSurf.hxx>
 #include <DrawTrSurf_Curve2d.hxx>
 #include <DBRep.hxx>
+#include <Geom_Curve.hxx>
 static Standard_Boolean AffichGeom  = Standard_False;
 static Standard_Boolean Affich2d    = Standard_False;
 static Standard_Boolean AffichEdge  = Standard_False;
@@ -219,6 +222,8 @@ static void MakeOffset
  const GeomAbs_JoinType                      theJoinType,
   const TopoDS_Vertex *                       Ends);
 
+Standard_Boolean CheckSmallParamOnEdge(const TopoDS_Edge& anEdge);
+
 //=======================================================================
 //function : KPartCircle
 //purpose  : 
@@ -264,7 +269,7 @@ static Standard_Boolean KPartCircle
     {
       if (E.Orientation() == TopAbs_REVERSED)
         anOffset *= -1;
-      Adaptor3d_OffsetCurve Off(AHC,anOffset);
+      Adaptor2d_OffsetCurve Off(AHC,anOffset);
       OC = new Geom2d_Line(Off.Line());
     }
     else if (AHC->GetType() == GeomAbs_Circle)
@@ -294,7 +299,7 @@ static Standard_Boolean KPartCircle
     
     myShape.Orientation(E.Orientation());
     myShape.Location(L);
-    if (Alt != 0.) {
+    if (fabs(Alt) > gp::Resolution()) {
       BRepAdaptor_Surface S(mySpine,0);
       gp_Ax1 Nor = S.Plane().Axis();
       gp_Trsf T;
@@ -720,8 +725,8 @@ void BRepFill_OffsetWire::PerformWithBiLo
   const Standard_Real             Alt)
 {
   myIsDone     = Standard_False;
-  TopoDS_Shape aLocalShape = Spine.Oriented(TopAbs_FORWARD);
-  myWorkSpine  = TopoDS::Face(aLocalShape);
+  TopoDS_Shape aLocalShapeWork = Spine.Oriented(TopAbs_FORWARD);
+  myWorkSpine  = TopoDS::Face(aLocalShapeWork);
   //  myWorkSpine  = TopoDS::Face(Spine.Oriented(TopAbs_FORWARD));
   myJoinType   = Join;
   myOffset     = Offset ;
@@ -770,12 +775,14 @@ void BRepFill_OffsetWire::PerformWithBiLo
   TopTools_ListOfShape                      EmptyList;
   TColStd_SequenceOfReal                    EmptySeqOfReal;
 
-  Standard_Real ALT = Alt;
   Handle(Geom_Plane) RefPlane = 
     Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(myWorkSpine));
-  if ( myWorkSpine.Orientation() == TopAbs_REVERSED) ALT = -Alt;
-  RefPlane = Handle(Geom_Plane)::DownCast
-    (RefPlane->Translated( ALT * gp_Vec(RefPlane->Axis().Direction() )));
+  if (fabs(Alt) > gp::Resolution()) {
+    Standard_Real anAlt = Alt;
+    if ( myWorkSpine.Orientation() == TopAbs_REVERSED) anAlt = -Alt;
+    RefPlane = Handle(Geom_Plane)::DownCast
+      (RefPlane->Translated( anAlt * gp_Vec(RefPlane->Axis().Direction() )));
+  }
 
   //---------------------------------------------------------------
   // Construction of Circles and OffsetCurves
@@ -808,6 +815,24 @@ void BRepFill_OffsetWire::PerformWithBiLo
     }
   }
 
+  //Remove possible hanging arcs on vertices
+  if (myIsOpenResult && myJoinType == GeomAbs_Arc)
+  {
+    if (!myMap.IsEmpty() &&
+        myMap.FindKey(1).ShapeType() == TopAbs_VERTEX)
+    {
+      //myMap.RemoveFirst();
+      TopoDS_Shape LastShape = myMap.FindKey(myMap.Extent());
+      TopTools_ListOfShape LastList;
+      LastList.Append(myMap(myMap.Extent()));
+      myMap.RemoveLast();
+      if (!myMap.IsEmpty())
+        myMap.Substitute(1, LastShape, LastList);
+    }
+    if (!myMap.IsEmpty() &&
+        myMap.FindKey(myMap.Extent()).ShapeType() == TopAbs_VERTEX)
+      myMap.RemoveLast();
+  }
 
 #ifdef OCCT_DEBUG
 #ifdef DRAW
@@ -915,7 +940,8 @@ void BRepFill_OffsetWire::PerformWithBiLo
     // Construction of vertices on edges parallel to the spine.
     //-----------------------------------------------------------
 
-    Trim.IntersectWith(E [0], E [1], myJoinType, Params);
+    Trim.IntersectWith(E[0], E[1], S[0], S[1], Ends[0], Ends[1],
+                       myJoinType, myIsOpenResult, Params);
 
     for (Standard_Integer s = 1; s <= Params.Length(); s++) {
       TopoDS_Vertex VC;
@@ -1019,7 +1045,7 @@ void BRepFill_OffsetWire::PerformWithBiLo
 
     myMap(j).Clear();
     if (MapBis.IsBound(CurrentEdge)) {
-      TopTools_SequenceOfShape S;
+      TopTools_SequenceOfShape aSeqOfShape;
       if (!MapBis(CurrentEdge).IsEmpty()) {
         Standard_Integer IndOfE = 0;
         if (myIsOpenResult)
@@ -1035,9 +1061,9 @@ void BRepFill_OffsetWire::PerformWithBiLo
           Detromp  (CurrentSpine),
           MapBis   (CurrentEdge) ,  
           MapVerPar(CurrentEdge) ,
-          S, MapVV, IndOfE);
-        for ( k = 1; k <= S.Length(); k++) {
-          myMap(j).Append(S.Value(k));
+          aSeqOfShape, MapVV, IndOfE);
+        for ( k = 1; k <= aSeqOfShape.Length(); k++) {
+          myMap(j).Append(aSeqOfShape.Value(k));
         }
       }
       else {
@@ -1100,15 +1126,15 @@ void BRepFill_OffsetWire::PerformWithBiLo
   TopExp_Explorer Explo( myShape, TopAbs_EDGE );
   for (; Explo.More(); Explo.Next())
   {
-    TopoDS_Edge E = TopoDS::Edge( Explo.Current() );
+    TopoDS_Edge anEdge = TopoDS::Edge( Explo.Current() );
     TopoDS_Vertex V1, V2;
-    TopExp::Vertices( E, V1, V2 );
+    TopExp::Vertices(anEdge, V1, V2 );
     Handle(BRep_TVertex)& TV1 = *((Handle(BRep_TVertex)*) &(V1).TShape());
     Handle(BRep_TVertex)& TV2 = *((Handle(BRep_TVertex)*) &(V2).TShape());
 
     TopLoc_Location loc;
     Standard_Real f, l;
-    Handle( Geom_Curve ) theCurve = BRep_Tool::Curve( E, loc, f, l );
+    Handle( Geom_Curve ) theCurve = BRep_Tool::Curve(anEdge, loc, f, l );
     theCurve = Handle( Geom_Curve )::DownCast( theCurve->Copy() );
     theCurve->Transform( loc.Transformation() );
     gp_Pnt f3d = theCurve->Value( f );
@@ -1134,7 +1160,8 @@ void BRepFill_OffsetWire::PerformWithBiLo
       TV2->UpdateTolerance( 1.5*dist2 );
   }
 
-  FixHoles();
+  if (!myIsOpenResult)
+    FixHoles();
 
   myIsDone = Standard_True;
 }
@@ -1267,69 +1294,84 @@ void BRepFill_OffsetWire::UpdateDetromp (BRepFill_DataMapOfOrientedShapeListOfSh
                                          const BRepFill_TrimEdgeTool&    Trim) const
 {
   Standard_Integer ii = 1;
-  Standard_Real    U1,U2;
-  TopoDS_Vertex    V1,V2;
 
-  Handle(Geom2d_Curve) Bis = Bisec.Value();
+  if (myJoinType == GeomAbs_Intersection)
+  {
+    for (; ii <= Vertices.Length(); ii++)
+    {
+      const TopoDS_Vertex& aVertex = TopoDS::Vertex(Vertices.Value(ii));
+      Detromp(Shape1).Append(aVertex);
+      Detromp(Shape2).Append(aVertex);
+    }
+  }
+  else //myJoinType == GeomAbs_Arc
+  {
+    Standard_Real    U1,U2;
+    TopoDS_Vertex    V1,V2;
+    
+    const Handle(Geom2d_Curve)& Bis = Bisec.Value();
+    Standard_Boolean ForceAdd = Standard_False;
+    Handle(Geom2d_TrimmedCurve) aTC = Handle(Geom2d_TrimmedCurve)::DownCast(Bis);
+    if(!aTC.IsNull() && aTC->BasisCurve()->IsPeriodic())
+    {
+      gp_Pnt2d Pf = Bis->Value(Bis->FirstParameter());
+      gp_Pnt2d Pl = Bis->Value(Bis->LastParameter());
+      ForceAdd = Pf.Distance(Pl) <= Precision::Confusion();
+    }
 
-  U1 = Bis->FirstParameter();
-  
-  if (SOnE) { 
-    // the first point of the bissectrice is on the offset
-    V1 = TopoDS::Vertex(Vertices.Value(ii));
-    ii++; 
-  }
-
-  while (ii <= Vertices.Length()) {
-    U2 = Params.Value(ii).X();
-    V2 = TopoDS::Vertex(Vertices.Value(ii));
-
-    gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);
-    Standard_Boolean IsP_inside = Standard_True;
-    if ((myJoinType != GeomAbs_Intersection) || EOnE)
-      IsP_inside = Trim.IsInside(P);
-    if (!IsP_inside) {
-      if (!V1.IsNull()) {
-        Detromp(Shape1).Append(V1);
-        Detromp(Shape2).Append(V1);
-      }
-      Detromp(Shape1).Append(V2);
-      Detromp(Shape2).Append(V2);
-    }
-    U1 = U2;
-    V1 = V2;
-    ii ++;
-  }
-
-  // test medium point between the last parameter and the end of the bissectrice.
-  U2 = Bis->LastParameter();
-  if (!EOnE) {
-    if (!Precision::IsInfinite(U2)) {
-      gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);  
-      Standard_Boolean IsP_inside = Standard_False;
-      if (myJoinType == GeomAbs_Arc)
-        IsP_inside = Trim.IsInside(P);
-      if (!IsP_inside) {
+    U1 = Bis->FirstParameter();
+    
+    if (SOnE) { 
+      // the first point of the bissectrice is on the offset
+      V1 = TopoDS::Vertex(Vertices.Value(ii));
+      ii++; 
+    }
+    
+    while (ii <= Vertices.Length()) {
+      U2 = Params.Value(ii).X();
+      V2 = TopoDS::Vertex(Vertices.Value(ii));
+      
+      gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);
+      if (!Trim.IsInside(P) || ForceAdd) {
         if (!V1.IsNull()) {
           Detromp(Shape1).Append(V1);
           Detromp(Shape2).Append(V1);
         }
+        Detromp(Shape1).Append(V2);
+        Detromp(Shape2).Append(V2);
       }
+      U1 = U2;
+      V1 = V2;
+      ii ++;
     }
-    else {
-      if (!V1.IsNull()) {
-        Detromp(Shape1).Append(V1);
-        Detromp(Shape2).Append(V1);
+    
+    // test medium point between the last parameter and the end of the bissectrice.
+    U2 = Bis->LastParameter();
+    if (!EOnE) {
+      if (!Precision::IsInfinite(U2)) {
+        gp_Pnt2d P = Bis->Value((U2 + U1)*0.5);
+        if (!Trim.IsInside(P) || ForceAdd) {
+          if (!V1.IsNull()) {
+            Detromp(Shape1).Append(V1);
+            Detromp(Shape2).Append(V1);
+          }
+        }
       }
-    }
-  }    
-  //else if(myJoinType != GeomAbs_Arc)
-  //{
-  //  if (!V1.IsNull()) {
-  //    Detromp(Shape1).Append(V1);
-  //    Detromp(Shape2).Append(V1);
-  //  }
-  //}
+      else {
+        if (!V1.IsNull()) {
+          Detromp(Shape1).Append(V1);
+          Detromp(Shape2).Append(V1);
+        }
+      }
+    }    
+    //else if(myJoinType != GeomAbs_Arc)
+    //{
+    //  if (!V1.IsNull()) {
+    //    Detromp(Shape1).Append(V1);
+    //    Detromp(Shape2).Append(V1);
+    //  }
+    //}
+  } //end of else (myJoinType==GeomAbs_Arc)
 }
 
 //=======================================================================
@@ -1357,6 +1399,8 @@ void BRepFill_OffsetWire::MakeWires()
       TopExp::Vertices (E,V1,V2);
       if (V1.IsSame(V2) && IsSmallClosedEdge(E, V1))
         continue; //remove small closed edges
+      if (!CheckSmallParamOnEdge(E))
+        continue;
       if (!MVE.Contains(V1)) {
         TopTools_ListOfShape empty;
         MVE.Add(V1,empty);
@@ -1399,7 +1443,19 @@ void BRepFill_OffsetWire::MakeWires()
     CV  = VF = TopoDS::Vertex(MVE.FindKey(i));
     CE  = TopoDS::Edge(MVE(i).First());
     End = Standard_False;
-    MVE.ChangeFromKey(CV).RemoveFirst(); 
+    MVE.ChangeFromKey(CV).RemoveFirst();
+
+    if (myIsOpenResult && MVE.FindFromKey(CV).IsEmpty())
+    {
+      //MVE.UnBind(CV);
+      TopoDS_Shape LastShape = MVE.FindKey(MVE.Extent());
+      TopTools_ListOfShape LastList;
+      LastList.Append(MVE(MVE.Extent()));
+      MVE.RemoveLast();
+      if (MVE.FindIndex(CV) != 0)
+        MVE.Substitute(MVE.FindIndex(CV), LastShape, LastList);
+    }
+      
 
     //  Modified by Sergey KHROMOV - Thu Mar 14 11:29:59 2002 Begin
     Standard_Boolean isClosed = Standard_False;
@@ -1443,6 +1499,9 @@ void BRepFill_OffsetWire::MakeWires()
           CE = TopoDS::Edge(MVE.FindFromKey(CV).First());
           MVE.ChangeFromKey(CV).RemoveFirst();
         }
+        else if (myIsOpenResult)//CV was a vertex with one edge
+          End = Standard_True;
+        
         if (MVE.FindFromKey(CV).IsEmpty())
         {
           //MVE.UnBind(CV);
@@ -1490,7 +1549,6 @@ void BRepFill_OffsetWire::FixHoles()
   TopTools_SequenceOfShape ClosedWires, UnclosedWires, IsolatedWires;
 
   Standard_Real MaxTol = 0.;
-  Standard_Integer i;
   BRep_Builder BB;
 
   TopExp_Explorer Explo( mySpine, TopAbs_VERTEX );
@@ -1553,7 +1611,7 @@ void BRepFill_OffsetWire::FixHoles()
     Pf = BRep_Tool::Pnt(Vf);
     Pl = BRep_Tool::Pnt(Vl);
     Standard_Real DistF = RealLast(), DistL = RealLast();
-    Standard_Integer IndexF = 1, IndexL = 1;
+    Standard_Integer IndexF = 0, IndexL = 0;
     Standard_Boolean IsFirstF = Standard_False, IsFirstL = Standard_False;
     for (Standard_Integer i = 2; i <= UnclosedWires.Length(); i++)
     {
@@ -1604,6 +1662,10 @@ void BRepFill_OffsetWire::FixHoles()
         IsFirstL = Standard_False;
       }
     }
+    if (DistF > MaxTol)
+      IndexF = 0;
+    if (DistL > MaxTol)
+      IndexL = 0;
     TopoDS_Wire theWire;
     TopoDS_Edge theEdge;
     TopoDS_Vertex theVertex;
@@ -1762,6 +1824,7 @@ void BRepFill_OffsetWire::FixHoles()
   {
     TopoDS_Compound R;
     BB.MakeCompound( R );
+    Standard_Integer i;
     for (i = 1; i <= ClosedWires.Length(); i++)
       BB.Add( R, ClosedWires(i) );
     for (i = 1; i <= IsolatedWires.Length(); i++)
@@ -2036,7 +2099,7 @@ void MakeOffset (const TopoDS_Edge&        E,
 
       Handle(Geom2dAdaptor_HCurve) AHC = 
         new Geom2dAdaptor_HCurve(G2d);
-      Adaptor3d_OffsetCurve   Off(AHC,-anOffset);
+      Adaptor2d_OffsetCurve   Off(AHC,-anOffset);
       Handle(Geom2d_Circle) CC = new Geom2d_Circle(Off.Circle());      
 
       Standard_Real Delta = 2*M_PI - l + f;
@@ -2071,7 +2134,7 @@ void MakeOffset (const TopoDS_Edge&        E,
   else if (AC.GetType() == GeomAbs_Line) {
     Handle(Geom2dAdaptor_HCurve) AHC = 
       new Geom2dAdaptor_HCurve(G2d);
-    Adaptor3d_OffsetCurve Off(AHC,anOffset);
+    Adaptor2d_OffsetCurve Off(AHC,anOffset);
     Handle(Geom2d_Line)       CC = new Geom2d_Line(Off.Line());
     Standard_Real Delta = (l - f);
     if (ToExtendFirstPar)
@@ -2715,3 +2778,18 @@ static void QuasiFleche(const Adaptor3d_Curve& C,
   }
 }
 
+Standard_Boolean CheckSmallParamOnEdge(const TopoDS_Edge& anEdge)
+{  
+  const BRep_ListOfCurveRepresentation& aList = ((Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->Curves());
+  if (!aList.IsEmpty())
+  {
+    Handle( BRep_CurveRepresentation ) CRep = ((Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->Curves()).First();
+    Standard_Real f = (Handle(BRep_GCurve)::DownCast(CRep))->First();
+    Standard_Real l = (Handle(BRep_GCurve)::DownCast(CRep))->Last();
+    if (Abs (l - f) < Precision::PConfusion())
+      return Standard_False;
+  }
+  return Standard_True;
+}
+
+