0029535: Modeling Algorithms - BRepExtrema_DistShapeShape returns only one solution...
authorifv <ifv@opencascade.com>
Fri, 2 Mar 2018 13:59:08 +0000 (16:59 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 16 Mar 2018 11:57:01 +0000 (14:57 +0300)
The subdivision of long curve is added in algorithm GenExtCC, if length of curves are too different.
Test case added

src/Extrema/Extrema_GenExtCC.gxx
tests/bugs/modalg_7/bug29535 [new file with mode: 0644]

index 10e497d..fec566c 100644 (file)
@@ -26,6 +26,7 @@
 #include <Precision.hxx>
 #include <NCollection_Vector.hxx>
 #include <NCollection_CellFilter.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
 
 // Comparator, used in std::sort.
 static Standard_Boolean comp(const gp_XY& theA,
@@ -47,6 +48,57 @@ static Standard_Boolean comp(const gp_XY& theA,
   return Standard_False;
 }
 
+static void ChangeIntervals(Handle(TColStd_HArray1OfReal)& theInts, const Standard_Integer theNbInts)
+{
+  Standard_Integer aNbInts = theInts->Length() - 1;
+  Standard_Integer aNbAdd = theNbInts - aNbInts;
+  Handle(TColStd_HArray1OfReal) aNewInts = new TColStd_HArray1OfReal(1, theNbInts + 1);
+  Standard_Integer aNbLast = theInts->Length();
+  Standard_Integer i;
+  if (aNbInts == 1)
+  {
+    aNewInts->SetValue(1, theInts->First());
+    aNewInts->SetValue(theNbInts + 1, theInts->Last());
+    Standard_Real dt = (theInts->Last() - theInts->First()) / theNbInts;
+    Standard_Real t = theInts->First() + dt;
+    for (i = 2; i <= theNbInts; ++i, t += dt)
+    {
+      aNewInts->SetValue(i, t);
+    }
+    theInts = aNewInts;
+    return;
+  }
+  //
+  for (i = 1; i <= aNbLast; ++i)
+  {
+    aNewInts->SetValue(i, theInts->Value(i));
+  }
+  //
+  while (aNbAdd > 0)
+  {
+    Standard_Real anLIntMax = -1.;
+    Standard_Integer aMaxInd = -1;
+    for (i = 1; i < aNbLast; ++i)
+    {
+      Standard_Real anL = aNewInts->Value(i + 1) - aNewInts->Value(i);
+      if (anL > anLIntMax)
+      {
+        anLIntMax = anL;
+        aMaxInd = i;
+      }
+    }
+
+    Standard_Real t = (aNewInts->Value(aMaxInd + 1) + aNewInts->Value(aMaxInd)) / 2.;
+    for (i = aNbLast; i > aMaxInd; --i)
+    {
+      aNewInts->SetValue(i + 1, aNewInts->Value(i));
+    }
+    aNbLast++;
+    aNbAdd--;
+    aNewInts->SetValue(aMaxInd + 1, t);
+  }
+  theInts = aNewInts;
+}
 class Extrema_CCPointsInspector : public NCollection_CellFilter_InspectorXY
 {
 public:
@@ -229,10 +281,65 @@ void Extrema_GenExtCC::Perform()
     aNbInter[1] = C2.NbIntervals(aContinuity);
   }
 
-  TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
-  TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
-  C1.Intervals(anIntervals1, aContinuity);
-  C2.Intervals(anIntervals2, aContinuity);
+  Standard_Real anL[2];
+  Standard_Integer indmax = -1, indmin = -1;
+  const Standard_Real mult = 20.;
+  if (!(Precision::IsInfinite(C1.FirstParameter()) || Precision::IsInfinite(C1.LastParameter()) ||
+        Precision::IsInfinite(C2.FirstParameter()) || Precision::IsInfinite(C2.LastParameter())))
+  {
+    anL[0] = GCPnts_AbscissaPoint::Length(C1);
+    anL[1] = GCPnts_AbscissaPoint::Length(C2);
+    if (anL[0] / aNbInter[0] > mult * anL[1] / aNbInter[1])
+    {
+      indmax = 0;
+      indmin = 1;
+    }
+    else if (anL[1] / aNbInter[1] > mult * anL[0] / aNbInter[0])
+    {
+      indmax = 1;
+      indmin = 0;
+    }
+  }
+  Standard_Integer aNbIntOpt = 0;
+  if (indmax >= 0)
+  {
+    aNbIntOpt = RealToInt(anL[indmax] * aNbInter[indmin] / anL[indmin] / (mult / 4.))  + 1;
+    if (aNbIntOpt > 100 || aNbIntOpt < aNbInter[indmax])
+    {
+      indmax = -1;
+    }
+    else
+    {
+      if (aNbIntOpt * aNbInter[indmin] > 100)
+      {
+        aNbIntOpt = 100 / aNbInter[indmin];
+        if (aNbIntOpt < aNbInter[indmax])
+        {
+          indmax = -1;
+        }
+      }
+    }
+  }
+
+  Handle(TColStd_HArray1OfReal) anIntervals1 = new TColStd_HArray1OfReal(1, aNbInter[0] + 1);
+  Handle(TColStd_HArray1OfReal) anIntervals2 = new TColStd_HArray1OfReal(1, aNbInter[1] + 1);
+  C1.Intervals(anIntervals1->ChangeArray1(), aContinuity);
+  C2.Intervals(anIntervals2->ChangeArray1(), aContinuity);
+  if (indmax >= 0)
+  {
+    if (indmax == 0)
+    {
+      //Change anIntervals1
+      ChangeIntervals(anIntervals1, aNbIntOpt);
+      aNbInter[0] = anIntervals1->Length() - 1;
+    }
+    else
+    {
+      //Change anIntervals2;
+      ChangeIntervals(anIntervals2, aNbIntOpt);
+      aNbInter[1] = anIntervals2->Length() - 1;
+    }
+  }
 
   // Lipchitz constant computation.
   const Standard_Real aMaxLC = 10000.;
@@ -286,8 +393,8 @@ 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(Max(anIntervals1.Last() - anIntervals1.First(),
-                                      anIntervals2.Last() - anIntervals2.First())
+  const Standard_Real aCellSize = Max(Max(anIntervals1->Last() - anIntervals1->First(),
+                                      anIntervals2->Last() - anIntervals2->First())
                                       * Precision::PConfusion() / (2.0 * Sqrt(2.0)),
                                       Precision::PConfusion());
   Extrema_CCPointsInspector anInspector(aCellSize);
@@ -303,10 +410,10 @@ void Extrema_GenExtCC::Perform()
   {
     for(j = 1; j <= aNbInter[1]; j++)
     {
-      aFirstBorderInterval(1) = anIntervals1(i);
-      aFirstBorderInterval(2) = anIntervals2(j); 
-      aSecondBorderInterval(1) = anIntervals1(i + 1);
-      aSecondBorderInterval(2) = anIntervals2(j + 1);
+      aFirstBorderInterval(1) = anIntervals1->Value(i);
+      aFirstBorderInterval(2) = anIntervals2->Value(j); 
+      aSecondBorderInterval(1) = anIntervals1->Value(i + 1);
+      aSecondBorderInterval(2) = anIntervals2->Value(j + 1);
 
       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
       aFinder.Perform(GetSingleSolutionFlag());
diff --git a/tests/bugs/modalg_7/bug29535 b/tests/bugs/modalg_7/bug29535
new file mode 100644 (file)
index 0000000..2c401a1
--- /dev/null
@@ -0,0 +1,20 @@
+puts "========"
+puts "OCC29535"
+puts "========"
+puts ""
+#################################################
+# [Regression] BRepExtrema_DistShapeShape returns only one solution but the wires have two intersections .
+#################################################
+
+restore [locate_data_file bug29535_shapes.brep] s
+explode s
+distmini res s_1 s_2
+
+
+if { ([isdraw res] && [isdraw res2]) } {
+  checknbshapes res -vertex 1 -edge 0
+  checknbshapes res2 -vertex 1 -edge 0
+} else { puts "Error : result of distmini is wrong" }
+
+
+