0024585: Wrong pcurve of the section curve
authornbv <nbv@opencascade.com>
Wed, 12 Feb 2014 10:21:54 +0000 (14:21 +0400)
committerapn <apn@opencascade.com>
Thu, 13 Feb 2014 10:04:42 +0000 (14:04 +0400)
PCurve is extended to surface boundary forcefully.
It is made by finding some additional points (if it is possibly).
"bopcurves" DRAW-command returns number of found 3D-curves and (as an option) 2D-curve (see help for more detail information).

Test cases for issue CR24585

src/BOPTest/BOPTest_BOPCommands.cxx
src/IntPatch/IntPatch_PrmPrmIntersection.cxx
src/IntPatch/IntPatch_RstInt.cdl
src/IntPatch/IntPatch_RstInt.cxx
src/IntPatch/IntPatch_WLine.cdl
src/IntPatch/IntPatch_WLine.cxx
src/IntWalk/IntWalk_PWalking.cdl
src/IntWalk/IntWalk_PWalking_1.gxx
tests/bugs/modalg_5/bug24472
tests/bugs/modalg_5/bug24585_1 [new file with mode: 0644]
tests/bugs/modalg_5/bug24585_2 [new file with mode: 0644]

index f4944b9..bcd8aa1 100644 (file)
@@ -103,7 +103,7 @@ static Standard_Integer bopnews   (Draw_Interpretor&, Standard_Integer, const ch
   theCommands.Add("bsection", "Use >bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]", 
                                                       __FILE__, bsection, g);
   //
-  theCommands.Add("bopcurves", "use  bopcurves F1 F2", __FILE__, bopcurves, g);
+  theCommands.Add("bopcurves", "use  bopcurves F1 F2 [-2d]", __FILE__, bopcurves, g);
   theCommands.Add("bopnews", "use  bopnews -v[e,f]"  , __FILE__, bopnews, g);
 }
 
@@ -541,7 +541,7 @@ Standard_Integer bopcurves (Draw_Interpretor& di,
                             const char** a)
 {
   if (n<3) {
-    di << " use bopcurves F1 F2\n";
+    di << " use bopcurves F1 F2 [-2d]\n";
     return 1;
   }
 
@@ -569,14 +569,25 @@ Standard_Integer bopcurves (Draw_Interpretor& di,
   const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
   const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
 
-  Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone;
+  Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone, bMake2dCurves;
   Standard_Integer i, aNbCurves;
   Standard_Real anAppTol, aTolR;
   TCollection_AsciiString aNm("c_");
 
-  aToApproxC3d=Standard_True;
-  aToApproxC2dOnS1=Standard_False;
-  aToApproxC2dOnS2=Standard_False;
+  bMake2dCurves = Standard_False;
+  if (n > 3) {
+    if (!strcasecmp(a[3],"-2d")) {
+      bMake2dCurves = Standard_True;
+    } else {
+      di << "Wrong key. To build 2d curves use: bopcurves F1 F2 -2d \n";
+      return 1;
+    }
+  }
+  //
+
+  aToApproxC3d = Standard_True;
+  aToApproxC2dOnS1 = bMake2dCurves;
+  aToApproxC2dOnS2 = bMake2dCurves;
   anAppTol=0.0000001;
 
 
@@ -595,7 +606,7 @@ Standard_Integer bopcurves (Draw_Interpretor& di,
     return 1;
   }
 
-  aFF.PrepareLines3D();
+  aFF.PrepareLines3D(Standard_False);
   const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
 
   //
@@ -607,22 +618,68 @@ Standard_Integer bopcurves (Draw_Interpretor& di,
     di << " has no 3d curve\n";
     return 1;
   }
+  else
+  {
+    di << aNbCurves << " curve(s) found.\n";
+  }
 
   for (i=1; i<=aNbCurves; i++) {
     const IntTools_Curve& anIC=aSCs(i);
 
-    Handle (Geom_Curve) aC3D=anIC.Curve();
+    Handle (Geom_Curve)  aC3D = anIC.Curve();
 
     if (aC3D.IsNull()) {
-      di << " has Null 3d curve# " << i << "%d\n";
+      di << " has Null 3d curve# " << i << "\n";
       continue;
     }
 
     TCollection_AsciiString anIndx(i), aNmx;
-    aNmx=aNm+anIndx;
-    Standard_CString name= aNmx.ToCString();
-    DrawTrSurf::Set(name, aC3D);
-    di << name << " ";
+    aNmx = aNm + anIndx;
+
+    Standard_CString nameC = aNmx.ToCString();
+
+    DrawTrSurf::Set(nameC, aC3D);
+    di << nameC << " ";
+    //
+    if (bMake2dCurves) {
+      Handle(Geom2d_Curve) aPC1 = anIC.FirstCurve2d();
+      Handle(Geom2d_Curve) aPC2 = anIC.SecondCurve2d();
+      //
+      if (aPC1.IsNull() && aPC2.IsNull()) {
+        di << " \n has Null 2d curves# " << i << "\n";
+        continue;
+      }
+      //
+      if (aPC1.IsNull()) {
+        TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
+        pc2Nx = pc2N + anIndx;
+        Standard_CString nameC2d2 = pc2Nx.ToCString();
+        //
+        DrawTrSurf::Set(nameC2d2, aPC2);
+        di << "(" << nameC2d2 << ") ";
+        di << " \n Null first 2d curve of the curve #" << i << "\n";
+        continue;
+      } else {
+        TCollection_AsciiString pc1N("c2d1_"), pc1Nx;
+        pc1Nx = pc1N + anIndx;
+        Standard_CString nameC2d1 = pc1Nx.ToCString();
+        //
+        DrawTrSurf::Set(nameC2d1, aPC1);
+        di << "(" << nameC2d1;
+      }
+      //
+      if (aPC2.IsNull()) {
+        di << ") \n Null second 2d curve of the curve #" << i << "\n";
+        continue;
+      } else {
+        TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
+        pc2Nx = pc2N + anIndx;
+        Standard_CString nameC2d2 = pc2Nx.ToCString();
+        //
+        DrawTrSurf::Set(nameC2d2, aPC2);
+        di << ", " << nameC2d2 << ") ";
+      }
+    }
   }
 
   di << "\n";
index b581ba6..82fda55 100644 (file)
@@ -1371,7 +1371,11 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)&
       if(dminiPointLigne > SeuildPointLigne) {
         PW.Perform(StartParams,UminLig1,VminLig1,UminLig2,VminLig2,UmaxLig1,VmaxLig1,UmaxLig2,VmaxLig2);
         if(PW.IsDone())        {
-          if(PW.NbPoints()>2) {
+          if(PW.NbPoints()>2)
+          {
+            //Try to extend the intersection line to boundary, if it is possibly
+            Standard_Boolean hasBeenAdded = PW.PutToBoundary(Surf1, Surf2);
+
             RejetLigne = Standard_False;
             Point3dDebut = PW.Value(1).Value();
             const IntSurf_PntOn2S& PointFin = PW.Value(PW.NbPoints());
@@ -1419,8 +1423,8 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)&
               Standard_Real TolTang = TolTangency;
               Handle(IntPatch_WLine) wline = new IntPatch_WLine(PW.Line(),Standard_False,trans1,trans2);
               if (RestrictLine){
-                IntPatch_RstInt::PutVertexOnLine(wline,Surf1,D1,Surf2,Standard_True,TolTang);
-                IntPatch_RstInt::PutVertexOnLine(wline,Surf2,D2,Surf1,Standard_False,TolTang);
+                IntPatch_RstInt::PutVertexOnLine(wline,Surf1,D1,Surf2,Standard_True,TolTang,hasBeenAdded);
+                IntPatch_RstInt::PutVertexOnLine(wline,Surf2,D2,Surf1,Standard_False,TolTang,hasBeenAdded);
               }
 
               if(wline->NbVertex() == 0) {
@@ -2125,10 +2129,14 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
                   //
                   if( iPWNbPoints > 2 )
                   {
+                    //Try to extend the intersection line to boundary, if it is possibly
+                    Standard_Boolean hasBeenAdded = PW.PutToBoundary(Surf1, Surf2);
+
                     const Standard_Integer aMinNbPoints = 40;
                     if(iPWNbPoints < aMinNbPoints)
                     {
-                      PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints);
+                      hasBeenAdded = 
+                        PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints) || hasBeenAdded;
                       iPWNbPoints = PW.NbPoints();
                     }
                     
@@ -2224,8 +2232,8 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
 
                       Standard_Real TolTang = TolTangency;
                       Handle(IntPatch_WLine) wline = new IntPatch_WLine(PW.Line(),Standard_False,trans1,trans2);
-                      IntPatch_RstInt::PutVertexOnLine(wline,Surf1,D1,Surf2,Standard_True,TolTang);
-                      IntPatch_RstInt::PutVertexOnLine(wline,Surf2,D2,Surf1,Standard_False,TolTang);
+                      IntPatch_RstInt::PutVertexOnLine(wline,Surf1,D1,Surf2,Standard_True,TolTang,hasBeenAdded);
+                      IntPatch_RstInt::PutVertexOnLine(wline,Surf2,D2,Surf1,Standard_False,TolTang,hasBeenAdded);
 
                       if(wline->NbVertex() == 0)
                       {
index 29e0ad0..5746f76 100644 (file)
@@ -34,7 +34,8 @@ is
                     Domain    : TopolTool from Adaptor3d; 
                     OtherSurf : HSurface from Adaptor3d; 
                     OnFirst   : Boolean from Standard ;
-                    Tol       : Real from Standard)
+                    Tol       : Real from Standard;
+                    hasBeenAdded: Boolean from Standard = Standard_False)
 
        raises DomainError from Standard;
        --- The exception is raised if the Line from is neither
index 8a5ca2c..f6a7710 100644 (file)
@@ -445,7 +445,8 @@ void IntPatch_RstInt::PutVertexOnLine (Handle(IntPatch_Line)& L,
                                       const Handle(Adaptor3d_TopolTool)& Domain,
                                       const Handle(Adaptor3d_HSurface)& OtherSurf,
                                       const Standard_Boolean OnFirst,
-                                      const Standard_Real Tol )
+                                      const Standard_Real Tol,
+               const Standard_Boolean hasBeenAdded)
  {
 
 // Domain est le domaine de restriction de la surface Surf.
@@ -1229,7 +1230,7 @@ void IntPatch_RstInt::PutVertexOnLine (Handle(IntPatch_Line)& L,
 */
 
     wlin->SetPeriod(pu1,pv1,pu2,pv2);
-    wlin->ComputeVertexParameters(Tol);
+    wlin->ComputeVertexParameters(Tol, hasBeenAdded);
   }
   else {
 #ifdef DEB
index d22d273..c3624cc 100644 (file)
@@ -236,7 +236,9 @@ is
        is static;
 
 
-    ComputeVertexParameters(me: mutable; Tol: Real from Standard)
+    ComputeVertexParameters(me: mutable;
+                            Tol: Real from Standard;
+                            hasBeenAdded: Boolean from Standard = Standard_False)
     
        ---Purpose: Set the parameters of all the vertex on the line.
        --          if a vertex is already in the line, 
index 14cdfbb..635f86c 100644 (file)
@@ -238,8 +238,9 @@ inline Standard_Boolean CompareVerticesOnS2(const IntPatch_Point& vtx1, const In
 {return CompareVerticesOnSurf (vtx1, vtx2, Standard_False);}
 
 
-void IntPatch_WLine::ComputeVertexParameters(const Standard_Real RTol) { 
-
+void IntPatch_WLine::ComputeVertexParameters( const Standard_Real RTol,
+                                              const Standard_Boolean hasBeenAdded)
+{
   // MSV Oct 15, 2001: use tolerance of vertex instead of RTol where 
   //                   it is possible
 
@@ -463,9 +464,9 @@ void IntPatch_WLine::ComputeVertexParameters(const Standard_Real RTol) {
   Standard_Real dmini = Precision::Confusion();
   dmini*=dmini;
   for(i=2; i<=nbponline; i++) { 
-    //const IntSurf_PntOn2S& aPntOn2S1=curv->Value(i-1);
-    //const IntSurf_PntOn2S& aPntOn2S2=curv->Value(i);
-    Standard_Real d = (curv->Value(i-1).Value()).SquareDistance((curv->Value(i).Value()));
+    const IntSurf_PntOn2S& aPnt1=curv->Value(i-1);
+    const IntSurf_PntOn2S& aPnt2=curv->Value(i);
+    Standard_Real d = (aPnt1.Value()).SquareDistance((aPnt2.Value()));
     if(d < dmini) { 
       curv->RemovePoint(i);
       nbponline--;
@@ -473,10 +474,10 @@ void IntPatch_WLine::ComputeVertexParameters(const Standard_Real RTol) {
       //-- On recadre les Vertex si besoin 
       //-- 
       for(j=1; j<=nbvtx; j++) { 
-       indicevertex = svtx.Value(j).ParameterOnLine();
-       if(indicevertex >= i) {
-         svtx.ChangeValue(j).SetParameter(indicevertex-1.0);
-       }
+        indicevertex = svtx.Value(j).ParameterOnLine();
+        if(indicevertex >= i) {
+          svtx.ChangeValue(j).SetParameter(indicevertex-1.0);
+        }
       }
       //modified by NIZNHY-PKV Mon Feb 11 09:28:02 2002 f
       i--;
@@ -487,7 +488,30 @@ void IntPatch_WLine::ComputeVertexParameters(const Standard_Real RTol) {
   for(i=1; i<=nbvtx; i++) {
     const gp_Pnt& P    = svtx.Value(i).Value();
     Standard_Real vTol = svtx.Value(i).Tolerance();
-    indicevertex = svtx.Value(i).ParameterOnLine();
+    
+    if(hasBeenAdded)
+    {
+      if(nbvtx == 2)
+      {
+        if(i == nbvtx)
+        {
+          indicevertex = curv->NbPoints();
+        }
+        else
+        {
+          indicevertex = svtx.Value(i).ParameterOnLine();
+        }
+      }
+      else
+      {
+        indicevertex = svtx.Value(i).ParameterOnLine();
+      }
+    }
+    else
+    {
+      indicevertex = svtx.Value(i).ParameterOnLine();
+    }
+    
     indicevertexonline = (Standard_Integer)indicevertex;
     //--------------------------------------------------
     //-- On Compare le vertex avec les points de la ligne
index 5c49296..61c59a0 100644 (file)
@@ -265,6 +265,8 @@ theDirectionFlag: Boolean from Standard)
                               theStep0U2V2: Real from Standard = 1.0e-6)
     returns Boolean from Standard
     is private;
+    -- Finds one intersection point of two given surfaces with given 
+    --  initial point.
   
   DistanceMinimizeByExtrema(me          : in out;
                             theASurf1   : ThePSurface ;
@@ -274,11 +276,36 @@ theDirectionFlag: Boolean from Standard)
                             theStep0V: Real from Standard = 1.0)
     returns Boolean from Standard
     is private;
+    -- Finds one intersection point of two given surfaces with given 
+    --  initial point.
   
+  SeekPointOnBoundary(me    : in out;
+                      theASurf1 , theASurf2  : ThePSurface ;
+                      theU1, theV1, theU2, theV2: Real from Standard;
+                      isTheFirst : Boolean from Standard)
+    returns Boolean from Standard
+    is private;
+    -- Unites and correctly coordinates of work of
+    -- "DistanceMinimizeByGradient" and "DistanceMinimizeByExtrema" functions.
+  
+  
+  PutToBoundary( me    : in out;
+                 theASurf1 , theASurf2  : ThePSurface)
+    -- Tries to extend existing intersection line 
+    --  (as set of points) to surface's boundaries,
+    --  if it is possibly.
+    --  If line is scienter far from boundaries
+    --  or is (almost) parralel with some boundary,
+    --  extending is not required.
+    returns Boolean from Standard;
+
+
   SeekAdditionalPoints( me    : in out;
                         theASurf1 , theASurf2  : ThePSurface;
                         theMinNbPoints : Integer from Standard)
     returns Boolean from Standard;
+    -- Unites and correctly coordinates of work of
+    -- "DistanceMinimizeByGradient" and "DistanceMinimizeByExtrema" functions.
 
 fields
 
index 0955a25..85e6222 100644 (file)
@@ -65,6 +65,167 @@ void ComputePasInit(Standard_Real *pasuv,
   pasuv[2]=Increment*du2;
   pasuv[3]=Increment*dv2;
 }
+
+//=======================================================================
+//function : IsParallel
+//purpose  : Checks if theLine is parallel of some boundary of given
+//            surface (it is determined by theCheckSurf1 flag). 
+//            Parallelism assumes small oscillations (swing is less or 
+//            equal than theToler).
+//            Small lines (if first and last parameters in the Surface 
+//            are almost equal) are classified as parallel (as same as 
+//            any point can be considered as parallel of any line).
+//=======================================================================
+static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
+                  const Standard_Boolean theCheckSurf1,
+                  const Standard_Real theToler,
+                  Standard_Boolean& theIsUparallel,
+                  Standard_Boolean& theIsVparallel)
+{
+  const Standard_Integer aNbPointsMAX = 23;
+
+  theIsUparallel = theIsVparallel = Standard_True;
+
+  Standard_Integer aNbPoints = theLine->NbPoints();
+  if(aNbPoints > aNbPointsMAX)
+  {
+    aNbPoints = aNbPointsMAX;
+  }
+  else if(aNbPoints < 3)
+  {
+    //Here we cannot estimate parallelism.
+    //Do all same as for small lines 
+    return;
+  }
+
+  Standard_Real aStep = IntToReal(theLine->NbPoints()) / aNbPoints;
+  Standard_Real aNPoint = 1.0;
+
+  Standard_Real aUmin = RealLast(), aUmax = RealFirst(), aVmin = RealLast(), aVmax = RealFirst();
+  for(Standard_Integer aNum = 1; aNum <= aNbPoints; aNum++, aNPoint += aStep)
+  {
+    if(aNPoint > aNbPoints)
+    {
+      aNPoint = aNbPoints;
+    }
+
+    Standard_Real u, v;
+    if(theCheckSurf1)
+      theLine->Value(RealToInt(aNPoint)).ParametersOnS1(u, v);
+    else
+      theLine->Value(RealToInt(aNPoint)).ParametersOnS2(u, v);
+
+    if(u < aUmin)
+      aUmin = u;
+
+    if(u > aUmax)
+      aUmax = u;
+
+    if(v < aVmin)
+      aVmin = v;
+
+    if(v > aVmax)
+      aVmax = v;
+  }
+
+  theIsVparallel = ((aUmax - aUmin) < theToler);
+  theIsUparallel = ((aVmax - aVmin) < theToler);
+}
+
+//=======================================================================
+//function : Checking
+//purpose  : Check, if given point is in surface's boundaries.
+//            If "yes" then theFactTol = 0.0, else theFactTol is
+//            equal maximal deviation.
+//=======================================================================
+static Standard_Boolean Checking( const Handle(Adaptor3d_HSurface)& theASurf1,
+                                  const Handle(Adaptor3d_HSurface)& theASurf2,
+                                  Standard_Real& theU1,
+                                  Standard_Real& theV1,
+                                  Standard_Real& theU2,
+                                  Standard_Real& theV2,
+                                  Standard_Real& theFactTol)
+{
+  const Standard_Real aTol = Precision::PConfusion();
+  const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
+  const Standard_Real aU1bLast = theASurf1->LastUParameter();
+  const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
+  const Standard_Real aU2bLast = theASurf2->LastUParameter();
+  const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
+  const Standard_Real aV1bLast = theASurf1->LastVParameter();
+  const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
+  const Standard_Real aV2bLast = theASurf2->LastVParameter();
+
+  Standard_Boolean isOnOrIn = Standard_True;
+  theFactTol = 0.0;
+
+  Standard_Real aDelta = aU1bFirst - theU1;
+  if(aDelta > aTol)
+  {
+    theU1 = aU1bFirst;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+  
+  aDelta = theU1 - aU1bLast;
+  if(aDelta > aTol)
+  {
+    theU1 = aU1bLast;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+
+  aDelta = aV1bFirst - theV1;
+  if(aDelta > aTol)
+  {
+    theV1 = aV1bFirst;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+  
+  aDelta = theV1 - aV1bLast;
+  if(aDelta > aTol)
+  {
+    theV1 = aV1bLast;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+
+  aDelta = aU2bFirst - theU2;
+  if(aDelta > aTol)
+  {
+    theU2 = aU2bFirst;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+  
+  aDelta = theU2 - aU2bLast;
+  if(aDelta > aTol)
+  {
+    theU2 = aU2bLast;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+
+  aDelta = aV2bFirst - theV2;
+  if(aDelta > aTol)
+  {
+    theV2 = aV2bFirst;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+  
+  aDelta = theV2 - aV2bLast;
+  if(aDelta > aTol)
+  {
+    theV2 = aV2bLast;
+    theFactTol = Max(theFactTol, aDelta);
+    isOnOrIn = Standard_False;
+  }
+
+  return isOnOrIn;
+}
+
 //==================================================================================
 // function : IntWalk_PWalking::IntWalk_PWalking
 // purpose  : 
@@ -1636,14 +1797,19 @@ Standard_Boolean IntWalk_PWalking::ExtendLineInCommonZone(const IntImp_ConstIsop
   return bOutOfTangentZone;
 }
 
-Standard_Boolean IntWalk_PWalking::DistanceMinimizeByGradient(const Handle(Adaptor3d_HSurface)& theASurf1,
-                                                              const Handle(Adaptor3d_HSurface)& theASurf2,
-                                                              Standard_Real& theU1,
-                                                              Standard_Real& theV1,
-                                                              Standard_Real& theU2,
-                                                              Standard_Real& theV2,
-                                                              const Standard_Real theStep0U1V1,
-                                                              const Standard_Real theStep0U2V2)
+//=======================================================================
+//function : DistanceMinimizeByGradient
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntWalk_PWalking::
+  DistanceMinimizeByGradient( const Handle(Adaptor3d_HSurface)& theASurf1,
+                              const Handle(Adaptor3d_HSurface)& theASurf2,
+                              Standard_Real& theU1,
+                              Standard_Real& theV1,
+                              Standard_Real& theU2,
+                              Standard_Real& theV2,
+                              const Standard_Real theStep0U1V1,
+                              const Standard_Real theStep0U2V2)
 {
   const Standard_Integer aNbIterMAX = 60;
   const Standard_Real aTol = 1.0e-14;
@@ -1698,13 +1864,21 @@ Standard_Boolean IntWalk_PWalking::DistanceMinimizeByGradient(const Handle(Adapt
   while(flRepeat)
   {
     Standard_Real anAdd = aGradFu*aSTEPuv;
-    Standard_Real aPARu = (anAdd >= 0.0)? (theU1 - Max(anAdd, Epsilon(theU1))) : (theU1 + Max(-anAdd, Epsilon(theU1)));
+    Standard_Real aPARu = (anAdd >= 0.0)?
+            (theU1 - Max(anAdd, Epsilon(theU1))) :
+            (theU1 + Max(-anAdd, Epsilon(theU1)));
     anAdd = aGradFv*aSTEPuv;
-    Standard_Real aPARv = (anAdd >= 0.0)? (theV1 - Max(anAdd, Epsilon(theV1))) : (theV1 + Max(-anAdd, Epsilon(theV1)));
+    Standard_Real aPARv = (anAdd >= 0.0)?
+            (theV1 - Max(anAdd, Epsilon(theV1))) :
+            (theV1 + Max(-anAdd, Epsilon(theV1)));
     anAdd = aGradFU*aStepUV;
-    Standard_Real aParU = (anAdd >= 0.0)? (theU2 - Max(anAdd, Epsilon(theU2))) : (theU2 + Max(-anAdd, Epsilon(theU2)));
+    Standard_Real aParU = (anAdd >= 0.0)?
+            (theU2 - Max(anAdd, Epsilon(theU2))) :
+            (theU2 + Max(-anAdd, Epsilon(theU2)));
     anAdd = aGradFV*aStepUV;
-    Standard_Real aParV = (anAdd >= 0.0)? (theV2 - Max(anAdd, Epsilon(theV2))) : (theV2 + Max(-anAdd, Epsilon(theV2)));
+    Standard_Real aParV = (anAdd >= 0.0)?
+            (theV2 - Max(anAdd, Epsilon(theV2))) :
+            (theV2 + Max(-anAdd, Epsilon(theV2)));
 
     gp_Pnt aPt1, aPt2;
 
@@ -1750,12 +1924,17 @@ Standard_Boolean IntWalk_PWalking::DistanceMinimizeByGradient(const Handle(Adapt
   return aStatus;
 }
 
-Standard_Boolean IntWalk_PWalking::DistanceMinimizeByExtrema( const Handle(Adaptor3d_HSurface)& theASurf, 
-                                                              const gp_Pnt& theP0,
-                                                              Standard_Real& theU0,
-                                                              Standard_Real& theV0,
-                                                              const Standard_Real theStep0U,
-                                                              const Standard_Real theStep0V)
+//=======================================================================
+//function : DistanceMinimizeByExtrema
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntWalk_PWalking::
+  DistanceMinimizeByExtrema(const Handle(Adaptor3d_HSurface)& theASurf, 
+                            const gp_Pnt& theP0,
+                            Standard_Real& theU0,
+                            Standard_Real& theV0,
+                            const Standard_Real theStep0U,
+                            const Standard_Real theStep0V)
 {
   const Standard_Real aTol = 1.0e-14;
   gp_Pnt aPS;
@@ -1801,9 +1980,318 @@ Standard_Boolean IntWalk_PWalking::DistanceMinimizeByExtrema( const Handle(Adapt
   return (aSQDistPrev < aTol);
 }
 
-Standard_Boolean IntWalk_PWalking::SeekAdditionalPoints(const Handle(Adaptor3d_HSurface)& theASurf1,
-                                                        const Handle(Adaptor3d_HSurface)& theASurf2,
-                                                        const Standard_Integer theMinNbPoints)
+//=======================================================================
+//function : SeekPointOnBoundary
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntWalk_PWalking::
+  SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
+                      const Handle(Adaptor3d_HSurface)& theASurf2,
+                      const Standard_Real theU1,
+                      const Standard_Real theV1,
+                      const Standard_Real theU2,
+                      const Standard_Real theV2,
+                      const Standard_Boolean isTheFirst)
+{
+  const Standard_Real aTol = 1.0e-14;
+  Standard_Boolean isOK = Standard_False;
+  Standard_Real U1prec = theU1, V1prec = theV1, U2prec = theU2, V2prec = theV2;
+
+  Standard_Boolean flFinish = Standard_False;
+
+  Standard_Integer aNbIter = 20;
+  while(!flFinish)
+  {
+    flFinish = Standard_False;
+    Standard_Boolean aStatus = Standard_False;
+
+    do
+    {
+      aNbIter--;
+      aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
+      if(aStatus)
+      {
+        break;
+      }
+
+      aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
+      if(aStatus)
+      {
+        break;
+      }
+
+      aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
+      if(aStatus)
+      {
+        break;
+      }
+    }
+    while(!aStatus && (aNbIter > 0));
+
+    if(aStatus)
+    {
+      const Standard_Real aTolMax = 1.0e-8;
+      Standard_Real aTolF = 0.0;
+
+      Standard_Real u1 = U1prec, v1 = V1prec, u2 = U2prec, v2 = V2prec;
+
+      flFinish = Checking(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec, aTolF);
+      
+      if(aTolF <= aTolMax)
+      {
+        gp_Pnt  aP1 = theASurf1->Value(u1, v1),
+                aP2 = theASurf2->Value(u2, v2);
+        gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
+
+        const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
+                            aSQDist2 = aPInt.SquareDistance(aP2);
+        if((aSQDist1 < aTol) && (aSQDist2 < aTol))
+        {
+          IntSurf_PntOn2S anIP;
+          anIP.SetValue(aPInt, u1, v1, u2, v2);
+          
+          if(isTheFirst)
+            line->InsertBefore(1,anIP);
+          else
+            line->Add(anIP);
+
+          isOK = Standard_True;
+        }
+      }
+    }
+    else
+    {
+      break;
+    }
+
+    if(aNbIter < 0)
+      break;
+  }
+
+  return isOK;
+}
+
+//=======================================================================
+//function : PutToBoundary
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntWalk_PWalking::
+  PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
+                const Handle(Adaptor3d_HSurface)& theASurf2)
+{
+  const Standard_Real aTolMin = Precision::Confusion();
+
+  Standard_Boolean hasBeenAdded = Standard_False;
+
+  const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
+  const Standard_Real aU1bLast = theASurf1->LastUParameter();
+  const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
+  const Standard_Real aU2bLast = theASurf2->LastUParameter();
+  const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
+  const Standard_Real aV1bLast = theASurf1->LastVParameter();
+  const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
+  const Standard_Real aV2bLast = theASurf2->LastVParameter();
+
+  Standard_Real aTol = 1.0;
+  aTol = Min(aTol, aU1bLast - aU1bFirst);
+  aTol = Min(aTol, aU2bLast - aU2bFirst);
+  aTol = Min(aTol, aV1bLast - aV1bFirst);
+  aTol = Min(aTol, aV2bLast - aV2bFirst)*1.0e-3;
+
+  if(aTol <= 2.0*aTolMin)
+    return hasBeenAdded;
+
+  Standard_Boolean isNeedAdding = Standard_False;
+  Standard_Boolean isU1parallel = Standard_False, isV1parallel = Standard_False;
+  Standard_Boolean isU2parallel = Standard_False, isV2parallel = Standard_False;
+  IsParallel(line, Standard_True, aTol, isU1parallel, isV1parallel);
+  IsParallel(line, Standard_False, aTol, isU2parallel, isV2parallel);
+
+  const Standard_Integer aNbPnts = line->NbPoints();
+  Standard_Real u1, v1, u2, v2;
+  line->Value(1).Parameters(u1, v1, u2, v2);
+  Standard_Real aDelta = 0.0;
+  
+  if(!isV1parallel)
+  {
+    aDelta = u1 - aU1bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      u1 = aU1bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aU1bLast - u1;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        u1 = aU1bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isV2parallel)
+  {
+    aDelta = u2 - aU2bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      u2 = aU2bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aU2bLast - u2;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        u2 = aU2bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isU1parallel)
+  {
+    aDelta = v1 - aV1bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      v1 = aV1bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aV1bLast - v1;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        v1 = aV1bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isU2parallel)
+  {
+    aDelta = v2 - aV2bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      v2 = aV2bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aV2bLast - v2;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        v2 = aV2bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(isNeedAdding)
+  {
+    hasBeenAdded = 
+      SeekPointOnBoundary(theASurf1, theASurf2, u1, 
+                            v1, u2, v2, Standard_True);
+  }
+
+  isNeedAdding = Standard_False;
+  line->Value(aNbPnts).Parameters(u1, v1, u2, v2);
+
+  if(!isV1parallel)
+  {
+    aDelta = u1 - aU1bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      u1 = aU1bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aU1bLast - u1;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        u1 = aU1bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isV2parallel)
+  {
+    aDelta = u2 - aU2bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      u2 = aU2bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aU2bLast - u2;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        u2 = aU2bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isU1parallel)
+  {
+    aDelta = v1 - aV1bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      v1 = aV1bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aV1bLast - v1;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        v1 = aV1bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(!isU2parallel)
+  {
+    aDelta = v2 - aV2bFirst;
+    if((aTolMin < aDelta) && (aDelta < aTol))
+    {
+      v2 = aV2bFirst - aDelta;
+      isNeedAdding = Standard_True;
+    }
+    else
+    {
+      aDelta = aV2bLast - v2;
+      if((aTolMin < aDelta) && (aDelta < aTol))
+      {
+        v2 = aV2bLast + aDelta;
+        isNeedAdding = Standard_True;
+      }
+    }
+  }
+
+  if(isNeedAdding)
+  {
+    hasBeenAdded = 
+      SeekPointOnBoundary(theASurf1, theASurf2, u1, 
+                            v1, u2, v2, Standard_False);
+  }
+
+  return hasBeenAdded;
+}
+
+//=======================================================================
+//function : SeekAdditionalPoints
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntWalk_PWalking::
+  SeekAdditionalPoints( const Handle(Adaptor3d_HSurface)& theASurf1,
+                        const Handle(Adaptor3d_HSurface)& theASurf2,
+                        const Standard_Integer theMinNbPoints)
 {
   const Standard_Real aTol = 1.0e-14;
   Standard_Integer aNbPoints = line->NbPoints();
@@ -1915,3 +2403,5 @@ Standard_Boolean IntWalk_PWalking::SeekAdditionalPoints(const Handle(Adaptor3d_H
 
   return isPrecise;
 }
+
+
index f1de831..255e723 100755 (executable)
@@ -23,8 +23,6 @@ proc checkList {List Tolerance D_good} {
       }
    }
 }
-smallview
-
 restore [locate_data_file bug24472_Pipe_1.brep] b1
 
 explode b1 f
diff --git a/tests/bugs/modalg_5/bug24585_1 b/tests/bugs/modalg_5/bug24585_1
new file mode 100644 (file)
index 0000000..462b196
--- /dev/null
@@ -0,0 +1,77 @@
+puts "========="
+puts "OCC24585"
+puts "========="
+puts ""
+###########################################################
+# Wrong pcurve of the section curve
+###########################################################
+set MaxTol 1.0e-7
+set NbCurv_OK 1
+
+restore [locate_data_file bug24585_b1.brep] b1
+restore [locate_data_file bug24585_b2.brep] b2
+
+mksurface s1 b1
+bounds s1 U1f_exp U1l_exp V1f_exp V1l_exp
+
+set log [bopcurves b1 b2 -2d]
+
+regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
+
+if {${NbCurv} != ${NbCurv_OK}} {
+  puts "Error: ${NbCurv_OK} curve(s) expected, but ${NbCurv} found."
+}
+
+if {${Toler} > ${MaxTol}} {
+  puts "Error: Tolerance is too big!"
+}
+
+#Theoretically, c2d1_1 must cover U-diapason of surface s1 fully.
+
+set log [dump c2d1_1]
+
+regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles
+puts "Degree=${Degree}"
+puts "Poles=${Poles}"
+puts "KnotsPoles=${KnotsPoles}"
+puts ""
+
+set Pole 1
+set exp_string " +${Pole} : +(\[-0-9.+eE\]+), +(\[-0-9.+eE\]+)"
+regexp ${exp_string} ${log} full U_begin V_begin
+
+puts "Pole=${Pole}"
+puts "U_begin=${U_begin}"
+puts "V_begin=${V_begin}"
+dset U_begin ${U_begin}
+puts ""
+
+set Pole ${Poles}
+set exp_string " +${Pole} : +(\[-0-9.+eE\]+), +(\[-0-9.+eE\]+)"
+regexp ${exp_string} ${log} full U_end V_end
+
+puts "Pole=${Pole}"
+puts "U_end=${U_end}"
+puts "V_end=${V_end}"
+dset U_end ${U_end}
+puts ""
+
+set delta_f [dval U1f_exp-U_begin]
+
+#ATTENTION!!! U_begin must be strictly equal U1f_exp (without any tolerance)
+if {${delta_f} != 0} {
+  puts "Error: Bad value. U_begin = [dval U_begin], Ufirst = [dval U1f_exp]."
+} else {
+  puts "OK: Good value. U_begin matches with Ufirst of surface."
+}
+
+puts ""
+
+set delta_l [dval U1l_exp-U_end]
+
+#ATTENTION!!! U_end must be strictly equal U1l_exp (without any tolerance)
+if {${delta_l} != 0} {
+  puts "Error: Bad value. U_end = [dval U_end], Ulast = [dval U1l_exp]."
+} else {
+  puts "OK: Good value. U_end matches with Ulast of surface."
+}
\ No newline at end of file
diff --git a/tests/bugs/modalg_5/bug24585_2 b/tests/bugs/modalg_5/bug24585_2
new file mode 100644 (file)
index 0000000..2c2492a
--- /dev/null
@@ -0,0 +1,31 @@
+puts "========="
+puts "OCC24585"
+puts "========="
+puts ""
+###########################################################
+# Wrong pcurve of the section curve
+###########################################################
+
+restore [locate_data_file bug24585_b1.brep] b1
+restore [locate_data_file bug24585_b2.brep] b2
+
+bclearobjects
+bcleartools
+baddobjects b1 b2
+
+bfillds
+bbuild result
+
+set square 933.33
+
+set nb_v_good 10
+set nb_e_good 11
+set nb_w_good 4
+set nb_f_good 3
+set nb_sh_good 0
+set nb_sol_good 0
+set nb_compsol_good 0
+set nb_compound_good 1
+set nb_shape_good 29
+
+set 2dviewer 1