]> OCCT Git - occt-copy.git/commitdiff
0024694: Wrong processing of two surfaces (implicit and parametric) having tangential... CR24694_2
authorjgv <jgv@opencascade.com>
Fri, 25 Apr 2014 14:26:03 +0000 (18:26 +0400)
committerjgv <jgv@opencascade.com>
Fri, 25 Apr 2014 14:26:03 +0000 (18:26 +0400)
23 files changed:
src/Contap/Contap_Contour.cxx
src/Contap/Contap_SurfFunction.cdl
src/Contap/Contap_SurfFunction.lxx
src/IntImp/IntImp_ZerImpFunc.cdl
src/IntImp/IntImp_ZerImpFunc.gxx
src/IntImp/IntImp_ZerImpFunc.lxx
src/IntPatch/IntPatch_ImpPrmIntersection.cxx
src/IntStart/IntStart_SearchInside.cdl
src/IntStart/IntStart_SearchInside.gxx
src/IntStart/IntStart_SearchInside.lxx
src/IntSurf/IntSurf_PntOn2S.cdl
src/IntSurf/IntSurf_PntOn2S.cxx
src/IntSurf/IntSurf_QuadricTool.cdl
src/IntSurf/IntSurf_QuadricTool.cxx
src/IntSurf/IntSurf_QuadricTool.lxx
src/IntWalk/IntWalk.cdl
src/IntWalk/IntWalk_IWalking.cdl
src/IntWalk/IntWalk_IWalking_1.gxx
src/IntWalk/IntWalk_IWalking_2.gxx
src/IntWalk/IntWalk_IWalking_3.gxx
src/IntWalk/IntWalk_IWalking_4.gxx
src/IntWalk/IntWalk_IWalking_5.gxx
src/IntWalk/IntWalk_IWalking_6.gxx

index ec9a8b01cb879def0d6b2e12e4f145930ba4affd..fb2db73a9eda1616cfe576485e578271d67cc9d7 100644 (file)
@@ -1491,7 +1491,8 @@ void Contap_Contour::Perform
   if (seqpdep.Length() != 0 || seqpins.Length() != 0) {
 
     Contap_TheIWalking iwalk(Preci,Fleche,Pas);
-    iwalk.Perform(seqpdep,seqpins,mySFunc ,Surf);
+    IntSurf_SequenceOfInteriorPoint seqptang; //dummy
+    iwalk.Perform(seqpdep,seqpins,seqptang,mySFunc ,Surf);
     if(!iwalk.IsDone()) {
       return;
     }
index ac5b4504ca2f1a8f2c9c56747771f1be9ad928ff..b61f70a8506e3c048a5c88394d4afbcccb840471 100644 (file)
@@ -148,6 +148,12 @@ is
        returns Boolean from Standard 
        is static;
     
+    IsTangentSmooth(me : in out)
+
+       returns Boolean from Standard 
+       ---C++: inline
+       is static;
+    
 
     Direction3d(me: in out)
 
@@ -167,6 +173,52 @@ is
        is static;
 
 
+    Projection1(me: in out)
+       returns Real from Standard
+       ---C++: inline
+       is static;
+    
+    Projection2(me: in out)
+       returns Real from Standard
+       ---C++: inline
+       is static;
+    
+    Projection3(me: in out)
+       returns Real from Standard
+       ---C++: inline
+       is static;
+    
+    Projection4(me: in out)
+       returns Real from Standard
+       ---C++: inline
+       is static;
+
+    DerivativesAndNormalOnPSurf(me: in out; D1U :    out Vec from gp;
+                                   D1V :    out Vec from gp;
+                                   Normal : out Vec from gp;
+                                   D2U :    out Vec from gp;
+                                   D2V :    out Vec from gp;
+                                   D2UV :   out Vec from gp)
+       returns Boolean from Standard
+       ---C++: inline
+       is static;
+    
+    DerivativesAndNormalOnISurf(me; D1U :    out Vec from gp;
+                                   D1V :    out Vec from gp;
+                                   Normal : out Vec from gp;
+                                   D2U :    out Vec from gp;
+                                   D2V :    out Vec from gp;
+                                   D2UV :   out Vec from gp)
+       returns Boolean from Standard
+       ---C++: inline
+       is static;
+    
+    SquareTangentError(me)
+       returns Real from Standard
+       ---C++: inline
+       is static;
+
+
     FunctionType(me)
     
        returns TFunction from Contap
index bad8a0560cb32e6bd9808fe3ff7c7b0648f2b9eb..21f04d1456961f6071a1651cee60d3093111ff5d 100644 (file)
@@ -100,6 +100,56 @@ inline Standard_Real Contap_SurfFunction::Angle () const
   return myAng;
 }
 
+inline Standard_Boolean Contap_SurfFunction::IsTangentSmooth()
+{
+  return Standard_False;
+}
+
+inline Standard_Real Contap_SurfFunction::Projection1()
+{
+  return 1.;
+}
+
+inline Standard_Real Contap_SurfFunction::Projection2()
+{
+  return 1.;
+}
+
+inline Standard_Real Contap_SurfFunction::Projection3()
+{
+  return 1.;
+}
+
+inline Standard_Real Contap_SurfFunction::Projection4()
+{
+  return 1.;
+}
+
+inline Standard_Boolean Contap_SurfFunction::DerivativesAndNormalOnPSurf(gp_Vec&,
+                                                                          gp_Vec&,
+                                                                          gp_Vec&,
+                                                                          gp_Vec&,
+                                                                          gp_Vec&,
+                                                                          gp_Vec&)
+{
+  return Standard_False;
+}
+
+inline Standard_Boolean Contap_SurfFunction::DerivativesAndNormalOnISurf(gp_Vec&,
+                                                                         gp_Vec&,
+                                                                         gp_Vec&,
+                                                                         gp_Vec&,
+                                                                         gp_Vec&,
+                                                                         gp_Vec&) const
+{
+  return Standard_False;
+}
+
+inline Standard_Real Contap_SurfFunction::SquareTangentError() const
+{
+  return 0.;
+}
+
 inline Contap_TFunction Contap_SurfFunction::FunctionType () const
 {
   return myType;
index 18b74e02fdf58f5e406572d6b320b031baa53b18..f816e0a910e73688d422302df860425f0559c14a 100644 (file)
@@ -141,6 +141,12 @@ is
 
        is static;
     
+    IsTangentSmooth(me : in out)
+
+       returns Boolean from Standard 
+
+       is static;
+    
 
     Direction3d(me: in out)
 
@@ -161,6 +167,45 @@ is
        raises UndefinedDerivative from StdFail
        is static;
     
+    Projection1(me: in out)
+       returns Real from Standard
+       is static;
+    
+    Projection2(me: in out)
+       returns Real from Standard
+       is static;
+    
+    Projection3(me: in out)
+       returns Real from Standard
+       is static;
+    
+    Projection4(me: in out)
+       returns Real from Standard
+       is static;
+    
+    DerivativesAndNormalOnPSurf(me: in out; D1U :    out Vec from gp;
+                                   D1V :    out Vec from gp;
+                                   Normal : out Vec from gp;
+                                   D2U :    out Vec from gp;
+                                   D2V :    out Vec from gp;
+                                   D2UV :   out Vec from gp)
+       returns Boolean from Standard
+       is static;
+    
+    DerivativesAndNormalOnISurf(me; D1U :    out Vec from gp;
+                                   D1V :    out Vec from gp;
+                                   Normal : out Vec from gp;
+                                   D2U :    out Vec from gp;
+                                   D2V :    out Vec from gp;
+                                   D2UV :   out Vec from gp)
+       returns Boolean from Standard
+       is static;
+    
+    SquareTangentError(me)
+       returns Real from Standard
+       ---C++: inline
+
+       is static;
 
     PSurface(me)
 
@@ -170,7 +215,6 @@ is
 
        is static;
     
-
     ISurface(me)
 
        returns TheISurface
@@ -195,11 +239,17 @@ fields
   tgdu        : Real    from Standard;
   tgdv        : Real    from Standard;
   gradient    : Vec     from gp;
+  d1u_isurf   : Vec     from gp;
+  d1v_isurf   : Vec     from gp;
   derived     : Boolean from Standard;
   d1u         : Vec     from gp;
   d1v         : Vec     from gp;
   d3d         : Vec     from gp;
   d2d         : Dir2d   from gp;
+  Proj1       : Real    from Standard;
+  Proj2       : Real    from Standard;
+  Proj3       : Real    from Standard;
+  Proj4       : Real    from Standard;
 
 end ZerImpFunc;
 
index ef6e2316948681ad8b3788561afeb9b2a341d0c9..f128aa4103194f30eba43d617ca7cd77a3e659a6 100644 (file)
@@ -92,7 +92,7 @@ Standard_Boolean IntImp_ZerImpFunc::Values(const math_Vector& X,
   v = X(2);
   ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
   TheISurfaceTool::ValueAndGradient(FUNC, pntsol.X(), pntsol.Y(), pntsol.Z(), 
-                                    valf, gradient);
+                                    valf, gradient, d1u_isurf, d1v_isurf);
   F(1) = valf;
   D(1,1) = d1u.Dot(gradient);
   D(1,2) = d1v.Dot(gradient);
@@ -118,17 +118,247 @@ Standard_Boolean IntImp_ZerImpFunc::IsTangent()
     Standard_Real N2d1v  = d1v.SquareMagnitude();
     tangent =(tgdu * tgdu <= N2grad_EpsAng2 * N2d1v) && 
              (tgdv * tgdv <= N2grad_EpsAng2 * N2d1u);
+
+    if (tangent)
+    {
+#ifdef DRAW
+      Standard_Real SumSquare = tgdu * tgdu + tgdv * tgdv;
+#endif
+      gp_Vec NormSURF = d1u ^ d1v;
+      Proj1 = gradient * d1u;
+      Proj2 = gradient * d1v;
+      Proj3 = NormSURF * d1u_isurf;
+      Proj4 = NormSURF * d1v_isurf;
+#ifdef DRAW
+      cout<<"Tangent !!!"<<endl;
+      cout<<"SumSquare = "<<SumSquare<<endl;
+      cout<<"u = "<<u<<", v = "<<v<<endl;
+      cout<<"pnt = "<<pntsol.X()<<" "<<pntsol.Y()<<" "<<pntsol.Z()<<endl;
+      cout<<"Proj1 = "<<Proj1<<endl;
+      cout<<"Proj2 = "<<Proj2<<endl;
+      cout<<"Proj3 = "<<Proj3<<endl;
+      cout<<"Proj4 = "<<Proj4<<endl<<endl;
+#endif
+    }
+    
     if(!tangent) {
       d3d.SetLinearForm(tgdu,d1u,tgdv,d1v);
       d2d = gp_Dir2d(tgdu, tgdv);
       if (d3d.Magnitude() <= Tolpetit) {    // jag
-        tangent = Standard_True;
+       tangent = Standard_True;
       }
-    }    
+      
+      gp_Vec NormSURF = d1u ^ d1v;
+      Proj1 = gradient * d1u;
+      Proj2 = gradient * d1v;
+      Proj3 = NormSURF * d1u_isurf;
+      Proj4 = NormSURF * d1v_isurf;
+#ifdef DRAW
+      cout<<"u = "<<u<<", v = "<<v<<endl;
+      cout<<"pnt = "<<pntsol.X()<<" "<<pntsol.Y()<<" "<<pntsol.Z()<<endl;
+      cout<<"d3d = "<<d3d.X()<<" "<<d3d.Y()<<" "<<d3d.Z()<<endl;
+      cout<<"Proj1 = "<<Proj1<<endl;
+      cout<<"Proj2 = "<<Proj2<<endl;
+      cout<<"Proj3 = "<<Proj3<<endl;
+      cout<<"Proj4 = "<<Proj4<<endl<<endl;
+#endif
+    }
   }
   return tangent;
 }
 
+Standard_Boolean IntImp_ZerImpFunc::IsTangentSmooth()
+{
+  const Standard_Real TolCrossProd = 1.e-15;
+  
+  if (!computed) {
+    computed = Standard_True;
+    if(!derived) {
+      ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
+      derived = Standard_True;
+    }
+
+    tgdu =  gradient.Dot(d1v);
+    tgdv = -gradient.Dot(d1u);
+    Standard_Real N2grad = gradient.SquareMagnitude();
+    Standard_Real N2grad_EpsAng2 = N2grad * EpsAng2;
+    Standard_Real N2d1u  = d1u.SquareMagnitude();
+    Standard_Real N2d1v  = d1v.SquareMagnitude();
+    tangent =(tgdu * tgdu <= N2grad_EpsAng2 * N2d1v) && 
+             (tgdv * tgdv <= N2grad_EpsAng2 * N2d1u);
+    
+    gp_Vec NormPSurf = d1u ^ d1v;
+    gp_Vec NormISurf = d1u_isurf ^ d1v_isurf;
+    NormPSurf.Normalize();
+    NormISurf.Normalize();
+#ifdef DRAW
+    Standard_Real theAngle = NormPSurf.Angle(NormISurf);
+#endif
+    gp_Vec CrossProd = NormPSurf ^ NormISurf;
+    Standard_Real CrossProdSqMagn = CrossProd.SquareMagnitude();
+    
+#ifdef DRAW
+    cout<<"Angle = "<<theAngle<<endl;
+    cout<<"CrossProdSqMagn = "<<CrossProdSqMagn<<endl;
+#endif
+
+    tangent = (CrossProdSqMagn <= TolCrossProd);
+    
+    if (tangent)
+    {
+#ifdef DRAW
+      Standard_Real SumSquare = tgdu * tgdu + tgdv * tgdv;
+#endif
+      gp_Vec NormSURF = d1u ^ d1v;
+      Proj1 = gradient * d1u;
+      Proj2 = gradient * d1v;
+      Proj3 = NormSURF * d1u_isurf;
+      Proj4 = NormSURF * d1v_isurf;
+#ifdef DRAW
+      cout<<"Tangent !!!"<<endl;
+      cout<<"SumSquare = "<<SumSquare<<endl;
+      cout<<"u = "<<u<<", v = "<<v<<endl;
+      cout<<"pnt = "<<pntsol.X()<<" "<<pntsol.Y()<<" "<<pntsol.Z()<<endl;
+      cout<<"Proj1 = "<<Proj1<<endl;
+      cout<<"Proj2 = "<<Proj2<<endl;
+      cout<<"Proj3 = "<<Proj3<<endl;
+      cout<<"Proj4 = "<<Proj4<<endl<<endl;
+#endif
+    }
+    
+    if(!tangent) {
+      d3d.SetLinearForm(tgdu,d1u,tgdv,d1v);
+      d2d = gp_Dir2d(tgdu, tgdv);
+      if (d3d.Magnitude() <= Tolpetit) {    // jag
+       tangent = Standard_True;
+      }
+      gp_Vec NormSURF = d1u ^ d1v;
+      Proj1 = gradient * d1u;
+      Proj2 = gradient * d1v;
+      Proj3 = NormSURF * d1u_isurf;
+      Proj4 = NormSURF * d1v_isurf;
+#ifdef DRAW
+      cout<<"u = "<<u<<", v = "<<v<<endl;
+      cout<<"pnt = "<<pntsol.X()<<" "<<pntsol.Y()<<" "<<pntsol.Z()<<endl;
+      cout<<"d3d = "<<d3d.X()<<" "<<d3d.Y()<<" "<<d3d.Z()<<endl;
+      cout<<"Proj1 = "<<Proj1<<endl;
+      cout<<"Proj2 = "<<Proj2<<endl;
+      cout<<"Proj3 = "<<Proj3<<endl;
+      cout<<"Proj4 = "<<Proj4<<endl<<endl;
+#endif
+    }
+  }
+  return tangent;
+}
+
+Standard_Real IntImp_ZerImpFunc::Projection1()
+{
+  if (!derived)
+  {
+    ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
+    derived = Standard_True;
+  }
+  if (!computed)
+  {
+    gp_Vec NormSURF = d1u ^ d1v;
+    Proj1 = gradient * d1u;
+    Proj2 = gradient * d1v;
+    Proj3 = NormSURF * d1u_isurf;
+    Proj4 = NormSURF * d1v_isurf;
+  }
+  return Proj1;
+}
+
+Standard_Real IntImp_ZerImpFunc::Projection2()
+{
+  if (!derived)
+  {
+    ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
+    derived = Standard_True;
+  }
+  if (!computed)
+  {
+    gp_Vec NormSURF = d1u ^ d1v;
+    Proj1 = gradient * d1u;
+    Proj2 = gradient * d1v;
+    Proj3 = NormSURF * d1u_isurf;
+    Proj4 = NormSURF * d1v_isurf;
+  }
+  return Proj2;
+}
+
+Standard_Real IntImp_ZerImpFunc::Projection3()
+{
+  if (!derived)
+  {
+    ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
+    derived = Standard_True;
+  }
+  if (!computed)
+  {
+    gp_Vec NormSURF = d1u ^ d1v;
+    Proj1 = gradient * d1u;
+    Proj2 = gradient * d1v;
+    Proj3 = NormSURF * d1u_isurf;
+    Proj4 = NormSURF * d1v_isurf;
+  }
+  return Proj3;
+}
+
+Standard_Real IntImp_ZerImpFunc::Projection4()
+{
+  if (!derived)
+  {
+    ThePSurfaceTool::D1(SURF, u, v, pntsol, d1u, d1v);
+    derived = Standard_True;
+  }
+  if (!computed)
+  {
+    gp_Vec NormSURF = d1u ^ d1v;
+    Proj1 = gradient * d1u;
+    Proj2 = gradient * d1v;
+    Proj3 = NormSURF * d1u_isurf;
+    Proj4 = NormSURF * d1v_isurf;
+  }
+  return Proj4;
+}
+
+Standard_Boolean IntImp_ZerImpFunc::DerivativesAndNormalOnPSurf(gp_Vec& D1U,
+                                                    gp_Vec& D1V,
+                                                    gp_Vec& Normal,
+                                                    gp_Vec& D2U,
+                                                    gp_Vec& D2V,
+                                                    gp_Vec& D2UV)
+{
+  ThePSurfaceTool::D2(SURF, u, v, pntsol, D1U, D1V, D2U, D2V, D2UV);
+  Normal = D1U ^ D1V;
+  Standard_Real theMagnitude = Normal.Magnitude();
+  if (theMagnitude <= gp::Resolution())
+    return Standard_False;
+  else
+    Normal /= theMagnitude;
+
+  return Standard_True;
+}
+
+Standard_Boolean IntImp_ZerImpFunc::DerivativesAndNormalOnISurf(gp_Vec& D1U,
+                                                    gp_Vec& D1V,
+                                                    gp_Vec& Normal,
+                                                    gp_Vec& D2U,
+                                                    gp_Vec& D2V,
+                                                    gp_Vec& D2UV) const
+{
+  TheISurfaceTool::D2(FUNC, pntsol, D1U, D1V, D2U, D2V, D2UV);
+  Normal = D1U ^ D1V;
+  Standard_Real theMagnitude = Normal.Magnitude();
+  if (theMagnitude <= gp::Resolution())
+    return Standard_False;
+  else
+    Normal /= theMagnitude;
+
+  return Standard_True;
+}
+
 #undef EpsAng
 #undef EpsAng2
 #undef Tolpetit
index 5c5e0e7b5d1e5003fb6b2a87a785ecc163890bad..8340240fcf2a776ba9d46462e6d1ea18855e83c3 100644 (file)
@@ -56,6 +56,11 @@ inline const gp_Dir2d& IntImp_ZerImpFunc::Direction2d()
   return d2d;
 }
 
+inline Standard_Real IntImp_ZerImpFunc::SquareTangentError() const
+{
+  return (tgdu * tgdu + tgdv * tgdv);
+}
+
 inline const ThePSurface& IntImp_ZerImpFunc::PSurface() const 
 {
   return  (*((ThePSurface *)(surf)));
index 7932aabb3d15543ed7bd6410b994353d23b1dc45..5b618213a1b1ee413e40652b30a870685bc4a583 100644 (file)
@@ -403,7 +403,7 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
 {
   Standard_Boolean reversed, procf, procl, dofirst, dolast;
   Standard_Integer indfirst = 0, indlast = 0, ind2, i,j,k, NbSegm;
-  Standard_Integer NbPointIns, NbPointRst, Nblines, Nbpts, NbPointDep;
+  Standard_Integer NbPointIns, NbPointsTang, NbPointRst, Nblines, Nbpts, NbPointDep;
   Standard_Real U1,V1,U2,V2,paramf,paraml,currentparam;
 
   IntPatch_TheSegmentOfTheSOnBounds thesegm;
@@ -518,6 +518,7 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
   //
   IntSurf_SequenceOfPathPoint seqpdep;
   IntSurf_SequenceOfInteriorPoint seqpins;
+  IntSurf_SequenceOfInteriorPoint seqptang;
   //
   NbPointRst = solrst.NbPoints();
   TColStd_Array1OfInteger Destination(1,NbPointRst+1); Destination.Init(0);
@@ -589,6 +590,9 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
     for (i=1; i <= NbPointIns; i++) {
       seqpins.Append(solins.Value(i));
     }
+    NbPointsTang = solins.NbTangentPoints();
+    for (i = 1; i <= NbPointsTang; i++)
+      seqptang.Append(solins.TangentPoint(i));
   }
   //
   NbPointDep=seqpdep.Length();
@@ -596,10 +600,10 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
   if (NbPointDep || NbPointIns) {
     IntPatch_TheIWalking iwalk(TolTang,Fleche,Pas);
     if (!reversed) {
-      iwalk.Perform(seqpdep,seqpins,Func,Surf2);
+      iwalk.Perform(seqpdep,seqpins,seqptang,Func,Surf2);
     }
     else {
-      iwalk.Perform(seqpdep,seqpins,Func,Surf1,Standard_True);
+      iwalk.Perform(seqpdep,seqpins,seqptang,Func,Surf1,Standard_True);
     }
     if(!iwalk.IsDone()) {
       return;
index b14200f8d5d9c97e70d8db54260419314389d8fb..2aec9add4a598f0eaea94355cb17ac336eb83c8e 100644 (file)
@@ -68,7 +68,20 @@ is
     NbPoints(me)
     
        ---Purpose: Returns the number of points.
-       --          The exception NotDone if raised if IsDone 
+       --          The exception NotDone is raised if IsDone 
+       --          returns False.
+    
+       returns Integer
+       ---C++: inline
+       
+       raises NotDone from StdFail
+       
+       is static;
+
+    NbTangentPoints(me)
+    
+       ---Purpose: Returns the number of tangent points.
+       --          The exception NotDone is raised if IsDone 
        --          returns False.
     
        returns Integer
@@ -96,10 +109,29 @@ is
 
        is static;
 
+    TangentPoint(me; Index: Integer)
+    
+       ---Purpose: Returns the tangent point of range Index.
+       --          
+       --          The exception NotDone is raised if IsDone 
+       --          returns False.
+       --          The exception OutOfRange if raised if
+       --          Index <= 0 or Index > NbTangentPoints.
+
+       returns InteriorPoint from IntSurf
+       ---C++: return const&
+       ---C++: inline
+       
+       raises NotDone from StdFail,
+              OutOfRange from Standard
+
+       is static;
+
 
 fields
 
-    done : Boolean                 from Standard;
-    list : SequenceOfInteriorPoint from IntSurf;
+    done            : Boolean                 from Standard;
+    list            : SequenceOfInteriorPoint from IntSurf;
+    myTangentPoints : SequenceOfInteriorPoint from IntSurf;
 
 end SearchInside;
index 9d071e690578647f9b0a0b00adab9edd70d9f34d..f68700cd63402f28903b482d382f903651f7f9ae 100644 (file)
 
 #include <TopAbs_State.hxx>
 
+#ifdef DRAW
+#include <DrawTrSurf.hxx>
+#endif
+
+
 IntStart_SearchInside::IntStart_SearchInside (): done(Standard_False)
 {}
 
@@ -49,6 +54,7 @@ void IntStart_SearchInside::Perform (TheFunction& Func,
 
   done = Standard_False;
   list.Clear();
+  myTangentPoints.Clear();
   Standard_Real aBinf[2], aBsup[2], aUVap[2], atoler[2];
   math_Vector Binf(aBinf,1,2), Bsup(aBsup,1,2), UVap(aUVap,1,2), toler(atoler,1,2);
   gp_Pnt psol;
@@ -118,6 +124,13 @@ void IntStart_SearchInside::Perform (TheFunction& Func,
   //--
 
   
+#ifdef DRAW
+  char* name = new char[100];
+#endif
+
+  gp_Vec NullDir(0.,0.,0.);
+  gp_Vec2d NullDir2d(0.,0.);
+  
   for (i=1; i <= Nbsample+12; i++) {
     gp_Pnt2d s2d;
     gp_Pnt s3d;
@@ -176,9 +189,9 @@ void IntStart_SearchInside::Perform (TheFunction& Func,
       Rsnld.Perform(Func,UVap,Binf,Bsup);
       if (Rsnld.IsDone()) {
        if (Abs(Func.Root()) <= Tol) {
+          psol = Func.Point();
+          Rsnld.Root(UVap);
          if (!Func.IsTangent()) {
-           psol = Func.Point();
-           Rsnld.Root(UVap);
            // On regarde si le point trouve est bien un nouveau point.   
            j = 1;
            nbpt = list.Length();
@@ -207,9 +220,54 @@ void IntStart_SearchInside::Perform (TheFunction& Func,
                list.Append(IntSurf_InteriorPoint(psol,UVap(1),UVap(2),
                                                  Func.Direction3d(),
                                                  Func.Direction2d()));
+#ifdef DRAW
+                gp_Pnt2d p2dsol(UVap(1),UVap(2));
+                sprintf(name, "pp%d", list.Length());
+                DrawTrSurf::Set(name, p2dsol);
+                sprintf(name, "p%d", list.Length());
+                DrawTrSurf::Set(name, psol);
+#endif
              }
            }
-         }
+         }//if (!Func.IsTangent())
+          else //tangent point
+          {
+            Standard_Boolean IsNewTangentPoint = Standard_True;
+            for (j = 1; j <= myTangentPoints.Length(); j++)
+            {
+             const IntSurf_InteriorPoint&  IPj = myTangentPoints(j);
+             const gp_Pnt& Pj = IPj.Value();
+             if (   (Abs(Pj.X()-psol.X()) <= Epsilon)
+                 && (Abs(Pj.Y()-psol.Y()) <= Epsilon)
+                 && (Abs(Pj.Z()-psol.Z()) <= Epsilon)
+                 && (Abs(UVap(1)-IPj.UParameter()) <= toler1)
+                 && (Abs(UVap(2)-IPj.VParameter()) <= toler2) )
+              {
+               IsNewTangentPoint = Standard_False;
+                break;
+             }
+            }
+            
+            if (IsNewTangentPoint)
+            {
+             situ = T->Classify(gp_Pnt2d(UVap(1),UVap(2)),
+                                Maxtoler1toler2,Standard_False);   //-- ,Standard_False pour ne pas recadrer on Periodic
+             if (situ == TopAbs_IN) {
+                myTangentPoints.Append(IntSurf_InteriorPoint(psol,UVap(1),UVap(2),
+                                                             NullDir, NullDir2d));
+#ifdef DRAW
+                gp_Pnt2d p2dsol(UVap(1),UVap(2));
+                sprintf(name, "tpp%d", myTangentPoints.Length());
+                //DrawTrSurf::Set(name, p2dsol);
+                sprintf(name, "tp%d", myTangentPoints.Length());
+                //DrawTrSurf::Set(name, psol);
+                cout<<myTangentPoints.Length()<<" tangent point :"<<endl;
+                cout<<"U = "<<UVap(1)<<", V = "<<UVap(2)<<endl;
+                cout<<"Dist = "<<aRootVal<<endl<<endl;
+#endif
+              }
+            }
+          }
        }
       }
     }
@@ -231,6 +289,7 @@ void IntStart_SearchInside::Perform (TheFunction& Func,
 {
   done = Standard_False;
   list.Clear();
+  myTangentPoints.Clear();
   math_Vector Binf(1,2), Bsup(1,2), toler(1,2);
 
   Binf(1) = ThePSurfaceTool::FirstUParameter(PS);
index c4c9408c6c09f8b242ae76525b3909deeefc16df..938e6da90720645a5b09f6742bcf4b42de14ff9c 100644 (file)
@@ -27,6 +27,12 @@ inline Standard_Integer IntStart_SearchInside::NbPoints () const {
   return list.Length();
 }
 
+inline Standard_Integer IntStart_SearchInside::NbTangentPoints () const {
+
+  if (!done) {StdFail_NotDone::Raise();}
+  return myTangentPoints.Length();
+}
+
 
 inline const IntSurf_InteriorPoint& IntStart_SearchInside::Value 
      (const Standard_Integer Index) const
@@ -36,3 +42,10 @@ inline const IntSurf_InteriorPoint& IntStart_SearchInside::Value
   return list.Value(Index);
 }
 
+inline const IntSurf_InteriorPoint& IntStart_SearchInside::TangentPoint
+     (const Standard_Integer Index) const
+
+{
+  if (!done) {StdFail_NotDone::Raise();}
+  return myTangentPoints.Value(Index);
+}
index ca9ed1415cab5e23540fe6a6ca767415810959af..4db96d31c6f372e8840114f72b9168763d1c27ab 100644 (file)
@@ -22,7 +22,9 @@ class PntOn2S from IntSurf
        --          parametric coordinates.
 
 
-uses Pnt from gp
+uses
+    Pnt   from gp,
+    Pnt2d from gp
 
 is
 
@@ -91,6 +93,13 @@ is
 
        is static;
 
+    ValueOnSurface(me; OnFirst: Boolean from Standard)
+    
+       ---Purpose: Returns the point in 2d space of one of the surfaces.
+
+       returns Pnt2d from gp
+       is static;
+
 
 
     ParametersOnS1(me; U1,V1: out Real from Standard)
@@ -110,6 +119,13 @@ is
 
        is static;
 
+    ParametersOnSurface(me; OnFirst: Boolean from Standard;
+                           U,V: out Real from Standard)
+    
+       ---Purpose: Returns the parameters of the point in the
+       --          parametric space of one of the surface.
+
+       is static;
 
     Parameters(me; U1,V1,U2,V2: out Real from Standard)
 
index ff0d19f7a6a24f5707183d88302766ab118d1e65..014920f1eb49fb36f928d37d0da1ef382bdb849f 100644 (file)
@@ -48,5 +48,26 @@ void IntSurf_PntOn2S::SetValue (const Standard_Boolean OnFirst,
   }
 }
 
+gp_Pnt2d IntSurf_PntOn2S::ValueOnSurface(const Standard_Boolean OnFirst) const
+{
+  gp_Pnt2d PointOnSurf;
+  if (OnFirst)
+    PointOnSurf.SetCoord(u1,v1);
+  else
+    PointOnSurf.SetCoord(u2,v2);
+  return PointOnSurf;
+}
 
-
+void IntSurf_PntOn2S::ParametersOnSurface(const Standard_Boolean OnFirst,
+                                          Standard_Real& U,
+                                          Standard_Real& V) const
+{
+  if (OnFirst) {
+    U = u1;
+    V = v1;
+  }
+  else {
+    U = u2;
+    V = v2;
+  }
+}
index 4dd1e914498c1a5a243dcab1a6aebf3a2fe06cb5..16ad9e1087af6c9dfc4b1ed85df2bcf74c17656e 100644 (file)
@@ -22,7 +22,8 @@ class QuadricTool from IntSurf
        --          as implicit surface.
 
 uses Quadric from IntSurf,
-     Vec     from gp
+     Vec     from gp,
+     Pnt     from gp
 
 is
 
@@ -47,11 +48,22 @@ is
 
     ValueAndGradient(myclass; Quad: Quadric from IntSurf;
                      X, Y, Z: Real from Standard;
-                     Val: out Real from Standard; Grad: out Vec from gp);
+                     Val: out Real from Standard;
+                    Grad: out Vec from gp;
+                    D1U_ISurf, D1V_ISurf: out Vec from gp);
                     
        ---Purpose: Returns the value and the gradient.
 
-       ---C++: inline
+    D2(myclass; Quad:  Quadric from IntSurf;
+                Point: Pnt from gp;
+               D1U:   out Vec from gp;
+               D1V:   out Vec from gp;
+               D2U:   out Vec from gp;
+               D2V:   out Vec from gp;
+               D2UV:  out Vec from gp);
+                    
+       ---Purpose: Returns all first and second derivatives.
+    
     
 
     Tolerance(myclass; Quad: Quadric from IntSurf )
index 798436160a67e9930d4be9d73e517f15576a99ea..229a7480735b82a6b915f23f5e29d4c33514c66c 100644 (file)
 #include <gp_Sphere.hxx>
 #include <gp_Cylinder.hxx>
 
+
+void IntSurf_QuadricTool::ValueAndGradient (const IntSurf_Quadric& Quad,
+                                            const Standard_Real X,
+                                            const Standard_Real Y,
+                                            const Standard_Real Z,
+                                            Standard_Real& Val,
+                                            gp_Vec& Grad,
+                                            gp_Vec& D1U,
+                                            gp_Vec& D1V)
+{
+  gp_Pnt thePoint(X,Y,Z);
+  Quad.ValAndGrad(thePoint, Val, Grad);
+  Standard_Real U, V;
+  Quad.Parameters(thePoint, U, V);
+  Quad.D1(U, V, thePoint, D1U, D1V);
+}
+
+void IntSurf_QuadricTool::D2 (const IntSurf_Quadric& Quad,
+                              const gp_Pnt& aPoint,
+                              gp_Vec& D1U,
+                              gp_Vec& D1V,
+                              gp_Vec& D2U,
+                              gp_Vec& D2V,
+                              gp_Vec& D2UV)
+{
+  Standard_Real U, V;
+  Quad.Parameters(aPoint, U, V);
+  gp_Pnt thePoint;
+  Quad.D1(U, V, thePoint, D1U, D1V);
+  D2U = Quad.DN(U, V, 2, 0);
+  D2V = Quad.DN(U, V, 0, 2);
+  D2UV = Quad.DN(U, V, 1, 1);
+}
+
 Standard_Real IntSurf_QuadricTool::Tolerance (const IntSurf_Quadric& Q) {
   switch (Q.TypeQuadric()) {
   case GeomAbs_Sphere:
index 7e7ef2d6e2209ddb60aa6ed3a6fc83469cf19286..e89af93dfacf7fb50ff3acaa045b9ae2a7b239f1 100644 (file)
@@ -31,15 +31,3 @@ inline void IntSurf_QuadricTool::Gradient (const IntSurf_Quadric& Quad,
 
   V = Quad.Gradient(gp_Pnt(X,Y,Z));
 }
-
-inline void IntSurf_QuadricTool::ValueAndGradient (const IntSurf_Quadric& Quad,
-                                                  const Standard_Real X,
-                                                  const Standard_Real Y,
-                                                  const Standard_Real Z,
-                                                  Standard_Real& Val,
-                                                  gp_Vec& V) {
-
-  Quad.ValAndGrad(gp_Pnt(X,Y,Z),Val,V);
-}
-
-
index ac0b0c98c3a2f68c5b3fd8f9235d6368250ed517..1d98a3fdfab6edbfc4d0a42331cf7ca0365c7490 100644 (file)
@@ -35,7 +35,7 @@ is
 
     enumeration StatusDeflection is 
                 PasTropGrand, PointConfondu, ArretSurPointPrecedent,
-                ArretSurPoint, OK;
+                ArretSurPoint, OK, OKtangent;
 
 -- StepTooGreat, ConfusedPoint, StopOnPreviousPoint, StopOnPoint, OK
     
index e501d02d10cbf4239a01d73f2ed3ef9a7eb58431..f457f45143bc20a833c2511149b4e4ffbd6a07ab 100644 (file)
@@ -88,6 +88,7 @@ is
     Perform(me: in out;
             Pnts1    : ThePOPIterator;
             Pnts2    : ThePOLIterator;
+           Pnts3    : ThePOLIterator;
             Func     : in out TheIWFunction;
            S        : ThePSurface;
             Reversed : Boolean from Standard = Standard_False)
@@ -180,7 +181,6 @@ is
 
         is static;
     
-
 -- -- private
 
     Cadrage(me; BornInf, BornSup, UVap : in out Vector from math;
@@ -206,6 +206,14 @@ is
     returns Boolean from Standard
     is static protected;                     
 
+    TestArretPassageTang (me: in out; Umult  : SequenceOfReal from TColStd;
+                                  Vmult  : SequenceOfReal from TColStd;
+                                  UV     : Vector from math;
+                                  Index  : Integer from Standard;
+                                 Irang  : out Integer from Standard) 
+    returns Boolean from Standard
+    is static protected;                     
+
     TestArretAjout(me: in out; Section: in out TheIWFunction;
                               UV     : in out Vector from math;
                               Irang  : out Integer from Standard; 
@@ -227,9 +235,10 @@ is
                                UV              : Vector from math;
                               StatusPrecedent : StatusDeflection from IntWalk;
                                NbDivision      : in out Integer from Standard;
-                               Step           : in out Real from Standard;
+                               Step            : in out Real from Standard;
 --                               StepV           : in out Real from Standard;
-                               StepSign        : Integer from Standard)
+                               StepSign        : Integer from Standard;
+                              CurNbPoints     : Integer from Standard)
     returns StatusDeflection from IntWalk                  
     is static protected;                     
 
@@ -251,6 +260,7 @@ is
                                   Vmult  : SequenceOfReal from TColStd;
                                   Pnts1  : ThePOPIterator;
                                  Pnts2  : ThePOLIterator;
+                                 Pnts3  : ThePOLIterator;
                                   Section: in out TheIWFunction;
                                   Rajout : in out Boolean from Standard)
     is static protected;       
@@ -267,6 +277,16 @@ is
 
     is static protected;
     
+    FindExactTangentPoint(me : in out ; TolTang : Real from Standard;
+                                       Section : in out TheIWFunction;
+                                       Psol    : in out PntOn2S from IntSurf)
+    is static protected;
+    
+    ComputeDirOfTangentialIntersection(me : in out; Section : in out TheIWFunction;
+                                                   StepSign: in out Integer from Standard)
+    returns Boolean from Standard
+    is static protected;
+    
     Clear (me: in out) is static protected;
     ---Purpose: Clears up internal containers
 
@@ -283,6 +303,7 @@ fields
 
     wd1                 : VectorOfWalkingData from IntWalk;
     wd2                 : VectorOfWalkingData from IntWalk;
+    wd3                 : VectorOfWalkingData from IntWalk;
     nbMultiplicities    : VectorOfInteger   from IntWalk;
     Um                  : Real              from Standard; -- Min U de la surf
     UM                  : Real              from Standard; -- Max U de la surf
@@ -291,7 +312,15 @@ fields
     previousPoint       : PntOn2S           from IntSurf;
     previousd3d         : Vec               from gp;
     previousd2d         : Dir2d             from gp;
+    previousProj1       : Real              from Standard;
+    previousProj2       : Real              from Standard;
+    previousProj3       : Real              from Standard;
+    previousProj4       : Real              from Standard;
+    PointAfterPossibleCuspPoint : PntOn2S   from IntSurf;
+    PossibleCuspPoint   : Boolean           from Standard;
+    IsTangentialIntersection : Boolean      from Standard;
     seqAjout            : SequenceOfInteger from TColStd; 
     lines               : SequenceOfIWLine;
+    
 end IWalking;
 
index b960c5afa9cb9bbcc252e97ea2237339b2605c3d..e29902361ff6ab19a7fd2fe477c4baa6de6387ca 100644 (file)
@@ -31,7 +31,10 @@ IntWalk_IWalking::IntWalk_IWalking (const Standard_Real Epsilon,
       epsilon(Epsilon*Epsilon),
       wd1 (IntWalk_VectorOfWalkingData::allocator_type (new NCollection_IncAllocator)),
       wd2 (wd1.get_allocator()),
-      nbMultiplicities (wd1.get_allocator())
+      wd3 (wd2.get_allocator()),
+      nbMultiplicities (wd1.get_allocator()),
+      PossibleCuspPoint(Standard_False),
+      IsTangentialIntersection(Standard_False)
 {
 }
 
@@ -48,11 +51,13 @@ void IntWalk_IWalking::Clear()
 {
   wd1.clear();
   wd2.clear();
+  wd3.clear();
   IntWalk_WalkingData aDummy;
   aDummy.etat = -10;
   aDummy.ustart = aDummy.vstart = 0.;
   wd1.push_back (aDummy);
   wd2.push_back (aDummy);
+  wd3.push_back (aDummy);
   nbMultiplicities.clear();
   nbMultiplicities.push_back (-1);
   
@@ -80,6 +85,7 @@ void IntWalk_IWalking::Clear()
 //
 void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
                               const ThePOLIterator& Pnts2,
+                               const ThePOLIterator& Pnts3,
                               TheIWFunction& Func,
                               const ThePSurface& Caro,
                               const Standard_Boolean Reversed)
@@ -90,6 +96,7 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
   Standard_Boolean Rajout = Standard_False;
   Standard_Integer nbPnts1 = Pnts1.Length();
   Standard_Integer nbPnts2 = Pnts2.Length();
+  Standard_Integer nbPnts3 = Pnts3.Length();
   Standard_Real U,V;
 
   Clear();
@@ -137,6 +144,14 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
     wd2.push_back (aWD2);
   }
 
+  wd3.reserve (nbPnts3);
+  for (I = 1; I <= nbPnts3; I++) {
+    IntWalk_WalkingData aWD3;
+    aWD3.etat = 13;
+    ThePointOfLoopTool::Value2d(Pnts3.Value(I), aWD3.ustart, aWD3.vstart);
+    wd3.push_back (aWD3);
+  }
+
   tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
   tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
 
@@ -160,12 +175,10 @@ void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
 
   // calculation of all open lines   
   if (nbPnts1 != 0)
-    ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout); 
-
+    ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout);
   // calculation of all closed lines 
-  if (nbPnts2 != 0)
-    ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Func,Rajout); 
-  
+  if (nbPnts2 != 0 || nbPnts3 != 0)
+    ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Pnts3,Func,Rajout); 
   for (I = 1; I <= nbPnts1; I++) { 
     if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
   }
index fa8544421e7636f9e46cd39741eb4c53391110de..62749512346665b7fecb50e83ed58056010dcba8 100644 (file)
@@ -251,6 +251,43 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
       }
     }
   }
+  for (size_t i = 1; i < wd3.size(); i++) { 
+    if (wd3[i].etat > 0) { 
+      // debug jag 05.04.94
+
+//      if ((Up-wd2[i].ustart)*(UV(1)-wd2[i].ustart) +
+//       (Vp-wd2[i].vstart)*(UV(2)-wd2[i].vstart) <= 0)
+      Utest = wd3[i].ustart;
+      Vtest = wd3[i].vstart;
+
+      Du  = UV(1)-Utest;
+      Dv  = UV(2)-Vtest;
+      Dup = Up - Utest;
+      Dvp = Vp - Vtest;
+      
+//-- lbr le 30 oct 97 
+
+      //IFV for OCC20285
+
+      if ((Abs(Du) < tolu2 && Abs(Dv) < tolv2) ||
+         (Abs(Dup) < tolu2 && Abs(Dvp) < tolv2)) { 
+           
+       wd3[i].etat = -wd3[i].etat;
+      }
+      else {
+       Standard_Real DDu = (UV(1)-Up);
+       Standard_Real DDv = (UV(2)-Vp);
+       Standard_Real DDD = DDu*DDu + DDv*DDv;
+       Standard_Real DD1 = Du*Du + Dv*Dv;
+       if(DD1 <= DDD) { 
+         Standard_Real DD2 = Dup*Dup + Dvp*Dvp;
+         if(DD2 <= DDD && ((Du*Dup) + (Dv*Dvp*tolu/tolv) <= 0.)) {     
+           wd3[i].etat = -wd3[i].etat;
+         }
+       }
+      }
+    }
+  }
 
   // stop test on point given at input and not yet processed
 
@@ -473,6 +510,62 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
       }
     }
   }
+  for (k = 1; k < (int)wd3.size(); k++) { 
+    if (wd3[k].etat > 0) {
+      Utest = wd3[k].ustart;
+      Vtest = wd3[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)) {
+        
+         wd3[k].etat = -wd3[k].etat; //-- mark the point as a crossing point 
+      }
+      else { 
+       Standard_Real UpmUtest = (Up-Utest);
+       Standard_Real VpmVtest = (Vp-Vtest);
+       Standard_Real dPreviousStart = (UpmUtest)*(UpmUtest)+(VpmVtest)*(VpmVtest);
+       Standard_Real dCurrentStart  = UV1mUtest * UV1mUtest + UV2mVtest * UV2mVtest;
+
+       Scal=(UpmUtest)*(UV1mUtest)+(VpmVtest)*(UV2mVtest);
+       if( (Abs(UpmUtest)<tolu && Abs(VpmVtest)<tolv)) {
+          
+           wd3[k].etat = -wd3[k].etat;
+       }
+       else if(Scal<0 && (dPreviousStart+dCurrentStart < dPreviousCurrent)) {
+          
+           wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+       }
+       else {
+         if(dPreviousStart < dPreviousCurrent*0.25) {
+            
+           wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+           //-- cout<<"**** etat2 : ("<<k<<")"<<endl;
+         }
+         else { 
+           if(dCurrentStart < dPreviousCurrent*0.25) {
+             //-- cout<<"***** etat2 : ("<<k<<")"<<endl;
+             wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+           }
+           else { 
+             Standard_Real UMidUtest = 0.5*(UV1+Up)-Utest;
+             Standard_Real VMidVtest = 0.5*(UV2+Vp)-Vtest;         
+             Standard_Real dMiddleStart =  UMidUtest*UMidUtest + VMidVtest*VMidVtest;
+
+             if(dMiddleStart < dPreviousCurrent*0.5) { 
+               //-- cout<<"*********** etat2 : ("<<k<<")"<<endl;
+               wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+             }
+           }
+         }
+       }
+      }
+    }
+  }
 
   // crossing test on crossing points.
   
@@ -507,6 +600,165 @@ Standard_Boolean IntWalk_IWalking::TestArretPassage
   return Arrive;
 }
 
+Standard_Boolean IntWalk_IWalking::TestArretPassageTang
+  (const TColStd_SequenceOfReal& Umult,
+   const TColStd_SequenceOfReal& Vmult,
+   const math_Vector& UV, 
+   const Standard_Integer Index, 
+   Standard_Integer& Irang)
+{
+// Umult, Vmult : table of stop (or crossing) points on border, here
+//          only crossing points are taken into account.
+// UV     : the current point.
+// Index  : index of the start point in uvstart2 of the current line
+//          (this is an interior point).
+// Irang  : at output : gives the index of the point passing in uvstart1 or 0.
+//          consider that there is risk to cross only one crossing point.
+
+// test of stop for a CLOSED intersection line.
+// 1) test of crossing on all interior points.
+// 2) test of crossing on all crossing points.
+
+  Standard_Real Up, Vp, Scal;
+  Standard_Boolean Arrive = Standard_False;
+  Standard_Integer N, k, i;
+  Standard_Real Utest,Vtest;
+  Standard_Real tolu = tolerance(1);
+  Standard_Real tolv = tolerance(2);
+
+  
+  // tests of stop and of crossing on all interior points.
+
+  if (!reversed) {
+    previousPoint.ParametersOnS2(Up,Vp);
+  }
+  else {
+    previousPoint.ParametersOnS1(Up,Vp);
+  }
+
+  Standard_Real UV1=UV(1);
+  Standard_Real UV2=UV(2);
+
+
+  //-- Put everything in one box 0 1  x 0 1 
+  //-- actually it is necessary to carry out tests in 3D
+
+  Standard_Real deltau=UM-Um;
+  Standard_Real deltav=VM-Vm;
+
+  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)wd3.size(); k++) { 
+    if (wd3[k].etat > 0) {
+      Utest = wd3[k].ustart;
+      Vtest = wd3[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(Index!=k) { 
+         //-- cout<<"* etat2 : ("<<k<<")"<<endl;
+         wd3[k].etat = -wd3[k].etat; //-- mark the point as a crossing point 
+       }
+       else {  //-- Index == k
+         //-- cout<<"* Arrive"<<endl;
+         Arrive=Standard_True;
+       }
+      }
+      else { 
+       Standard_Real UpmUtest = (Up-Utest);
+       Standard_Real VpmVtest = (Vp-Vtest);
+       Standard_Real dPreviousStart = (UpmUtest)*(UpmUtest)+(VpmVtest)*(VpmVtest);
+       Standard_Real dCurrentStart  = UV1mUtest * UV1mUtest + UV2mVtest * UV2mVtest;
+
+       Scal=(UpmUtest)*(UV1mUtest)+(VpmVtest)*(UV2mVtest);
+       if( (Abs(UpmUtest)<tolu && Abs(VpmVtest)<tolv)) { 
+         if(Index != k ) { 
+           //-- cout<<"** etat2 : ("<<k<<")"<<endl;
+           wd3[k].etat = -wd3[k].etat;
+         }
+       }
+       else if(Scal<0 && (dPreviousStart+dCurrentStart < dPreviousCurrent)) { 
+         if (Index == k ) { // on a boucle.
+           Arrive = Standard_True;
+           //-- cout<<"** Arrive  : k="<<k<<endl;
+         }
+         else {
+           //-- cout<<"*** etat2 : ("<<k<<")"<<endl;
+           wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+         }
+       }
+       else if(k!=Index) {
+         if(dPreviousStart < dPreviousCurrent*0.25) { 
+           wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+           //-- cout<<"**** etat2 : ("<<k<<")"<<endl;
+         }
+         else { 
+           if(dCurrentStart < dPreviousCurrent*0.25) {
+             //-- cout<<"***** etat2 : ("<<k<<")"<<endl;
+             wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+           }
+           else { 
+             Standard_Real UMidUtest = 0.5*(UV1+Up)-Utest;
+             Standard_Real VMidVtest = 0.5*(UV2+Vp)-Vtest;         
+             Standard_Real dMiddleStart =  UMidUtest*UMidUtest + VMidVtest*VMidVtest;
+
+             if(dMiddleStart < dPreviousCurrent*0.5) { 
+               //-- cout<<"*********** etat2 : ("<<k<<")"<<endl;
+               wd3[k].etat = -wd3[k].etat; // mark the point as a crossing point 
+             }
+           }
+         }
+       }
+      }
+    }
+  }
+
+  // crossing test on crossing points.
+  
+  Irang =0;
+  for (i = 1; i < (int)wd1.size(); i++) {
+    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)) 
+       Irang = i;
+      else if (nbMultiplicities[i] > 0) {
+       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)) {
+           Irang=i;
+           break;
+          }
+       }
+      }
+    }    
+  }
+  return Arrive;
+}
 
 Standard_Boolean IntWalk_IWalking::TestArretAjout
   (TheIWFunction& sp,
index 6bc7b7a133e82c2ef66a377371bf398a056c7875..da3f6e06362862e118f2964d61abec62855940de 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <NCollection_IncAllocator.hxx>
 #include <NCollection_LocalArray.hxx>
+#include <Bnd_Box2d.hxx>
 
 
 // modified by NIZHNY-MKK  Thu Nov  2 15:07:26 2000.BEGIN
@@ -66,7 +67,7 @@ void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
   Standard_Integer I, N;
   Standard_Real aBornInf[2], aBornSup[2], aUVap[2];
   math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2), UVap(aUVap,1,2);
-  Standard_Real PasC, PasCu, PasCv;
+  Standard_Real PasC, PasCu, PasCv, PasSav;
   Standard_Boolean Arrive; // shows if the line ends
   Standard_Boolean Cadre;  // shows if one is on border of the domain
   Standard_Boolean ArretAjout;  //shows if one is on added point
@@ -74,12 +75,15 @@ void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
   Handle(IntWalk_TheIWLine)  CurrentLine;    // line under construction
   Standard_Boolean Tgtend;
 
+  Standard_Real TolTang = 5.e-28;
+
   IntWalk_StatusDeflection Status, StatusPrecedent;
   
   Standard_Integer NbDivision; 
   // number of divisions of step for each section
 
   Standard_Integer StepSign;
+  Standard_Integer StepSignTangent;
   
   ThePointOfPath PathPnt;
 
@@ -105,40 +109,50 @@ void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
     // modified by NIZHNY-MKK  Fri Oct 27 12:33:37 2000.BEGIN
     if ((wd1[I].etat > 11) || ((wd1[I].etat < -11) && (movementdirectioninfo[I]!=0))) {
     // modified by NIZHNY-MKK  Fri Oct 27 12:33:43 2000.END
-      PathPnt = Pnts1.Value(I);     
+      PathPnt = Pnts1.Value(I);
+#ifdef DRAW
+      cout<<"PathPnt("<<I<<"):"<<endl;
+#endif
       CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
       CurrentLine->SetTangencyAtBegining(Standard_False);
       Tgtend = Standard_False;
       CurrentLine->AddStatusFirst(Standard_False, Standard_True, I, PathPnt);
+      PossibleCuspPoint = Standard_False;
+      IsTangentialIntersection = Standard_False;
       UVap(1) = wd1[I].ustart;
       UVap(2) = wd1[I].vstart;
       MakeWalkingPoint(11, UVap(1), UVap(2), Func, previousPoint);
       previousd3d = Func.Direction3d();
       previousd2d = Func.Direction2d();
+      //prevtg = Standard_False;
+      previousProj1 = Func.Projection1();
+      previousProj2 = Func.Projection2();
+      previousProj3 = Func.Projection3();
+      previousProj4 = Func.Projection4();
       CurrentLine->AddPoint(previousPoint);
       // modified by NIZHNY-MKK  Fri Oct 27 12:34:32 2000.BEGIN
       if(movementdirectioninfo[I] !=0) {
-        if(movementdirectioninfo[I] < 0) {
-          StepSign = -1;
-          CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
-        } else {
-          StepSign = 1; 
-          CurrentLine->SetTangentVector(previousd3d,1);
-        }
+       if(movementdirectioninfo[I] < 0) {
+         StepSign = -1;
+         CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
+       } else {
+         StepSign = 1; 
+         CurrentLine->SetTangentVector(previousd3d,1);
+       }
       } else {
-        Standard_Real tyutuyt=ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
-        if( tyutuyt < 0) {
-          StepSign = -1;
-          CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
-        }
-        else {
-          StepSign = 1; 
-          CurrentLine->SetTangentVector(previousd3d,1);
-        }
+       Standard_Real tyutuyt=ThePointOfPathTool::Direction3d(PathPnt) * previousd3d;
+       if( tyutuyt < 0) {
+         StepSign = -1;
+         CurrentLine->SetTangentVector(previousd3d.Reversed(),1);
+       }
+       else {
+         StepSign = 1; 
+         CurrentLine->SetTangentVector(previousd3d,1);
+       }
       }
       // modified by NIZHNY-MKK  Fri Oct 27 12:34:37 2000.END
 
-      //  Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
+//  Modified by Sergey KHROMOV - Tue Nov 20 10:41:45 2001 Begin
       wd1[I].etat = - abs(wd1[I].etat);
       movementdirectioninfo[I] = (movementdirectioninfo[I]==0) ? StepSign : 0;
 //  Modified by Sergey KHROMOV - Tue Nov 20 10:41:56 2001 End
@@ -146,300 +160,348 @@ void IntWalk_IWalking::ComputeOpenLine(const TColStd_SequenceOfReal& Umult,
       Standard_Real d2dx = Abs(previousd2d.X()); 
       Standard_Real d2dy = Abs(previousd2d.Y()); 
       if (d2dx < tolerance(1)) {
-        PasC = pas * (VM-Vm)/d2dy;
+       PasC = pas * (VM-Vm)/d2dy;
       }
       else if (d2dy < tolerance(2)) {
-        PasC = pas * (UM-Um)/d2dx;
+       PasC = pas * (UM-Um)/d2dx;
       }
       else {
-        PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
+       PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
       }
 
+      PasSav = PasC;
+
       Arrive = Standard_False;
       ArretAjout = Standard_False;
       NbDivision = 0;
       StatusPrecedent = IntWalk_OK;
       // modified by NIZHNY-MKK  Fri Oct 27 12:39:37 2000
       Standard_Integer IndexOfPathPointDoNotCheck=0;
-      Standard_Integer aNbIter = 10;
+      //Standard_Integer aNbIter = 10;
+
       while (!Arrive) { //    as one of stop tests is not checked
-        Cadre = Cadrage(BornInf,BornSup,UVap,PasC,StepSign);
-        //  Border?
+
+       Cadre = Cadrage(BornInf,BornSup,UVap,PasC,StepSign);
+       //  Border?
 
 #ifdef CHRONO
-        Chronrsnld.Start();
+       Chronrsnld.Start();
 #endif
 
-        Rsnld.Perform(Func,UVap,BornInf,BornSup);
+       Rsnld.Perform(Func,UVap,BornInf,BornSup);
 
 #ifdef CHRONO
-        Chronrsnld.Stop();
+       Chronrsnld.Stop();
 #endif
 
-        if (Cadre) {
-          BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM;
-        }
-        if (Rsnld.IsDone()) {
-          if (Abs(Func.Root()) > Func.Tolerance()) {
-            PasC = PasC / 2.0;
-            PasCu = Abs(PasC*previousd2d.X());
-            PasCv = Abs(PasC*previousd2d.Y());
-            if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
-              if (CurrentLine->NbPoints() == 1) break;
-              Arrive = Standard_True;
-              CurrentLine->AddStatusLast(Standard_False);
-              Tgtend = Standard_True; // check
+       if (Cadre) {
+         BornInf(1) = Um; BornSup(1) = UM; BornInf(2) = Vm; BornSup(2) = VM;
+       }
+       if (Rsnld.IsDone()) {
+         if (Abs(Func.Root()) > Func.Tolerance()) {
+           PasC = PasC / 2.0;
+           PasCu = Abs(PasC*previousd2d.X());
+           PasCv = Abs(PasC*previousd2d.Y());
+           if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+             if (CurrentLine->NbPoints() == 1) break;
+             Arrive = Standard_True;
+             CurrentLine->AddStatusLast(Standard_False);
+             Tgtend = Standard_True; // check
               Rajout = Standard_True;
-              seqAjout.Append(lines.Length() + 1);
-            }  
-          }
-          else { // test stop
-            Rsnld.Root(UVap);
-            Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
-            if (Arrive) {
-              Cadre = Standard_False;
-              //in case if there is a frame and arrive at the same time
-            }
-            else {
-              if (Rajout) {
-                ArretAjout =TestArretAjout(Func, UVap, N, Psol);
-                if (ArretAjout) {
-                  // jag 940615
-                  Tgtend = lines.Value(N)->IsTangentAtEnd();
-                  N = -N;
-                }
-              }
-              // modified by NIZHNY-MKK  Thu Nov  2 15:09:08 2000.BEGIN
-              if(!(Rajout && ArretAjout)) {
-                Standard_Real prevUp, prevVp;
-                if (!reversed) {
-                  previousPoint.ParametersOnS2(prevUp, prevVp);
-                }
-                else {
-                  previousPoint.ParametersOnS1(prevUp, prevVp);
-                }
-                Arrive = TestPassedSolutionWithNegativeState(wd1, Umult, Vmult, prevUp, prevVp,
-                  nbMultiplicities, tolerance, Func, UVap, N);         
-                if(Arrive) {
-                  Cadre = Standard_False;
-                }
-              }
-              // modified by NIZHNY-MKK  Thu Nov  2 15:09:13 2000.END
-              if (!ArretAjout && Cadre) {
-                if (CurrentLine->NbPoints() == 1) break; // cancel the line
-                TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
-                //             if (N == 0) {
-                if (N <= 0) { // jag 941017
-                  MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
-                  Tgtend = Func.IsTangent();
+             seqAjout.Append(lines.Length() + 1);
+           }  
+         }
+         else { // test stop
+           Rsnld.Root(UVap);
+           Arrive = TestArretPassage(Umult, Vmult, Func, UVap, N);
+           if (Arrive) {
+             Cadre = Standard_False;
+             //in case if there is a frame and arrive at the same time
+           }
+           else {
+             if (Rajout) {
+               ArretAjout =TestArretAjout(Func, UVap, N, Psol);
+               if (ArretAjout) {
+                 // jag 940615
+                 Tgtend = lines.Value(N)->IsTangentAtEnd();
+                 N = -N;
+               }
+             }
+             // modified by NIZHNY-MKK  Thu Nov  2 15:09:08 2000.BEGIN
+             if(!(Rajout && ArretAjout)) {
+               Standard_Real prevUp, prevVp;
+               if (!reversed) {
+                 previousPoint.ParametersOnS2(prevUp, prevVp);
+               }
+               else {
+                 previousPoint.ParametersOnS1(prevUp, prevVp);
+               }
+               Arrive = TestPassedSolutionWithNegativeState(wd1, Umult, Vmult, prevUp, prevVp,
+                                                            nbMultiplicities, tolerance, Func, UVap, N);               
+               if(Arrive) {
+                 Cadre = Standard_False;
+               }
+             }
+             // modified by NIZHNY-MKK  Thu Nov  2 15:09:13 2000.END
+             if (!ArretAjout && Cadre) {
+               if (CurrentLine->NbPoints() == 1) break; // cancel the line
+               TestArretCadre(Umult, Vmult, CurrentLine, Func, UVap, N);
+//             if (N == 0) {
+               if (N <= 0) { // jag 941017
+                 MakeWalkingPoint(2, UVap(1), UVap(2), Func, Psol);
+                 Tgtend = Func.IsTangent();
                   N = -N;
-                }
-              }
-            }
-            Status = TestDeflection(Func, Arrive, UVap, StatusPrecedent,
-              NbDivision,PasC,StepSign);
-            StatusPrecedent = Status;
-            if (Status == IntWalk_PasTropGrand) {
-              Arrive = Standard_False;
-              ArretAjout = Standard_False;
-              Tgtend = Standard_False; // jag 940615
-              if (!reversed) {
-                previousPoint.ParametersOnS2(UVap(1), UVap(2));
-              }
-              else {
-                previousPoint.ParametersOnS1(UVap(1), UVap(2));
+               }
+             }
+           }
+           Status = TestDeflection(Func, Arrive, UVap, StatusPrecedent,
+                                   NbDivision,PasC,StepSign,CurrentLine->NbPoints());
+           StatusPrecedent = Status;
+
+            if (Status == IntWalk_ArretSurPoint && !PossibleCuspPoint && Func.IsTangent())
+            {
+              if (ComputeDirOfTangentialIntersection(Func, StepSignTangent))
+              {
+                MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
+                previousProj1 = previousProj2 = previousProj3 = previousProj4 = 0.;
+                CurrentLine->AddPoint(previousPoint);
+                Status = IntWalk_OKtangent;
               }
             }
-            else if (ArretAjout || Cadre) {
-              Arrive = Standard_True;
-              CurrentLine->AddStatusLast(Standard_False);
-              if (Status != IntWalk_ArretSurPointPrecedent) {
-                CurrentLine->AddPoint(Psol);                      
-              }
-              if (Cadre && N==0) {
-                Rajout = Standard_True;
-                seqAjout.Append(lines.Length()+1);
-              }
+            
+           if (Status == IntWalk_PasTropGrand) {
+             Arrive = Standard_False;
+             ArretAjout = Standard_False;
+             Tgtend = Standard_False; // jag 940615
+             if (!reversed) {
+               previousPoint.ParametersOnS2(UVap(1), UVap(2));
+             }
+             else {
+               previousPoint.ParametersOnS1(UVap(1), UVap(2));
+             }
+           }
+           else if (ArretAjout || Cadre) {
+             Arrive = Standard_True;
+             CurrentLine->AddStatusLast(Standard_False);
+             if (Status != IntWalk_ArretSurPointPrecedent) {
+               CurrentLine->AddPoint(Psol);                      
+             }
+             if (Cadre && N==0) {
+               Rajout = Standard_True;
+               seqAjout.Append(lines.Length()+1);
+             }
+           }
+           else if (Status == IntWalk_ArretSurPointPrecedent &&
+                     PossibleCuspPoint &&
+                     !Func.IsTangent()) //continue the line because no cusp point and no tangent point
+            {
+              Status = IntWalk_OK;
+              StatusPrecedent = IntWalk_OK;
+              PasC = PasSav;
+              PossibleCuspPoint = Standard_False;
+              
+              MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
+             previousd3d = Func.Direction3d();
+             previousd2d = Func.Direction2d();
+              //prevtg = Standard_False;
+              previousProj1 = Func.Projection1();
+              previousProj2 = Func.Projection2();
+              previousProj3 = Func.Projection3();
+              previousProj4 = Func.Projection4();
+             CurrentLine->AddPoint(previousPoint);
             }
-            else if (Status == IntWalk_ArretSurPointPrecedent) {
-              if (CurrentLine->NbPoints() == 1) { //cancel the line
-                Arrive = Standard_False;
-                break;
-              }
-              Arrive = Standard_True;
-              Rajout = Standard_True;
+           else if (Status == IntWalk_ArretSurPointPrecedent) {
+             if (CurrentLine->NbPoints() == 1) { //cancel the line
+               Arrive = Standard_False;
+               break;
+             }
+             Arrive = Standard_True;
+             Rajout = Standard_True;
               seqAjout.Append(lines.Length() + 1);
-              CurrentLine->AddStatusLast(Standard_False);
-              Tgtend = Standard_True; // check
-            }
-            else if (Arrive)  {
-              if (CurrentLine->NbPoints() == 1 &&    // cancel the line
-                (N == I || Status == IntWalk_PointConfondu) ) {
-                  // if N == I the main uv is probably lost
-                  // or the point is a point of accumulation
-                  // if point is confused the start data is bad
-                  Arrive =  Standard_False;
-                  break;
-              }
-              // necessairily N > 0 jag 940617
+             CurrentLine->AddStatusLast(Standard_False);
+             Tgtend = Standard_True; // check
+           }
+           else if (Arrive)  {
+             if (CurrentLine->NbPoints() == 1 &&    // cancel the line
+                 (N == I || Status == IntWalk_PointConfondu) ) {
+               // if N == I the main uv is probably lost
+               // or the point is a point of accumulation
+               // if point is confused the start data is bad
+               Arrive =  Standard_False;
+               break;
+             }
+             // necessairily N > 0 jag 940617
               // point of stop given at input 
-              PathPnt = Pnts1.Value(N);
-
-              Standard_Integer etat1N=wd1[N].etat;
-              // modified by NIZHNY-MKK  Thu Nov  2 15:09:51 2000.BEGIN
-              //             if (etat1N < 11) { // passing point that is a stop  
-              if (Abs(etat1N) < 11) { // passing point that is a stop    
-                // modified by NIZHNY-MKK  Thu Nov  2 15:12:11 2000.END
-                if (Status == IntWalk_ArretSurPoint) { 
-                  CurrentLine->AddStatusLast(Standard_False);
-                  Tgtend = Standard_True; // need check
-                }
-                else { 
-                  Arrive = Standard_False;
-                }
-                CurrentLine->AddIndexPassing(N);
-              }
-              else { // point of stop given at input
-                if (etat1N == 11) {
-                  Tgtend = Standard_True;
-                }
-                CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
-              }
-              AddPointInCurrentLine(N,PathPnt,CurrentLine);
-              if ((etat1N != 1 && etat1N != 11)) {
-                // modified by NIZHNY-MKK  Fri Oct 27 12:43:05 2000.BEGIN
-                //             wd1[N].etat= - wd1[N].etat;
-                wd1[N].etat = - Abs(etat1N);           
-                movementdirectioninfo[N] = (movementdirectioninfo[N]==0) ? StepSign : 0;
-                if(Arrive && movementdirectioninfo[N]!=0) {
-                  IndexOfPathPointDoNotCheck = N;
-                }
+             PathPnt = Pnts1.Value(N);
+             
+             Standard_Integer etat1N=wd1[N].etat;
+             // modified by NIZHNY-MKK  Thu Nov  2 15:09:51 2000.BEGIN
+             //              if (etat1N < 11) { // passing point that is a stop  
+             if (Abs(etat1N) < 11) { // passing point that is a stop    
+               // modified by NIZHNY-MKK  Thu Nov  2 15:12:11 2000.END
+               if (Status == IntWalk_ArretSurPoint) { 
+                 CurrentLine->AddStatusLast(Standard_False);
+                 Tgtend = Standard_True; // need check
+               }
+               else { 
+                 Arrive = Standard_False;
+               }
+               CurrentLine->AddIndexPassing(N);
+             }
+             else { // point of stop given at input
+               if (etat1N == 11) {
+                 Tgtend = Standard_True;
+               }
+               CurrentLine->AddStatusLast(Standard_True, N, PathPnt);
+             }
+             AddPointInCurrentLine(N,PathPnt,CurrentLine);
+             if ((etat1N != 1 && etat1N != 11)) {
+               // modified by NIZHNY-MKK  Fri Oct 27 12:43:05 2000.BEGIN
+               //              wd1[N].etat= - wd1[N].etat;
+               wd1[N].etat = - Abs(etat1N);            
+               movementdirectioninfo[N] = (movementdirectioninfo[N]==0) ? StepSign : 0;
+               if(Arrive && movementdirectioninfo[N]!=0) {
+                 IndexOfPathPointDoNotCheck = N;
+               }
 
-                if(Arrive) {
-                  Rajout = Standard_True;
-                  seqAjout.Append(lines.Length() + 1);
-                }
-                // modified by NIZHNY-MKK  Fri Oct 27 12:45:33 2000.END
-              }
-            }
-            else if (Status == IntWalk_ArretSurPoint) {
-              Arrive = Standard_True;                   
+               if(Arrive) {
+                 Rajout = Standard_True;
+                 seqAjout.Append(lines.Length() + 1);
+               }
+               // modified by NIZHNY-MKK  Fri Oct 27 12:45:33 2000.END
+             }
+           }
+           else if (Status == IntWalk_ArretSurPoint) {
+              Arrive = Standard_True;
               CurrentLine->AddStatusLast(Standard_False);
               Tgtend = Standard_True;
               MakeWalkingPoint(1, UVap(1), UVap(2), Func, Psol);
+              //jgv
+              if (PossibleCuspPoint &&
+                  Func.IsTangent() && Func.SquareTangentError() > TolTang)
+                FindExactTangentPoint(TolTang, Func, Psol);
+              /////
               CurrentLine->AddPoint(Psol);
               Rajout = Standard_True;
               seqAjout.Append(lines.Length() + 1);
-            }
-            else if (Status == IntWalk_OK) { 
+           }
+           else if (Status == IntWalk_OK) { 
               MakeWalkingPoint(2, UVap(1), UVap(2), Func, previousPoint);
-              previousd3d = Func.Direction3d();
-              previousd2d = Func.Direction2d();
-              CurrentLine->AddPoint(previousPoint);
-            }     
+             previousd3d = Func.Direction3d();
+             previousd2d = Func.Direction2d();
+              //prevtg = Standard_False;
+              previousProj1 = Func.Projection1();
+              previousProj2 = Func.Projection2();
+              previousProj3 = Func.Projection3();
+              previousProj4 = Func.Projection4();
+             CurrentLine->AddPoint(previousPoint);
+           }                           
             else if (Status == IntWalk_PointConfondu)
             {
-              aNbIter --;
+              //aNbIter --;
             }
-          }
-        }
-        else { // no numerical solution
-          PasC = PasC / 2.;
-          PasCu = Abs(PasC*previousd2d.X());
-          PasCv = Abs(PasC*previousd2d.Y());
-          if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
-            if (CurrentLine->NbPoints()==1) break;
-            Arrive = Standard_True;
-            CurrentLine->AddStatusLast(Standard_False);
-            Tgtend = Standard_True; // need check
-            Rajout = Standard_True;
+         }
+       }
+       else { // no numerical solution
+         PasC = PasC / 2.;
+         PasCu = Abs(PasC*previousd2d.X());
+         PasCv = Abs(PasC*previousd2d.Y());
+         if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+           if (CurrentLine->NbPoints()==1) break;
+           Arrive = Standard_True;
+           CurrentLine->AddStatusLast(Standard_False);
+           Tgtend = Standard_True; // need check
+           Rajout = Standard_True;
             seqAjout.Append(lines.Length() + 1);
-          }  
-        }
+         }  
+       }
 
+        /*
         if(aNbIter < 0)
           break;
+        */
       } // end of started line
       
       if (Arrive) {
-        CurrentLine->SetTangencyAtEnd(Tgtend);
-        lines.Append(CurrentLine);
-        // modified by NIZHNY-MKK  Fri Oct 27 12:59:29 2000.BEGIN
-        movementdirectioninfo[I]=0;
-        if(wd1[I].etat > 0)
-          // modified by NIZHNY-MKK  Fri Oct 27 12:59:42 2000.END
-          wd1[I].etat=-wd1[I].etat;
+       CurrentLine->SetTangencyAtEnd(Tgtend);
+       lines.Append(CurrentLine);
+       // modified by NIZHNY-MKK  Fri Oct 27 12:59:29 2000.BEGIN
+       movementdirectioninfo[I]=0;
+       if(wd1[I].etat > 0)
+       // modified by NIZHNY-MKK  Fri Oct 27 12:59:42 2000.END
+         wd1[I].etat=-wd1[I].etat;
 
-        //-- lbr le 5 juin 97 (Pb ds Contap)
-        for(Standard_Integer av=1; av<=nbPath; av++) { 
-          // modified by NIZHNY-MKK  Fri Oct 27 13:00:22 2000.BEGIN
-          //     if (wd1[av].etat > 11) {
-          if ((wd1[av].etat > 11) || 
-            ((av!=I) && 
-            (av!=IndexOfPathPointDoNotCheck) && 
-            (wd1[av].etat < -11)  && 
-            (movementdirectioninfo[av]!=0)))
-          {
-            // modified by NIZHNY-MKK  Fri Oct 27 13:00:26 2000.END
-            Standard_Real Uav=wd1[av].ustart;
-            Standard_Real Vav=wd1[av].vstart;
-            Standard_Real Uavp,Vavp;
-            const IntSurf_PntOn2S &avP=CurrentLine->Value(CurrentLine->NbPoints());
-            if (!reversed) {
-              avP.ParametersOnS2(Uavp,Vavp);
-            }
-            else {
-              avP.ParametersOnS1(Uavp,Vavp);
-            }
-            Uav-=Uavp;
-            Vav-=Vavp;
-            Uav*=0.001; Vav*=0.001;
-            if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
-              // modified by NIZHNY-MKK  Fri Oct 27 13:01:38 2000.BEGIN
-              //             wd1[av].etat=-wd1[av].etat;
-              if(wd1[av].etat < 0) {
-                movementdirectioninfo[av] = 0;
-              } else {
-                wd1[av].etat=-wd1[av].etat;
-                movementdirectioninfo[av] = StepSign;
-              }
-              // modified by NIZHNY-MKK  Fri Oct 27 13:01:42 2000.END
-              CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
-              //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
-            }
-
-            const IntSurf_PntOn2S &avPP=CurrentLine->Value(1);
-            if (!reversed) {
-              avPP.ParametersOnS2(Uavp,Vavp);
-            }
-            else {
-              avPP.ParametersOnS1(Uavp,Vavp);
-            }
-            Uav=wd1[av].ustart;
-            Vav=wd1[av].vstart;
-            Uav-=Uavp;
-            Vav-=Vavp;
-            Uav*=0.001; Vav*=0.001;
-            if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
-              // modified by NIZHNY-MKK  Fri Oct 27 13:02:49 2000.BEGIN
-              //             wd1[av].etat=-wd1[av].etat;
-              if(wd1[av].etat < 0) {
-                movementdirectioninfo[av] = 0;
-              } else {
-                wd1[av].etat=-wd1[av].etat;
-                movementdirectioninfo[av] = -StepSign;
-              }
-              // modified by NIZHNY-MKK  Fri Oct 27 13:02:52 2000.END
-              //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
-              CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
-            }
-          }
-        }
+       //-- lbr le 5 juin 97 (Pb ds Contap)
+       for(Standard_Integer av=1; av<=nbPath; av++) { 
+         // modified by NIZHNY-MKK  Fri Oct 27 13:00:22 2000.BEGIN
+         //      if (wd1[av].etat > 11) {
+         if ((wd1[av].etat > 11) || 
+             ((av!=I) && 
+              (av!=IndexOfPathPointDoNotCheck) && 
+              (wd1[av].etat < -11)  && 
+              (movementdirectioninfo[av]!=0))) {
+         // modified by NIZHNY-MKK  Fri Oct 27 13:00:26 2000.END
+           Standard_Real Uav=wd1[av].ustart;
+           Standard_Real Vav=wd1[av].vstart;
+           Standard_Real Uavp,Vavp;
+           const IntSurf_PntOn2S &avP=CurrentLine->Value(CurrentLine->NbPoints());
+           if (!reversed) {
+             avP.ParametersOnS2(Uavp,Vavp);
+           }
+           else {
+             avP.ParametersOnS1(Uavp,Vavp);
+           }
+           Uav-=Uavp;
+           Vav-=Vavp;
+           Uav*=0.001; Vav*=0.001;
+           if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
+             // modified by NIZHNY-MKK  Fri Oct 27 13:01:38 2000.BEGIN
+             //              wd1[av].etat=-wd1[av].etat;
+             if(wd1[av].etat < 0) {
+               movementdirectioninfo[av] = 0;
+             } else {
+               wd1[av].etat=-wd1[av].etat;
+               movementdirectioninfo[av] = StepSign;
+             }
+             // modified by NIZHNY-MKK  Fri Oct 27 13:01:42 2000.END
+             CurrentLine->AddStatusLast(Standard_True, av, Pnts1.Value(av));
+             //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
+           }
+           
+           const IntSurf_PntOn2S &avPP=CurrentLine->Value(1);
+           if (!reversed) {
+             avPP.ParametersOnS2(Uavp,Vavp);
+           }
+           else {
+             avPP.ParametersOnS1(Uavp,Vavp);
+           }
+           Uav=wd1[av].ustart;
+           Vav=wd1[av].vstart;
+           Uav-=Uavp;
+           Vav-=Vavp;
+           Uav*=0.001; Vav*=0.001;
+           if(Abs(Uav)<tolerance(1) && Abs(Vav)<tolerance(2)) { 
+             // modified by NIZHNY-MKK  Fri Oct 27 13:02:49 2000.BEGIN
+             //              wd1[av].etat=-wd1[av].etat;
+             if(wd1[av].etat < 0) {
+               movementdirectioninfo[av] = 0;
+             } else {
+               wd1[av].etat=-wd1[av].etat;
+               movementdirectioninfo[av] = -StepSign;
+             }
+             // modified by NIZHNY-MKK  Fri Oct 27 13:02:52 2000.END
+             //-- cout<<"\n Debug ? lbr ds IntWalk_IWalking_3.gxx"<<endl;
+             CurrentLine->AddStatusFirst(Standard_False, Standard_True, av, Pnts1.Value(av));
+           }
+         }
+       }
+         
       }
     } //end of point processing
   } //end of all points
 }
 
+
 // modified by NIZHNY-MKK  Thu Nov  2 15:07:53 2000.BEGIN
 static Standard_Boolean TestPassedSolutionWithNegativeState(const IntWalk_VectorOfWalkingData& wd,
                                                            const TColStd_SequenceOfReal& Umult,
index bddf8ff15c5214a5140ec695e38f50bd22a615ed..9675df08a24a711565e9e01d0e4f531670e78005 100644 (file)
 // commercial license or contractual agreement.
 
 #include <NCollection_IncAllocator.hxx>
+#include <IntSurf_Quadric.hxx>
 
 void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
                                        const TColStd_SequenceOfReal& Vmult,
                                        const ThePOPIterator& Pnts1,
                                        const ThePOLIterator& Pnts2,
+                                       const ThePOLIterator& Pnts3,
                                        TheIWFunction& Func,
                                         Standard_Boolean& Rajout ) 
 // *********** Processing of closed line **********************
@@ -42,7 +44,7 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
 // ******************************************************************** 
 {
 
-  Standard_Integer I,N = 0;
+  Standard_Integer I, N = 0;
   Standard_Real aBornInf[2], aBornSup[2], aUVap[2];
   math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2);
   math_Vector Uvap(aUVap,1,2);// parameters of current approach
@@ -61,6 +63,7 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
   Standard_Boolean Tgtbeg,Tgtend;
 
   Standard_Integer StepSign;
+  Standard_Integer StepSignTangent;
   
   IntWalk_StatusDeflection Status,StatusPrecedent;
   Standard_Integer NbDivision ;   // number of divisions of step 
@@ -79,19 +82,38 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
   Standard_Integer nbLoop = Pnts2.Length();
 
   for (I = 1;I<=nbLoop;I++) {
-    if (wd2[I].etat > 12)
-    { // start point of closed line
+    if (wd2[I].etat > 12) { // start point of closed line
+      
       LoopPnt = Pnts2.Value(I);
-      previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt),reversed,
-           wd2[I].ustart,wd2[I].vstart);
+      gp_Pnt thePoint = ThePointOfLoopTool::Value3d(LoopPnt);
+      previousPoint.SetValue(thePoint,reversed,
+                            wd2[I].ustart,wd2[I].vstart);
       previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt);
       previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt);
-
+      
+      Standard_Real theU, theV;
+      ThePointOfLoopTool::Value2d(LoopPnt, theU, theV);
+      
+#ifdef DRAW
+      cout<<"LoopPnt("<<I<<"):"<<endl;
+      cout<<"u = "<<theU<<", v = "<<theV<<endl;
+      cout<<"pnt = "<<thePoint.X()<<" "<<thePoint.Y()<<" "<<thePoint.Z()<<endl<<endl;
+#endif
+      
+      IntSurf_PntOn2S PrevPointFromFunc;
+      MakeWalkingPoint(11, theU, theV, Func, PrevPointFromFunc);
+      previousProj1 = Func.Projection1();
+      previousProj2 = Func.Projection2();
+      previousProj3 = Func.Projection3();
+      previousProj4 = Func.Projection4();
+      /////
       CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
       CurrentLine->AddPoint(previousPoint);
       CurrentLine->SetTangentVector(previousd3d,1);
       Tgtbeg = Standard_False;
       Tgtend = Standard_False;
+      PossibleCuspPoint = Standard_False;
+      IsTangentialIntersection = Standard_False;
       Uvap(1) = wd2[I].ustart;
       Uvap(2) = wd2[I].vstart;
 
@@ -102,13 +124,13 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
       Standard_Real d2dx = Abs(previousd2d.X()); 
       Standard_Real d2dy = Abs(previousd2d.Y()); 
       if (d2dx < tolerance(1)) {
-        PasC = pas * (VM-Vm)/d2dy;
+       PasC = pas * (VM-Vm)/d2dy;
       }
       else if (d2dy < tolerance(2)) {
-        PasC = pas * (UM-Um)/d2dx;
+       PasC = pas * (UM-Um)/d2dx;
       }
       else {
-        PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
+       PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
       }
 
       PasSav = PasC;
@@ -119,233 +141,548 @@ void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
       StatusPrecedent = IntWalk_OK;
       Standard_Integer aNbIter = 10;
       while (!Arrive) {  // as no test of stop is passed
-        Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign);  // border?
+       Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign);  // border?
 #ifdef CHRONO
-        Chronrsnld.Start();
+       Chronrsnld.Start();
 #endif
 
-        Rsnld.Perform(Func,Uvap,BornInf,BornSup);
+       Rsnld.Perform(Func,Uvap,BornInf,BornSup);
 
 #ifdef CHRONO
-        Chronrsnld.Stop();
+       Chronrsnld.Stop();
 #endif
 
-        if (Cadre) { // update of limits.
-          BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
-        }
-        if (Rsnld.IsDone()) {
-          if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
-            PasC = PasC/2.;
-            PasCu = Abs(PasC*previousd2d.X());
-            PasCv = Abs(PasC*previousd2d.Y());
-
-            if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
-              if (CurrentLine->NbPoints()==1) break;
-              Arrive = Standard_True;
-              CurrentLine->AddStatusFirstLast(Standard_False,
-                Standard_False,Standard_False);
-              Rajout = Standard_True;
+       if (Cadre) { // update of limits.
+         BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
+       }
+       if (Rsnld.IsDone()) {
+         if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
+           PasC = PasC/2.;
+           PasCu = Abs(PasC*previousd2d.X());
+           PasCv = Abs(PasC*previousd2d.Y());
+
+           if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+             if (CurrentLine->NbPoints()==1) break;
+             Arrive = Standard_True;
+             CurrentLine->AddStatusFirstLast(Standard_False,
+                                             Standard_False,Standard_False);
+             Rajout = Standard_True;
               seqAjout.Append(lines.Length()+1);
-              Tgtend = Standard_True;
-            }
-          }
-          else { // there is a solution
-            Rsnld.Root(Uvap);
-            Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
-            if (Arrive) {//reset proper parameter to test the arrow.
-              Psol = CurrentLine->Value(1);
-              if (!reversed) {
-                Psol.ParametersOnS2(Uvap(1),Uvap(2));
-              }
-              else {
-                Psol.ParametersOnS1(Uvap(1),Uvap(2));
-              }
+             Tgtend = Standard_True;
+           }
+         }
+         else { // there is a solution
+           Rsnld.Root(Uvap);
+           Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
+           if (Arrive) {//reset proper parameter to test the arrow.
+             Psol = CurrentLine->Value(1);
+             if (!reversed) {
+               Psol.ParametersOnS2(Uvap(1),Uvap(2));
+             }
+             else {
+               Psol.ParametersOnS1(Uvap(1),Uvap(2));
+             }
               Cadre=Standard_False; 
-              //in case if there is a frame and arrival at the same time
-            }
-            else { // modif jag 940615
-              if (Rajout) {    // test on added points
-                ArretAjout =TestArretAjout(Func,Uvap,N,Psol);
-                if (ArretAjout) {
-                  if (N >0) {
-                    Tgtend = lines.Value(N)->IsTangentAtEnd();
-                    N = -N;
-                  }
-                  else {
-                    Tgtend = lines.Value(-N)->IsTangentAtBegining();
-                  }
-                  Arrive = (wd2[I].etat == 12);
-                }
-              }
-
-              if (!ArretAjout&& Cadre) {  // test on already marked points
-                if (CurrentLine->NbPoints() == 1)  break; // cancel the line
-                TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
-                //             if (N==0) {
-                if (N <= 0) { // jag 941017
-                  MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
-                  Tgtend = Func.IsTangent(); // jag 940616
-                  N = -N;
-                }
-                Arrive = (wd2[I].etat == 12); // the line is open
-              }
-            }
-            Status = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
-                                                NbDivision,PasC,StepSign);
-
-            StatusPrecedent = Status; 
-            if (Status == IntWalk_PasTropGrand) {// division of the step
-              Arrive = Standard_False;
-              ArretAjout = Standard_False;
-              Tgtend = Standard_False; // jag 940616
-              if (!reversed) {
-                previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
-              }
-              else {
-                previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
-              }
-            }
-            else if (ArretAjout || Cadre) {
-
-              if (Arrive) { // line s is open
-                CurrentLine->AddStatusLast(Standard_False);
-                if (Status != IntWalk_ArretSurPointPrecedent) {
-                  CurrentLine->AddPoint(Psol);                      
-                }
-                if (Cadre && N==0) {
-                  Rajout = Standard_True;
-                  seqAjout.Append(lines.Length()+1);
-                }
-
-              }
-              else { // open
-                wd2[I].etat = 12; // declare it open
-                Tgtbeg = Tgtend;
-                Tgtend = Standard_False;
-                ArretAjout = Standard_False;
-                StepSign = -1;
+             //in case if there is a frame and arrival at the same time
+           }
+           else { // modif jag 940615
+
+             if (Rajout) {    // test on added points
+               ArretAjout =TestArretAjout(Func,Uvap,N,Psol);
+               if (ArretAjout) {
+                 if (N >0) {
+                   Tgtend = lines.Value(N)->IsTangentAtEnd();
+                   N = -N;
+                 }
+                 else {
+                   Tgtend = lines.Value(-N)->IsTangentAtBegining();
+                 }
+                 Arrive = (wd2[I].etat == 12);
+               }
+             }
+
+             if (!ArretAjout&& Cadre) {  // test on already marked points
+               if (CurrentLine->NbPoints() == 1)  break; // cancel the line
+               TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
+//             if (N==0) {
+               if (N <= 0) { // jag 941017
+                 MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
+                 Tgtend = Func.IsTangent(); // jag 940616
+                 N = -N;
+               }
+               Arrive = (wd2[I].etat == 12); // the line is open
+             }
+           }
+           Status = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
+                                   NbDivision,PasC,StepSign,CurrentLine->NbPoints());
+           StatusPrecedent = Status; 
+           if (Status == IntWalk_PasTropGrand) {// division of the step
+             Arrive = Standard_False;
+             ArretAjout = Standard_False;
+             Tgtend = Standard_False; // jag 940616
+             if (!reversed) {
+               previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
+             }
+             else {
+               previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
+             }
+           }
+           else if (ArretAjout || Cadre) {
+
+             if (Arrive) { // line s is open
+               CurrentLine->AddStatusLast(Standard_False);
+               if (Status != IntWalk_ArretSurPointPrecedent) {
+                 CurrentLine->AddPoint(Psol);                      
+               }
+               if (Cadre && N==0) {
+                 Rajout = Standard_True;
+                 seqAjout.Append(lines.Length()+1);
+               }
+                
+             }
+             else { // open
+               wd2[I].etat = 12; // declare it open
+               Tgtbeg = Tgtend;
+               Tgtend = Standard_False;
+               ArretAjout = Standard_False;
+               StepSign = -1;
                 StatusPrecedent = IntWalk_OK;
-                PasC = PasSav;
-                if (Status == IntWalk_ArretSurPointPrecedent) {
-                  OpenLine(0,Psol,Pnts1,Func,CurrentLine);
-                }
-                else {
-                  OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
-                }
-                if (Cadre && N==0) {
-                  Rajout = Standard_True;
-                  seqAjout.Append(-lines.Length()-1);
-                }
-              }
+               PasC = PasSav;
+                PossibleCuspPoint = Standard_False;
+               if (Status == IntWalk_ArretSurPointPrecedent) {
+                 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
+               }
+               else {
+                 OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
+               }
+               if (Cadre && N==0) {
+                 Rajout = Standard_True;
+                 seqAjout.Append(-lines.Length()-1);
+               }
+             }
+           }
+           else if (Status == IntWalk_ArretSurPointPrecedent &&
+                     PossibleCuspPoint &&
+                     !Func.IsTangent()) //continue the line because no cusp point and no tangent point
+            {
+              Status = IntWalk_OK;
+              StatusPrecedent = IntWalk_OK;
+              PasC = PasSav;
+              PossibleCuspPoint = Standard_False;
+
+             if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
+             previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+             previousd3d = Func.Direction3d();
+             previousd2d = Func.Direction2d();
+              previousProj1 = Func.Projection1();
+              previousProj2 = Func.Projection2();
+              previousProj3 = Func.Projection3();
+              previousProj4 = Func.Projection4();
+             CurrentLine->AddPoint(previousPoint);
             }
-            else if ( Status == IntWalk_ArretSurPointPrecedent) {
-              if (CurrentLine->NbPoints() == 1) { //cancel the line
-                Arrive = Standard_False;
-                break;
-              }
-              if (wd2[I].etat >12) { //the line should become open
-                wd2[I].etat = 12; //declare it open
-                ArretAjout = Standard_False;
-                OpenLine(0,Psol,Pnts1,Func,CurrentLine);
-                StepSign = -1;
+           else if ( Status == IntWalk_ArretSurPointPrecedent) {
+             if (CurrentLine->NbPoints() == 1) { //cancel the line
+               Arrive = Standard_False;
+               break;
+             }
+             if (wd2[I].etat >12) { //the line should become open
+               wd2[I].etat = 12; //declare it open
+               ArretAjout = Standard_False;
+               OpenLine(0,Psol,Pnts1,Func,CurrentLine);
+               StepSign = -1;
                 StatusPrecedent = IntWalk_OK;
-                Arrive = Standard_False;
-                PasC = PasSav;
-                Rajout = Standard_True;
+               Arrive = Standard_False;
+               PasC = PasSav;
+               Rajout = Standard_True;
                 seqAjout.Append(-lines.Length()-1);
-              }
-              else { // line s is open                 
-                Arrive =Standard_True;
-                CurrentLine->AddStatusLast(Standard_False);
-                Rajout = Standard_True;
+             }
+             else { // line s is open                 
+               Arrive =Standard_True;
+               CurrentLine->AddStatusLast(Standard_False);
+               Rajout = Standard_True;
                 seqAjout.Append(lines.Length()+1);
-              
-            }
-            else if (Arrive)  {
-              if (wd2[I].etat > 12) {  //line closed good case
-                CurrentLine->AddStatusFirstLast(Standard_True,
-                  Standard_False,Standard_False);
-                CurrentLine->AddPoint(CurrentLine->Value(1));              
-              }
-              else if (N >0) { //point of stop given at input 
-                PathPnt = Pnts1.Value(N);
-                CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
+             } 
+           }
+           else if (Arrive)  {
+             if (wd2[I].etat > 12) {  //line closed good case
+               CurrentLine->AddStatusFirstLast(Standard_True,
+                                               Standard_False,Standard_False);
+               CurrentLine->AddPoint(CurrentLine->Value(1));              
+             }
+             else if (N >0) { //point of stop given at input 
+               PathPnt = Pnts1.Value(N);
+               CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
                 AddPointInCurrentLine(N,PathPnt,CurrentLine);
-              }
+             }
+           }
+            else if (Status == IntWalk_ArretSurPoint &&
+                     !PossibleCuspPoint && Func.IsTangent())
+            {
+              ComputeDirOfTangentialIntersection(Func, StepSignTangent);
+              MakeWalkingPoint(2, Uvap(1), Uvap(2), Func, previousPoint);
+              previousProj1 = previousProj2 = previousProj3 = previousProj4 = 0.;
+             CurrentLine->AddPoint(previousPoint);
+              Status = IntWalk_OKtangent;
             }
-            else if (Status == IntWalk_ArretSurPoint) {
-              if (wd2[I].etat >12) { //line should become open
-                wd2[I].etat = 12; //declare it open
-                Tgtbeg = Standard_True;
-                Tgtend = Standard_False;
+           else if (Status == IntWalk_ArretSurPoint) {
+             if (wd2[I].etat >12) { //line should become open
+               wd2[I].etat = 12; //declare it open
+               Tgtbeg = Standard_True;
+               Tgtend = Standard_False;
                 N= -lines.Length()-1;
                 Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
-                OpenLine(N,Psol,Pnts1,Func,CurrentLine);
-                StepSign = -1;
-                Rajout = Standard_True;
+               OpenLine(N,Psol,Pnts1,Func,CurrentLine);
+               StepSign = -1;
+               Rajout = Standard_True;
                 seqAjout.Append(N);
                 StatusPrecedent = IntWalk_OK;
-                Arrive = Standard_False;
-                PasC = PasSav; 
-              }
-              else { 
-                Arrive = Standard_True;                   
-                if (Ipass!=0) { //point of passage, point of stop
-                  PathPnt = Pnts1.Value(Ipass);
-                  CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
+               Arrive = Standard_False;
+               PasC = PasSav;  
+             }
+             else { 
+               Arrive = Standard_True;                   
+               if (Ipass!=0) { //point of passage, point of stop
+                 PathPnt = Pnts1.Value(Ipass);
+                 CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
                   AddPointInCurrentLine(Ipass,PathPnt,CurrentLine);
-                }
-                else {
+               }
+               else {
                   CurrentLine->AddStatusLast(Standard_False);
-                  IntSurf_PntOn2S newP;
-                  newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+                 IntSurf_PntOn2S newP;
+                 newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
                   CurrentLine->AddPoint(newP);
-                  Rajout = Standard_True;
-                  seqAjout.Append(lines.Length()+1);
+                 Rajout = Standard_True;
+                 seqAjout.Append(lines.Length()+1);
                 }
-              }
-            }
-            else if (Status == IntWalk_OK) { 
-              if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
-              previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
-              previousd3d = Func.Direction3d();
-              previousd2d = Func.Direction2d();
-              CurrentLine->AddPoint(previousPoint);
-            }
+             }
+           }
+           else if (Status == IntWalk_OK) { 
+             if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
+             previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+             previousd3d = Func.Direction3d();
+             previousd2d = Func.Direction2d();
+              previousProj1 = Func.Projection1();
+              previousProj2 = Func.Projection2();
+              previousProj3 = Func.Projection3();
+              previousProj4 = Func.Projection4();
+             CurrentLine->AddPoint(previousPoint);
+           }
             else if (Status == IntWalk_PointConfondu)
             {
               aNbIter --;
             }
-          }
-        }
-        else { //no numerical solution NotDone
-          PasC = PasC/2.;
-          PasCu = Abs(PasC*previousd2d.X());
-          PasCv = Abs(PasC*previousd2d.Y());
-
-          if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+         }
+       }
+       else { //no numerical solution NotDone
+         PasC = PasC/2.;
+         PasCu = Abs(PasC*previousd2d.X());
+         PasCv = Abs(PasC*previousd2d.Y());
+
+         if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
             if (CurrentLine->NbPoints() == 1)  break; // cancel the line
-            Arrive = Standard_True;
-            CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
-              Standard_False);
-            Tgtend = Standard_True;
-            Rajout = Standard_True;
-            seqAjout.Append(lines.Length()+1);
-          }  
-        }
-
+           Arrive = Standard_True;
+           CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
+                                           Standard_False);
+           Tgtend = Standard_True;
+           Rajout = Standard_True;
+           seqAjout.Append(lines.Length()+1);
+         }  
+       }
+        
         if(aNbIter < 0)
           break;
       }// end of started line 
       if (Arrive) {
-        CurrentLine->SetTangencyAtBegining(Tgtbeg);
-        CurrentLine->SetTangencyAtEnd(Tgtend);
-
-        lines.Append(CurrentLine);
-        wd2[I].etat=-wd2[I].etat; //mark point as processed
+       CurrentLine->SetTangencyAtBegining(Tgtbeg);
+       CurrentLine->SetTangencyAtEnd(Tgtend);
+       
+       lines.Append(CurrentLine);
+       wd2[I].etat=-wd2[I].etat; //mark point as processed
       }
     } //end of processing of start point
   } //end of all start points
+
+  //Process inner tangent points
+  IsTangentialIntersection = Standard_True;
+  StepSign = 1;
+  StepSignTangent = 1;
+  Standard_Integer nbTang = Pnts3.Length();
+  for (I = 1; I <= nbTang; I++) {
+    if (wd3[I].etat > 12) { // start point of closed line
+      
+      LoopPnt = Pnts3.Value(I);
+      gp_Pnt thePoint = ThePointOfLoopTool::Value3d(LoopPnt);
+      previousPoint.SetValue(thePoint,reversed,
+                            wd3[I].ustart, wd3[I].vstart);
+      Standard_Real theU, theV;
+      ThePointOfLoopTool::Value2d(LoopPnt, theU, theV);
+      IntSurf_PntOn2S PrevPointFromFunc;
+      MakeWalkingPoint(11, theU, theV, Func, PrevPointFromFunc);
+      /////
+      ComputeDirOfTangentialIntersection(Func, StepSignTangent);
+      //here <previousd3d> and <previousd2d> are defined
+      
+      CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
+      CurrentLine->AddPoint(previousPoint);
+      CurrentLine->SetTangentVector(previousd3d,1);
+      Tgtbeg = Standard_False;
+      Tgtend = Standard_False;
+      PossibleCuspPoint = Standard_False;
+      Uvap(1) = wd3[I].ustart;
+      Uvap(2) = wd3[I].vstart;
+
+      StepSign = 1;
+
+      // first step of advancement
+
+      Standard_Real d2dx = Abs(previousd2d.X()); 
+      Standard_Real d2dy = Abs(previousd2d.Y()); 
+      if (d2dx < tolerance(1)) {
+       PasC = pas * (VM-Vm)/d2dy;
+      }
+      else if (d2dy < tolerance(2)) {
+       PasC = pas * (UM-Um)/d2dx;
+      }
+      else {
+       PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
+      }
+
+      PasSav = PasC;
+
+      Arrive = Standard_False;
+      ArretAjout = Standard_False;
+      NbDivision = 0;
+      StatusPrecedent = IntWalk_OK;
+      while (!Arrive) {  // as no test of stop is passed
+       Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign);  // border?
+#ifdef CHRONO
+       Chronrsnld.Start();
+#endif
+
+       Rsnld.Perform(Func,Uvap,BornInf,BornSup);
+
+#ifdef CHRONO
+       Chronrsnld.Stop();
+#endif
+
+       if (Cadre) { // update of limits.
+         BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
+       }
+       if (Rsnld.IsDone()) {
+         if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
+           PasC = PasC/2.;
+           PasCu = Abs(PasC*previousd2d.X());
+           PasCv = Abs(PasC*previousd2d.Y());
+
+           if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+             if (CurrentLine->NbPoints()==1) break;
+             Arrive = Standard_True;
+             CurrentLine->AddStatusFirstLast(Standard_False,
+                                             Standard_False,Standard_False);
+             Rajout = Standard_True;
+              seqAjout.Append(lines.Length()+1);
+             Tgtend = Standard_True;
+           }
+         }
+         else { // there is a solution
+           Rsnld.Root(Uvap);
+           Arrive = TestArretPassageTang(Umult,Vmult,Uvap,I,Ipass);
+           if (Arrive) {//reset proper parameter to test the arrow.
+             Psol = CurrentLine->Value(1);
+             if (!reversed) {
+               Psol.ParametersOnS2(Uvap(1),Uvap(2));
+             }
+             else {
+               Psol.ParametersOnS1(Uvap(1),Uvap(2));
+             }
+              Cadre = Standard_False; 
+             //in case if there is a frame and arrival at the same time
+           }
+           else { // modif jag 940615
+
+             if (Rajout) {    // test on added points
+               ArretAjout = TestArretAjout(Func,Uvap,N,Psol);
+               if (ArretAjout) {
+                 if (N >0) {
+                   Tgtend = lines.Value(N)->IsTangentAtEnd();
+                   N = -N;
+                 }
+                 else {
+                   Tgtend = lines.Value(-N)->IsTangentAtBegining();
+                 }
+                 Arrive = (wd3[I].etat == 12);
+               }
+             }
+
+             if (!ArretAjout&& Cadre) {  // test on already marked points
+               if (CurrentLine->NbPoints() == 1)  break; // cancel the line
+               TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
+//             if (N==0) {
+               if (N <= 0) { // jag 941017
+                 MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
+                 Tgtend = Func.IsTangent(); // jag 940616
+                 N = -N;
+               }
+               Arrive = (wd3[I].etat == 12); // the line is open
+             }
+           }
+           Status = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
+                                   NbDivision,PasC,StepSign,CurrentLine->NbPoints());
+           StatusPrecedent = Status; 
+           if (Status == IntWalk_PasTropGrand) {// division of the step
+             Arrive = Standard_False;
+             ArretAjout = Standard_False;
+             Tgtend = Standard_False; // jag 940616
+             if (!reversed) {
+               previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
+             }
+             else {
+               previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
+             }
+           }
+           else if (ArretAjout || Cadre) {
+
+             if (Arrive) { // line s is open
+               CurrentLine->AddStatusLast(Standard_False);
+               if (Status != IntWalk_ArretSurPointPrecedent) {
+                 CurrentLine->AddPoint(Psol);                      
+               }
+               if (Cadre && N==0) {
+                 Rajout = Standard_True;
+                 seqAjout.Append(lines.Length()+1);
+               }
+                
+             }
+             else { // open
+               wd3[I].etat = 12; // declare it open
+               Tgtbeg = Tgtend;
+               Tgtend = Standard_False;
+               ArretAjout = Standard_False;
+               StepSign = -1;
+                StatusPrecedent = IntWalk_OK;
+               PasC = PasSav;
+               if (Status == IntWalk_ArretSurPointPrecedent) {
+                 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
+               }
+               else {
+                 OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
+               }
+               if (Cadre && N==0) {
+                 Rajout = Standard_True;
+                 seqAjout.Append(-lines.Length()-1);
+               }
+             }
+           }
+
+           else if ( Status == IntWalk_ArretSurPointPrecedent) {
+             if (CurrentLine->NbPoints() == 1) { //cancel the line
+               Arrive = Standard_False;
+               break;
+             }
+             if (wd3[I].etat >12) { //the line should become open
+               wd3[I].etat = 12; //declare it open
+               ArretAjout = Standard_False;
+               OpenLine(0,Psol,Pnts1,Func,CurrentLine);
+               StepSign = -1;
+                StatusPrecedent = IntWalk_OK;
+               Arrive = Standard_False;
+               PasC = PasSav;
+               Rajout = Standard_True;
+                seqAjout.Append(-lines.Length()-1);
+             }
+             else { // line s is open                 
+               Arrive = Standard_True;
+               CurrentLine->AddStatusLast(Standard_False);
+               Rajout = Standard_True;
+                seqAjout.Append(lines.Length()+1);
+             } 
+           }
+           else if (Arrive)  {
+             if (wd3[I].etat > 12) {  //line closed good case
+               CurrentLine->AddStatusFirstLast(Standard_True,
+                                               Standard_False,Standard_False);
+               CurrentLine->AddPoint(CurrentLine->Value(1));              
+             }
+             else if (N >0) { //point of stop given at input 
+               PathPnt = Pnts1.Value(N);
+               CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
+                AddPointInCurrentLine(N,PathPnt,CurrentLine);
+             }
+           }
+            else if (Status == IntWalk_ArretSurPoint &&
+                     !PossibleCuspPoint && Func.IsTangent())
+            {
+              ComputeDirOfTangentialIntersection(Func, StepSignTangent);
+              MakeWalkingPoint(2, Uvap(1), Uvap(2), Func, previousPoint);
+             CurrentLine->AddPoint(previousPoint);
+              Status = IntWalk_OKtangent;
+            }
+           else if (Status == IntWalk_ArretSurPoint) {
+             if (wd3[I].etat >12) { //line should become open
+               wd3[I].etat = 12; //declare it open
+               Tgtbeg = Standard_True;
+               Tgtend = Standard_False;
+                N= -lines.Length()-1;
+                Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+               OpenLine(N,Psol,Pnts1,Func,CurrentLine);
+               StepSign = -1;
+               Rajout = Standard_True;
+                seqAjout.Append(N);
+                StatusPrecedent = IntWalk_OK;
+               Arrive = Standard_False;
+               PasC = PasSav;  
+             }
+             else { 
+               Arrive = Standard_True;                   
+               if (Ipass!=0) { //point of passage, point of stop
+                 PathPnt = Pnts1.Value(Ipass);
+                 CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
+                  AddPointInCurrentLine(Ipass,PathPnt,CurrentLine);
+               }
+               else {
+                  CurrentLine->AddStatusLast(Standard_False);
+                 IntSurf_PntOn2S newP;
+                 newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+                  CurrentLine->AddPoint(newP);
+                 Rajout = Standard_True;
+                 seqAjout.Append(lines.Length()+1);
+                }
+             }
+           }
+           else if (Status == IntWalk_OK) { 
+             if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
+             previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
+             //previousd3d = Func.Direction3d();
+             //previousd2d = Func.Direction2d();
+             CurrentLine->AddPoint(previousPoint);
+           }
+         }
+       }
+       else { //no numerical solution NotDone
+         PasC = PasC/2.;
+         PasCu = Abs(PasC*previousd2d.X());
+         PasCv = Abs(PasC*previousd2d.Y());
+
+         if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
+            if (CurrentLine->NbPoints() == 1)  break; // cancel the line
+           Arrive = Standard_True;
+           CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
+                                           Standard_False);
+           Tgtend = Standard_True;
+           Rajout = Standard_True;
+           seqAjout.Append(lines.Length()+1);
+         }  
+       }
+      }// end of started line 
+      if (Arrive) {
+       CurrentLine->SetTangencyAtBegining(Tgtbeg);
+       CurrentLine->SetTangencyAtEnd(Tgtend);
+       
+       lines.Append(CurrentLine);
+       wd3[I].etat = -wd3[I].etat; //mark point as processed
+      }
+    } //end of processing of tangent point
+  } //end of all tangent points
 }
 
 
index 98dce89f3e7915a03b0e95ad2b47af82b33962c7..a898e27763f94befcce6150df2da09f4ddf0eb71 100644 (file)
@@ -20,6 +20,13 @@ namespace {
                                                    // because the angle is too great in 2d (U4)
 }
 
+static Standard_Real RealSign(const Standard_Real aValue)
+{
+  if (aValue >= 0.)
+    return 1.;
+  else return -1.;
+}
+
 IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
   (TheIWFunction& sp,
    const Standard_Boolean Finished,
@@ -27,7 +34,8 @@ IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
    const IntWalk_StatusDeflection StatusPrecedent,
    Standard_Integer& NbDivision,
    Standard_Real& Step,
-   const Standard_Integer StepSign)
+   const Standard_Integer StepSign,
+   const Standard_Integer CurNbPoints)
 {
   // Check the step of advancement, AND recalculate this step :
   //
@@ -58,83 +66,84 @@ IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
   //-- if epsilon is great enough (1e-11). In this case one loops 
   //-- without ever changing the values sent to Rsnld. 
   //---------------------------------------------------------------------------------
-  Standard_Real Paramu = 0.0, Paramv = 0.0;
-
-  if (!reversed) {
-    previousPoint.ParametersOnS2(Paramu, Paramv);
-  }
-  else
-  {
-    previousPoint.ParametersOnS1(Paramu, Paramv);
-  }
-
-  const Standard_Real Du = UV(1) - Paramu;
-  const Standard_Real Dv = UV(2) - Paramv;
-  const Standard_Real Duv = Du * Du + Dv * Dv;
+  Standard_Real Paramu, Paramv, StepU,StepV;
+  Standard_Real Cosi, Cosi2, Norme;
 
   gp_Vec Corde(previousPoint.Value(), sp.Point());
 
-  const Standard_Real Norme = Corde.SquareMagnitude(), 
-                      aTol = epsilon*Precision::PConfusion();
-
-  //if ((++NbPointsConfondusConsecutifs < 10) && (Norme <= epsilon)) { // the square is already taken in the constructor
-  if ((Norme <= epsilon) && ((Duv <= aTol) || (StatusPrecedent != IntWalk_OK)))
-  { // the square is already taken in the constructor
+  Norme = Corde.SquareMagnitude();
+//  if (Norme <= epsilon*epsilon) {
+//  if (Norme <= epsilon) { // the square is already taken in the constructor
+  if (Norme <= gp::Resolution()) {
     Status = IntWalk_PointConfondu;
     if (StatusPrecedent == IntWalk_PasTropGrand) {
       return IntWalk_ArretSurPointPrecedent;
     }
   }
   else {
-    Standard_Real Cosi = Corde * previousd3d;
-    Standard_Real Cosi2 = 0.0;
-
-    if (Cosi*StepSign >= 0.) {// angle 3d <= pi/2 !!!!
-      const Standard_Real aDiv = previousd3d.SquareMagnitude()*Norme;
-      if(aDiv == 0)
-        return Status;
-      Cosi2 = Cosi * Cosi / aDiv;
+    Cosi = Corde * previousd3d;
+    if (Cosi*StepSign < 0.) { // angle 3d > pi/2 !!!!
+      Cosi2 = 0.;
+    }
+    else {
+      Cosi2 = Cosi * Cosi / previousd3d.SquareMagnitude() / Norme;
     }
     if (Cosi2 < CosRef3D) { //angle 3d too great
       Step = Step /2.0;
-      Standard_Real StepU = Abs(Step*previousd2d.X()),
-                    StepV = Abs(Step*previousd2d.Y());
+      StepU = Abs(Step*previousd2d.X());
+      StepV = Abs(Step*previousd2d.Y());
       if (StepU < tolerance(1) && StepV < tolerance(2)) 
-        Status = IntWalk_ArretSurPointPrecedent;
+       Status = IntWalk_ArretSurPointPrecedent;
       else 
-        Status = IntWalk_PasTropGrand;
+       Status = IntWalk_PasTropGrand;
       return Status;
     }
   }
 
+  if (!reversed) {
+    previousPoint.ParametersOnS2(Paramu, Paramv);
+  }
+  else {
+    previousPoint.ParametersOnS1(Paramu, Paramv);
+  }
+  Standard_Real Du = UV(1) - Paramu;
+  Standard_Real Dv = UV(2) - Paramv;
+  Standard_Real Duv = Du * Du + Dv * Dv;
   if (Abs(Du) < tolerance(1) && Abs(Dv) < tolerance(2))
     return IntWalk_ArretSurPointPrecedent; //confused point 2d
-
-  Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
-
+  Cosi = StepSign * (Du * previousd2d.X() + 
+                     Dv * previousd2d.Y());
   if (Cosi < 0 && Status == IntWalk_PointConfondu) 
     return IntWalk_ArretSurPointPrecedent; // leave as step back  
                                            // with confused point
 
-  if (sp.IsTangent()) 
-    return IntWalk_ArretSurPoint;       
+  if (IsTangentialIntersection)
+  {
+    if (sp.IsTangentSmooth()) 
+      return IntWalk_ArretSurPoint;       
+  }
+  else
+  {
+    if (sp.IsTangent()) 
+      return IntWalk_ArretSurPoint;
+  }
 
 //if during routing one has subdivided more than  MaxDivision for each
 //previous step, bug on the square; do nothing (experience U4)
 
-  if ((NbDivision < MaxDivision) && (Status != IntWalk_PointConfondu) && 
-    (StatusPrecedent!= IntWalk_PointConfondu))
-  {
-    Standard_Real Cosi2 = Cosi * Cosi / Duv;
+  if (NbDivision < MaxDivision && 
+      Status != IntWalk_PointConfondu && 
+      StatusPrecedent!= IntWalk_PointConfondu ) {
+    Cosi2 = Cosi * Cosi / Duv;
     if (Cosi2 < CosRef2D || Cosi < 0  ) {
       Step = Step / 2.0;
-      Standard_Real StepU = Abs(Step*previousd2d.X()),
-                    StepV = Abs(Step*previousd2d.Y());
+      StepU = Abs(Step*previousd2d.X());
+      StepV = Abs(Step*previousd2d.Y());
 
       if (StepU < tolerance(1) && StepV < tolerance(2))
-        Status = IntWalk_ArretSurPointPrecedent;
+       Status = IntWalk_ArretSurPointPrecedent;
       else 
-        Status = IntWalk_PasTropGrand;
+       Status = IntWalk_PasTropGrand;
       NbDivision = NbDivision + 1;
       return Status;
     }
@@ -143,149 +152,164 @@ IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
     Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
     if (Cosi2 < CosRef3D ){ //angle 3d too great
       Step = Step / 2.;
-      Standard_Real StepU = Abs(Step*previousd2d.X()),
-                    StepV = Abs(Step*previousd2d.Y());
+      StepU = Abs(Step*previousd2d.X());
+      StepV = Abs(Step*previousd2d.Y());
       if (StepU < tolerance(1) && StepV < tolerance(2))
-        Status = IntWalk_ArretSurPoint;
+       Status = IntWalk_ArretSurPoint;
       else 
-        Status = IntWalk_PasTropGrand;
+       Status = IntWalk_PasTropGrand;
       return Status;
     }
     Cosi = Du * sp.Direction2d().X() + 
-      Dv * sp.Direction2d().Y();
+           Dv * sp.Direction2d().Y();
     Cosi2 = Cosi * Cosi / Duv;
     if (Cosi2 < CosRef2D || 
-      sp.Direction2d() * previousd2d < 0) {
-        //angle 2d too great or change the side       
+       sp.Direction2d() * previousd2d < 0) {
+      //angle 2d too great or change the side       
+      Step  = Step / 2.;
+      StepU = Abs(Step*previousd2d.X());
+      StepV = Abs(Step*previousd2d.Y());
+      if (StepU < tolerance(1) && StepV < tolerance(2))
+       Status = IntWalk_ArretSurPointPrecedent;
+      else 
+       Status = IntWalk_PasTropGrand;
+      return Status;
+    }
+    //jgv: detect possible cusp points
+    //point is suspicious to be a cusp point
+    //if there are 2 or more changes of sign
+    if (!IsTangentialIntersection && CurNbPoints > 1)
+    {
+      Standard_Real ChangeSign [5];
+      ChangeSign[1] = RealSign(previousProj1) * RealSign(sp.Projection1());
+      ChangeSign[2] = RealSign(previousProj2) * RealSign(sp.Projection2());
+      ChangeSign[3] = RealSign(previousProj3) * RealSign(sp.Projection3());
+      ChangeSign[4] = RealSign(previousProj4) * RealSign(sp.Projection4());
+      Standard_Real SumChange = ChangeSign[1]+ChangeSign[2]+ChangeSign[3]+ChangeSign[4];
+      if (SumChange <= 0 || //at least 2 changes of sign
+          (StatusPrecedent == IntWalk_PasTropGrand && SumChange <= 2)) //1 change of sign
+      {
+        PossibleCuspPoint = Standard_True;
+        if (SumChange <= 0)
+          MakeWalkingPoint(1, UV(1), UV(2), sp, PointAfterPossibleCuspPoint);
         Step  = Step / 2.;
-        Standard_Real StepU = Abs(Step*previousd2d.X()),
-                      StepV = Abs(Step*previousd2d.Y());
+        StepU = Abs(Step*previousd2d.X());
+        StepV = Abs(Step*previousd2d.Y());
         if (StepU < tolerance(1) && StepV < tolerance(2))
           Status = IntWalk_ArretSurPointPrecedent;
         else 
           Status = IntWalk_PasTropGrand;
         return Status;
+      }
     }
+    //////////////////////////////////
   }
 
   if (!Finished) {
-    if (Status == IntWalk_PointConfondu)
-    {
-      Standard_Real StepU = Min(Abs(1.5 * Du),pas*(UM-Um)),
-                    StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
+
+    if (Status == IntWalk_PointConfondu) {
+      StepU = Min(Abs(1.5 * Du),pas*(UM-Um));
+      StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
 
       Standard_Real d2dx = Abs(previousd2d.X()); 
       Standard_Real d2dy = Abs(previousd2d.Y()); 
 
-      if (d2dx < tolerance(1))
-      {
-        Step = StepV/d2dy;
+      if (d2dx < tolerance(1)) {
+       Step = StepV/d2dy;
       }
-      else if (d2dy < tolerance(2))
-      {
-        Step = StepU/d2dx;
+      else if (d2dy < tolerance(2)) {
+       Step = StepU/d2dx;
       }
-      else
-      {
-        Step = Min(StepU/d2dx,StepV/d2dy);
+      else {
+       Step = Min(StepU/d2dx,StepV/d2dy);
       }
     }
-    else
-    {
-      //   estimate the current vector.
-      //   if vector/2<=current vector<= vector it is considered that the criterion
-      //   is observed.
-      //   otherwise adjust the step depending on the previous step 
+    else {
+//   estimate the current vector.
+//   if vector/2<=current vector<= vector it is considered that the criterion
+//   is observed.
+//   otherwise adjust the step depending on the previous step 
 
-      /*
-        Standard_Real Dist = Sqrt(Norme)/3.;
-        TColgp_Array1OfPnt Poles(1,4);
-        gp_Pnt POnCurv,Milieu;
-        Poles(1) = previousPoint.Value();
-        Poles(4) = sp.Point();
-        Poles(2) = Poles(1).XYZ() + 
-      StepSign * Dist* previousd3d.Normalized().XYZ();
-        Poles(3) = Poles(4).XYZ() - 
-      StepSign * Dist*sp.Direction3d().Normalized().XYZ();
-        BzCLib::PntPole(0.5,Poles,POnCurv);
-        Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
-      //      FlecheCourante = Milieu.Distance(POnCurv);
-        Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
-      */
+/*
+      Standard_Real Dist = Sqrt(Norme)/3.;
+      TColgp_Array1OfPnt Poles(1,4);
+      gp_Pnt POnCurv,Milieu;
+      Poles(1) = previousPoint.Value();
+      Poles(4) = sp.Point();
+      Poles(2) = Poles(1).XYZ() + 
+       StepSign * Dist* previousd3d.Normalized().XYZ();
+      Poles(3) = Poles(4).XYZ() - 
+       StepSign * Dist*sp.Direction3d().Normalized().XYZ();
+      BzCLib::PntPole(0.5,Poles,POnCurv);
+      Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
+//      FlecheCourante = Milieu.Distance(POnCurv);
+      Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
+*/
 
-        // Direct calculation : 
-        // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
-        // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
-        // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
-        // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
-        // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
-        // the norm (square) of 3.*lambda (d1 - d4)/8.
-        // either the norm of :
-        //    3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
-        // which produces, takin the square :
-        //         Norme * (d1-d4).SquareMagnitude()/64.
+      // Direct calculation : 
+      // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
+      // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
+      // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
+      // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
+      // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
+      // the norm (square) of 3.*lambda (d1 - d4)/8.
+      // either the norm of :
+      //    3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
+      // which produces, takin the square :
+      //         Norme * (d1-d4).SquareMagnitude()/64.
 
       Standard_Real FlecheCourante = 
        (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
 
   
 //      if (FlecheCourante <= 0.5*fleche) {
-      if (FlecheCourante <= 0.25*fleche*fleche)
-      {
-        Standard_Real d2dx = Abs(sp.Direction2d().X()); 
-        Standard_Real d2dy = Abs(sp.Direction2d().Y()); 
-        
-        Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
-                      StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
+      if (FlecheCourante <= 0.25*fleche*fleche) {
+
+       Standard_Real d2dx = Abs(sp.Direction2d().X()); 
+       Standard_Real d2dy = Abs(sp.Direction2d().Y()); 
 
-        if (d2dx < tolerance(1))
-        {
-          Step = StepV/d2dy;
-        }
-        else if (d2dy < tolerance(2))
-        {
-          Step = StepU/d2dx;
-        }
-        else
-        {
-          Step = Min(StepU/d2dx,StepV/d2dy);
-        }      
+       StepU = Min(Abs(1.5*Du),pas*(UM-Um));
+       StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
+
+       if (d2dx < tolerance(1)) {
+         Step = StepV/d2dy;
+       }
+       else if (d2dy < tolerance(2)) {
+         Step = StepU/d2dx;
+       }
+       else {
+         Step = Min(StepU/d2dx,StepV/d2dy);
+       }
+       
       }
-      else
-      {
-        //if (FlecheCourante > fleche) {  // step too great
-        if (FlecheCourante > fleche*fleche)
-        {  // step too great
-          Step = Step /2.;
-          Standard_Real StepU = Abs(Step*previousd2d.X()),
-                        StepV = Abs(Step*previousd2d.Y());
-          
+      else {
+//     if (FlecheCourante > fleche) {  // step too great
+       if (FlecheCourante > fleche*fleche) {  // step too great
+         Step = Step /2.;
+          StepU = Abs(Step*previousd2d.X());
+          StepV = Abs(Step*previousd2d.Y());
           if (StepU < tolerance(1) && StepV < tolerance(2)) 
             Status = IntWalk_ArretSurPointPrecedent;
           else 
             Status = IntWalk_PasTropGrand;
-        }
-        else
-        {
-          Standard_Real d2dx = Abs(sp.Direction2d().X()); 
-          Standard_Real d2dy = Abs(sp.Direction2d().Y()); 
-          
-          Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
-                        StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
+       }
+       else {
+         Standard_Real d2dx = Abs(sp.Direction2d().X()); 
+         Standard_Real d2dy = Abs(sp.Direction2d().Y()); 
+
+         StepU = Min(Abs(1.5*Du),pas*(UM-Um));
+         StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
 
-          if (d2dx < tolerance(1))
-          {
-            Step = Min(Step,StepV/d2dy);
-          }
-          else if (d2dy < tolerance(2))
-          {
-            Step = Min(Step,StepU/d2dx);
-          }
-          else
-          {
-            Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
-          }
-        }
+         if (d2dx < tolerance(1)) {
+           Step = Min(Step,StepV/d2dy);
+         }
+         else if (d2dy < tolerance(2)) {
+           Step = Min(Step,StepU/d2dx);
+         }
+         else {
+           Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
+         }
+       }
       }
     }
   }
index cbf903ac24f8af57c7e96ef7f9a7cc590fb413b6..f9e8d94aef0446f7569a452303212e822ae88039 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <Geom2d_Line.hxx>
+#include <GCE2d_MakeLine.hxx>
+
+
 #ifndef DEB
 #define No_Standard_RangeError
 #define No_Standard_OutOfRange
@@ -39,7 +43,6 @@ void IntWalk_IWalking::MakeWalkingPoint
          IntSurf_PntOn2S& Psol )
 
 {
-
 // Case == 1      : make a WalkinkPoint.
 // Case == 2      : make a WalkinkPoint.
 //                  The computation of the tangency on is done  
@@ -60,16 +63,211 @@ void IntWalk_IWalking::MakeWalkingPoint
     UV(1) = U;
     UV(2) = V;
     sp.Values(UV, FF, DD);
-    MakeWalkingPoint(Case - 10, U, V, sp, Psol); 
+    MakeWalkingPoint(Case - 10, U, V, sp, Psol);
   }
   else {
     Standard_ConstructionError::Raise();
   }
+}
+
+Standard_Boolean
+ IntWalk_IWalking::ComputeDirOfTangentialIntersection(TheIWFunction& sp,
+                                                      Standard_Integer& StepSignTangent)
+{
+  gp_Vec Pu, Pv, Puu, Puv, Pvv;
+  gp_Vec Iu, Iv, Iuu, Iuv, Ivv;
+  gp_Vec NormalP, NormalI;
+
+  if (!sp.DerivativesAndNormalOnPSurf(Pu, Pv, NormalP, Puu, Pvv, Puv))
+    return Standard_False;
+  if (!sp.DerivativesAndNormalOnISurf(Iu, Iv, NormalI, Iuu, Ivv, Iuv))
+    return Standard_False;
+
+  Standard_Real Lp, Mp, Np, Li, Mi, Ni; //second fundamental form coefficients
+  Lp = Puu * NormalP;
+  Mp = Puv * NormalP;
+  Np = Pvv * NormalP;
+  Li = Iuu * NormalI;
+  Mi = Iuv * NormalI;
+  Ni = Ivv * NormalI;
+
+  gp_Vec Normal;
+  if (NormalP * NormalI < 0.)
+    NormalI.Reverse();
+  Normal.SetXYZ(0.5*(NormalP.XYZ() + NormalI.XYZ()));
+  Normal.Normalize();
+
+  Standard_Real A11, A12, A21, A22;
+  Standard_Real NormIdotNorm = (Iu ^ Iv) * Normal;
+  A11 = ((Pu ^ Iv) * Normal) / NormIdotNorm;
+  A12 = ((Pv ^ Iv) * Normal) / NormIdotNorm;
+  A21 = ((Iu ^ Pu) * Normal) / NormIdotNorm;
+  A22 = ((Iu ^ Pv) * Normal) / NormIdotNorm;
 
+  Standard_Real B11, B12, B22;
+  B11 = A11*A11*Li + 2*A11*A21*Mi + A21*A21*Ni - Lp;
+  B12 = A11*A12*Li + (A11*A22 + A21*A12)*Mi + A21*A22*Ni - Mp;
+  B22 = A12*A12*Li + 2*A12*A22*Mi + A22*A22*Ni - Np;
 
+  Standard_Real Discriminant = B12*B12 - B11*B22;
+#ifdef DRAW
+  cout<<"Discriminant = "<<Discriminant<<endl<<endl;
+#endif
+
+  const Standard_Real TolDiscr = 1.e-8;
+  const Standard_Real TolB = 1.e-5;
+  if (Abs(Discriminant) < TolDiscr)
+  {
+    if (Abs(B11) <= TolB && Abs(B22) <= TolB)
+    {
+#ifdef DRAW
+      cout<<"Possible branching"<<endl<<endl;
+#endif
+    }
+    else
+    {
+      gp_Vec NewPreviousD3d;
+      gp_Dir2d NewPreviousD2d;
+      if (Abs(B11) > TolB)
+      {
+        Standard_Real CoefPu = -B12/B11;
+        NewPreviousD3d = CoefPu*Pu + Pv;
+        NewPreviousD3d.Normalize();
+        NewPreviousD2d = gp_Dir2d(CoefPu, 1.);
+      }
+      else
+      {
+        Standard_Real CoefPv = -B12/B22;
+        NewPreviousD3d = Pu + CoefPv*Pv;
+        NewPreviousD3d.Normalize();
+        NewPreviousD2d = gp_Dir2d(1., CoefPv);
+      }
+      
+      if (!IsTangentialIntersection)
+      {
+        IsTangentialIntersection = Standard_True;
+        if (NewPreviousD3d * previousd3d < 0)
+          StepSignTangent = -1;
+        else
+          StepSignTangent = 1;
+      }
+      previousd3d = StepSignTangent * NewPreviousD3d;
+      previousd2d = StepSignTangent * NewPreviousD2d;
+    }
+  }
+  
+  return Standard_True;
 }
 
+void IntWalk_IWalking::FindExactTangentPoint(const Standard_Real TolTang,
+                                             TheIWFunction& sp,
+                                             IntSurf_PntOn2S& Psol)
+                                             
+{
+  IntSurf_PntOn2S TangentPoint = Psol;
+
+  IntSurf_PntOn2S Pfirst, Plast;
+
+  Standard_Real newU, newV;
+  IntSurf_PntOn2S newPoint;
+
+  Standard_Real MinOffset = Sqrt(tolerance(1)*tolerance(1) + tolerance(2)*tolerance(2));
+
+  gp_Pnt2d prevP2d = previousPoint.ValueOnSurface(reversed);
+  gp_Pnt2d TangP2d = TangentPoint.ValueOnSurface(reversed);
+  gp_Pnt2d EndP2d = PointAfterPossibleCuspPoint.ValueOnSurface(reversed);
+  Handle(Geom2d_Line) Line1 = GCE2d_MakeLine(TangP2d, prevP2d);
+  Handle(Geom2d_Line) Line2 = GCE2d_MakeLine(TangP2d, EndP2d);
 
+  Standard_Real Dist1 = prevP2d.Distance(TangP2d);
+  Standard_Real Dist2 = TangP2d.Distance(EndP2d);
+  Standard_Real Dist = (Dist1 < Dist2)? Dist1 : Dist2;
+  Standard_Real Offset = 0.01*Dist;
+  if (Offset < MinOffset)
+    Offset = MinOffset;
+
+  Standard_Real TangentError = sp.SquareTangentError();
+
+  gp_Pnt2d DeltaUV1 = Line1->Value(Offset);
+  gp_Pnt2d DeltaUV2 = Line2->Value(Offset);
+  IntSurf_PntOn2S DeltaPnt1, DeltaPnt2;
+
+  MakeWalkingPoint(11, DeltaUV1.X(), DeltaUV1.Y(), sp, DeltaPnt1);
+  Standard_Boolean IsTangentPoint = sp.IsTangent();
+  Standard_Real DeltaError1 = sp.SquareTangentError();
+  MakeWalkingPoint(11, DeltaUV2.X(), DeltaUV2.Y(), sp, DeltaPnt2);
+  IsTangentPoint = sp.IsTangent();
+  Standard_Real DeltaError2 = sp.SquareTangentError();
+
+  if (DeltaError1 <= TangentError && TangentError <= DeltaError2)
+  {
+    Pfirst = previousPoint;
+    Plast  = TangentPoint;
+    Dist = Dist1;
+  }
+  else if (DeltaError1 >= TangentError && TangentError >= DeltaError2)
+  {
+    Pfirst = TangentPoint;
+    Plast  = PointAfterPossibleCuspPoint;
+    Dist = Dist2;
+  }
+  else
+  {
+    Pfirst = DeltaPnt1;
+    Plast  = DeltaPnt2;
+    Dist = DeltaUV1.Distance(DeltaUV2);
+  }
+
+  Standard_Real newError;
+  for (;;)
+  {
+    Standard_Real Ufirst, Vfirst, Ulast, Vlast;
+    Pfirst.ParametersOnSurface(reversed, Ufirst, Vfirst);
+    Plast.ParametersOnSurface(reversed, Ulast, Vlast);
+    
+    newU = 0.5*(Ufirst + Ulast);
+    newV = 0.5*(Vfirst + Vlast);
+
+    if (Abs(newU - Ufirst) < tolerance(1) &&
+        Abs(newV - Vfirst) < tolerance(2))
+      break;
+    
+    MakeWalkingPoint(11, newU, newV, sp, newPoint);
+    
+    IsTangentPoint = sp.IsTangent();
+    newError = sp.SquareTangentError();
+    if (newError <= TolTang)
+      break;
+
+    gp_Pnt2d newP2d(newU, newV);
+    Handle(Geom2d_Line) newLine = GCE2d_MakeLine(newP2d, Plast.ValueOnSurface(reversed));
+    Dist *= 0.5;
+    Offset = 0.01*Dist;
+
+    DeltaUV1 = newLine->Value(-Offset);
+    DeltaUV2 = newLine->Value(Offset);
+
+    MakeWalkingPoint(11, DeltaUV1.X(), DeltaUV1.Y(), sp, DeltaPnt1);
+    IsTangentPoint = sp.IsTangent();
+    DeltaError1 = sp.SquareTangentError();
+    MakeWalkingPoint(11, DeltaUV2.X(), DeltaUV2.Y(), sp, DeltaPnt2);
+    IsTangentPoint = sp.IsTangent();
+    DeltaError2 = sp.SquareTangentError();
+
+    if (DeltaError1 <= newError && newError <= DeltaError2)
+      Plast = newPoint;
+    else if (DeltaError1 >= newError && newError >= DeltaError2)
+      Pfirst = newPoint;
+    else
+    {
+      Pfirst = DeltaPnt1;
+      Plast  = DeltaPnt2;
+      Dist = DeltaUV1.Distance(DeltaUV2);
+    }
+  }
+
+  Psol = newPoint;
+}
 
 void IntWalk_IWalking::OpenLine(const Standard_Integer N,
                                 const IntSurf_PntOn2S& Psol,
@@ -94,8 +292,20 @@ void IntWalk_IWalking::OpenLine(const Standard_Integer N,
     previousPoint.ParametersOnS1(UV(1),UV(2));
   }
   sp.Values(UV, FF, DD);
-  previousd3d = sp.Direction3d();
-  previousd2d = sp.Direction2d();
+  if (sp.IsTangent())
+  {
+    Standard_Integer theSign = 1;
+    ComputeDirOfTangentialIntersection(sp, theSign);
+  }
+  else
+  {
+    previousd3d = sp.Direction3d();
+    previousd2d = sp.Direction2d();
+    previousProj1 = sp.Projection1();
+    previousProj2 = sp.Projection2();
+    previousProj3 = sp.Projection3();
+    previousProj4 = sp.Projection4();
+  }
 
   if (N>0) { //departure point given at input
     PathPnt = Pnts1.Value(N);