0030435: Improving performance of Approx_ComputeCLine
authorifv <ifv@opencascade.com>
Thu, 10 Jan 2019 10:07:01 +0000 (13:07 +0300)
committerifv <ifv@opencascade.com>
Mon, 22 Apr 2019 11:03:45 +0000 (14:03 +0300)
1. Approx_ComputeCLine.gxx, Approx_FitAndDivide.hxx, Approx_FitAndDivide2d.hxx, BRepFill_ComputeCLine.hxx
It is base modification, which allows improve performance of approximation with help of Approx_ComputeCLine. The main idea of improvement is using degree selection by inverse order - from maxdegree to mindegree. If tolerance for maxdegree is not reached, there is no sense to make approximation for current number of knots with lower degree, it is necessary to cut parametric interval.

2. ProjLib_ComputeApprox, ProjLib_ComputeApproxOnPolarSurface, ProjLib_ComputeApproxOnPolarSurface, ProjLib_ProjectOnPlane
It is additional modification of methods using Approx_ComputeCLine.
Mainly, modifications concern to more optimal choosing parameters for approximation algorithm.

3. BRepCheck_Face
Small improvement of method Intersect(...), which intersects two wires on face.

4. BRepTopAdaptor_FClass2d
Impovement of treatment infinitely narrow faces.

5. ChFi3d/ChFi3d_Builder_6.cxx
Small improvement, which forbids extension of singular boundary of surface.
It was TODO problem in tests/bugs/modalg_7/bug27711_3

6. IntTools_EdgeEdge.cxx
Improvement of performance for cases of searching common parts between line  and analytical curve

7. GeomliteTest_CurveCommands.cxx
Adding Draw command fitcurve. This command is analog of approxcurve, but uses Approx_FitAndDivide algorithm.
Mainly to have direct draw command for testing Approx_ComputeCLine.

8. Extrema_ExtElC.cxx

Treatment of case "infinite solutions" for extrema line-ellipse

9. Modification of some tests according to new behavior of algorithm.

10. tests/perf/moddata/bug30435
Test for new improved algorithm.

11. Implementation QAcommand OCC30435 in QABugs_20.cxx used in test bug30435

21 files changed:
src/Approx/Approx_ComputeCLine.gxx
src/Approx/Approx_FitAndDivide.hxx
src/Approx/Approx_FitAndDivide2d.hxx
src/BRepCheck/BRepCheck_Face.cxx
src/BRepFill/BRepFill_ComputeCLine.hxx
src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx
src/ChFi3d/ChFi3d_Builder_6.cxx
src/Extrema/Extrema_ExtElC.cxx
src/GeomliteTest/GeomliteTest_CurveCommands.cxx
src/IntTools/IntTools_EdgeEdge.cxx
src/ProjLib/ProjLib_ComputeApprox.cxx
src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx
src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx
src/ProjLib/ProjLib_ProjectOnPlane.cxx
src/QABugs/QABugs_20.cxx
tests/bugs/mesh/bug30008_2
tests/bugs/modalg_7/bug27711_3
tests/de/step_4/D9
tests/de/step_4/E1
tests/lowalgos/intss/bug27263
tests/perf/moddata/bug30435 [new file with mode: 0644]

index d13c01e..c9e7ed8 100644 (file)
@@ -25,6 +25,8 @@
 #include <Approx_Status.hxx>
 #include <Precision.hxx>
 
+const static Standard_Integer MAXSEGM = 1000;
+
 //=======================================================================
 //function : Approx_ComputeCLine
 //purpose  : The MultiLine <Line> will be approximated until tolerances
@@ -50,7 +52,8 @@ const AppParCurves_Constraint LastC)
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
-  myMaxSegments = IntegerLast();
+  myMaxSegments = MAXSEGM;
+  myInvOrder = Standard_True;
   alldone = Standard_False;
   Perform(Line);
 }
@@ -77,7 +80,8 @@ const AppParCurves_Constraint LastC)
   mycut = cutting;
   myfirstC = FirstC;
   mylastC = LastC;
-  myMaxSegments = IntegerLast();
+  myMaxSegments = MAXSEGM;
+  myInvOrder = Standard_True;
 }
 
 //=======================================================================
@@ -244,33 +248,117 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
 {
 
 
-  Standard_Integer deg, NbPoints = 24;
+  const Standard_Integer NbPointsMax = 24;
+  const Standard_Real aMinRatio = 0.05;
+  const Standard_Integer aMaxDeg = 8;
+  //
+  Standard_Integer deg, NbPoints;
   Standard_Boolean mydone;
   Standard_Real Fv;
 
-  for (deg = mydegremin; deg <= mydegremax; deg++) {
-
-    AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
-    mydone = LSquare.IsDone();
-    if (mydone) {
-      LSquare.Error(Fv, TheTol3d, TheTol2d);
-      if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
+  AppParCurves_MultiCurve aPrevCurve;
+  Standard_Real aPrevTol3d = RealLast(), aPrevTol2d = RealLast();
+  Standard_Boolean aPrevIsOk = Standard_False;
+  Standard_Boolean anInvOrder = myInvOrder;
+  if (anInvOrder && mydegremax > aMaxDeg)
+  {
+    if ((Ulast - Ufirst) / (Line.LastParameter() - Line.FirstParameter()) < aMinRatio)
+    {
+      anInvOrder = Standard_False;
+    }
+  }
+  if (anInvOrder)
+  {
+    for (deg = mydegremax; deg >= mydegremin; deg--) {
+      NbPoints = Min(2 * deg + 1, NbPointsMax);
+      AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
+      mydone = LSquare.IsDone();
+      if (mydone)
+      {
+        LSquare.Error(Fv, TheTol3d, TheTol2d);
+        if (TheTol3d <= mytol3d && TheTol2d <= mytol2d)
+        {
+          if (deg == mydegremin)
+          {
+            // Stockage de la multicurve approximee.
+            tolreached = Standard_True;
+            myMultiCurves.Append(LSquare.Value());
+            myfirstparam.Append(Ufirst);
+            mylastparam.Append(Ulast);
+            Tolers3d.Append(TheTol3d);
+            Tolers2d.Append(TheTol2d);
+            return Standard_True;
+          }
+          aPrevTol3d = TheTol3d;
+          aPrevTol2d = TheTol2d;
+          aPrevCurve = LSquare.Value();
+          aPrevIsOk = Standard_True;
+          continue;
+        }
+        else if (aPrevIsOk)
+        {
+          // Stockage de la multicurve approximee.
+          tolreached = Standard_True;
+          TheTol3d = aPrevTol3d;
+          TheTol2d = aPrevTol2d;
+          myMultiCurves.Append(aPrevCurve);
+          myfirstparam.Append(Ufirst);
+          mylastparam.Append(Ulast);
+          Tolers3d.Append(aPrevTol3d);
+          Tolers2d.Append(aPrevTol2d);
+          return Standard_True;
+        }
+      }
+      else if (aPrevIsOk)
+      {
         // Stockage de la multicurve approximee.
         tolreached = Standard_True;
-        myMultiCurves.Append(LSquare.Value());
+        TheTol3d = aPrevTol3d;
+        TheTol2d = aPrevTol2d;
+        myMultiCurves.Append(aPrevCurve);
         myfirstparam.Append(Ufirst);
         mylastparam.Append(Ulast);
-        Tolers3d.Append(TheTol3d);
-        Tolers2d.Append(TheTol2d);
+        Tolers3d.Append(aPrevTol3d);
+        Tolers2d.Append(aPrevTol2d);
         return Standard_True;
       }
+      if (!aPrevIsOk && deg == mydegremax)
+      {
+        TheMultiCurve = LSquare.Value();
+        currenttol3d = TheTol3d;
+        currenttol2d = TheTol2d;
+        aPrevTol3d = TheTol3d;
+        aPrevTol2d = TheTol2d;
+        aPrevCurve = TheMultiCurve;
+        break;
+      }
     }
-    if (deg == mydegremax) {
-      TheMultiCurve = LSquare.Value();
-      currenttol3d = TheTol3d;
-      currenttol2d = TheTol2d;
+  }
+  else
+  {
+    for (deg = mydegremin; deg <= mydegremax; deg++) {
+      NbPoints = Min(2 * deg + 1, NbPointsMax);
+      AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
+      mydone = LSquare.IsDone();
+      if (mydone) {
+        LSquare.Error(Fv, TheTol3d, TheTol2d);
+        if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
+          // Stockage de la multicurve approximee.
+          tolreached = Standard_True;
+          myMultiCurves.Append(LSquare.Value());
+          myfirstparam.Append(Ufirst);
+          mylastparam.Append(Ulast);
+          Tolers3d.Append(TheTol3d);
+          Tolers2d.Append(TheTol2d);
+          return Standard_True;
+        }
+      }
+      if (deg == mydegremax) {
+        TheMultiCurve = LSquare.Value();
+        currenttol3d = TheTol3d;
+        currenttol2d = TheTol2d;
+      }
     }
-
   }
   return Standard_False;
 }
@@ -336,6 +424,15 @@ void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
 }
 
 //=======================================================================
+//function : SetInvOrder
+//purpose  : 
+//=======================================================================
+void Approx_ComputeCLine::SetInvOrder(const Standard_Boolean theInvOrder)
+{
+  myInvOrder = theInvOrder;
+}
+
+//=======================================================================
 //function : IsAllApproximated
 //purpose  : returns False if at a moment of the approximation,
 //           the status NoApproximation has been sent by the user
index f33f83e..552af14 100644 (file)
@@ -64,6 +64,12 @@ public:
   //! Changes the max number of segments, which is allowed for cutting.
   Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
   
+  //! Set inverse order of degree selection:
+  //! if theInvOrdr = true, current degree is chosen by inverse order -
+  //! from maxdegree to mindegree.
+  //! By default inverse order is used.
+  Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder);
+
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
   //! when more points were needed.
@@ -118,6 +124,7 @@ private:
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
   Standard_Integer myMaxSegments;
+  Standard_Boolean myInvOrder;
 
 
 };
index 829bd82..c1d4283 100644 (file)
@@ -64,6 +64,12 @@ public:
   //! Changes the max number of segments, which is allowed for cutting.
   Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
   
+  //! Set inverse order of degree selection:
+  //! if theInvOrdr = true, current degree is chosen by inverse order -
+  //! from maxdegree to mindegree.
+  //! By default inverse order is used.
+  Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder);
+
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
   //! when more points were needed.
@@ -118,7 +124,7 @@ private:
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
   Standard_Integer myMaxSegments;
-
+  Standard_Boolean myInvOrder;
 
 };
 
index fd500c5..d185feb 100644 (file)
@@ -685,7 +685,9 @@ static Standard_Boolean Intersect(const TopoDS_Wire& wir1,
                              for (Standard_Integer j = 1; j <= PntSeq.Length(); j++)
                                {
                                  Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) );
-                                 if (P.IsEqual( PntSeq(j), tolv ))
+                                  tolv += 1.e-8; //possible tolerance of intersection point
+                                  Standard_Real dd = P.SquareDistance(PntSeq(j));
+                                 if (dd <= tolv * tolv)
                                    {
                                      NbCoinc++;
                                      break;
index 5391c41..2735150 100644 (file)
@@ -64,6 +64,12 @@ public:
   //! Changes the max number of segments, which is allowed for cutting.
   Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments);
 
+  //! Set inverse order of degree selection:
+  //! if theInvOrdr = true, current degree is chosen by inverse order -
+  //! from maxdegree to mindegree.
+  //! By default inverse order is used.
+  Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder);
+
   //! returns False if at a moment of the approximation,
   //! the status NoApproximation has been sent by the user
   //! when more points were needed.
@@ -118,6 +124,7 @@ private:
   AppParCurves_Constraint myfirstC;
   AppParCurves_Constraint mylastC;
   Standard_Integer myMaxSegments;
+  Standard_Boolean myInvOrder;
 
 };
 
index 1ab9716..aa332b7 100644 (file)
@@ -105,6 +105,8 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const
   Umin = Vmin = 0.0; //RealLast();
   Umax = Vmax = -Umin;
 
+  Standard_Integer aNbE = 0;
+  Standard_Real eps = 1.e-10;
   Standard_Integer BadWire=0;
   for( FaceExplorer.Init(Face,TopAbs_WIRE); (FaceExplorer.More() && BadWire==0); FaceExplorer.Next() )
     {
@@ -118,6 +120,7 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const
 
       TopExp_Explorer Explorer;
       for( Explorer.Init(FaceExplorer.Current(),TopAbs_EDGE); Explorer.More(); Explorer.Next() ) NbEdges++;
+      aNbE = NbEdges;
         
       gp_Pnt Ancienpnt3d(0,0,0);
       Standard_Boolean Ancienpnt3dinitialise = Standard_False;
@@ -394,6 +397,15 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const
       
              //-- FlecheU*=10.0;
              //-- FlecheV*=10.0;
+              if (aNbE == 1 && FlecheU < eps && FlecheV < eps && Abs(square) < eps)
+              {
+                TabOrien.Append(1);
+              }
+              else
+              { 
+                TabOrien.Append(((square < 0.0)? 1 : 0));
+              }
+             
              if(FlecheU<Toluv) FlecheU = Toluv;
              if(FlecheV<Toluv) FlecheV = Toluv;
              //-- cout<<" U:"<<FlecheU<<" V:"<<FlecheV<<endl;
@@ -411,7 +423,6 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const
 //#endif
 //             } 
 //           else TabOrien.Append(((angle>0.0)? 1 : 0));
-             TabOrien.Append(((square < 0.0)? 1 : 0));
            }//if(nbpoints>3
          else
            { 
index a43192a..58188b7 100644 (file)
@@ -689,14 +689,36 @@ Standard_Boolean ChFi3d_Builder::StoreData(Handle(ChFiDS_SurfData)& Data,
   length2=Data->LastExtensionValue();
 
   Handle(Geom_BoundedSurface) aBndSurf = Surf;
-  if (length1 > Precision::Confusion())
-    GeomLib::ExtendSurfByLength(aBndSurf,length1,1,Standard_False,Standard_False);
-  if (length2 >  Precision::Confusion())
-    GeomLib::ExtendSurfByLength(aBndSurf,length2,1,Standard_False,Standard_True);
-  Surf = Handle(Geom_BSplineSurface)::DownCast (aBndSurf);
+  Standard_Boolean ext1 = Standard_False, ext2 = Standard_False;
+  Standard_Real eps = Max(tolget3d, 2. * Precision::Confusion());
+  if (length1 > eps)
+  {
+    gp_Pnt P11, P21;
+    P11 = Surf->Pole(1, 1);
+    P21 = Surf->Pole(Surf->NbUPoles(), 1);
+    if (P11.Distance(P21) > eps)
+    {
+      //to avoid extending surface with singular boundary
+      GeomLib::ExtendSurfByLength(aBndSurf, length1, 1, Standard_False, Standard_False);
+      ext1 = Standard_True;
+    }
+  }
+  if (length2 > eps)
+  {
+    gp_Pnt P12, P22;
+    P12 = Surf->Pole(1, Surf->NbVPoles());
+    P22 = Surf->Pole(Surf->NbUPoles(), Surf->NbVPoles());
+    if (P12.Distance(P22) > eps)
+    {
+      //to avoid extending surface with singular boundary
+      GeomLib::ExtendSurfByLength(aBndSurf, length2, 1, Standard_False, Standard_True);
+      ext2 = Standard_True;
+    }
+  }
+  Surf = Handle(Geom_BSplineSurface)::DownCast(aBndSurf);
 
   //Correction of surface on extremities
-  if (length1 <= Precision::Confusion())
+  if (!ext1)
   {
     gp_Pnt P11, P21;
     P11 = lin->StartPointOnFirst().Value();
@@ -704,7 +726,7 @@ Standard_Boolean ChFi3d_Builder::StoreData(Handle(ChFiDS_SurfData)& Data,
     Surf->SetPole(1, 1, P11);
     Surf->SetPole(Surf->NbUPoles(), 1, P21);
   }
-  if (length2 <= Precision::Confusion())
+  if (!ext2)
   {
     gp_Pnt P12, P22;
     P12 = lin->EndPointOnFirst().Value();
index 8c81128..c3d08e2 100644 (file)
@@ -674,6 +674,15 @@ Method:
   //
   ExtremaExtElC_TrigonometricRoots Sol(A1,A2,A3,A4,A5,0.,M_PI+M_PI);
   if (!Sol.IsDone()) { return; }
+  //
+  if (Sol.InfiniteRoots()) {
+    myIsPar = Standard_True;
+    gp_Pnt aP = ElCLib::EllipseValue(0., C2.Position(), C2.MajorRadius(), C2.MinorRadius());
+    mySqDist[0] = C1.SquareDistance(aP);
+    myNbExt = 1;
+    myDone = Standard_True;
+    return;
+  }
 
 // Storage of solutions ...
   gp_Pnt P1,P2;
index 180bae2..426d8d7 100644 (file)
 #include <Approx_CurvilinearParameter.hxx>
 #include <Approx_CurveOnSurface.hxx>
 #include <Geom_BSplineSurface.hxx>
+
+#include <AppCont_Function.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <Approx_FitAndDivide.hxx>
+#include <Convert_CompBezierCurvesToBSplineCurve.hxx>
+
 #ifdef _WIN32
 Standard_IMPORT Draw_Viewer dout;
 #endif
 
+//Class is used in fitcurve
+class CurveEvaluator : public AppCont_Function
+
+{
+
+public:
+  Handle(Adaptor3d_HCurve) myCurve;
+
+  CurveEvaluator(const Handle(Adaptor3d_HCurve)& C)
+    : myCurve(C)
+  {
+    myNbPnt = 1;
+    myNbPnt2d = 0;
+  }
+
+  Standard_Real FirstParameter() const
+  {
+    return myCurve->FirstParameter();
+  }
+
+  Standard_Real LastParameter() const
+  {
+    return myCurve->LastParameter();
+  }
+
+  Standard_Boolean Value(const Standard_Real   theT,
+    NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
+    NCollection_Array1<gp_Pnt>&   thePnt) const
+  {
+    thePnt(1) = myCurve->Value(theT);
+    return Standard_True;
+  }
+
+  Standard_Boolean D1(const Standard_Real   theT,
+    NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
+    NCollection_Array1<gp_Vec>&   theVec) const
+  {
+    gp_Pnt aDummyPnt;
+    myCurve->D1(theT, aDummyPnt, theVec(1));
+    return Standard_True;
+  }
+};
+
+
 //=======================================================================
 //function : anacurve
 //purpose  : 
@@ -1672,6 +1723,99 @@ static Standard_Integer approxcurve(Draw_Interpretor& di, Standard_Integer n, co
   return 0;
 }
 
+
+//=======================================================================
+//function : fitcurve
+//purpose  : 
+//=======================================================================
+
+static Standard_Integer fitcurve(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+  if (n<3) return 1;
+
+  Handle(Geom_Curve) GC;
+  GC = DrawTrSurf::GetCurve(a[2]);
+  if (GC.IsNull())
+    return 1;
+
+  Standard_Integer Dmin = 3;
+  Standard_Integer Dmax = 14;
+  Standard_Real Tol3d = 1.e-5;
+  Standard_Boolean inverse = Standard_True;
+
+  if (n > 3)
+  {
+    Tol3d = Atof(a[3]);
+  }
+
+  if (n > 4)
+  {
+    Dmax = atoi(a[4]);
+  }
+
+  if (n > 5)
+  {
+    Standard_Integer inv = atoi(a[5]);
+    if (inv > 0)
+    {
+      inverse = Standard_True;
+    }
+    else
+    {
+      inverse = Standard_False;
+    }
+  }
+
+  Handle(GeomAdaptor_HCurve) aGAC = new GeomAdaptor_HCurve(GC);
+
+  CurveEvaluator aCE(aGAC);
+
+  Approx_FitAndDivide anAppro(Dmin, Dmax, Tol3d, 0., Standard_True);
+  anAppro.SetInvOrder(inverse);
+  anAppro.Perform(aCE);
+
+  if (!anAppro.IsAllApproximated())
+  {
+    di << "Approximation failed \n";
+    return 1;
+  }
+  Standard_Integer i;
+  Standard_Integer NbCurves = anAppro.NbMultiCurves();
+
+  Convert_CompBezierCurvesToBSplineCurve Conv;
+
+  Standard_Real tol3d, tol2d, tolreached = 0.;
+  for (i = 1; i <= NbCurves; i++) {
+    anAppro.Error(i, tol3d, tol2d);
+    tolreached = Max(tolreached, tol3d);
+    AppParCurves_MultiCurve MC = anAppro.Value(i);
+    TColgp_Array1OfPnt Poles(1, MC.Degree() + 1);
+    MC.Curve(1, Poles);
+    Conv.AddCurve(Poles);
+  }
+  Conv.Perform();
+  Standard_Integer NbPoles = Conv.NbPoles();
+  Standard_Integer NbKnots = Conv.NbKnots();
+
+  TColgp_Array1OfPnt      NewPoles(1, NbPoles);
+  TColStd_Array1OfReal    NewKnots(1, NbKnots);
+  TColStd_Array1OfInteger NewMults(1, NbKnots);
+
+  Conv.KnotsAndMults(NewKnots, NewMults);
+  Conv.Poles(NewPoles);
+
+  BSplCLib::Reparametrize(GC->FirstParameter(),
+    GC->LastParameter(),
+    NewKnots);
+  Handle(Geom_BSplineCurve) TheCurve = new Geom_BSplineCurve(NewPoles, NewKnots, NewMults, Conv.Degree());
+
+  DrawTrSurf::Set(a[1], TheCurve);
+  di << a[1] << ": tolreached = " << tolreached << "\n";
+
+  return 0;
+
+}
+
 //=======================================================================
 //function : newbspline
 //purpose  : reduce the multiplicity of the knots to their minimum 
@@ -2060,6 +2204,8 @@ void  GeomliteTest::CurveCommands(Draw_Interpretor& theCommands)
                  __FILE__,
                  approxcurveonsurf,g);
 
+ theCommands.Add("fitcurve", "fitcurve result  curve [tol [maxdeg [inverse]]]", __FILE__, fitcurve, g);
+
  theCommands.Add("length", "length curve [Tol]", 
                  __FILE__,
                  length, g);
index 38c3646..78ef6ab 100644 (file)
@@ -35,6 +35,7 @@
 #include <IntTools_Tools.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
 
 static 
   void BndBuildBox(const BRepAdaptor_Curve& theBAC,
@@ -224,6 +225,24 @@ void IntTools_EdgeEdge::Perform()
     }
   }
   //
+  if ((myCurve1.GetType() <= GeomAbs_Parabola && myCurve2.GetType() <= GeomAbs_Parabola) &&
+      (myCurve1.GetType() == GeomAbs_Line || myCurve2.GetType() == GeomAbs_Line))
+  {
+    //Improvement of performance for cases of searching common parts between line  
+    //and analytical curve. This code allows to define that edges have no
+    //common parts more fast, then regular algorithm (FindSolution(...))
+    //Check minimal distance between edges
+    BRepExtrema_DistShapeShape  aMinDist(myEdge1, myEdge2, Extrema_ExtFlag_MIN);
+    if (aMinDist.IsDone())
+    {
+      Standard_Real d = aMinDist.Value();
+      if (d > 1.1 * myTol)
+      {
+        return;
+      }
+    }
+  }
+
   IntTools_SequenceOfRanges aRanges1, aRanges2;
   //
   //3.2. Find ranges containig solutions
index 5090998..e71fe84 100644 (file)
@@ -1011,6 +1011,15 @@ void ProjLib_ComputeApprox::Perform
                                 (CType != GeomAbs_OtherCurve)     ;
 
   Standard_Boolean simplecase = SurfIsAnal && CurvIsAnal;
+  if (CType == GeomAbs_BSplineCurve || CType == GeomAbs_BezierCurve)
+  {
+    Standard_Integer aNbKnots = 1;
+    if (CType == GeomAbs_BSplineCurve)
+    {
+      aNbKnots = C->NbKnots();
+    }
+    simplecase = simplecase && C->Degree() <= 2 && aNbKnots <= 2;
+  }
 
   if (CType == GeomAbs_BSplineCurve &&
       SType == GeomAbs_Plane ) {
@@ -1111,12 +1120,12 @@ void ProjLib_ComputeApprox::Perform
 #endif    
 
 //-----------
-    Standard_Integer Deg1 = 8, Deg2;
-    if(simplecase) {
-      Deg2 = 10; 
+    Standard_Integer Deg1 = 5, Deg2;
+    if (simplecase) {
+      Deg2 = 8;
     }
     else {
-      Deg2 = 12; 
+      Deg2 = 10;
     }
     if(myDegMin > 0)
     {
@@ -1188,6 +1197,10 @@ void ProjLib_ComputeApprox::Perform
                               C->LastParameter(),
                               NewKnots);
 
+      // Set NewKnots(NbKnots) exactly C->LastParameter()
+      // to avoid problems if trim is used.
+      NewKnots(NbKnots) = C->LastParameter();
+
       // il faut recadrer les poles de debut et de fin:
       // ( Car pour les problemes de couture, on a du ouvrir l`intervalle
       // de definition de la courbe.)
index c104aa0..14a5f98 100644 (file)
@@ -482,7 +482,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface()
   myDegMin(-1), myDegMax(-1),
   myMaxSegments(-1),
   myMaxDist(-1.),
-  myBndPnt(AppParCurves_TangencyPoint)
+  myBndPnt(AppParCurves_TangencyPoint),
+  myDist(0.)
 {
 }
 
@@ -502,7 +503,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
   myDegMin(-1), myDegMax(-1),
   myMaxSegments(-1),
   myMaxDist(-1.),
-  myBndPnt(AppParCurves_TangencyPoint)
+  myBndPnt(AppParCurves_TangencyPoint),
+  myDist(0.)
 {
   myBSpline = Perform(theInitialCurve2d, theCurve, theSurface);
 }
@@ -522,7 +524,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
   myDegMin(-1), myDegMax(-1),
   myMaxSegments(-1),
   myMaxDist(-1.),
-  myBndPnt(AppParCurves_TangencyPoint)
+  myBndPnt(AppParCurves_TangencyPoint),
+  myDist(0.)
 {
   const Handle(Adaptor2d_HCurve2d) anInitCurve2d;
   myBSpline = Perform(anInitCurve2d, theCurve, theSurface);  
@@ -545,7 +548,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface
   myDegMin(-1), myDegMax(-1),
   myMaxSegments(-1),
   myMaxDist(-1.),
-  myBndPnt(AppParCurves_TangencyPoint)
+  myBndPnt(AppParCurves_TangencyPoint),
+  myDist(0.)
 {
   // InitialCurve2d and InitialCurve2dBis are two pcurves of the sewing 
   Handle(Geom2d_BSplineCurve) bsc =
@@ -1079,6 +1083,7 @@ Handle(Adaptor2d_HCurve2d)
   else {
     myProjIsDone = Standard_False;
     Standard_Real Dist2Min = 1.e+200, u = 0., v = 0.;
+    myDist = 0.;
     gp_Pnt pntproj;
 
     TColgp_SequenceOfPnt2d Sols;
@@ -1253,7 +1258,7 @@ Handle(Adaptor2d_HCurve2d)
       // U0 and V0 are the points in the initialized period 
       // (period with u and v),
       // U1 and V1 are the points for construction of poles
-
+      myDist = Dist2Min;
       for ( i = 2 ; i <= NbOfPnts ; i++) 
        if(myProjIsDone) {
          myProjIsDone = Standard_False;
@@ -1267,6 +1272,10 @@ Handle(Adaptor2d_HCurve2d)
            if (aLocateExtPS.SquareDistance() < DistTol3d2)
             {  //OCC217
               //if (aLocateExtPS.SquareDistance() < Tol3d * Tol3d) {
+              if (aLocateExtPS.SquareDistance() > myDist)
+              {
+                myDist = aLocateExtPS.SquareDistance();
+              }
              (aLocateExtPS.Point()).Parameter(U0,V0);
              U1 = U0 + usens*uperiod;
              V1 = V0 + vsens*vperiod;
@@ -1291,6 +1300,10 @@ Handle(Adaptor2d_HCurve2d)
                 }
                 if (LocalMinSqDist < DistTol3d2)
                 {
+                  if (LocalMinSqDist > myDist)
+                  {
+                    myDist = LocalMinSqDist;
+                  }
                   Standard_Real LocalU, LocalV;
                   aGlobalExtr.Point(imin).Parameter(LocalU, LocalV);
                   if (uperiod > 0. && Abs(U0 - LocalU) >= uperiod/2.)
@@ -1363,6 +1376,10 @@ Handle(Adaptor2d_HCurve2d)
            if (locext.IsDone())
              if (locext.SquareDistance() < DistTol3d2) {  //OCC217
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
+                if (locext.SquareDistance() > myDist)
+                {
+                  myDist = locext.SquareDistance();
+                }
                (locext.Point()).Parameter(u,v);
                if((aUsup - U0) > (U0 - aUinf)) 
                  usens--;
@@ -1390,7 +1407,11 @@ Handle(Adaptor2d_HCurve2d)
            if (locext.IsDone())
              if (locext.SquareDistance() < DistTol3d2) {  //OCC217
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
-               (locext.Point()).Parameter(u,v);
+                if (locext.SquareDistance() > myDist)
+                {
+                  myDist = locext.SquareDistance();
+                }
+                (locext.Point()).Parameter(u, v);
                if((aVsup - V0) > (V0 - aVinf)) 
                  vsens--;
                else 
@@ -1419,7 +1440,11 @@ Handle(Adaptor2d_HCurve2d)
            if (locext.IsDone())
              if (locext.SquareDistance() < DistTol3d2) {
              //if (locext.SquareDistance() < Tol3d * Tol3d) {
-               (locext.Point()).Parameter(u,v);
+                if (locext.SquareDistance() > myDist)
+                {
+                  myDist = locext.SquareDistance();
+                }
+                (locext.Point()).Parameter(u, v);
                if((Usup - U0) > (U0 - Uinf)) 
                  usens--;
                else 
@@ -1447,7 +1472,11 @@ Handle(Adaptor2d_HCurve2d)
                }
              if (Dist2Min < DistTol3d2) {
              //if (Dist2Min < Tol3d * Tol3d) {
-               (ext.Point(aGoodValue)).Parameter(u,v);
+                if (Dist2Min > myDist)
+                {
+                  myDist = Dist2Min;
+                }
+                (ext.Point(aGoodValue)).Parameter(u, v);
                if(uperiod) {
                  if((U0 - u) > (2*uperiod/3)) {
                    usens++;
@@ -1862,8 +1891,18 @@ Handle(Geom2d_BSplineCurve)
     aLastC = myBndPnt;
   }
 
+  if (myDist > 10.*Tol3d)
+  {
+    aFistC = AppParCurves_PassPoint; 
+    aLastC = AppParCurves_PassPoint;
+  }
+
   Approx_FitAndDivide2d Fit(Deg1, Deg2, Tol3d, Tol2d, Standard_True, aFistC, aLastC);
   Fit.SetMaxSegments(aMaxSegments);
+  if (InitCurve2d->GetType() == GeomAbs_Line)
+  {
+    Fit.SetInvOrder(Standard_False);
+  }
   Fit.Perform(F);
 
   Standard_Real anOldTol2d = Tol2d;
@@ -1936,6 +1975,10 @@ Handle(Geom2d_BSplineCurve)
 
     Standard_Boolean OK = Standard_True;
     Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d);
+    if (myBndPnt == AppParCurves_PassPoint)
+    {
+      aSmoothTol *= 10.;
+    }
     for (Standard_Integer ij = 2; ij < NbKnots; ij++) {
       OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1, aSmoothTol);  
     }
index 3927f27..393c8c6 100644 (file)
@@ -142,7 +142,7 @@ private:
   Standard_Integer myMaxSegments;
   Standard_Real myMaxDist;
   AppParCurves_Constraint myBndPnt;
-
+  Standard_Real myDist;
 
 };
 
index 61375aa..b059fca 100644 (file)
@@ -317,8 +317,14 @@ static void  PerformApprox (const Handle(Adaptor3d_HCurve)& C,
   Standard_Integer Deg1, Deg2;
   Deg1 = 8; Deg2 = 8;
   
-  Approx_FitAndDivide Fit(F,Deg1,Deg2,Precision::Approximation(),
+  Approx_FitAndDivide Fit(Deg1,Deg2,Precision::Approximation(),
                          Precision::PApproximation(),Standard_True);
+  Fit.SetMaxSegments(100);
+  Fit.Perform(F);
+  if (!Fit.IsAllApproximated())
+  {
+    return;
+  }
   Standard_Integer i;
   Standard_Integer NbCurves = Fit.NbMultiCurves();
   Standard_Integer MaxDeg = 0;
@@ -347,9 +353,8 @@ static void  PerformApprox (const Handle(Adaptor3d_HCurve)& C,
     MC.Curve(1, LocalPoles);
     
     //Augmentation eventuelle du degre
-    Standard_Integer Inc = MaxDeg - MC.Degree();
-    if ( Inc > 0) {
-      BSplCLib::IncreaseDegree(Inc, Poles, BSplCLib::NoWeights(),
+    if (MaxDeg > MC.Degree() ) {
+      BSplCLib::IncreaseDegree(MaxDeg, LocalPoles, BSplCLib::NoWeights(),
                               TempPoles, BSplCLib::NoWeights());
       //mise a jour des poles de la PCurve
       for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) {
index 6d92a0e..09653f6 100644 (file)
@@ -3098,6 +3098,132 @@ static Standard_Integer QAEndsWith(Draw_Interpretor& di, Standard_Integer n, con
   return 1;
 }
 
+//Class is used in OCC30435
+#include <AppCont_Function.hxx>
+#include <Adaptor3d_HCurve.hxx>
+class CurveEvaluator : public AppCont_Function
+
+{
+
+public:
+  Handle(Adaptor3d_HCurve) myCurve;
+
+  CurveEvaluator(const Handle(Adaptor3d_HCurve)& C)
+    : myCurve(C)
+  {
+    myNbPnt = 1;
+    myNbPnt2d = 0;
+  }
+
+  Standard_Real FirstParameter() const
+  {
+    return myCurve->FirstParameter();
+  }
+
+  Standard_Real LastParameter() const
+  {
+    return myCurve->LastParameter();
+  }
+
+  Standard_Boolean Value(const Standard_Real   theT,
+    NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
+    NCollection_Array1<gp_Pnt>&   thePnt) const
+  {
+    thePnt(1) = myCurve->Value(theT);
+    return Standard_True;
+  }
+
+  Standard_Boolean D1(const Standard_Real   theT,
+    NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
+    NCollection_Array1<gp_Vec>&   theVec) const
+  {
+    gp_Pnt aDummyPnt;
+    myCurve->D1(theT, aDummyPnt, theVec(1));
+    return Standard_True;
+  }
+};
+
+#include <GeomAdaptor_HCurve.hxx>
+#include <Approx_FitAndDivide.hxx>
+#include <Convert_CompBezierCurvesToBSplineCurve.hxx>
+static Standard_Integer OCC30435(Draw_Interpretor& di, Standard_Integer, const char** a)
+{
+
+  Handle(Geom_Curve) GC;
+  GC = DrawTrSurf::GetCurve(a[2]);
+  if (GC.IsNull())
+    return 1;
+
+  Standard_Integer Dmin = 3;
+  Standard_Integer Dmax = 12;
+  Standard_Real Tol3d = 1.e-7;
+  Standard_Boolean inverse = Standard_True;
+
+
+  Standard_Integer inv = atoi(a[3]);
+  if (inv > 0)
+  {
+    inverse = Standard_True;
+  }
+  else
+  {
+    inverse = Standard_False;
+  }
+
+  Standard_Integer maxit = atoi(a[4]);
+
+  Handle(GeomAdaptor_HCurve) aGAC = new GeomAdaptor_HCurve(GC);
+
+  CurveEvaluator aCE(aGAC);
+
+  Approx_FitAndDivide anAppro(Dmin, Dmax, Tol3d, 0., Standard_True);
+  anAppro.SetInvOrder(inverse);
+  Standard_Integer i;
+  for (i = 1; i <= maxit; ++i)
+    anAppro.Perform(aCE);
+
+  if (!anAppro.IsAllApproximated())
+  {
+    di << "Approximation failed \n";
+    return 1;
+  }
+  Standard_Integer NbCurves = anAppro.NbMultiCurves();
+
+  Convert_CompBezierCurvesToBSplineCurve Conv;
+
+  Standard_Real tol3d, tol2d, tolreached = 0.;
+  for (i = 1; i <= NbCurves; i++) {
+    anAppro.Error(i, tol3d, tol2d);
+    tolreached = Max(tolreached, tol3d);
+    AppParCurves_MultiCurve MC = anAppro.Value(i);
+    TColgp_Array1OfPnt Poles(1, MC.Degree() + 1);
+    MC.Curve(1, Poles);
+    Conv.AddCurve(Poles);
+  }
+  Conv.Perform();
+  Standard_Integer NbPoles = Conv.NbPoles();
+  Standard_Integer NbKnots = Conv.NbKnots();
+
+  TColgp_Array1OfPnt      NewPoles(1, NbPoles);
+  TColStd_Array1OfReal    NewKnots(1, NbKnots);
+  TColStd_Array1OfInteger NewMults(1, NbKnots);
+
+  Conv.KnotsAndMults(NewKnots, NewMults);
+  Conv.Poles(NewPoles);
+
+  BSplCLib::Reparametrize(GC->FirstParameter(),
+    GC->LastParameter(),
+    NewKnots);
+  Handle(Geom_BSplineCurve) TheCurve = new Geom_BSplineCurve(NewPoles, NewKnots, NewMults, Conv.Degree());
+
+  DrawTrSurf::Set(a[1], TheCurve);
+  di << a[1] << ": tolreached = " << tolreached << "\n";
+
+  return 0;
+
+}
+
+
 void QABugs::Commands_20(Draw_Interpretor& theCommands) {
   const char *group = "QABugs";
 
@@ -3138,6 +3264,7 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
   theCommands.Add("OCC29807", "OCC29807 surface1 surface2 u1 v1 u2 v2", __FILE__, OCC29807, group);
   theCommands.Add("OCC29311", "OCC29311 shape counter nbiter: check performance of OBB calculation", __FILE__, OCC29311, group);
   theCommands.Add("OCC30391", "OCC30391 result face LenBeforeUfirst LenAfterUlast LenBeforeVfirst LenAfterVlast", __FILE__, OCC30391, group);
+  theCommands.Add("OCC30435", "OCC30435 result curve inverse nbit", __FILE__, OCC30435, group);
 
   theCommands.Add("QAStartsWith",
                   "QAStartsWith string startstring",
index 7daf3f0..e7997c1 100644 (file)
@@ -19,7 +19,7 @@ nurbsconvert result result
 incmesh result 0.15 -a 20
 
 tricheck result
-checktrinfo result -tri 193 -nod 147 -defl 0.042090809832482222 -tol_abs_defl 1.0e-7
+checktrinfo result -tri 193 -nod 147 -defl 0.04209 -tol_abs_defl 1.0e-6
 
 vinit
 
index bf3a0af..d76d1cd 100644 (file)
@@ -1,6 +1,3 @@
-puts "TODO CR27711 Linux: Tcl Exception: tolerance ang : 0.01"
-puts "TODO CR27711 Linux: TEST INCOMPLETE"
-
 puts "========"
 puts "OCC27711"
 puts "========"
index b824324..8bc1f9c 100644 (file)
@@ -6,11 +6,11 @@ set filename test-m020306-v1.stp
 
 set ref_data {
 DATA        : Faulties = 0  ( 0 )  Warnings = 0  ( 0 )  Summary  = 0  ( 0 )
-TPSTAT      : Faulties = 0  ( 0 )  Warnings = 151  ( 114 )  Summary  = 151  ( 114 )
+TPSTAT      : Faulties = 0  ( 0 )  Warnings = 153  ( 114 )  Summary  = 153  ( 114 )
 CHECKSHAPE  : Wires    = 0  ( 0 )  Faces    = 0  ( 0 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
 NBSHAPES    : Solid    = 1  ( 1 )  Shell    = 1  ( 1 )  Face     = 742  ( 742 ) 
 STATSHAPE   : Solid    = 1  ( 1 )  Shell    = 1  ( 1 )  Face     = 742  ( 742 )   FreeWire = 0  ( 0 ) 
-TOLERANCE   : MaxTol   = 0.008481946718  (  0.01609778278 )  AvgTol   =  0.000132185171  (  0.0003164960473 )
+TOLERANCE   : MaxTol   = 0.008481946718  (  0.01167623167 )  AvgTol   =  0.000132472064  (  0.0003097606769 )
 LABELS      : N0Labels = 1  ( 1 )  N1Labels = 0  ( 0 )  N2Labels = 0  ( 0 )   TotalLabels = 1  ( 1 )   NameLabels = 1  ( 1 )   ColorLabels = 0  ( 0 )   LayerLabels = 0  ( 0 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )
 NCOLORS     : NColors  = 0  ( 0 )
index 449a579..fc7ab98 100644 (file)
@@ -7,7 +7,7 @@ TPSTAT      : Faulties = 0  ( 0 )  Warnings = 61  ( 157 )  Summary  = 61  ( 157
 CHECKSHAPE  : Wires    = 0  ( 0 )  Faces    = 0  ( 0 )  Shells   = 0  ( 0 )   Solids   = 0 ( 0 )
 NBSHAPES    : Solid    = 1  ( 1 )  Shell    = 1  ( 1 )  Face     = 956  ( 956 ) 
 STATSHAPE   : Solid    = 1  ( 1 )  Shell    = 1  ( 1 )  Face     = 956  ( 956 )   FreeWire = 0  ( 0 ) 
-TOLERANCE   : MaxTol   = 0.008481946718  (  0.01609778278 )  AvgTol   =  0.0001239210368  (  0.0003823229569 )
+TOLERANCE   : MaxTol   = 0.008481946718  (  0.05394823207 )  AvgTol   =  0.0001239210367  (  0.0004089750747 )
 LABELS      : N0Labels = 1  ( 1 )  N1Labels = 0  ( 0 )  N2Labels = 0  ( 0 )   TotalLabels = 1  ( 1 )   NameLabels = 1  ( 1 )   ColorLabels = 0  ( 0 )   LayerLabels = 0  ( 0 )
 PROPS       : Centroid = 0  ( 0 )  Volume   = 0  ( 0 )  Area     = 0  ( 0 )
 NCOLORS     : NColors  = 0  ( 0 )
index f6c316e..9471b1e 100644 (file)
@@ -7,7 +7,7 @@ puts ""
 #######################################################################
 
 set MaxTol 1.e-7
-set GoodNbCurv 1
+set GoodNbCurv 2
 
 restore [locate_data_file  bug27262_cmpd.brep] b
 explode b
@@ -30,5 +30,6 @@ if {${NbCurv} != ${GoodNbCurv}} {
 }
 
 checklength c_1 -l 2.9620641619623407
+checklength c_2 -l 3.1050603628884668
 
 checkview -screenshot -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
diff --git a/tests/perf/moddata/bug30435 b/tests/perf/moddata/bug30435
new file mode 100644 (file)
index 0000000..934405e
--- /dev/null
@@ -0,0 +1,46 @@
+puts "========"
+puts "BUG30435"
+puts "Improving performance of Approx_ComputeCLine"
+puts "========"
+puts ""
+
+pload QAcommands
+cone con 0 0 0 0 0 -1 1 0 0 -30 0
+2dbeziercurve b 4 0 0 15 15 35 -15 50 1.
+approxcurveonsurf cc b con  1.e-7 1 12 1000
+clear con
+clpoles cc
+
+set time0 ""
+set time1 ""
+
+dchrono t0 restart
+OCC30435 r0 cc 0 50
+dchrono t0 stop 
+set inf0 [dchrono t0 counter OCC30435] 
+
+regexp {COUNTER OCC30435: ([-0-9.+eE]+)} $inf0 full0 time0
+
+dchrono t1 restart
+OCC30435 r1 cc 1 50
+dchrono t1 stop
+set inf1 [dchrono t1 counter OCC30435_1] 
+regexp {COUNTER OCC30435_1: ([-0-9.+eE]+)} $inf1 full1 time1
+
+if { $time1 > $time0 } {
+    puts "Error : optimized algorithm works slowly then initial one"
+} else {
+    puts "Performance ratio is [expr $time0/$time1]"
+}
+
+clpoles r0
+clpoles r1
+smallview
+fit
+xwd $imagedir/${test_image}.png
+
+
+
+
+