0027302: Invalid curves number in intersection result
authornbv <nbv@opencascade.com>
Tue, 29 Mar 2016 13:38:53 +0000 (16:38 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 22 Apr 2016 12:21:57 +0000 (15:21 +0300)
1. In frame of the fix for #27282 issue, we have obtained several prolonged curves, which have common point(s). Fix for this issue joins these curves if it is possible.

2. ElCLib::InPeriod(...) method has been improved. Now it has become more faster (in general cases) and more reliable (in frame of  FLT_OVERFLOW and DIVISION_BY_ZERO cases processing).

Creation of test case for issue #27302
Test case tests\bugs\modalg_6\bug27282_2 has been adjusted in accordance with its new behavior.

src/ElCLib/ElCLib.cxx
src/IntPatch/IntPatch_Intersection.cxx
src/IntPatch/IntPatch_PointLine.hxx
src/IntPatch/IntPatch_RLine.hxx
src/IntPatch/IntPatch_RLine.lxx
src/IntPatch/IntPatch_WLine.hxx
src/IntPatch/IntPatch_WLine.lxx
src/IntPatch/IntPatch_WLineTool.cxx
src/IntPatch/IntPatch_WLineTool.hxx
tests/bugs/modalg_6/bug27282_2
tests/bugs/modalg_6/bug27302 [new file with mode: 0644]

index 121ce56..170dd2d 100644 (file)
@@ -48,20 +48,25 @@ static Standard_Real PIPI = M_PI + M_PI;
 
 //=======================================================================
 //function : InPeriod
-//purpose  : 
+//purpose  : Value theULast is never returned.
 //=======================================================================
-
-Standard_Real  ElCLib::InPeriod(const Standard_Real U, 
-                               const Standard_Real UFirst, 
-                               const Standard_Real ULast)
+Standard_Real  ElCLib::InPeriod(const Standard_Real theU, 
+                                const Standard_Real theUFirst, 
+                                const Standard_Real theULast)
 {
-  Standard_Real u = U, period = ULast - UFirst;
-  Standard_Real Eps = Epsilon(period);
+  if( Precision::IsInfinite(theU) ||
+      Precision::IsInfinite(theUFirst) ||
+      Precision::IsInfinite(theULast))
+  {//In order to avoid FLT_Overflow exception
+    return theU;
+  }
+
+  const Standard_Real aPeriod = theULast - theUFirst;
+
+  if(aPeriod < Epsilon(theULast))
+    return theU;
 
-  while (Eps < (UFirst-u)) u += period;
-  while (Eps > (ULast -u)) u -= period;
-  if ( u < UFirst) u = UFirst;
-  return u;
+  return Max(theUFirst, theU + aPeriod*Ceiling((theUFirst-theU)/aPeriod));
 }
 
 //=======================================================================
index 719b406..5e02c67 100644 (file)
@@ -1442,12 +1442,34 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the
 
       if(isQuadSet)
       {
+        Bnd_Box2d aBx1, aBx2;
+        const Standard_Real aU1F = theS1->FirstUParameter(),
+                            aU1L = theS1->LastUParameter(),
+                            aV1F = theS1->FirstVParameter(),
+                            aV1L = theS1->LastVParameter(),
+                            aU2F = theS2->FirstUParameter(),
+                            aU2L = theS2->LastUParameter(),
+                            aV2F = theS2->FirstVParameter(),
+                            aV2L = theS2->LastVParameter();
+        aBx1.Add(gp_Pnt2d(aU1F, aV1F));
+        aBx1.Add(gp_Pnt2d(aU1L, aV1F));
+        aBx1.Add(gp_Pnt2d(aU1L, aV1L));
+        aBx1.Add(gp_Pnt2d(aU1F, aV1L));
+        aBx2.Add(gp_Pnt2d(aU2F, aV2F));
+        aBx2.Add(gp_Pnt2d(aU2L, aV2F));
+        aBx2.Add(gp_Pnt2d(aU2L, aV2L));
+        aBx2.Add(gp_Pnt2d(aU2F, aV2L));
+
+        aBx1.Enlarge(Precision::PConfusion());
+        aBx2.Enlarge(Precision::PConfusion());
+
         IntPatch_WLineTool::
           ExtendTwoWlinesToEachOther(slin, Quad1, Quad2, TolTang,
                                      theS1->IsUPeriodic()? theS1->UPeriod() : 0.0,
                                      theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
                                      theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
-                                     theS2->IsVPeriodic()? theS2->VPeriod() : 0.0);
+                                     theS2->IsVPeriodic()? theS2->VPeriod() : 0.0,
+                                     aBx1, aBx2);
       }
 
       for (Standard_Integer i = 1; i <= interii.NbPnts(); i++)
index 71477fe..9dc3bad 100644 (file)
@@ -45,8 +45,12 @@ class IntPatch_PointLine : public IntPatch_Line
 
 public:
 
-  //! Adds a vertex in the list.
-  Standard_EXPORT virtual void AddVertex (const IntPatch_Point& Pnt) = 0;
+  //! Adds a vertex in the list. If theIsPrepend == TRUE the new
+  //! vertex will be added before the first element of vertices sequence.
+  //! Otherwise, to the end of the sequence
+  Standard_EXPORT virtual
+            void AddVertex (const IntPatch_Point& Pnt,
+                            const Standard_Boolean theIsPrepend = Standard_False) = 0;
 
   //! Returns the number of intersection points.
   Standard_EXPORT virtual Standard_Integer NbPnts() const = 0;
index f91273b..7c56124 100644 (file)
@@ -58,8 +58,11 @@ public:
   //! when the transitions are Undecided.
   Standard_EXPORT IntPatch_RLine(const Standard_Boolean Tang);
   
-  //! To add a vertex in the list.
-  virtual void AddVertex (const IntPatch_Point& Pnt) Standard_OVERRIDE;
+  //! Adds a vertex in the list. If theIsPrepend == TRUE the new
+  //! vertex will be added before the first element of vertices sequence.
+  //! Otherwise, to the end of the sequence
+  virtual void AddVertex (const IntPatch_Point& Pnt,
+                    const Standard_Boolean theIsPrepend = Standard_False) Standard_OVERRIDE;
   
   //! Replaces the element of range Index in the list
   //! of points.
index 70debb4..e4275ea 100644 (file)
@@ -32,9 +32,13 @@ inline const Handle(Adaptor2d_HCurve2d)& IntPatch_RLine::ArcOnS2() const
 //-- Il faut mettre cet include ici , car l include fait un define Handle(Adaptor2d_HCurve2d) ...
 //-- et en fin de fichier un undef Handle(Adaptor2d_HCurve2d) ... 
 
-inline void IntPatch_RLine::AddVertex (const IntPatch_Point& Pnt)
+inline void IntPatch_RLine::AddVertex (const IntPatch_Point& thePnt,
+                                       const Standard_Boolean theIsPrepend)
 {
-  svtx.Append(Pnt);
+  if(theIsPrepend)
+    svtx.Prepend(thePnt);
+  else
+    svtx.Append(thePnt);
 }
 
 inline void IntPatch_RLine::Replace (const Standard_Integer Index,
index 4cfeabf..1dba818 100644 (file)
@@ -62,8 +62,11 @@ public:
   //! transitions are Undecided.
   Standard_EXPORT IntPatch_WLine(const Handle(IntSurf_LineOn2S)& Line, const Standard_Boolean Tang);
   
-  //! Adds a vertex in the list.
-  virtual void AddVertex (const IntPatch_Point& Pnt) Standard_OVERRIDE;
+  //! Adds a vertex in the list. If theIsPrepend == TRUE the new
+  //! vertex will be added before the first element of vertices sequence.
+  //! Otherwise, to the end of the sequence
+  virtual void AddVertex (const IntPatch_Point& Pnt,
+                    const Standard_Boolean theIsPrepend = Standard_False) Standard_OVERRIDE;
   
   //! Set the Point of index <Index> in the LineOn2S
   Standard_EXPORT void SetPoint (const Standard_Integer Index, const IntPatch_Point& Pnt);
index 6c95ee8..9eab7c6 100644 (file)
 #include <IntPatch_Point.hxx>
 
 
-inline void IntPatch_WLine::AddVertex (const IntPatch_Point& Pnt)
+inline void IntPatch_WLine::AddVertex (const IntPatch_Point& thePnt,
+                                       const Standard_Boolean theIsPrepend)
 {
-  svtx.Append(Pnt);
+  if(theIsPrepend)
+    svtx.Prepend(thePnt);
+  else
+    svtx.Append(thePnt);
 }
 
 inline void IntPatch_WLine::Replace (const Standard_Integer Index,
index 9da9e9d..e6080a3 100644 (file)
 
 #include <Adaptor3d_HSurface.hxx>
 #include <Adaptor3d_TopolTool.hxx>
+#include <ElCLib.hxx>
+
+//Bit-mask is used for information about 
+//the operation made in
+//IntPatch_WLineTool::ExtendTwoWlinesToEachOther() method.
+enum
+{
+  IntPatchWT_EnAll = 0x00,
+  IntPatchWT_DisLastLast = 0x01,
+  IntPatchWT_DisLastFirst = 0x02,
+  IntPatchWT_DisFirstLast = 0x04,
+  IntPatchWT_DisFirstFirst = 0x08
+};
 
 //=======================================================================
 //function : MinMax
@@ -458,23 +471,24 @@ static Handle(IntPatch_WLine)
 }
 
 //=======================================================================
-//function : IsSeam
-//purpose  : Returns:
-//            0 - if interval [theU1, theU2] does not intersect the "seam-edge"
-//                or if "seam-edge" do not exist;
-//            1 - if interval (theU1, theU2) intersect the "seam-edge".
-//            2 - if theU1 or/and theU2 lie ON the "seam-edge"
+//function : IsOnPeriod
+//purpose  : Checks, if [theU1, theU2] intersects the period-value
+//            (k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...).
+//
+//           Returns:
+//            0 - if interval [theU1, theU2] does not intersect the "period-value"
+//                or if thePeriod == 0.0;
+//            1 - if interval (theU1, theU2) intersect the "period-value".
+//            2 - if theU1 or/and theU2 lie ON the "period-value"
 //
 //ATTENTION!!!
 //  If (theU1 == theU2) then this function will return only both 0 or 2.
-//
-//           Static subfunction in IsSeamOrBound.
 //=======================================================================
-static Standard_Integer IsSeam( const Standard_Real theU1,
-                                const Standard_Real theU2,
-                                const Standard_Real thePeriod)
+static Standard_Integer IsOnPeriod(const Standard_Real theU1,
+                                   const Standard_Real theU2,
+                                   const Standard_Real thePeriod)
 {
-  if(IsEqual(thePeriod, 0.0))
+  if(thePeriod < RealSmall())
     return 0;
 
   //If interval [theU1, theU2] intersect seam-edge then there exists an integer
@@ -590,16 +604,16 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
     return Standard_True;
   }
 
-  if(IsSeam(aU11, aU21, theU1Period))
+  if(IsOnPeriod(aU11, aU21, theU1Period))
     return Standard_True;
 
-  if(IsSeam(aV11, aV21, theV1Period))
+  if(IsOnPeriod(aV11, aV21, theV1Period))
     return Standard_True;
 
-  if(IsSeam(aU12, aU22, theU2Period))
+  if(IsOnPeriod(aU12, aU22, theU2Period))
     return Standard_True;
 
-  if(IsSeam(aV12, aV22, theV2Period))
+  if(IsOnPeriod(aV12, aV22, theV2Period))
     return Standard_True;
 
   /*
@@ -634,16 +648,16 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
   if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
     return Standard_True;
 
-  if(IsSeam(aU1, aU1, theU1Period))
+  if(IsOnPeriod(aU1, aU1, theU1Period))
     return Standard_True;
 
-  if(IsSeam(aU2, aU2, theU2Period))
+  if(IsOnPeriod(aU2, aU2, theU2Period))
     return Standard_True;
 
-  if(IsSeam(aV1, aV1, theV1Period))
+  if(IsOnPeriod(aV1, aV1, theV1Period))
     return Standard_True;
 
-  if(IsSeam(aV2, aV2, theV2Period))
+  if(IsOnPeriod(aV2, aV2, theV2Period))
     return Standard_True;
 
   return Standard_False;
@@ -712,22 +726,42 @@ static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
 //purpose  : Adds thePOn2S to the begin of theWline
 //=======================================================================
 static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
-                        const IntSurf_PntOn2S &thePOn2S)
+                        const IntSurf_PntOn2S& theAddedPt)
 {
-  theWline->Curve()->InsertBefore(1, thePOn2S);
+  Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+  theAddedPt.Parameters(aU1, aV1, aU2, aV2);
 
-  IntPatch_Point &aVert = theWline->ChangeVertex(1);
+  if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
+  {
+    theWline->Curve()->Value(1, theAddedPt);
+    for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
+    {
+      IntPatch_Point &aVert = theWline->ChangeVertex(i);
+      if(aVert.ParameterOnLine() != 1)
+        break;
 
-  Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
-  thePOn2S.Parameters(aU1, aV1, aU2, aV2);
+      aVert.SetParameters(aU1, aV1, aU2, aV2);
+      aVert.SetValue(theAddedPt.Value());
+    }
+
+    return;
+  }
 
-  aVert.SetParameters(aU1, aV1, aU2, aV2);
-  aVert.SetValue(thePOn2S.Value());
+  theWline->Curve()->InsertBefore(1, theAddedPt);
 
-  for(Standard_Integer i = 2; i <= theWline->NbVertex(); i++)
+  for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
   {
-    IntPatch_Point &aV = theWline->ChangeVertex(i);
-    aV.SetParameter(aV.ParameterOnLine()+1);
+    IntPatch_Point &aVert = theWline->ChangeVertex(i);
+
+    if(aVert.ParameterOnLine() == 1)
+    {
+      aVert.SetParameters(aU1, aV1, aU2, aV2);
+      aVert.SetValue(theAddedPt.Value());
+    }
+    else
+    {
+      aVert.SetParameter(aVert.ParameterOnLine()+1);
+    }
   }
 }
 
@@ -736,18 +770,421 @@ static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
 //purpose  : Adds thePOn2S to the end of theWline
 //=======================================================================
 static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
-                       const IntSurf_PntOn2S &thePOn2S)
+                        const IntSurf_PntOn2S& theAddedPt)
 {
-  theWline->Curve()->Add(thePOn2S);
+  Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+  theAddedPt.Parameters(aU1, aV1, aU2, aV2);
+
+  const Standard_Integer aNbPnts = theWline->NbPnts();
+  if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
+  {
+    theWline->Curve()->Value(aNbPnts, theAddedPt);
+  }
+  else
+  {
+    theWline->Curve()->Add(theAddedPt);
+  }
 
-  IntPatch_Point &aVert = theWline->ChangeVertex(theWline->NbVertex());
+  for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
+  {
+    IntPatch_Point &aVert = theWline->ChangeVertex(i);
+    if(aVert.ParameterOnLine() != aNbPnts)
+      break;
 
+    aVert.SetParameters(aU1, aV1, aU2, aV2);
+    aVert.SetValue(theAddedPt.Value());
+    aVert.SetParameter(theWline->NbPnts());
+  }
+}
+
+//=========================================================================
+// function: IsOutOfDomain
+// purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
+//            defined by bounding-boxes theBoxS1 and theBoxS2
+//=========================================================================
+static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
+                                      const Bnd_Box2d& theBoxS2,
+                                      const IntSurf_PntOn2S &thePOn2S,
+                                      const Standard_Real theU1Period,
+                                      const Standard_Real theU2Period,
+                                      const Standard_Real theV1Period,
+                                      const Standard_Real theV2Period)
+{
   Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+  Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
+  Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
+
   thePOn2S.Parameters(aU1, aV1, aU2, aV2);
 
-  aVert.SetParameters(aU1, aV1, aU2, aV2);
-  aVert.SetValue(thePOn2S.Value());
-  aVert.SetParameter(theWline->NbPnts());
+  theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
+  theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
+
+  aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theU1Period);
+  aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theV1Period);
+  aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theU2Period);
+  aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theV2Period);
+
+  return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
+          theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
+}
+
+//=======================================================================
+//function : CheckArguments
+//purpose  : Check if extending is possible
+//            (see IntPatch_WLineTool::ExtendTwoWlinesToEachOther)
+//=======================================================================
+static Standard_Boolean CheckArguments(const IntSurf_Quadric& theS1,
+                                       const IntSurf_Quadric& theS2,
+                                       const IntSurf_PntOn2S& thePtWL1,
+                                       const IntSurf_PntOn2S& thePtWL2,
+                                       IntSurf_PntOn2S& theNewPoint,
+                                       const gp_Vec& theVec1,
+                                       const gp_Vec& theVec2,
+                                       const gp_Vec& theVec3,
+                                       const Bnd_Box2d& theBoxS1,
+                                       const Bnd_Box2d& theBoxS2,
+                                       const Standard_Real theToler3D,
+                                       const Standard_Real theU1Period,
+                                       const Standard_Real theU2Period,
+                                       const Standard_Real theV1Period,
+                                       const Standard_Real theV2Period)
+{
+  const Standard_Real aMaxAngle = M_PI/6; //30 degree
+  const Standard_Real aSqToler = theToler3D*theToler3D;
+
+  if(theVec3.SquareMagnitude() <= aSqToler)
+  {
+    return Standard_False;
+  }
+
+  if((theVec1.Angle(theVec2) > aMaxAngle) ||
+     (theVec1.Angle(theVec3) > aMaxAngle) ||
+     (theVec2.Angle(theVec3) > aMaxAngle))
+  {
+    return Standard_False;
+  }
+
+  const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
+
+  Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
+
+  theBoxS1.Get(aU1, aV1, aU2, aV2);
+  const Standard_Real aU1f = aU1, aV1f = aV1;
+  theBoxS2.Get(aU1, aV1, aU2, aV2);
+  const Standard_Real aU2f = aU1, aV2f = aV1;
+
+  if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
+                          theU1Period, theU2Period, theV1Period, theV2Period,
+                          aU1, aV1, aU2, aV2))
+  {
+    return Standard_False;
+  }
+
+  theNewPoint.SetValue(aPmid, aU1, aV1, aU2, aV2);
+
+  if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint,
+                   theU1Period, theU2Period,
+                   theV1Period, theV2Period))
+  {
+    return Standard_False;
+  }
+
+  Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
+                aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
+
+  thePtWL1.Parameters(aU11, aV11, aU21, aV21);
+  thePtWL2.Parameters(aU12, aV12, aU22, aV22);
+
+  if(IsOnPeriod(aU11 - aU1f, aU12 - aU1f, theU1Period) ||
+     IsOnPeriod(aV11 - aV1f, aV12 - aV1f, theV1Period) ||
+     IsOnPeriod(aU21 - aU2f, aU22 - aU2f, theU2Period) ||
+     IsOnPeriod(aV21 - aV2f, aV22 - aV2f, theV2Period))
+  {
+    return Standard_False;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : ExtendTwoWLFirstFirst
+//purpose  : Performs extending theWLine1 and theWLine2 through their
+//            respecting start point.
+//=======================================================================
+static void ExtendTwoWLFirstFirst(const IntSurf_Quadric& theS1,
+                                   const IntSurf_Quadric& theS2,
+                                   const Handle(IntPatch_WLine)& theWLine1,
+                                   const Handle(IntPatch_WLine)& theWLine2,
+                                   const IntSurf_PntOn2S& thePtWL1,
+                                   const IntSurf_PntOn2S& thePtWL2,
+                                   const gp_Vec& theVec1,
+                                   const gp_Vec& theVec2,
+                                   const gp_Vec& theVec3,
+                                   const Bnd_Box2d& theBoxS1,
+                                   const Bnd_Box2d& theBoxS2,
+                                   const Standard_Real theToler3D,
+                                   const Standard_Real theU1Period,
+                                   const Standard_Real theU2Period,
+                                   const Standard_Real theV1Period,
+                                   const Standard_Real theV2Period,
+                                   unsigned int &theCheckResult,
+                                   Standard_Boolean &theHasBeenJoined)
+{
+  IntSurf_PntOn2S aPOn2S;
+  if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
+                     theVec1, theVec2, theVec3, 
+                     theBoxS1, theBoxS2, theToler3D,
+                     theU1Period, theU2Period, theV1Period, theV2Period))
+  {
+    return;
+  }
+
+  theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
+
+  ExtendFirst(theWLine1, aPOn2S);
+  ExtendFirst(theWLine2, aPOn2S);
+
+  if(theHasBeenJoined)
+    return;
+
+  Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
+  while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
+    theWLine1->RemoveVertex(1);
+
+  aPrm = theWLine2->Vertex(1).ParameterOnLine();
+  while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
+    theWLine2->RemoveVertex(1);
+
+  const Standard_Integer aNbPts = theWLine2->NbPnts();
+  for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
+  {
+    const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
+    theWLine1->Curve()->InsertBefore(1, aPt);
+  }
+
+  for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
+  {
+    IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
+    const Standard_Real aCurParam = aVert.ParameterOnLine();
+    aVert.SetParameter(aNbPts+aCurParam-1);
+  }
+
+  for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
+  {
+    IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
+    const Standard_Real aCurParam = aVert.ParameterOnLine();
+    aVert.SetParameter(aNbPts-aCurParam+1);
+    theWLine1->AddVertex(aVert, Standard_True);
+  }
+
+  theHasBeenJoined = Standard_True;
+}
+
+//=======================================================================
+//function : ExtendTwoWLFirstLast
+//purpose  : Performs extending theWLine1 through its start point and theWLine2
+//            through its end point.
+//=======================================================================
+static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1,
+                                 const IntSurf_Quadric& theS2,
+                                 const Handle(IntPatch_WLine)& theWLine1,
+                                 const Handle(IntPatch_WLine)& theWLine2,
+                                 const IntSurf_PntOn2S& thePtWL1,
+                                 const IntSurf_PntOn2S& thePtWL2,
+                                 const gp_Vec& theVec1,
+                                 const gp_Vec& theVec2,
+                                 const gp_Vec& theVec3,
+                                 const Bnd_Box2d& theBoxS1,
+                                 const Bnd_Box2d& theBoxS2,
+                                 const Standard_Real theToler3D,
+                                 const Standard_Real theU1Period,
+                                 const Standard_Real theU2Period,
+                                 const Standard_Real theV1Period,
+                                 const Standard_Real theV2Period,
+                                 unsigned int &theCheckResult,
+                                 Standard_Boolean &theHasBeenJoined)
+{
+  IntSurf_PntOn2S aPOn2S;
+  if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
+                     theVec1, theVec2, theVec3, 
+                     theBoxS1, theBoxS2, theToler3D,
+                     theU1Period, theU2Period, theV1Period, theV2Period))
+  {
+    return;
+  }
+
+  theCheckResult |= IntPatchWT_DisLastLast;
+
+  ExtendFirst(theWLine1, aPOn2S);
+  ExtendLast (theWLine2, aPOn2S);
+
+  if(theHasBeenJoined)
+    return;
+
+  Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
+  while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
+    theWLine1->RemoveVertex(1);
+
+  aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
+  while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
+    theWLine2->RemoveVertex(theWLine2->NbVertex());
+
+  const Standard_Integer aNbPts = theWLine2->NbPnts();
+  for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
+  {
+    const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
+    theWLine1->Curve()->InsertBefore(1, aPt);
+  }
+
+  for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
+  {
+    IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
+    const Standard_Real aCurParam = aVert.ParameterOnLine();
+    aVert.SetParameter(aNbPts+aCurParam-1);
+  }
+
+  for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
+  {
+    const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
+    theWLine1->AddVertex(aVert, Standard_True);
+  }
+
+  theHasBeenJoined = Standard_True;
+}
+
+//=======================================================================
+//function : ExtendTwoWLLastFirst
+//purpose  : Performs extending theWLine1 through its end point and theWLine2
+//            through its start point.
+//=======================================================================
+static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1,
+                                 const IntSurf_Quadric& theS2,
+                                 const Handle(IntPatch_WLine)& theWLine1,
+                                 const Handle(IntPatch_WLine)& theWLine2,
+                                 const IntSurf_PntOn2S& thePtWL1,
+                                 const IntSurf_PntOn2S& thePtWL2,
+                                 const gp_Vec& theVec1,
+                                 const gp_Vec& theVec2,
+                                 const gp_Vec& theVec3,
+                                 const Bnd_Box2d& theBoxS1,
+                                 const Bnd_Box2d& theBoxS2,
+                                 const Standard_Real theToler3D,
+                                 const Standard_Real theU1Period,
+                                 const Standard_Real theU2Period,
+                                 const Standard_Real theV1Period,
+                                 const Standard_Real theV2Period,
+                                 unsigned int &theCheckResult,
+                                 Standard_Boolean &theHasBeenJoined)
+{
+  IntSurf_PntOn2S aPOn2S;
+  if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
+                     theVec1, theVec2, theVec3, 
+                     theBoxS1, theBoxS2, theToler3D,
+                     theU1Period, theU2Period, theV1Period, theV2Period))
+  {
+    return;
+  }
+
+  theCheckResult |= IntPatchWT_DisLastLast;
+
+  ExtendLast (theWLine1, aPOn2S);
+  ExtendFirst(theWLine2, aPOn2S);
+
+  if(theHasBeenJoined)
+  {
+    return;
+  }
+
+  Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
+  while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
+    theWLine1->RemoveVertex(theWLine1->NbVertex());
+
+  aPrm = theWLine2->Vertex(1).ParameterOnLine();
+  while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
+    theWLine2->RemoveVertex(1);
+
+  const Standard_Integer aNbPts = theWLine1->NbPnts();
+  for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
+  {
+    const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
+    theWLine1->Curve()->Add(aPt);
+  }
+
+  for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
+  {
+    IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
+    const Standard_Real aCurParam = aVert.ParameterOnLine();
+    aVert.SetParameter(aNbPts+aCurParam-1);
+    theWLine1->AddVertex(aVert, Standard_False);
+  }
+
+  theHasBeenJoined = Standard_True;
+}
+
+//=======================================================================
+//function : ExtendTwoWLLastLast
+//purpose  : 
+//=======================================================================
+static void ExtendTwoWLLastLast(const IntSurf_Quadric& theS1,
+                                const IntSurf_Quadric& theS2,
+                                const Handle(IntPatch_WLine)& theWLine1,
+                                const Handle(IntPatch_WLine)& theWLine2,
+                                const IntSurf_PntOn2S& thePtWL1,
+                                const IntSurf_PntOn2S& thePtWL2,
+                                const gp_Vec& theVec1,
+                                const gp_Vec& theVec2,
+                                const gp_Vec& theVec3,
+                                const Bnd_Box2d& theBoxS1,
+                                const Bnd_Box2d& theBoxS2,
+                                const Standard_Real theToler3D,
+                                const Standard_Real theU1Period,
+                                const Standard_Real theU2Period,
+                                const Standard_Real theV1Period,
+                                const Standard_Real theV2Period,
+                                unsigned int &/*theCheckResult*/,
+                                Standard_Boolean &theHasBeenJoined)
+{
+  IntSurf_PntOn2S aPOn2S;
+  if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
+                     theVec1, theVec2, theVec3, 
+                     theBoxS1, theBoxS2, theToler3D,
+                     theU1Period, theU2Period, theV1Period, theV2Period))
+  {
+    return;
+  }
+  
+  //theCheckResult |= IntPatchWT_DisLastLast;
+
+  ExtendLast(theWLine1, aPOn2S);
+  ExtendLast(theWLine2, aPOn2S);
+
+  if(theHasBeenJoined)
+    return;
+
+  Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
+  while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
+    theWLine1->RemoveVertex(theWLine1->NbVertex());
+
+  aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
+  while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
+    theWLine2->RemoveVertex(theWLine2->NbVertex());
+
+  const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
+  for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
+  {
+    const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
+    theWLine1->Curve()->Add(aPt);
+  }
+
+  for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
+  {
+    IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
+    const Standard_Real aCurParam = aVert.ParameterOnLine();
+    aVert.SetParameter(aNbPts - aCurParam);
+    theWLine1->AddVertex(aVert, Standard_False);
+  }
+
+  theHasBeenJoined = Standard_True;
 }
 
 //=========================================================================
@@ -1054,7 +1491,8 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
 
 //=======================================================================
 //function : ExtendTwoWlinesToEachOther
-//purpose  : 
+//purpose  : Performs extending theWLine1 and theWLine2 through their
+//            respecting end point.
 //=======================================================================
 void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin,
                                                     const IntSurf_Quadric& theS1,
@@ -1063,15 +1501,13 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
                                                     const Standard_Real theU1Period,
                                                     const Standard_Real theU2Period,
                                                     const Standard_Real theV1Period,
-                                                    const Standard_Real theV2Period)
+                                                    const Standard_Real theV2Period,
+                                                    const Bnd_Box2d& theBoxS1,
+                                                    const Bnd_Box2d& theBoxS2)
 {
   if(theSlin.Length() < 2)
     return;
 
-  const Standard_Real aMaxAngle = M_PI/6; //30 degree
-  const Standard_Real aSqToler = theToler3D*theToler3D;
-  Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
-  gp_Pnt aPmid;
   gp_Vec aVec1, aVec2, aVec3;
 
   for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
@@ -1086,6 +1522,12 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
     
     const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
 
+    if(aWLine1->Vertex(1).ParameterOnLine() != 1)
+      continue;
+
+    if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
+      continue;
+
     for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
         aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
     {
@@ -1095,21 +1537,20 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
       if(aWLine2.IsNull())
         continue;
 
+      if(aWLine2->Vertex(1).ParameterOnLine() != 1)
+        continue;
+
+      if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
+        continue;
+
       //Enable/Disable of some ckeck. Bit-mask is used for it.
       //E.g. if 1st point of aWLine1 matches with
       //1st point of aWLine2 then we do not need in check
       //1st point of aWLine1 and last point of aWLine2 etc.
-      enum
-      {
-        IntPatchWT_EnAll = 0x00,
-        IntPatchWT_DisLastLast = 0x01,
-        IntPatchWT_DisLastFirst = 0x02,
-        IntPatchWT_DisFirstLast = 0x04,
-        IntPatchWT_DisFirstFirst = 0x08
-      };
-
       unsigned int aCheckResult = IntPatchWT_EnAll;
 
+      Standard_Boolean hasBeenJoined = Standard_False;
+
       const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
 
       const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
@@ -1130,55 +1571,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
         aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
         aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
 
-        if(aVec3.SquareMagnitude() > aSqToler)
-        {
-          if( (aVec1.Angle(aVec2) < aMaxAngle) &&
-              (aVec1.Angle(aVec3) < aMaxAngle) &&
-              (aVec2.Angle(aVec3) < aMaxAngle))
-          {
-            aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
-            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
-                                   theU1Period, theU2Period, theV1Period, theV2Period,
-                                   aU1, aV1, aU2, aV2))
-            {
-              IntSurf_PntOn2S aPOn2S;
-              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
-              
-              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
-                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
-              aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
-              aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
-
-              if(!IsSeam(aU11, aU12, theU1Period) &&
-                 !IsSeam(aV11, aV12, theV1Period) &&
-                 !IsSeam(aU21, aU22, theU2Period) &&
-                 !IsSeam(aV21, aV22, theV2Period))
-              {
-                aCheckResult |= (IntPatchWT_DisFirstLast |
-                                 IntPatchWT_DisLastFirst);
-
-                if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
-                {
-                  ExtendFirst(aWLine1, aPOn2S);
-                }
-                else
-                {
-                  aWLine1->Curve()->Value(1, aPOn2S);
-                }
-
-                if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
-                {
-                  ExtendFirst(aWLine2, aPOn2S);
-                }
-                else
-                {
-                  aWLine2->Curve()->Value(1, aPOn2S);
-                }
-              }
-            }
-          }
-        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
-      }//if(!(aCheckResult & 0x08)) cond.
+        ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
+                              aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
+                              theU1Period, theU2Period, theV1Period, theV2Period,
+                              aCheckResult, hasBeenJoined);
+      }
 
       if(!(aCheckResult & IntPatchWT_DisFirstLast))
       {// First/Last
@@ -1186,54 +1583,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
         aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
         aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
 
-        if(aVec3.SquareMagnitude() > aSqToler)
-        {
-          if((aVec1.Angle(aVec2) < aMaxAngle) &&
-             (aVec1.Angle(aVec3) < aMaxAngle) &&
-             (aVec2.Angle(aVec3) < aMaxAngle))
-          {
-            aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
-            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
-                                   theU1Period, theU2Period, theV1Period, theV2Period,
-                                   aU1, aV1, aU2, aV2))
-            {
-              IntSurf_PntOn2S aPOn2S;
-              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
-
-              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
-                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
-              aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
-              aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
-
-              if(!IsSeam(aU11, aU12, theU1Period) &&
-                 !IsSeam(aV11, aV12, theV1Period) &&
-                 !IsSeam(aU21, aU22, theU2Period) &&
-                 !IsSeam(aV21, aV22, theV2Period))
-              {
-                aCheckResult |= IntPatchWT_DisLastLast;
-
-                if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
-                {
-                  ExtendFirst(aWLine1, aPOn2S);
-                }
-                else
-                {
-                  aWLine1->Curve()->Value(1, aPOn2S);
-                }
-
-                if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
-                {
-                  ExtendLast(aWLine2, aPOn2S);
-                }
-                else
-                {
-                  aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
-                }
-              }
-            }
-          }
-        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
-      }//if(!(aCheckResult & 0x04)) cond.
+        ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
+                             aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
+                             theU1Period, theU2Period, theV1Period, theV2Period,
+                             aCheckResult, hasBeenJoined);
+      }
 
       if(!(aCheckResult & IntPatchWT_DisLastFirst))
       {// Last/First
@@ -1241,54 +1595,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
         aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
         aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
 
-        if(aVec3.SquareMagnitude() > aSqToler)
-        {
-          if((aVec1.Angle(aVec2) < aMaxAngle) &&
-             (aVec1.Angle(aVec3) < aMaxAngle) &&
-             (aVec2.Angle(aVec3) < aMaxAngle))
-          {
-            aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
-            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
-                                   theU1Period, theU2Period, theV1Period, theV2Period,
-                                   aU1, aV1, aU2, aV2))
-            {
-              IntSurf_PntOn2S aPOn2S;
-              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
-
-              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
-                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
-              aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
-              aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
-
-              if(!IsSeam(aU11, aU12, theU1Period) &&
-                 !IsSeam(aV11, aV12, theV1Period) &&
-                 !IsSeam(aU21, aU22, theU2Period) &&
-                 !IsSeam(aV21, aV22, theV2Period))
-              {
-                aCheckResult |= IntPatchWT_DisLastLast;
-
-                if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
-                {
-                  ExtendLast(aWLine1, aPOn2S);
-                }
-                else
-                {
-                  aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
-                }
-
-                if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
-                {
-                  ExtendFirst(aWLine2, aPOn2S);
-                }
-                else
-                {
-                  aWLine2->Curve()->Value(1, aPOn2S);
-                }
-              }
-            }
-          }
-        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
-      }//if(!(aCheckResult & 0x02)) cond.
+        ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
+                             aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
+                             theU1Period, theU2Period, theV1Period, theV2Period,
+                             aCheckResult, hasBeenJoined);
+      }
 
       if(!(aCheckResult & IntPatchWT_DisLastLast))
       {// Last/Last
@@ -1296,52 +1607,17 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
         aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
         aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
 
-        if(aVec3.SquareMagnitude() > aSqToler)
-        {
-          if((aVec1.Angle(aVec2) < aMaxAngle) &&
-             (aVec1.Angle(aVec3) < aMaxAngle) &&
-             (aVec2.Angle(aVec3) < aMaxAngle))
-          {
-            aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
-            if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
-                                   theU1Period, theU2Period, theV1Period, theV2Period,
-                                   aU1, aV1, aU2, aV2))
-            {
-              IntSurf_PntOn2S aPOn2S;
-              aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
-
-              Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
-                            aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
-              aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
-              aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
-
-              if(!IsSeam(aU11, aU12, theU1Period) &&
-                 !IsSeam(aV11, aV12, theV1Period) &&
-                 !IsSeam(aU21, aU22, theU2Period) &&
-                 !IsSeam(aV21, aV22, theV2Period))
-              {
-                if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
-                {
-                  ExtendLast(aWLine1, aPOn2S);
-                }
-                else
-                {
-                  aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
-                }
-
-                if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
-                {
-                  ExtendLast(aWLine2, aPOn2S);
-                }
-                else
-                {
-                  aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
-                }
-              }
-            }
-          }
-        }//if(aVec3.SquareMagnitude() > aSqToler) cond.
-      }//if(!(aCheckResult & 0x01)) cond.
+        ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
+                            aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
+                            theU1Period, theU2Period, theV1Period, theV2Period,
+                            aCheckResult, hasBeenJoined);
+      }
+
+      if(hasBeenJoined)
+      {
+        theSlin.Remove(aNumOfLine2);
+        aNumOfLine2--;
+      }
     }
   }
 }
index 75a8e73..865913c 100644 (file)
@@ -78,11 +78,9 @@ public:
                                          const Standard_Real theVlSurf2);
 
 
-//! Concatenates two some Walking lines from theSlin if it is possible.
-//! This method does not create single line from several. It allows every
-//! extended line to be started/finished in strictly determined point
-//! (in the place of joint of two lines). As result, some gaps between two lines
-//! will vanish.
+//! Extends every line from theSlin (if it is possible) to be started/finished
+//! in strictly determined point (in the place of joint of two lines).
+//! As result, some gaps between two lines will vanish.
 //! The Walking lines are supposed (algorithm will do nothing for not-Walking line)
 //! to be computed as a result of intersection of two quadrics.
 //! The quadrics definition is accepted in input parameters.
@@ -93,7 +91,9 @@ public:
                                                          const Standard_Real theU1Period,
                                                          const Standard_Real theU2Period,
                                                          const Standard_Real theV1Period,
-                                                         const Standard_Real theV2Period);
+                                                         const Standard_Real theV2Period,
+                                                         const Bnd_Box2d& theBoxS1,
+                                                         const Bnd_Box2d& theBoxS2);
 };
 
 #endif
\ No newline at end of file
index 2b48d65..da6fbca 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC27302 ALL: Error: Curve Number is bad!"
-
 puts "============"
 puts "OCC27282"
 puts "============"
@@ -8,7 +6,7 @@ puts ""
 ## [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape
 ###############################
 
-set MaxTol 4.8106951786435371e-006
+set MaxTol 4.8106952270863644e-006
 set GoodNbCurv 1
 
 restore [locate_data_file bug27282_cmpd.brep] a
@@ -27,7 +25,7 @@ checkreal ToleranceReached ${Toler} ${MaxTol} 0.0 0.1
 checkview -screenshot -2d -path ${imagedir}/${test_image}.png
 
 if {${NbCurv} != ${GoodNbCurv}} {
-  puts "Error: Curve Number is bad!"
+  puts "Error: Number of curves is bad!"
   
   for {set i 1} {$i < ${NbCurv}} {incr i} {
     for {set j [expr $i+1]} {$j <= $NbCurv} {incr j} {
@@ -43,5 +41,5 @@ if {${NbCurv} != ${GoodNbCurv}} {
     }
   }
 } else {
-  checklength c_1 -l 833.56846559428755
+  checklength c_1 -l 833.56846557106064
 }
\ No newline at end of file
diff --git a/tests/bugs/modalg_6/bug27302 b/tests/bugs/modalg_6/bug27302
new file mode 100644 (file)
index 0000000..efd39e5
--- /dev/null
@@ -0,0 +1,48 @@
+puts "============"
+puts "OCC27302"
+puts "============"
+puts ""
+###############################
+## Invalid curves number in intersection result
+###############################
+
+set MaxTol 9.9579577516847715e-005
+set GoodNbCurv 1
+
+restore [locate_data_file CTO900_pro12913a.rle] a
+restore [locate_data_file CTO900_pro12913b.rle] b
+
+explode a f
+explode b f
+
+smallview
+don a_34 b_9
+fit
+
+set log [bopcurves a_34 b_9 -2d]
+
+regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
+
+checkreal ToleranceReached ${Toler} ${MaxTol} 0.0 0.1
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+
+if {${NbCurv} != ${GoodNbCurv}} {
+  puts "Error: Number of curves is bad!"
+  
+  for {set i 1} {$i < ${NbCurv}} {incr i} {
+    for {set j [expr $i+1]} {$j <= $NbCurv} {incr j} {
+      mkedge e1 c_$i
+      mkedge e2 c_$j
+      
+      dset dd_val 100.0*${Toler}
+      distmini dd e1 e2
+      
+      if { [dval dd_val] > ${Toler} } {
+        puts "Error: Intersection result is not closed"
+      }
+    }
+  }
+} else {
+  checklength c_1 -l 86.536841230136204
+}
\ No newline at end of file