]> OCCT Git - occt.git/commitdiff
0029103: No intersection curve between faces if starting points are given
authornbv <nbv@opencascade.com>
Thu, 14 Sep 2017 11:49:16 +0000 (14:49 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 22 Sep 2017 08:52:02 +0000 (11:52 +0300)
Sometimes the algorithm of Walking-line creation finds points out of the domain. Some such places have been detected and fixed in frame of this issue.

src/IntWalk/IntWalk_PWalking.cxx
tests/bugs/modalg_7/bug29103 [new file with mode: 0644]

index 54c42a130432c7bf3e58e08a6a0d239e626e1a26..eed1c6334a320f690755d1aced5cbe5fe51a3f9e 100644 (file)
@@ -159,6 +159,35 @@ static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
   theIsUparallel = ((aVmax - aVmin) < theToler);
 }
 
+//=======================================================================
+//function : AdjustToDomain
+//purpose  : Returns TRUE if theP has been changed (i.e. initial value
+//            was out of the domain)
+//=======================================================================
+static Standard_Boolean AdjustToDomain(const Standard_Integer theNbElem,
+                                       Standard_Real* theParam,
+                                       const Standard_Real* const theLowBorder,
+                                       const Standard_Real* const theUppBorder)
+{
+  Standard_Boolean aRetVal = Standard_False;
+  for (Standard_Integer i = 0; i < theNbElem; i++)
+  {
+    if ((theParam[i] - theLowBorder[i]) < -Precision::PConfusion())
+    {
+      theParam[i] = theLowBorder[i];
+      aRetVal = Standard_True;
+    }
+
+    if ((theParam[i] - theUppBorder[i]) > Precision::PConfusion())
+    {
+      theParam[i] = theUppBorder[i];
+      aRetVal = Standard_True;
+    }
+  }
+
+  return aRetVal;
+}
+
 //==================================================================================
 // function : IntWalk_PWalking::IntWalk_PWalking
 // purpose  : 
@@ -2247,7 +2276,19 @@ Standard_Boolean IntWalk_PWalking::HandleSingleSingularPoint(const Handle(Adapto
         continue;
 
       anInt.Point().Parameters(thePnt(1), thePnt(2), thePnt(3), thePnt(4));
-      return Standard_True;
+
+      Standard_Boolean isInDomain = Standard_True;
+      for (Standard_Integer j = 1; isInDomain && (j <= 4); ++j)
+      {
+        if ((thePnt(j) - aLowBorder[j - 1] + Precision::PConfusion())*
+            (thePnt(j) - aUppBorder[j - 1] - Precision::PConfusion()) > 0.0)
+        {
+          isInDomain = Standard_False;
+        }
+      }
+
+      if (isInDomain)
+        return Standard_True;
     }
   }
 
@@ -2259,16 +2300,26 @@ Standard_Boolean IntWalk_PWalking::HandleSingleSingularPoint(const Handle(Adapto
 //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)
+        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)
 {
   Standard_Boolean isOK = Standard_False;
 
+  // u1, v1, u2, v2 order is used.
+  const Standard_Real aLowBorder[4] = {theASurf1->FirstUParameter(),
+                                       theASurf1->FirstVParameter(),
+                                       theASurf2->FirstUParameter(),
+                                       theASurf2->FirstVParameter()};
+  const Standard_Real aUppBorder[4] = {theASurf1->LastUParameter(),
+                                       theASurf1->LastVParameter(),
+                                       theASurf2->LastUParameter(),
+                                       theASurf2->LastVParameter()};
+
   // Tune solution tolerance according with object size.
   const Standard_Real aRes1 = Max(Precision::PConfusion() / theASurf1->UResolution(1.0),
                                   Precision::PConfusion() / theASurf1->VResolution(1.0));
@@ -2288,21 +2339,26 @@ SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
   {
     aNbIter--;
     aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, aPnt);
-    if(aStatus)
+    if (aStatus && !AdjustToDomain(4, &aPnt(1), &aLowBorder[0], &aUppBorder[0]))
       break;
 
-    aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(aPnt(3), aPnt(4)), aPnt(1), aPnt(2));
-    if(aStatus)
+    aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(aPnt(3), aPnt(4)),
+                                        aPnt(1), aPnt(2));
+    if (aStatus && !AdjustToDomain(2, &aPnt(1), &aLowBorder[0], &aUppBorder[0]))
       break;
 
-    aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(aPnt(1), aPnt(2)), aPnt(3), aPnt(4));
-    if(aStatus)
+    aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(aPnt(1), aPnt(2)),
+                                        aPnt(3), aPnt(4));
+    if (aStatus && !AdjustToDomain(2, &aPnt(3), &aLowBorder[2], &aUppBorder[2]))
       break;
   }
   while(!aStatus && (aNbIter > 0));
 
   // Handle singular points.
-  Standard_Boolean aSingularStatus = HandleSingleSingularPoint(theASurf1, theASurf2, aTol, aSingularPnt);
+  Standard_Boolean aSingularStatus = HandleSingleSingularPoint(theASurf1,
+                                                               theASurf2,
+                                                               aTol,
+                                                               aSingularPnt);
   if (aSingularStatus)
     aPnt = aSingularPnt;
 
diff --git a/tests/bugs/modalg_7/bug29103 b/tests/bugs/modalg_7/bug29103
new file mode 100644 (file)
index 0000000..33bc06c
--- /dev/null
@@ -0,0 +1,56 @@
+puts "========"
+puts "OCC29103"
+puts "========"
+puts ""
+#################################################
+# No intersection curve between faces if starting points are given
+#################################################
+
+set MaxTolReached 2.0e-7
+set GoodNbCurv 1
+set ExpLength 0.074141742883251954
+
+restore [locate_data_file bug29073_M6.brep] a
+restore [locate_data_file bug29073_Shell.brep] b
+explode a f
+explode b f
+
+don b_2
+axo
+fit
+disp a_6
+
+set log1 [bopcurves a_6 b_2 -2d]
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}_1.png
+checklength c_1 -l $ExpLength
+
+don b_2
+axo
+fit
+disp a_6
+
+set log2 [bopcurves a_6 b_2 -2d -p -0.55478319275098653 1.2919191091235780 0.80333089657224976 0.67079577554162440 -p -0.62451407353846222 1.2667484772947102 0.82894736842100003 0.70523311453721027]
+
+checkview -screenshot -2d -path ${imagedir}/${test_image}_2.png
+checklength c_1 -l $ExpLength
+
+regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log1} full Toler1 NbCurv1
+regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log2} full Toler2 NbCurv2
+
+if {$Toler1 > $MaxTolReached} {
+  puts "Error: Big tolerance is returned by intersector w/o start points"
+}
+
+if {$Toler2 > $MaxTolReached} {
+  puts "Error: Big tolerance is returned by intersector with start points"
+}
+
+if {$NbCurv1 != $GoodNbCurv} {
+  puts "Error: Please check NbCurves for intersector w/o start points"
+}
+
+if {$NbCurv2 != $GoodNbCurv} {
+  puts "Error: Please check NbCurves for intersector with start points"
+}
+