diff --git a/src/BRepExtrema/BRepExtrema_ExtCC.cxx b/src/BRepExtrema/BRepExtrema_ExtCC.cxx index 9ca3b84ade..c4fbdc97eb 100644 --- a/src/BRepExtrema/BRepExtrema_ExtCC.cxx +++ b/src/BRepExtrema/BRepExtrema_ExtCC.cxx @@ -65,6 +65,7 @@ void BRepExtrema_ExtCC::Perform(const TopoDS_Edge& E1) BRep_Tool::Range(E1,U1,U2); myExtCC.SetCurve (1, HC->Curve(), U1, U2); myExtCC.SetTolerance(1, Tol); + myExtCC.SetSingleSolutionFlag(Standard_True); myExtCC.Perform(); } diff --git a/src/Extrema/Extrema_ECC.hxx b/src/Extrema/Extrema_ECC.hxx index c4f7f8a652..c3f1b529bc 100644 --- a/src/Extrema/Extrema_ECC.hxx +++ b/src/Extrema/Extrema_ECC.hxx @@ -55,7 +55,13 @@ public: Standard_EXPORT void SetParams (const Adaptor3d_Curve& C1, const Adaptor3d_Curve& C2, const Standard_Real Uinf, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup); Standard_EXPORT void SetTolerance (const Standard_Real Tol); - + + //! Set flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag); + + //! Get flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const; + Standard_EXPORT void Perform(); Standard_EXPORT Standard_Boolean IsDone() const; @@ -80,7 +86,7 @@ protected: private: - + Standard_Boolean myIsFindSingleSolution; // Default value is false. Standard_Boolean myParallel; Standard_Real myCurveMinTol; math_Vector myLowBorder; diff --git a/src/Extrema/Extrema_ECC2d.hxx b/src/Extrema/Extrema_ECC2d.hxx index 3b37ee9c79..c339723b30 100644 --- a/src/Extrema/Extrema_ECC2d.hxx +++ b/src/Extrema/Extrema_ECC2d.hxx @@ -55,7 +55,13 @@ public: Standard_EXPORT void SetParams (const Adaptor2d_Curve2d& C1, const Adaptor2d_Curve2d& C2, const Standard_Real Uinf, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup); Standard_EXPORT void SetTolerance (const Standard_Real Tol); - + + //! Set flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag); + + //! Get flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const; + Standard_EXPORT void Perform(); Standard_EXPORT Standard_Boolean IsDone() const; @@ -80,7 +86,7 @@ protected: private: - + Standard_Boolean myIsFindSingleSolution; // Default value is false. Standard_Boolean myParallel; Standard_Real myCurveMinTol; math_Vector myLowBorder; diff --git a/src/Extrema/Extrema_ExtCC.cxx b/src/Extrema/Extrema_ExtCC.cxx index c0ffa6b8bd..fffd4c83a5 100644 --- a/src/Extrema/Extrema_ExtCC.cxx +++ b/src/Extrema/Extrema_ExtCC.cxx @@ -53,8 +53,9 @@ //purpose : //======================================================================= Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1, - const Standard_Real TolC2) : - myDone (Standard_False) + const Standard_Real TolC2) +: myIsFindSingleSolution(Standard_False), + myDone (Standard_False) { myC[0] = 0; myC[1] = 0; myTol[0] = TolC1; myTol[1] = TolC2; @@ -65,15 +66,16 @@ Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1, //purpose : //======================================================================= -Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, - const Adaptor3d_Curve& C2, - const Standard_Real U1, - const Standard_Real U2, - const Standard_Real V1, - const Standard_Real V2, - const Standard_Real TolC1, - const Standard_Real TolC2) -: myECC(C1, C2, U1, U2, V1, V2), +Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, + const Adaptor3d_Curve& C2, + const Standard_Real U1, + const Standard_Real U2, + const Standard_Real V1, + const Standard_Real V2, + const Standard_Real TolC1, + const Standard_Real TolC2) +: myIsFindSingleSolution(Standard_False), + myECC(C1, C2, U1, U2, V1, V2), myDone (Standard_False) { SetCurve (1, C1, U1, U2); @@ -90,10 +92,11 @@ Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, //======================================================================= Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, - const Adaptor3d_Curve& C2, - const Standard_Real TolC1, - const Standard_Real TolC2) -: myECC(C1, C2), + const Adaptor3d_Curve& C2, + const Standard_Real TolC1, + const Standard_Real TolC2) +: myIsFindSingleSolution(Standard_False), + myECC(C1, C2), myDone (Standard_False) { SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter()); @@ -165,6 +168,7 @@ void Extrema_ExtCC::Perform() myECC.SetParams(*((Adaptor3d_Curve*)myC[0]), *((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]); myECC.SetTolerance(Min(myTol[0], myTol[1])); + myECC.SetSingleSolutionFlag(GetSingleSolutionFlag()); myDone = Standard_False; mypoints.Clear(); mySqDist.Clear(); @@ -720,3 +724,21 @@ void Extrema_ExtCC::Results(const Extrema_ECC& AlgExt, } } } + +//======================================================================= +//function : SetSingleSolutionFlag +//purpose : +//======================================================================= +void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag) +{ + myIsFindSingleSolution = theFlag; +} + +//======================================================================= +//function : GetSingleSolutionFlag +//purpose : +//======================================================================= +Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const +{ + return myIsFindSingleSolution; +} diff --git a/src/Extrema/Extrema_ExtCC.hxx b/src/Extrema/Extrema_ExtCC.hxx index 8785317222..57180fe571 100644 --- a/src/Extrema/Extrema_ExtCC.hxx +++ b/src/Extrema/Extrema_ExtCC.hxx @@ -88,8 +88,11 @@ public: //! parameter FirstParameter on C2. Standard_EXPORT void TrimmedSquareDistances (Standard_Real& dist11, Standard_Real& distP12, Standard_Real& distP21, Standard_Real& distP22, gp_Pnt& P11, gp_Pnt& P12, gp_Pnt& P21, gp_Pnt& P22) const; + //! Set flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag); - + //! Get flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const; protected: @@ -104,7 +107,7 @@ protected: private: - + Standard_Boolean myIsFindSingleSolution; // Default value is false. Extrema_ECC myECC; Standard_Boolean myDone; Standard_Boolean myIsPar; diff --git a/src/Extrema/Extrema_ExtCC2d.cxx b/src/Extrema/Extrema_ExtCC2d.cxx index cf145c2855..cf93af4159 100644 --- a/src/Extrema/Extrema_ExtCC2d.cxx +++ b/src/Extrema/Extrema_ExtCC2d.cxx @@ -41,27 +41,30 @@ #include <StdFail_NotDone.hxx> Extrema_ExtCC2d::Extrema_ExtCC2d() +: myIsFindSingleSolution(Standard_False) { } -Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1, - const Adaptor2d_Curve2d& C2, - const Standard_Real TolC1, - const Standard_Real TolC2) +Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1, + const Adaptor2d_Curve2d& C2, + const Standard_Real TolC1, + const Standard_Real TolC2) +: myIsFindSingleSolution(Standard_False) { Initialize(C2, Extrema_Curve2dTool::FirstParameter(C2), Extrema_Curve2dTool::LastParameter(C2), TolC1, TolC2); Perform(C1, Extrema_Curve2dTool::FirstParameter(C1), Extrema_Curve2dTool::LastParameter(C1)); } Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d& C1, - const Adaptor2d_Curve2d& C2, - const Standard_Real U1, - const Standard_Real U2, - const Standard_Real V1, - const Standard_Real V2, - const Standard_Real TolC1, - const Standard_Real TolC2) + const Adaptor2d_Curve2d& C2, + const Standard_Real U1, + const Standard_Real U2, + const Standard_Real V1, + const Standard_Real V2, + const Standard_Real TolC1, + const Standard_Real TolC2) +: myIsFindSingleSolution(Standard_False) { Initialize(C2, V1, V2, TolC1, TolC2); Perform(C1, U1, U2); @@ -137,11 +140,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, case GeomAbs_BezierCurve: case GeomAbs_OtherCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Standard_Real Period2 = 0.; - if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Standard_Real Period2 = 0.; + if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); + Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2); } break; case GeomAbs_Line: { @@ -166,35 +170,39 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI); } break; - case GeomAbs_Ellipse: { - //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22,2*M_PI, 2*M_PI); + case GeomAbs_Ellipse: + { + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22,2*M_PI, 2*M_PI); } break; case GeomAbs_Parabola: { //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.); } break; case GeomAbs_Hyperbola: { //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.); } break; case GeomAbs_BezierCurve: case GeomAbs_OtherCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); Standard_Real Period2 = 0.; if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2); + Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2); } break; case GeomAbs_Line: { @@ -222,34 +230,38 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, case GeomAbs_Ellipse: { //inverse = Standard_True; //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1)); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI); } break; case GeomAbs_Parabola: { //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Parabola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 0.); } break; case GeomAbs_Hyperbola: { //inverse = Standard_True; //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1)); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 0.); } break; case GeomAbs_BezierCurve: case GeomAbs_OtherCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); Standard_Real Period2 = 0.; if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, 0., Period2); + Results(aParamSolver, U11, U12, U21, U22, 0., Period2); } break; case GeomAbs_Line: { @@ -277,33 +289,37 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, case GeomAbs_Ellipse: { //inverse = Standard_True; //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1)); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI ); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI ); } break; case GeomAbs_Parabola: { //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 0.); } break; case GeomAbs_Hyperbola: { //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC))); - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); - Results(Xtrem, U11, U12, U21, U22, 0., 0.); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); + Results(aParamSolver, U11, U12, U21, U22, 0., 0.); } break; case GeomAbs_OtherCurve: case GeomAbs_BezierCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); Standard_Real Period2 = 0.; if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, 0., Period2); + Results(aParamSolver, U11, U12, U21, U22, 0., Period2); } break; case GeomAbs_Line: { @@ -322,13 +338,14 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, case GeomAbs_BezierCurve: case GeomAbs_OtherCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); Standard_Real Period1 = 0.; if (Extrema_Curve2dTool::IsPeriodic(C1)) Period1 = Extrema_Curve2dTool::Period(C1); Standard_Real Period2 = 0.; if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, Period1, Period2); + Results(aParamSolver, U11, U12, U21, U22, Period1, Period2); } break; @@ -361,11 +378,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d& C1, case GeomAbs_BezierCurve: case GeomAbs_OtherCurve: case GeomAbs_BSplineCurve: { - Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC)); - Xtrem.Perform(); + Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC)); + aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag()); + aParamSolver.Perform(); Standard_Real Period2 = 0.; if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC)); - Results(Xtrem, U11, U12, U21, U22, 0., Period2); + Results(aParamSolver, U11, U12, U21, U22, 0., Period2); } break; case GeomAbs_Line: { @@ -558,3 +576,21 @@ Standard_Boolean Extrema_ExtCC2d::IsParallel() const if (!myDone) StdFail_NotDone::Raise(); return myIsPar; } + +//======================================================================= +//function : SetSingleSolutionFlag +//purpose : +//======================================================================= +void Extrema_ExtCC2d::SetSingleSolutionFlag(const Standard_Boolean theFlag) +{ + myIsFindSingleSolution = theFlag; +} + +//======================================================================= +//function : GetSingleSolutionFlag +//purpose : +//======================================================================= +Standard_Boolean Extrema_ExtCC2d::GetSingleSolutionFlag() const +{ + return myIsFindSingleSolution; +} diff --git a/src/Extrema/Extrema_ExtCC2d.hxx b/src/Extrema/Extrema_ExtCC2d.hxx index 0ff2c1947f..fe7bc96efb 100644 --- a/src/Extrema/Extrema_ExtCC2d.hxx +++ b/src/Extrema/Extrema_ExtCC2d.hxx @@ -82,7 +82,11 @@ public: //! parameter FirstParameter on C2. Standard_EXPORT void TrimmedSquareDistances (Standard_Real& dist11, Standard_Real& distP12, Standard_Real& distP21, Standard_Real& distP22, gp_Pnt2d& P11, gp_Pnt2d& P12, gp_Pnt2d& P21, gp_Pnt2d& P22) const; + //! Set flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT void SetSingleSolutionFlag (const Standard_Boolean theSingleSolutionFlag); + //! Get flag for single extrema computation. Works on parametric solver only. + Standard_EXPORT Standard_Boolean GetSingleSolutionFlag () const; protected: @@ -98,7 +102,7 @@ protected: private: - + Standard_Boolean myIsFindSingleSolution; // Default value is false. Standard_Boolean myDone; Standard_Boolean myIsPar; Extrema_SequenceOfPOnCurv2d mypoints; diff --git a/src/Extrema/Extrema_GenExtCC.gxx b/src/Extrema/Extrema_GenExtCC.gxx index 6acba89bd9..88ca463c7c 100644 --- a/src/Extrema/Extrema_GenExtCC.gxx +++ b/src/Extrema/Extrema_GenExtCC.gxx @@ -97,7 +97,8 @@ private: //purpose : //======================================================================= Extrema_GenExtCC::Extrema_GenExtCC() -: myParallel(Standard_False), +: myIsFindSingleSolution(Standard_False), + myParallel(Standard_False), myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), @@ -112,7 +113,8 @@ Extrema_GenExtCC::Extrema_GenExtCC() //======================================================================= Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1, const Curve2& C2) -: myParallel(Standard_False), +: myIsFindSingleSolution(Standard_False), + myParallel(Standard_False), myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), @@ -136,7 +138,8 @@ Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup) -: myParallel(Standard_False), +: myIsFindSingleSolution(Standard_False), + myParallel(Standard_False), myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), @@ -204,6 +207,7 @@ void Extrema_GenExtCC::Perform() Standard_Real aValueTol = 1.0e-2; Standard_Real aSameTol = myCurveMinTol / (aDiscTol); aFinder.SetTol(aDiscTol, aSameTol); + aFinder.SetFunctionalMinimalValue(0.0); // Best disntance cannot be lower than 0.0 // Size computed to have cell index inside of int32 value. const Standard_Real aCellSize = Max(anIntervals1.Upper() - anIntervals1.Lower(), @@ -228,7 +232,7 @@ void Extrema_GenExtCC::Perform() aSecondBorderInterval(2) = anIntervals2(j + 1); aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval); - aFinder.Perform(); + aFinder.Perform(GetSingleSolutionFlag()); // Check that solution found on current interval is not worse than previous. aCurrF = aFinder.GetF(); @@ -388,3 +392,21 @@ void Extrema_GenExtCC::Points(const Standard_Integer N, P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N))); P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N))); } + +//======================================================================= +//function : SetSingleSolutionFlag +//purpose : +//======================================================================= +void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag) +{ + myIsFindSingleSolution = theFlag; +} + +//======================================================================= +//function : GetSingleSolutionFlag +//purpose : +//======================================================================= +Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const +{ + return myIsFindSingleSolution; +} diff --git a/src/math/math_GlobOptMin.cxx b/src/math/math_GlobOptMin.cxx index 99e968d3d2..2560aa252d 100644 --- a/src/math/math_GlobOptMin.cxx +++ b/src/math/math_GlobOptMin.cxx @@ -54,6 +54,7 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc, myFunc = theFunc; myC = theC; myIsFindSingleSolution = Standard_False; + myFunctionalMinimalValue = -Precision::Infinite(); myZ = -1; mySolCount = 0; @@ -247,6 +248,13 @@ void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution) myE3 = - maxLength * myTol * myC / 4.0; } + // Search single solution and current solution in its neighbourhood. + if (CheckFunctionalStopCriteria()) + { + myDone = Standard_True; + return; + } + isFirstCellFilterInvoke = Standard_True; computeGlobalExtremum(myN); @@ -409,7 +417,7 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) Standard_Real r; Standard_Boolean isReached = Standard_False; - for(myX(j) = myA(j) + myE1; + for(myX(j) = myA(j) + myE1; (myX(j) < myB(j) + myE1) && (!isReached); myX(j) += myV(j)) { @@ -419,6 +427,9 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) isReached = Standard_True; } + if (CheckFunctionalStopCriteria()) + return; // Best possible value is obtained. + if (j == 1) { isInside = Standard_False; @@ -463,6 +474,9 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) isFirstCellFilterInvoke = Standard_True; } + if (CheckFunctionalStopCriteria()) + return; // Best possible value is obtained. + aRealStep = myE2 + Abs(myF - d) / myC; myV(1) = Min(aRealStep, myMaxV(1)); } @@ -588,6 +602,24 @@ Standard_Real math_GlobOptMin::GetF() return myF; } +//======================================================================= +//function : SetFunctionalMinimalValue +//purpose : +//======================================================================= +void math_GlobOptMin::SetFunctionalMinimalValue(const Standard_Real theMinimalValue) +{ + myFunctionalMinimalValue = theMinimalValue; +} + +//======================================================================= +//function : GetFunctionalMinimalValue +//purpose : +//======================================================================= +Standard_Real math_GlobOptMin::GetFunctionalMinimalValue() +{ + return myFunctionalMinimalValue; +} + //======================================================================= //function : IsDone //purpose : @@ -621,3 +653,17 @@ void math_GlobOptMin::initCellSize() * Precision::PConfusion() / (2.0 * Sqrt(2.0)); } } + +//======================================================================= +//function : CheckFunctionalStopCriteria +//purpose : +//======================================================================= +Standard_Boolean math_GlobOptMin::CheckFunctionalStopCriteria() +{ + // Search single solution and current solution in its neighbourhood. + if (myIsFindSingleSolution && + Abs (myF - myFunctionalMinimalValue) < mySameTol * 0.01) + return Standard_True; + + return Standard_False; +} diff --git a/src/math/math_GlobOptMin.hxx b/src/math/math_GlobOptMin.hxx index 0af9820d9e..1d42ab91e3 100644 --- a/src/math/math_GlobOptMin.hxx +++ b/src/math/math_GlobOptMin.hxx @@ -141,7 +141,13 @@ public: //! Return solution theIndex, 1 <= theIndex <= NbExtrema. Standard_EXPORT void Points(const Standard_Integer theIndex, math_Vector& theSol); - Standard_Boolean isDone(); + Standard_EXPORT Standard_Boolean isDone(); + + //! Set functional minimal value. + Standard_EXPORT void SetFunctionalMinimalValue(const Standard_Real theMinimalValue); + + //! Get functional minimal value. + Standard_EXPORT Standard_Real GetFunctionalMinimalValue(); private: @@ -154,6 +160,10 @@ private: void computeGlobalExtremum(Standard_Integer theIndex); + //! Check possibility to stop computations. + //! Find single solution + in neighbourhood of best possible solution. + Standard_Boolean CheckFunctionalStopCriteria(); + //! Computes starting value / approximation: //! myF - initial best value. //! myY - initial best point. @@ -180,6 +190,7 @@ private: // default value is 1.0e-7. Standard_Real myC; //Lipschitz constant, default 9 Standard_Boolean myIsFindSingleSolution; // Default value is false. + Standard_Real myFunctionalMinimalValue; // Default value is -Precision::Infinite // Output. Standard_Boolean myDone; diff --git a/tests/bugs/modalg_6/bug26674 b/tests/bugs/modalg_6/bug26674 new file mode 100644 index 0000000000..7fa68135d1 --- /dev/null +++ b/tests/bugs/modalg_6/bug26674 @@ -0,0 +1,37 @@ +puts "========" +puts "OCC26674" +puts "========" +puts "" +################################################# +# Performance regression in BRepExtrema_DistShapeShape in OCCT 6.9.0 in compare with OCCT 6.7.1 +################################################# + +set max_time 1 + +restore [locate_data_file OCC26674-face.brep] a1 +restore [locate_data_file OCC26674-shell.brep] a2 + +dchrono cr reset +dchrono cr start + +distmini dd a1 a2 + +dchrono cr stop + +set log [dchrono cr show] + +regexp {CPU user time: ([-0-9.+eE]+) seconds} $log full z +puts "$z" + +if { $z > ${max_time} } { + puts "Elapsed time of BRepExtrema_DistShapeShape is more than ${max_time} seconds - Error" +} else { + puts "Elapsed time of BRepExtrema_DistShapeShape is less than ${max_time} seconds - OK" +} + +regexp {([-0-9.+eE]+)$} [dump dd_val] full dist + +set expected_dist 0.0 +set tol_abs_dist 1.0e-07 +set tol_rel_dist 0.0 +checkreal "Dump of dd_val" ${dist} ${expected_dist} ${tol_abs_dist} ${tol_rel_dist}