From bd01983fe94ec64210e945edd676ab99777d0cca Mon Sep 17 00:00:00 2001
From: nbv <nbv@opencascade.com>
Date: Wed, 1 Aug 2018 15:49:36 +0300
Subject: [PATCH] 0024429: Cylinder-torus intersection throws an exception and
 produces no result

1. The reason of exception has been eliminated.

2. Interfaces of the following methods have been changed in the classes Contap_TheIWalking and IntPatch_TheIWalking: Perform(...), TestArretPassage(...) and ComputeCloseLine(...).

<break!>

Main changes are:

1. IntWalk_IWalking::TestArretPassage(...).
  a) Anisotropic normalization of 2D-coordinates has been eliminated.
  b) Algorithm of check of validity of WLine has been improved.

2. IntWalk_IWalking::ComputeCloseLine(...). Check of indices of the sequence of points has been added (to avoid exceptions).
---
 src/Contap/Contap_Contour.cxx                |  2 +-
 src/Contap/Contap_TheIWalking.hxx            | 22 +++++++++--
 src/IntPatch/IntPatch_ImpPrmIntersection.cxx |  2 +-
 src/IntPatch/IntPatch_TheIWalking.hxx        | 22 +++++++++--
 src/IntWalk/IntWalk_IWalking_1.gxx           |  5 ++-
 src/IntWalk/IntWalk_IWalking_2.gxx           | 47 ++++++++++------------
 src/IntWalk/IntWalk_IWalking_4.gxx           | 10 +++--
 tests/bugs/modalg_7/bug24429                 | 59 +++++++++++++++++++++++-----
 8 files changed, 120 insertions(+), 49 deletions(-)

diff --git a/src/Contap/Contap_Contour.cxx b/src/Contap/Contap_Contour.cxx
index d23c73f..a699281 100644
--- a/src/Contap/Contap_Contour.cxx
+++ b/src/Contap/Contap_Contour.cxx
@@ -1499,7 +1499,7 @@ void Contap_Contour::Perform
 
     Standard_Boolean theToFillHoles = Standard_True;
     Contap_TheIWalking iwalk(Preci,Fleche,Pas,theToFillHoles);
-    iwalk.Perform(seqpdep,seqpins,mySFunc ,Surf);
+    iwalk.Perform(seqpdep,seqpins,mySFunc,Surf, Precision::Confusion());
     if(!iwalk.IsDone()) {
       return;
     }
diff --git a/src/Contap/Contap_TheIWalking.hxx b/src/Contap/Contap_TheIWalking.hxx
index 88b6935..33787d0 100644
--- a/src/Contap/Contap_TheIWalking.hxx
+++ b/src/Contap/Contap_TheIWalking.hxx
@@ -81,7 +81,12 @@ public:
   //! Searches a set of polylines starting on a point of Pnts1
   //! or Pnts2.
   //! Each point on a resulting polyline verifies F(u,v)=0
-  Standard_EXPORT void Perform (const IntSurf_SequenceOfPathPoint& Pnts1, const IntSurf_SequenceOfInteriorPoint& Pnts2, Contap_SurfFunction& Func, const Handle(Adaptor3d_HSurface)& S, const Standard_Boolean Reversed = Standard_False);
+  Standard_EXPORT void Perform (const IntSurf_SequenceOfPathPoint& Pnts1,
+                                const IntSurf_SequenceOfInteriorPoint& Pnts2,
+                                Contap_SurfFunction& Func,
+                                const Handle(Adaptor3d_HSurface)& S,
+                                const Standard_Real theTolArc,
+                                const Standard_Boolean Reversed = Standard_False);
   
   //! Searches a set of polylines starting on a point of Pnts1.
   //! Each point on a resulting polyline verifies F(u,v)=0
@@ -120,7 +125,12 @@ protected:
   
   Standard_EXPORT Standard_Boolean TestArretPassage (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, Contap_SurfFunction& Section, math_Vector& UV, Standard_Integer& Irang);
   
-  Standard_EXPORT Standard_Boolean TestArretPassage (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, const math_Vector& UV, const Standard_Integer Index, Standard_Integer& Irang);
+  Standard_EXPORT Standard_Boolean TestArretPassage (const TColStd_SequenceOfReal& Umult,
+                                                     const TColStd_SequenceOfReal& Vmult,
+                                                     const math_Vector& UV,
+                                                     const Standard_Integer Index,
+                                                     const Standard_Real theTolArc,
+                                                     Standard_Integer& Irang);
   
   Standard_EXPORT Standard_Boolean TestArretAjout (Contap_SurfFunction& Section, math_Vector& UV, Standard_Integer& Irang, IntSurf_PntOn2S& PSol);
   
@@ -142,7 +152,13 @@ protected:
   
   Standard_EXPORT Standard_Boolean IsPointOnLine (const gp_Pnt2d& theP2d, const Standard_Integer Irang);
   
-  Standard_EXPORT void ComputeCloseLine (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, const IntSurf_SequenceOfPathPoint& Pnts1, const IntSurf_SequenceOfInteriorPoint& Pnts2, Contap_SurfFunction& Section, Standard_Boolean& Rajout);
+  Standard_EXPORT void ComputeCloseLine (const TColStd_SequenceOfReal& Umult,
+                                         const TColStd_SequenceOfReal& Vmult,
+                                         const IntSurf_SequenceOfPathPoint& Pnts1,
+                                         const IntSurf_SequenceOfInteriorPoint& Pnts2,
+                                         const Standard_Real theTolArc,
+                                         Contap_SurfFunction& Section,
+                                         Standard_Boolean& Rajout);
   
   Standard_EXPORT void AddPointInCurrentLine (const Standard_Integer N, const IntSurf_PathPoint& PathPnt, const Handle(Contap_TheIWLineOfTheIWalking)& CurrentLine) const;
   
diff --git a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx
index 5c74b94..eb5836d 100644
--- a/src/IntPatch/IntPatch_ImpPrmIntersection.cxx
+++ b/src/IntPatch/IntPatch_ImpPrmIntersection.cxx
@@ -687,7 +687,7 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
   //
   if (NbPointDep || NbPointIns) {
     IntPatch_TheIWalking iwalk(TolTang, Fleche, Pas);
-    iwalk.Perform(seqpdep, seqpins, Func, reversed ? Surf1 : Surf2, reversed);
+    iwalk.Perform(seqpdep, seqpins, Func, reversed ? Surf1 : Surf2, TolArc, reversed);
 
     if(!iwalk.IsDone()) {
       return;
diff --git a/src/IntPatch/IntPatch_TheIWalking.hxx b/src/IntPatch/IntPatch_TheIWalking.hxx
index a58d30c..66144ed 100644
--- a/src/IntPatch/IntPatch_TheIWalking.hxx
+++ b/src/IntPatch/IntPatch_TheIWalking.hxx
@@ -81,7 +81,12 @@ public:
   //! Searches a set of polylines starting on a point of Pnts1
   //! or Pnts2.
   //! Each point on a resulting polyline verifies F(u,v)=0
-  Standard_EXPORT void Perform (const IntSurf_SequenceOfPathPoint& Pnts1, const IntSurf_SequenceOfInteriorPoint& Pnts2, IntPatch_TheSurfFunction& Func, const Handle(Adaptor3d_HSurface)& S, const Standard_Boolean Reversed = Standard_False);
+  Standard_EXPORT void Perform (const IntSurf_SequenceOfPathPoint& Pnts1,
+                                const IntSurf_SequenceOfInteriorPoint& Pnts2,
+                                IntPatch_TheSurfFunction& Func,
+                                const Handle(Adaptor3d_HSurface)& S,
+                                const Standard_Real theTolArc,
+                                const Standard_Boolean Reversed = Standard_False);
   
   //! Searches a set of polylines starting on a point of Pnts1.
   //! Each point on a resulting polyline verifies F(u,v)=0
@@ -120,7 +125,12 @@ protected:
   
   Standard_EXPORT Standard_Boolean TestArretPassage (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, IntPatch_TheSurfFunction& Section, math_Vector& UV, Standard_Integer& Irang);
   
-  Standard_EXPORT Standard_Boolean TestArretPassage (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, const math_Vector& UV, const Standard_Integer Index, Standard_Integer& Irang);
+  Standard_EXPORT Standard_Boolean TestArretPassage(const TColStd_SequenceOfReal& Umult,
+                                                    const TColStd_SequenceOfReal& Vmult,
+                                                    const math_Vector& UV,
+                                                    const Standard_Integer Index,
+                                                    const Standard_Real theTolArc,
+                                                    Standard_Integer& Irang);
   
   Standard_EXPORT Standard_Boolean TestArretAjout (IntPatch_TheSurfFunction& Section, math_Vector& UV, Standard_Integer& Irang, IntSurf_PntOn2S& PSol);
   
@@ -142,7 +152,13 @@ protected:
   
   Standard_EXPORT Standard_Boolean IsPointOnLine (const gp_Pnt2d& theP2d, const Standard_Integer Irang);
   
-  Standard_EXPORT void ComputeCloseLine (const TColStd_SequenceOfReal& Umult, const TColStd_SequenceOfReal& Vmult, const IntSurf_SequenceOfPathPoint& Pnts1, const IntSurf_SequenceOfInteriorPoint& Pnts2, IntPatch_TheSurfFunction& Section, Standard_Boolean& Rajout);
+  Standard_EXPORT void ComputeCloseLine (const TColStd_SequenceOfReal& Umult,
+                                         const TColStd_SequenceOfReal& Vmult,
+                                         const IntSurf_SequenceOfPathPoint& Pnts1,
+                                         const IntSurf_SequenceOfInteriorPoint& Pnts2,
+                                         const Standard_Real theTolArc,
+                                         IntPatch_TheSurfFunction& Section,
+                                         Standard_Boolean& Rajout);
   
   Standard_EXPORT void AddPointInCurrentLine (const Standard_Integer N, const IntSurf_PathPoint& PathPnt, const Handle(IntPatch_TheIWLineOfTheIWalking)& CurrentLine) const;
   
diff --git a/src/IntWalk/IntWalk_IWalking_1.gxx b/src/IntWalk/IntWalk_IWalking_1.gxx
index 5d8ab33..5783359 100644
--- a/src/IntWalk/IntWalk_IWalking_1.gxx
+++ b/src/IntWalk/IntWalk_IWalking_1.gxx
@@ -131,6 +131,7 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
 			       const ThePOLIterator& Pnts2,
 			       TheIWFunction& Func,
 			       const ThePSurface& Caro,
+                               const Standard_Real theTolArc,
 			       const Standard_Boolean Reversed)
 
 {
@@ -243,7 +244,7 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
 
   // calculation of all closed lines 
   if (nbPnts2 != 0)
-    ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Func,Rajout);
+    ComputeCloseLine(Umult, Vmult, Pnts1, Pnts2, theTolArc, Func, Rajout);
 
   if (ToFillHoles)
   {
@@ -269,7 +270,7 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
         ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
         wd2.push_back (aWD2);
       }
-      ComputeCloseLine(Umult,Vmult,Pnts1,PntsInHoles,Func,Rajout);
+      ComputeCloseLine(Umult, Vmult, Pnts1, PntsInHoles, theTolArc, Func, Rajout);
     }
   }
   
diff --git a/src/IntWalk/IntWalk_IWalking_2.gxx b/src/IntWalk/IntWalk_IWalking_2.gxx
index 69db4cd..ef51763 100644
--- a/src/IntWalk/IntWalk_IWalking_2.gxx
+++ b/src/IntWalk/IntWalk_IWalking_2.gxx
@@ -355,6 +355,7 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
    const TColStd_SequenceOfReal& Vmult,
    const math_Vector& UV, 
    const Standard_Integer Index, 
+   const Standard_Real theTolArc,
    Standard_Integer& Irang)
 {
 // Umult, Vmult : table of stop (or crossing) points on border, here
@@ -389,21 +390,8 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
   Standard_Real UV1=UV(1);
   Standard_Real UV2=UV(2);
 
-
-  //Normalizing factor. If it is less than 1.0 then the range will be expanded. 
-  //This is no good for computation. Therefore, it is limited.
-  const Standard_Real deltau = mySRangeU.IsVoid() ? UM - Um : Max(mySRangeU.Delta(), 1.0);
-  const Standard_Real deltav = mySRangeV.IsVoid() ? VM - Vm : Max(mySRangeV.Delta(), 1.0);
-
-  Up/=deltau; UV1/=deltau; 
-  Vp/=deltav; UV2/=deltav;
-
-  tolu/=deltau;
-  tolv/=deltav;
-
   Standard_Real tolu2=tolu+tolu;
   Standard_Real tolv2=tolv+tolv;
-
   
   Standard_Real dPreviousCurrent = (Up-UV1)*(Up-UV1)+(Vp-UV2)*(Vp-UV2);
   for (k = 1; k < (int)wd2.size(); k++) { 
@@ -411,13 +399,10 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
       Utest = wd2[k].ustart;
       Vtest = wd2[k].vstart;
       
-      Utest/=deltau;
-      Vtest/=deltav;
-      
       Standard_Real UV1mUtest=UV1-Utest;
       Standard_Real UV2mVtest=UV2-Vtest;
-      if(   (UV1mUtest<tolu2 && UV1mUtest>-tolu2)
-	 && (UV2mVtest<tolv2 && UV2mVtest>-tolv2)) { 
+      if (Abs(UV1mUtest) < tolu2 && Abs(UV2mVtest) < tolv2)
+      {
 	if(Index!=k) { 
 	  //-- cout<<"* etat2 : ("<<k<<")"<<endl;
 	  wd2[k].etat=-wd2[k].etat; //-- mark the point as a crossing point 
@@ -440,7 +425,19 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
 	    wd2[k].etat = -wd2[k].etat;
 	  }
 	}
-	else if(Scal<0 && (dPreviousStart+dCurrentStart < dPreviousCurrent)) { 
+        else if (Scal<0 && 
+                 (Abs(UV1mUtest*(Vp - UV2) - UV2mVtest*(Up - UV1)) <
+                                                  theTolArc*dCurrentStart))
+        {
+          //        T(Utest, Vtest)
+          //          *
+          //
+          //  *             *
+          //P(Up, Vp)     C(UV1, UV2)
+
+          //The angle T is obtuse and the point T lies in the segment CP
+
+
 	  if (Index == k ) { // on a boucle.
 	    Arrive = Standard_True;
 	    //-- cout<<"** Arrive  : k="<<k<<endl;
@@ -483,8 +480,6 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
     if (wd1[i].etat > 0 && wd1[i].etat < 11) { //test of crossing points 
       Utest = wd1[i].ustart;
       Vtest = wd1[i].vstart;
-      Utest/=deltau;
-      Vtest/=deltav;
       
       if (((Up-Utest) * (UV1-Utest) + (Vp-Vtest) * (UV2-Vtest) < 0) ||
 	  (Abs(UV1-Utest) < tolu &&  Abs(UV2-Vtest) < tolv)) 
@@ -493,12 +488,10 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
 	N=0;
 	for (k = 1; k < i; k++) N = N + nbMultiplicities[k];
 	for (Standard_Integer j = N + 1; j <= N + nbMultiplicities[i]; j++) {
-	  Standard_Real Umultj = Umult(j)/deltau;
-	  Standard_Real Vmultj = Vmult(j)/deltav;	  
-          if (((Up-Umultj)*(UV1-Umultj) +
-	       (Vp-Vmultj)*(UV2-Vmultj) < 0) ||
-	      (Abs(UV1-Umultj) < tolu &&
-	       Abs(UV2-Vmultj) < tolv)) {
+          if (((Up - Umult(j))*(UV1 - Umult(j)) +
+              (Vp - Vmult(j))*(UV2 - Vmult(j)) < 0) ||
+              (Abs(UV1 - Umult(j)) < tolu && Abs(UV2 - Vmult(j)) < tolv))
+          {
 	    Irang=i;
 	    break;
           }
diff --git a/src/IntWalk/IntWalk_IWalking_4.gxx b/src/IntWalk/IntWalk_IWalking_4.gxx
index 0824c58..ee3ca57 100644
--- a/src/IntWalk/IntWalk_IWalking_4.gxx
+++ b/src/IntWalk/IntWalk_IWalking_4.gxx
@@ -13,11 +13,13 @@
 // commercial license or contractual agreement.
 
 #include <NCollection_IncAllocator.hxx>
+#include <IntPatch_TheIWLineOfTheIWalking.hxx>
 
 void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
 					const TColStd_SequenceOfReal& Vmult,
 					const ThePOPIterator& Pnts1,
 					const ThePOLIterator& Pnts2,
+                                        const Standard_Real theTolArc,
 					TheIWFunction& Func,
                                         Standard_Boolean& Rajout )
 // *********** Processing of closed line **********************
@@ -267,7 +269,7 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
               }
             }
 
-            Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
+            Arrive = TestArretPassage(Umult, Vmult, Uvap, I, theTolArc, Ipass);
             if (Arrive) {//reset proper parameter to test the arrow.
               Psol = CurrentLine->Value(1);
               if (!reversed) {
@@ -446,9 +448,11 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
               if (wd2[I].etat > 12) {  //line closed good case
                 CurrentLine->AddStatusFirstLast(Standard_True,
                   Standard_False,Standard_False);
-                CurrentLine->AddPoint(CurrentLine->Value(1));              
+                CurrentLine->AddPoint(CurrentLine->Value(1));
               }
-              else if (N >0) { //point of stop given at input 
+              else if ((N >0) && (Pnts1.Length() >= N))
+              {
+                //point of stop given at input 
                 PathPnt = Pnts1.Value(N);
                 CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
                 AddPointInCurrentLine(N,PathPnt,CurrentLine);
diff --git a/tests/bugs/modalg_7/bug24429 b/tests/bugs/modalg_7/bug24429
index 24ba38f..872d9eb 100644
--- a/tests/bugs/modalg_7/bug24429
+++ b/tests/bugs/modalg_7/bug24429
@@ -1,16 +1,57 @@
-puts "TODO OCC24429 ALL: An exception was caught"
-puts "TODO OCC24429 ALL: \\*\\* Exception \\*\\*.*"
-puts "TODO OCC24429 ALL: TEST INCOMPLETE"
-
 puts "========"
-puts "OCC24429"
+puts "OCC24429: Cylinder-torus intersection throws an ex-ception and produces no result"
 puts "========"
 puts ""
-##########################################################################
-# Cylinder-torus intersection throws an exception and produces no result
-##########################################################################
+
+set GoodNbCurves 8
 
 restore [locate_data_file bug24429_s1.draw] s1
 restore [locate_data_file bug24429_s2.draw] s2
 
-intersect result s1 s2
+intersect res s1 s2
+
+if { [info exists res] } {
+  #Only variable "res" exists
+  renamevar res res_1
+}
+
+bclearobjects
+bcleartools
+
+set ic 1
+set AllowRepeat 1
+while { $AllowRepeat != 0 } {
+  if { ![info exists res_$ic] } {
+    set AllowRepeat 0
+  } else {
+    bounds res_$ic U1 U2
+    
+    if {[dval U2-U1] < 1.0e-9} {
+      puts "Error: Wrong curve's range!"
+    }
+    
+    xdistcs res_$ic s1 U1 U2 100 2.0e-6
+    xdistcs res_$ic s2 U1 U2 100 2.0e-6
+    
+    mkedge ee res_$ic
+    baddobjects ee
+    
+    incr ic
+  }
+}
+
+# Check of gaps between intersection curves
+bfillds
+bbuild rs
+
+checknbshapes rs -edge $GoodNbCurves
+checksection rs -r 0
+
+smallview
+don res_*
+
+fit
+don s1 s2
+disp res_*
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
-- 
1.9.5.msysgit.0

