0027252: Implicit-implicit intersection (Cylinder-Plane) loses intersection curve
[occt.git] / src / IntTools / IntTools_FaceFace.cxx
index ce8f371..9e4ba48 100644 (file)
@@ -56,9 +56,9 @@
 #include <gp_Elips.hxx>
 
 static
-  void TolR3d(const TopoDS_Face& ,
-              const TopoDS_Face& ,
-              Standard_Real& );
+  void TolR3d(const Standard_Real aTolF1,
+              const Standard_Real aTolF2,
+              Standard_Real& myTolReached3d);
 
 static 
   void Parameters(const Handle(GeomAdaptor_HSurface)&,
@@ -84,6 +84,7 @@ static
                                           const TopoDS_Face&        theFace2,
                                           const Standard_Real       theOtherParameter,
                                           const Standard_Boolean    bIncreasePar,
+                                          const Standard_Real       theTol,
                                           Standard_Real&            theNewParameter,
                                           const Handle(IntTools_Context)& );
 
@@ -133,7 +134,8 @@ static
 //
 static
   Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
-                               const TopoDS_Face& aFace);
+                               const TopoDS_Face& aFace,
+                               const Handle(IntTools_Context)& theCtx);
 
 static
   Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
@@ -174,8 +176,11 @@ IntTools_FaceFace::IntTools_FaceFace()
   myTolReached2d=0.; 
   myTolReached3d=0.;
   myTolReal = 0.;
+  myTolF1 = 0.;
+  myTolF2 = 0.;
+  myTol = 0.;
+  myFuzzyValue = Precision::Confusion();
   SetParameters(Standard_True, Standard_True, Standard_True, 1.e-07);
-  
 }
 //=======================================================================
 //function : SetContext
@@ -282,6 +287,23 @@ void IntTools_FaceFace::SetParameters(const Standard_Boolean ToApproxC3d,
   myApprox2 = ToApproxC2dOnS2;
   myTolApprox = ApproximationTolerance;
 }
+//=======================================================================
+//function : SetFuzzyValue
+//purpose  : 
+//=======================================================================
+void IntTools_FaceFace::SetFuzzyValue(const Standard_Real theFuzz)
+{
+  myFuzzyValue = Max(theFuzz, Precision::Confusion());
+}
+//=======================================================================
+//function : FuzzyValue
+//purpose  : 
+//=======================================================================
+Standard_Real IntTools_FaceFace::FuzzyValue() const
+{
+  return myFuzzyValue;
+}
+
 //=======================================================================
 //function : SetList
 //purpose  : 
@@ -292,28 +314,25 @@ void IntTools_FaceFace::SetList(IntSurf_ListOfPntOn2S& aListOfPnts)
 }
 
 
-static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
-                                        const TopoDS_Face& theF2)
+static Standard_Boolean isTreatAnalityc(const BRepAdaptor_Surface& theBAS1,
+                                        const BRepAdaptor_Surface& theBAS2,
+                                        const Standard_Real theTol)
 {
   const Standard_Real Tolang = 1.e-8;
-  const Standard_Real aTolF1=BRep_Tool::Tolerance(theF1);
-  const Standard_Real aTolF2=BRep_Tool::Tolerance(theF2);
-  const Standard_Real aTolSum = aTolF1 + aTolF2 + Precision::Confusion();
   Standard_Real aHigh = 0.0;
 
-  const BRepAdaptor_Surface aBAS1(theF1), aBAS2(theF2);
-  const GeomAbs_SurfaceType aType1=aBAS1.GetType();
-  const GeomAbs_SurfaceType aType2=aBAS2.GetType();
+  const GeomAbs_SurfaceType aType1=theBAS1.GetType();
+  const GeomAbs_SurfaceType aType2=theBAS2.GetType();
   
   gp_Pln aS1;
   gp_Cylinder aS2;
   if(aType1 == GeomAbs_Plane)
   {
-    aS1=aBAS1.Plane();
+    aS1=theBAS1.Plane();
   }
   else if(aType2 == GeomAbs_Plane)
   {
-    aS1=aBAS2.Plane();
+    aS1=theBAS2.Plane();
   }
   else
   {
@@ -322,9 +341,9 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
   if(aType1 == GeomAbs_Cylinder)
   {
-    aS2=aBAS1.Cylinder();
-    const Standard_Real VMin = aBAS1.FirstVParameter();
-    const Standard_Real VMax = aBAS1.LastVParameter();
+    aS2=theBAS1.Cylinder();
+    const Standard_Real VMin = theBAS1.FirstVParameter();
+    const Standard_Real VMax = theBAS1.LastVParameter();
 
     if( Precision::IsNegativeInfinite(VMin) ||
         Precision::IsPositiveInfinite(VMax))
@@ -334,10 +353,10 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   }
   else if(aType2 == GeomAbs_Cylinder)
   {
-    aS2=aBAS2.Cylinder();
+    aS2=theBAS2.Cylinder();
 
-    const Standard_Real VMin = aBAS2.FirstVParameter();
-    const Standard_Real VMax = aBAS2.LastVParameter();
+    const Standard_Real VMin = theBAS2.FirstVParameter();
+    const Standard_Real VMax = theBAS2.LastVParameter();
 
     if( Precision::IsNegativeInfinite(VMin) ||
         Precision::IsPositiveInfinite(VMax))
@@ -351,7 +370,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   }
 
   IntAna_QuadQuadGeo inter;
-  inter.Perform(aS1,aS2,Tolang,aTolSum, aHigh);
+  inter.Perform(aS1,aS2,Tolang,theTol, aHigh);
   if(inter.TypeInter() == IntAna_Ellipse)
   {
     const gp_Elips anEl = inter.Ellipse(1);
@@ -388,8 +407,8 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
   myFace1=aF1;
   myFace2=aF2;
 
-  const BRepAdaptor_Surface aBAS1(myFace1, Standard_False);
-  const BRepAdaptor_Surface aBAS2(myFace2, Standard_False);
+  const BRepAdaptor_Surface& aBAS1 = myContext->SurfaceAdaptor(myFace1);
+  const BRepAdaptor_Surface& aBAS2 = myContext->SurfaceAdaptor(myFace2);
   GeomAbs_SurfaceType aType1=aBAS1.GetType();
   GeomAbs_SurfaceType aType2=aBAS2.GetType();
 
@@ -424,10 +443,12 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
   const Handle(Geom_Surface) S1=BRep_Tool::Surface(myFace1);
   const Handle(Geom_Surface) S2=BRep_Tool::Surface(myFace2);
 
-  const Standard_Real aTolF1=BRep_Tool::Tolerance(myFace1);
-  const Standard_Real aTolF2=BRep_Tool::Tolerance(myFace2);
+  Standard_Real aFuzz = myFuzzyValue / 2.;
+  myTolF1 = BRep_Tool::Tolerance(myFace1) + aFuzz;
+  myTolF2 = BRep_Tool::Tolerance(myFace2) + aFuzz;
+  myTol = myTolF1 + myTolF2;
 
-  Standard_Real TolArc = aTolF1 + aTolF2 + Precision::Confusion();
+  Standard_Real TolArc = myTol;
   Standard_Real TolTang = TolArc;
 
   const Standard_Boolean isFace1Quad = (aType1 == GeomAbs_Cylinder ||
@@ -441,18 +462,18 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
   if(aType1==GeomAbs_Plane && aType2==GeomAbs_Plane)  {
     Standard_Real umin, umax, vmin, vmax;
     //
-    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace1, umin, umax, vmin, vmax);
     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     //
-    BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
     //
     Standard_Real TolAng = 1.e-8;
     //
     PerformPlanes(myHS1, myHS2, 
-                  aTolF1, aTolF2, TolAng, TolTang, 
+                  myTolF1, myTolF2, TolAng, TolTang, 
                   myApprox1, myApprox2, 
                   mySeqOfCurve, myTangentFaces, myTolReached3d);
     //
@@ -462,7 +483,7 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
       const Standard_Integer NbLinPP = mySeqOfCurve.Length();
       if(NbLinPP) {
         Standard_Real aTolFMax;
-        aTolFMax=Max(aTolF1, aTolF2);
+        aTolFMax=Max(myTolF1, myTolF2);
         myTolReal = Precision::Confusion();
         if (aTolFMax > myTolReal) {
           myTolReal = aTolFMax;
@@ -493,34 +514,34 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
   {
     Standard_Real umin, umax, vmin, vmax;
     // F1
-    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax); 
+    myContext->UVBounds(myFace1, umin, umax, vmin, vmax); 
     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     // F2
-    BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
-    CorrectSurfaceBoundaries(myFace2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
+    CorrectSurfaceBoundaries(myFace2, myTol * 2., umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
   }
   else if ((aType2==GeomAbs_Plane) && isFace1Quad)
   {
     Standard_Real umin, umax, vmin, vmax;
     //F1
-    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
-    CorrectSurfaceBoundaries(myFace1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace1, umin, umax, vmin, vmax);
+    CorrectSurfaceBoundaries(myFace1, myTol * 2., umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     // F2
-    BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
     CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
   }
   else
   {
     Standard_Real umin, umax, vmin, vmax;
-    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
-    CorrectSurfaceBoundaries(myFace1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace1, umin, umax, vmin, vmax);
+    CorrectSurfaceBoundaries(myFace1, myTol * 2., umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
-    BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
-    CorrectSurfaceBoundaries(myFace2, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
+    myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
+    CorrectSurfaceBoundaries(myFace2, myTol * 2., umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
   }
 
@@ -605,7 +626,7 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
     }
 #endif
 
-  const Standard_Boolean isGeomInt = isTreatAnalityc(aF1, aF2);
+  const Standard_Boolean isGeomInt = isTreatAnalityc(aBAS1, aBAS2, myTol);
   myIntersector.Perform(myHS1, dom1, myHS2, dom2, TolArc, TolTang, 
                                   myListOfPnts, RestrictLine, isGeomInt);
 
@@ -909,7 +930,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
     //
     // myTolReached3d
     if (typl == IntPatch_Lin) {
-      TolR3d (myFace1, myFace2, myTolReached3d);
+      TolR3d (myTolF1, myTolF2, myTolReached3d);
     }
     //
     aNbParts=myLConstruct.NbParts();
@@ -928,12 +949,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
         Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
         aCurve.SetCurve(aCT3D);
         if (typl == IntPatch_Parabola) {
-          Standard_Real aTolF1, aTolF2, aTolBase;
-          
-          aTolF1 = BRep_Tool::Tolerance(myFace1);
-          aTolF2 = BRep_Tool::Tolerance(myFace2);
-          aTolBase=aTolF1+aTolF2;
-          myTolReached3d=IntTools_Tools::CurveTolerance(aCT3D, aTolBase);
+          myTolReached3d=IntTools_Tools::CurveTolerance(aCT3D, myTol);
         }
         //
         aCurve.SetCurve(new Geom_TrimmedCurve(newc, fprm, lprm));
@@ -1035,7 +1051,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
     }
     //
     // myTolReached3d
-    TolR3d (myFace1, myFace2, myTolReached3d);
+    TolR3d (myTolF1, myTolF2, myTolReached3d);
     //
     aNbParts=myLConstruct.NbParts();
     //
@@ -1060,14 +1076,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
         else {
           gp_Pnt P1 = newc->Value(fprm);
           gp_Pnt P2 = newc->Value(aPeriod);
-          Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
+          Standard_Real aTolDist = myTol;
           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
 
           if(P1.Distance(P2) > aTolDist) {
             Standard_Real anewpar = fprm;
 
             if(ParameterOutOfBoundary(fprm, newc, myFace1, myFace2, 
-                                      lprm, Standard_False, anewpar, myContext)) {
+                                      lprm, Standard_False, myTol, anewpar, myContext)) {
               fprm = anewpar;
             }
             aSeqFprm.Append(fprm);
@@ -1083,14 +1099,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
         else {
           gp_Pnt P1 = newc->Value(aNul);
           gp_Pnt P2 = newc->Value(lprm);
-          Standard_Real aTolDist = BRep_Tool::Tolerance(myFace1) + BRep_Tool::Tolerance(myFace2);
+          Standard_Real aTolDist = myTol;
           aTolDist = (myTolReached3d > aTolDist) ? myTolReached3d : aTolDist;
 
           if(P1.Distance(P2) > aTolDist) {
             Standard_Real anewpar = lprm;
 
             if(ParameterOutOfBoundary(lprm, newc, myFace1, myFace2, 
-                                      fprm, Standard_True, anewpar, myContext)) {
+                                      fprm, Standard_True, myTol, anewpar, myContext)) {
               lprm = anewpar;
             }
             aSeqFprm.Append(aNul);
@@ -1387,6 +1403,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                              myFace2, 
                              myLConstruct, 
                              bAvoidLineConstructor, 
+                             myTol,
                              aSeqOfL, 
                              aReachedTol,
                              myContext);
@@ -1631,7 +1648,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                   }
                 }
                 // ###########################################
-                bPCurvesOk = CheckPCurve(BS1, myFace2);
+                bPCurvesOk = CheckPCurve(BS1, myFace2, myContext);
                 aCurve.SetSecondCurve2d(BS1);
               }
               else {
@@ -1657,7 +1674,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                   }
                 }
                 // ###########################################
-                bPCurvesOk = bPCurvesOk && CheckPCurve(BS2, myFace1);
+                bPCurvesOk = bPCurvesOk && CheckPCurve(BS2, myFace1, myContext);
                 aCurve.SetFirstCurve2d(BS2);
               }
               else { 
@@ -1676,12 +1693,12 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                 
                 if(myApprox1) {
                   H1 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
-                  bPCurvesOk = CheckPCurve(H1, myFace1);
+                  bPCurvesOk = CheckPCurve(H1, myFace1, myContext);
                 }
                 
                 if(myApprox2) {
                   H2 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
-                  bPCurvesOk = bPCurvesOk && CheckPCurve(H2, myFace2);
+                  bPCurvesOk = bPCurvesOk && CheckPCurve(H2, myFace2, myContext);
                 }
                 //
                 //if pcurves created without approximation are out of the 
@@ -1736,7 +1753,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                   newCheck.FixTangent(Standard_True,Standard_True);
                   //         
                   if (!reApprox) {
-                    bIsValid1=CheckPCurve(BS1, myFace1);
+                    bIsValid1=CheckPCurve(BS1, myFace1, myContext);
                   }
                   //
                   aCurve.SetFirstCurve2d(BS1);
@@ -1768,7 +1785,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
                   newCheck.FixTangent(Standard_True,Standard_True);
                 //                 
                   if (!reApprox) {
-                    bIsValid2=CheckPCurve(BS2, myFace2);        
+                    bIsValid2=CheckPCurve(BS2, myFace2, myContext);
                   }
                   aCurve.SetSecondCurve2d(BS2);
                 }
@@ -2225,15 +2242,13 @@ Handle(Geom_Curve) MakeBSpline  (const Handle(IntPatch_WLine)& WL,
 //function : TolR3d
 //purpose  : 
 //=======================================================================
-void TolR3d(const TopoDS_Face& aF1,
-            const TopoDS_Face& aF2,
+void TolR3d(const Standard_Real aTolF1,
+            const Standard_Real aTolF2,
             Standard_Real& myTolReached3d)
 {
-  Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
+  Standard_Real aTolFMax, aTolTresh;
       
   aTolTresh=2.999999e-3;
-  aTolF1 = BRep_Tool::Tolerance(aF1);
-  aTolF2 = BRep_Tool::Tolerance(aF2);
   aTolFMax=Max(aTolF1, aTolF2);
   
   if (aTolFMax>aTolTresh) {
@@ -2252,6 +2267,7 @@ Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter,
                                         const TopoDS_Face&        theFace2,
                                         const Standard_Real       theOtherParameter,
                                         const Standard_Boolean    bIncreasePar,
+                                        const Standard_Real       theTol,
                                         Standard_Real&            theNewParameter,
                                         const Handle(IntTools_Context)& aContext)
 {
@@ -2261,7 +2277,7 @@ Standard_Boolean ParameterOutOfBoundary(const Standard_Real       theParameter,
   Standard_Real acurpar = theParameter;
   TopAbs_State aState = TopAbs_ON;
   Standard_Integer iter = 0;
-  Standard_Real asumtol = BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
+  Standard_Real asumtol = theTol;
   Standard_Real adelta = asumtol * 0.1;
   adelta = (adelta < Precision::Confusion()) ? Precision::Confusion() : adelta;
   Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1);
@@ -2883,28 +2899,25 @@ Standard_Real FindMaxDistance(const Handle(Geom_Curve)& theC,
   aA = theFirst;
   aB = theLast;
   //
-  aX1 = aB - aCf * (aB - aA);
+  aX1=aB - aCf*(aB-aA);
   aF1 = MaxDistance(theC, aX1, theProjPS);
   aX2 = aA + aCf * (aB - aA);
   aF2 = MaxDistance(theC, aX2, theProjPS);
-  //
-  for (;;) {
-    if ((aB - aA) < theEps) {
-      break;
-    }
-    //
+
+  while (Abs(aX1-aX2) > theEps)
+  {
     if (aF1 > aF2) {
       aB = aX2;
       aX2 = aX1;
       aF2 = aF1;
-      aX1 = aB - aCf * (aB - aA); 
+      aX1 = aB-aCf*(aB-aA);
       aF1 = MaxDistance(theC, aX1, theProjPS);
     }
     else {
       aA = aX1;
       aX1 = aX2;
       aF1 = aF2;
-      aX2 = aA + aCf * (aB - aA);
+      aX2=aA+aCf*(aB-aA);
       aF2 = MaxDistance(theC, aX2, theProjPS);
     }
   }
@@ -2945,14 +2958,15 @@ Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
 //function : CheckPCurve
 //purpose  : Checks if points of the pcurve are out of the face bounds.
 //=======================================================================
-  Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
-                               const TopoDS_Face& aFace) 
+  Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC,
+                               const TopoDS_Face& aFace,
+                               const Handle(IntTools_Context)& theCtx)
 {
   const Standard_Integer NPoints = 23;
   Standard_Integer i;
   Standard_Real umin,umax,vmin,vmax;
 
-  BRepTools::UVBounds(aFace, umin, umax, vmin, vmax);
+  theCtx->UVBounds(aFace, umin, umax, vmin, vmax);
   Standard_Real tolU = Max ((umax-umin)*0.01, Precision::Confusion());
   Standard_Real tolV = Max ((vmax-vmin)*0.01, Precision::Confusion());
   Standard_Real fp = aPC->FirstParameter();