0029465: Regression relation to 691 version: Extrema_ExtCC returns IsParallel equal...
authoremv <emv@opencascade.com>
Thu, 1 Feb 2018 10:10:16 +0000 (13:10 +0300)
committerapn <apn@opencascade.com>
Fri, 2 Feb 2018 14:17:47 +0000 (17:17 +0300)
Strengthening of the criteria of the parallel status of the curves by additional checking if the ends of the curves do not diverge.
Test cases for the issue.

src/Extrema/Extrema_ECC2d_0.cxx
src/Extrema/Extrema_ECC_0.cxx
src/Extrema/Extrema_GenExtCC.gxx
tests/bugs/modalg_5/bug23706_10
tests/lowalgos/extcc/begin [new file with mode: 0644]
tests/lowalgos/extcc/bug29465_1 [new file with mode: 0644]
tests/lowalgos/extcc/bug29465_2 [new file with mode: 0644]
tests/lowalgos/grids.list

index 9ab8870..0e989c4 100644 (file)
@@ -21,6 +21,7 @@
 #include <Standard_OutOfRange.hxx>
 #include <Adaptor2d_Curve2d.hxx>
 #include <Extrema_Curve2dTool.hxx>
+#include <Extrema_ExtPC2d.hxx>
 #include <Extrema_POnCurv2d.hxx>
 #include <gp_Pnt2d.hxx>
 #include <gp_Vec2d.hxx>
@@ -43,6 +44,7 @@
 #define Pnt_hxx <gp_Pnt2d.hxx>
 #define Vec gp_Vec2d
 #define Vec_hxx <gp_Vec2d.hxx>
+#define Extrema_GExtPC Extrema_ExtPC2d
 #define Extrema_GenExtCC Extrema_ECC2d
 #define Extrema_GenExtCC_hxx <Extrema_ECC2d.hxx>
 #include <Extrema_GenExtCC.gxx>
index d0e884b..50b5c06 100644 (file)
@@ -21,6 +21,7 @@
 #include <Standard_OutOfRange.hxx>
 #include <Adaptor3d_Curve.hxx>
 #include <Extrema_CurveTool.hxx>
+#include <Extrema_ExtPC.hxx>
 #include <Extrema_POnCurv.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Vec.hxx>
@@ -43,6 +44,7 @@
 #define Pnt_hxx <gp_Pnt.hxx>
 #define Vec gp_Vec
 #define Vec_hxx <gp_Vec.hxx>
+#define Extrema_GExtPC Extrema_ExtPC
 #define Extrema_GenExtCC Extrema_ECC
 #define Extrema_GenExtCC_hxx <Extrema_ECC.hxx>
 #include <Extrema_GenExtCC.gxx>
index 250f610..10e497d 100644 (file)
@@ -22,6 +22,7 @@
 #include <Standard_OutOfRange.hxx>
 #include <StdFail_NotDone.hxx>
 #include <TColStd_Array1OfReal.hxx>
+#include <TColStd_ListOfInteger.hxx>
 #include <Precision.hxx>
 #include <NCollection_Vector.hxx>
 #include <NCollection_CellFilter.hxx>
@@ -93,6 +94,29 @@ private:
 };
 
 //=======================================================================
+//function : ProjPOnC
+//purpose  : Projects the point on the curve and returns the minimal
+//           projection distance
+//=======================================================================
+static Standard_Real ProjPOnC(const Pnt& theP,
+                              Extrema_GExtPC& theProjTool)
+{
+  Standard_Real aDist = ::RealLast();
+  theProjTool.Perform(theP);
+  if (theProjTool.IsDone() && theProjTool.NbExt())
+  {
+    for (Standard_Integer i = 1; i <= theProjTool.NbExt(); ++i)
+    {
+      Standard_Real aD = theProjTool.SquareDistance(i);
+      if (aD < aDist)
+        aDist = aD;
+    }
+    aDist = sqrt(aDist);
+  }
+  return aDist;
+}
+
+//=======================================================================
 //function : Extrema_GenExtCC
 //purpose  : 
 //=======================================================================
@@ -262,9 +286,10 @@ void Extrema_GenExtCC::Perform()
   aFinder.SetFunctionalMinimalValue(0.0); // Best distance cannot be lower than 0.0.
 
   // Size computed to have cell index inside of int32 value.
-  const Standard_Real aCellSize = Max(anIntervals1.Last() - anIntervals1.First(),
+  const Standard_Real aCellSize = Max(Max(anIntervals1.Last() - anIntervals1.First(),
                                       anIntervals2.Last() - anIntervals2.First())
-                                  * Precision::PConfusion() / (2.0 * Sqrt(2.0));
+                                      * Precision::PConfusion() / (2.0 * Sqrt(2.0)),
+                                      Precision::PConfusion());
   Extrema_CCPointsInspector anInspector(aCellSize);
   NCollection_CellFilter<Extrema_CCPointsInspector> aFilter(aCellSize);
   NCollection_Vector<gp_XY> aPnts;
@@ -329,63 +354,150 @@ void Extrema_GenExtCC::Perform()
     }
   }
 
-  if (aPnts.Size() == 0)
+  const Standard_Integer aNbSol = aPnts.Length();
+  if (aNbSol == 0)
   {
     // No solutions.
     myDone = Standard_False;
     return;
   }
 
+  myDone = Standard_True;
+
+  if (aNbSol == 1)
+  {
+    // Single solution
+    const gp_XY& aSol = aPnts.First();
+    myPoints1.Append(aSol.X());
+    myPoints2.Append(aSol.Y());
+    return;
+  }
+
+  // More than one solution is found.
   // Check for infinity solutions case, for this:
   // Sort points lexicographically and check midpoint between each two neighboring points.
-  // If all midpoints functional value is acceptable
-  // then set myParallel flag to true and return one solution.
+  // If all midpoints functional value is acceptable then check the projection distances
+  // of the bounding points of the curves onto the opposite curves.
+  // If these distances are also acceptable set myParallel flag to true and return one solution.
   std::sort(aPnts.begin(), aPnts.end(), comp);
-  Standard_Boolean isParallel = Standard_False;
+
+  // Solutions to pass into result.
+  // If the parallel segment is found, save only extreme solutions on that segment.
+  // The first and last solutions will always be the extreme ones, thus save them unconditionally.
+  TColStd_ListOfInteger aSolutions;
+
+  // Manages the addition of the solution into result.
+  // Set it to TRUE to add the first solution.
+  Standard_Boolean bSaveSolution = Standard_True;
+
+  // Define direction of the second curve relatively the first one
+  // (it will be needed for projection).
+  Standard_Boolean bDirsCoinside = Standard_True;
+  // Check also if the found solutions are not concentrated in one point
+  // on any of the curves. And if they are, avoid marking the curves as parallel.
+  Standard_Boolean bDifferentSolutions = Standard_False;
+
+  Standard_Boolean isParallel = Standard_True;
   Standard_Real aVal = 0.0;
-  math_Vector aVec(1,2, 0.0);
+  math_Vector aVec(1, 2, 0.0);
 
-  // Avoid mark parallel case when have duplicates out of tolerance.
-  // Bad conditioned task: bug25635_1, bug23706_10, bug23706_13.
-  if (aPnts.Size() >= 2)
+  // Iterate on all solutions and collect the extreme solutions on all parallel segments.
+  for (Standard_Integer anIdx = 0; anIdx < aNbSol - 1; anIdx++)
   {
-    isParallel = Standard_True;
-    for(Standard_Integer anIdx = aPnts.Lower(); anIdx <= aPnts.Upper() - 1; anIdx++)
-    {
-      const gp_XY& aCurrent = aPnts(anIdx);
-      const gp_XY& aNext    = aPnts(anIdx + 1);
+    const gp_XY& aCurrent = aPnts(anIdx);
+    const gp_XY& aNext    = aPnts(anIdx + 1);
 
-      aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
-      aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
+    aVec(1) = (aCurrent.X() + aNext.X()) * 0.5;
+    aVec(2) = (aCurrent.Y() + aNext.Y()) * 0.5;
 
-      aFunc.Value(aVec, aVal);
+    aFunc.Value(aVec, aVal);
+
+    if (Abs(aVal - aF) < Precision::Confusion())
+    {
+      // It seems the parallel segment is found.
+      // Save only extreme solutions on that segment.
+      if (bSaveSolution)
+      {
+        // Add current solution as the beginning of the parallel segment.
+        aSolutions.Append(anIdx);
+        // Do not keep the next solution in current parallel segment.
+        bSaveSolution = Standard_False;
+      }
+    }
+    else
+    {
+      // Mid point does not satisfy the tolerance criteria, curves are not parallel.
+      isParallel = Standard_False;
+      // Add current solution as the last one in previous parallel segment.
+      aSolutions.Append(anIdx);
+      // Save also the next solution as the first one in next parallel segment.
+      bSaveSolution = Standard_True;
+    }
 
-      if (Abs(aVal - aF) > Precision::Confusion())
+    if (!bDifferentSolutions)
+    {
+      if (aNext.X() > aCurrent.X())
       {
-        isParallel = Standard_False;
-        break;
+        if (aNext.Y() > aCurrent.Y())
+        {
+          bDifferentSolutions = Standard_True;
+          bDirsCoinside = Standard_True;
+        }
+        else if (aNext.Y() < aCurrent.Y())
+        {
+          bDifferentSolutions = Standard_True;
+          bDirsCoinside = Standard_False;
+        }
       }
     }
   }
+  // Save the last solution
+  aSolutions.Append(aNbSol - 1);
+
+  if (!bDifferentSolutions)
+    isParallel = Standard_False;
+
+  if (isParallel)
+  {
+    // For the check on parallel case it is also necessary to check additionally
+    // if the ends of the curves do not diverge. For this, project the bounding
+    // points of the curves on the opposite curves and check the distances.
+
+    Standard_Real aT1[2] = {myLowBorder(1), myUppBorder(1)};
+    Standard_Real aT2[2] = {bDirsCoinside ? myLowBorder(2) : myUppBorder(2),
+                            bDirsCoinside ? myUppBorder(2) : myLowBorder(2)};
+
+    Extrema_GExtPC anExtPC1, anExtPC2;
+    anExtPC1.Initialize(C1, myLowBorder(1), myUppBorder(1));
+    anExtPC2.Initialize(C2, myLowBorder(2), myUppBorder(2));
+
+    for (Standard_Integer iT = 0; isParallel && (iT < 2); ++iT)
+    {
+      Standard_Real aDist1 = ProjPOnC(C1.Value(aT1[iT]), anExtPC2);
+      Standard_Real aDist2 = ProjPOnC(C2.Value(aT2[iT]), anExtPC1);
+      isParallel = (Abs(Min(aDist1, aDist2) - aF) < Precision::Confusion());
+    }
+  }
 
   if (isParallel)
   {
-    const gp_XY& aCurrent = aPnts.First();
-    myPoints1.Append(aCurrent.X());
-    myPoints2.Append(aCurrent.Y());
+    // Keep only one solution
+    const gp_XY& aSol = aPnts.First();
+    myPoints1.Append(aSol.X());
+    myPoints2.Append(aSol.Y());
     myParallel = Standard_True;
   }
   else
   {
-    for(Standard_Integer anIdx = aPnts.Lower(); anIdx <= aPnts.Upper(); anIdx++)
+    // Keep all saved solutions
+    TColStd_ListIteratorOfListOfInteger aItSol(aSolutions);
+    for (; aItSol.More(); aItSol.Next())
     {
-      const gp_XY& aCurrent = aPnts(anIdx);
-      myPoints1.Append(aCurrent.X());
-      myPoints2.Append(aCurrent.Y());
+      const gp_XY& aSol = aPnts(aItSol.Value());
+      myPoints1.Append(aSol.X());
+      myPoints2.Append(aSol.Y());
     }
   }
-
-  myDone = Standard_True;
 }
 
 //=======================================================================
index 2fc95e4..d80c11f 100755 (executable)
@@ -6,17 +6,16 @@ puts ""
 # Cannot project point on curve
 #########################################################################
 
-cpulimit 1500
-
 bsplinecurve r3 2 6 1 3 2 1 3 1 4 1 5 1 6 3 2 5 3 1 3 7 3 1 4 8 3 1 4 8 3 1 4 8 3 1 5 9 3 1 9 7 3 1
 bsplinecurve r4 2 6 2 3 2.5 1 3 1 3.5 1 4 1 4.5 3 -1 2 3 1 1 11 3 1 3 9 3 1 3 9 3 1 3 9 3 1 5 7 3 1 7 4 3 1
 
 set info [extrema r3 r4] 
 
-regexp {Infinite number of extremas, distance = +([-0-9.+eE]+)} $info full dist
-
-if { $dist > 4.0e-13 } {
-    puts "Error : Extrema distance is too big"
+if {[regexp "ext_1" $info]} {
+  set dist [lindex [length ext_1] end]
+  if { $dist > 4.0e-13 } {
+    puts "Error: Extrema distance is too big"
+  }
 } else {
-    puts "OK: Extrema distance is good"
+  puts "Error: Extrema is not found"
 }
diff --git a/tests/lowalgos/extcc/begin b/tests/lowalgos/extcc/begin
new file mode 100644 (file)
index 0000000..2598fdb
--- /dev/null
@@ -0,0 +1,12 @@
+proc CheckExtResult {info ref_dist} {
+  global ext_1
+  if {[regexp "ext_1" $info]} {
+    set dist [lindex [length ext_1] end]
+    if { $dist > $ref_dist } {
+      puts "Error: Extrema distance is too big"
+    }
+  } else {
+    puts "Error: Extrema is not found"
+  }
+}
+
diff --git a/tests/lowalgos/extcc/bug29465_1 b/tests/lowalgos/extcc/bug29465_1
new file mode 100644 (file)
index 0000000..fed9c4c
--- /dev/null
@@ -0,0 +1,29 @@
+puts "============"
+puts "OCC29465"
+puts "============"
+puts ""
+#########################################################################
+# Regression relation to 691 version: Extrema_ExtCC returns IsParallel equal to true for not parallel curves
+#########################################################################
+
+set dist 3.e-5
+
+restore [locate_data_file bug29465.brep] ce
+explode ce e
+mkcurve c1 ce_1
+mkcurve c2 ce_2
+
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c1
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c2
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c1
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
diff --git a/tests/lowalgos/extcc/bug29465_2 b/tests/lowalgos/extcc/bug29465_2
new file mode 100644 (file)
index 0000000..721b641
--- /dev/null
@@ -0,0 +1,31 @@
+puts "============"
+puts "OCC29465"
+puts "============"
+puts ""
+#########################################################################
+# Regression relation to 691 version: Extrema_ExtCC returns IsParallel equal to true for not parallel curves
+#########################################################################
+
+set dist 0.2
+
+restore [locate_data_file bug27371.brep] s
+explode s
+explode s_1 e
+mkcurve c1 s_1_1
+explode s_2 e
+mkcurve c2 s_2_20
+
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c1
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c2
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
+
+reverse c1
+CheckExtResult [extrema c1 c2] $dist
+CheckExtResult [extrema c2 c1] $dist
index 381fd9d..9a19d5f 100644 (file)
@@ -1,3 +1,4 @@
 001 2dinter
 002 bnd
 003 extcs
+004 extcc
\ No newline at end of file