From ba7f665dce92eb21ac0031497558d14de17fa4d3 Mon Sep 17 00:00:00 2001 From: ifv Date: Thu, 10 Jan 2019 13:07:01 +0300 Subject: [PATCH] 0030435: Improving performance of Approx_ComputeCLine 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 --- src/Approx/Approx_ComputeCLine.gxx | 133 +++++++++++++--- src/Approx/Approx_FitAndDivide.hxx | 7 + src/Approx/Approx_FitAndDivide2d.hxx | 8 +- src/BRepCheck/BRepCheck_Face.cxx | 4 +- src/BRepFill/BRepFill_ComputeCLine.hxx | 7 + .../BRepTopAdaptor_FClass2d.cxx | 13 +- src/ChFi3d/ChFi3d_Builder_6.cxx | 36 ++++- src/Extrema/Extrema_ExtElC.cxx | 9 ++ .../GeomliteTest_CurveCommands.cxx | 146 ++++++++++++++++++ src/IntTools/IntTools_EdgeEdge.cxx | 19 +++ src/ProjLib/ProjLib_ComputeApprox.cxx | 21 ++- .../ProjLib_ComputeApproxOnPolarSurface.cxx | 59 ++++++- .../ProjLib_ComputeApproxOnPolarSurface.hxx | 2 +- src/ProjLib/ProjLib_ProjectOnPlane.cxx | 13 +- src/QABugs/QABugs_20.cxx | 127 +++++++++++++++ tests/bugs/mesh/bug30008_2 | 2 +- tests/bugs/modalg_7/bug27711_3 | 3 - tests/de/step_4/D9 | 4 +- tests/de/step_4/E1 | 2 +- tests/lowalgos/intss/bug27263 | 3 +- tests/perf/moddata/bug30435 | 46 ++++++ 21 files changed, 611 insertions(+), 53 deletions(-) create mode 100644 tests/perf/moddata/bug30435 diff --git a/src/Approx/Approx_ComputeCLine.gxx b/src/Approx/Approx_ComputeCLine.gxx index d13c01e6e3..c9e7ed838d 100644 --- a/src/Approx/Approx_ComputeCLine.gxx +++ b/src/Approx/Approx_ComputeCLine.gxx @@ -25,6 +25,8 @@ #include #include +const static Standard_Integer MAXSEGM = 1000; + //======================================================================= //function : Approx_ComputeCLine //purpose : The MultiLine 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; } @@ -335,6 +423,15 @@ void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments) myMaxSegments = 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, diff --git a/src/Approx/Approx_FitAndDivide.hxx b/src/Approx/Approx_FitAndDivide.hxx index f33f83e243..552af14087 100644 --- a/src/Approx/Approx_FitAndDivide.hxx +++ b/src/Approx/Approx_FitAndDivide.hxx @@ -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; }; diff --git a/src/Approx/Approx_FitAndDivide2d.hxx b/src/Approx/Approx_FitAndDivide2d.hxx index 829bd82fcb..c1d4283b3e 100644 --- a/src/Approx/Approx_FitAndDivide2d.hxx +++ b/src/Approx/Approx_FitAndDivide2d.hxx @@ -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; }; diff --git a/src/BRepCheck/BRepCheck_Face.cxx b/src/BRepCheck/BRepCheck_Face.cxx index fd500c5e53..d185feb409 100644 --- a/src/BRepCheck/BRepCheck_Face.cxx +++ b/src/BRepCheck/BRepCheck_Face.cxx @@ -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; diff --git a/src/BRepFill/BRepFill_ComputeCLine.hxx b/src/BRepFill/BRepFill_ComputeCLine.hxx index 5391c41aae..273515069a 100644 --- a/src/BRepFill/BRepFill_ComputeCLine.hxx +++ b/src/BRepFill/BRepFill_ComputeCLine.hxx @@ -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; }; diff --git a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx index 1ab9716ece..aa332b7c1c 100644 --- a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx +++ b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx @@ -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(FlecheU0.0)? 1 : 0)); - TabOrien.Append(((square < 0.0)? 1 : 0)); }//if(nbpoints>3 else { diff --git a/src/ChFi3d/ChFi3d_Builder_6.cxx b/src/ChFi3d/ChFi3d_Builder_6.cxx index a43192a558..58188b7901 100644 --- a/src/ChFi3d/ChFi3d_Builder_6.cxx +++ b/src/ChFi3d/ChFi3d_Builder_6.cxx @@ -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(); diff --git a/src/Extrema/Extrema_ExtElC.cxx b/src/Extrema/Extrema_ExtElC.cxx index 8c81128afa..c3d08e2a98 100644 --- a/src/Extrema/Extrema_ExtElC.cxx +++ b/src/Extrema/Extrema_ExtElC.cxx @@ -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; diff --git a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx index 180bae2373..426d8d7981 100644 --- a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx +++ b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx @@ -108,10 +108,61 @@ #include #include #include + +#include +#include +#include +#include +#include + #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& /*thePnt2d*/, + NCollection_Array1& thePnt) const + { + thePnt(1) = myCurve->Value(theT); + return Standard_True; + } + + Standard_Boolean D1(const Standard_Real theT, + NCollection_Array1& /*theVec2d*/, + NCollection_Array1& 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); diff --git a/src/IntTools/IntTools_EdgeEdge.cxx b/src/IntTools/IntTools_EdgeEdge.cxx index 38c36465d7..78ef6ab78d 100644 --- a/src/IntTools/IntTools_EdgeEdge.cxx +++ b/src/IntTools/IntTools_EdgeEdge.cxx @@ -35,6 +35,7 @@ #include #include #include +#include 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 diff --git a/src/ProjLib/ProjLib_ComputeApprox.cxx b/src/ProjLib/ProjLib_ComputeApprox.cxx index 5090998187..e71fe844a6 100644 --- a/src/ProjLib/ProjLib_ComputeApprox.cxx +++ b/src/ProjLib/ProjLib_ComputeApprox.cxx @@ -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.) diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index c104aa09ee..14a5f98616 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -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); } diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx index 3927f2759c..393c8c68db 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx @@ -142,7 +142,7 @@ private: Standard_Integer myMaxSegments; Standard_Real myMaxDist; AppParCurves_Constraint myBndPnt; - + Standard_Real myDist; }; diff --git a/src/ProjLib/ProjLib_ProjectOnPlane.cxx b/src/ProjLib/ProjLib_ProjectOnPlane.cxx index 61375aa3ed..b059fcadfa 100644 --- a/src/ProjLib/ProjLib_ProjectOnPlane.cxx +++ b/src/ProjLib/ProjLib_ProjectOnPlane.cxx @@ -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++) { diff --git a/src/QABugs/QABugs_20.cxx b/src/QABugs/QABugs_20.cxx index 6d92a0e549..09653f6e70 100644 --- a/src/QABugs/QABugs_20.cxx +++ b/src/QABugs/QABugs_20.cxx @@ -3098,6 +3098,132 @@ static Standard_Integer QAEndsWith(Draw_Interpretor& di, Standard_Integer n, con return 1; } +//Class is used in OCC30435 +#include +#include +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& /*thePnt2d*/, + NCollection_Array1& thePnt) const + { + thePnt(1) = myCurve->Value(theT); + return Standard_True; + } + + Standard_Boolean D1(const Standard_Real theT, + NCollection_Array1& /*theVec2d*/, + NCollection_Array1& theVec) const + { + gp_Pnt aDummyPnt; + myCurve->D1(theT, aDummyPnt, theVec(1)); + return Standard_True; + } +}; + +#include +#include +#include +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", diff --git a/tests/bugs/mesh/bug30008_2 b/tests/bugs/mesh/bug30008_2 index 7daf3f0f66..e7997c15bc 100644 --- a/tests/bugs/mesh/bug30008_2 +++ b/tests/bugs/mesh/bug30008_2 @@ -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 diff --git a/tests/bugs/modalg_7/bug27711_3 b/tests/bugs/modalg_7/bug27711_3 index bf3a0afc64..d76d1cd245 100644 --- a/tests/bugs/modalg_7/bug27711_3 +++ b/tests/bugs/modalg_7/bug27711_3 @@ -1,6 +1,3 @@ -puts "TODO CR27711 Linux: Tcl Exception: tolerance ang : 0.01" -puts "TODO CR27711 Linux: TEST INCOMPLETE" - puts "========" puts "OCC27711" puts "========" diff --git a/tests/de/step_4/D9 b/tests/de/step_4/D9 index b824324113..8bc1f9c450 100644 --- a/tests/de/step_4/D9 +++ b/tests/de/step_4/D9 @@ -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 ) diff --git a/tests/de/step_4/E1 b/tests/de/step_4/E1 index 449a5797b3..fc7ab98fb3 100644 --- a/tests/de/step_4/E1 +++ b/tests/de/step_4/E1 @@ -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 ) diff --git a/tests/lowalgos/intss/bug27263 b/tests/lowalgos/intss/bug27263 index f6c316ede9..9471b1eb4d 100644 --- a/tests/lowalgos/intss/bug27263 +++ b/tests/lowalgos/intss/bug27263 @@ -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 index 0000000000..934405e6b9 --- /dev/null +++ b/tests/perf/moddata/bug30435 @@ -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 + + + + + -- 2.39.5