From: aml Date: Fri, 25 Mar 2016 10:10:12 +0000 (+0300) Subject: 0027299: Incorrect result of the normal projection algorithm X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=79168b6678e422c2e33854b0585143953ed22389;p=occt-copy.git 0027299: Incorrect result of the normal projection algorithm Curve splitting is added to handle seam passing by initial curve. test cases are added. Minor corrections. 0026044: Optimize math_GlobOptMin class to enter options for solutions of some specified problems Possibility to search single optimum added. Additional backporting to improve performance. --- diff --git a/src/Extrema/Extrema_ExtCC.cdl b/src/Extrema/Extrema_ExtCC.cdl index 2990897d15..1f8b8b6a3c 100644 --- a/src/Extrema/Extrema_ExtCC.cdl +++ b/src/Extrema/Extrema_ExtCC.cdl @@ -131,6 +131,15 @@ is Ut11, Ut12, Ut21, Ut22: Real) is static protected; + + GetSingleSolutionFlag (me) returns Boolean + ---Purpose: Returns single solution flag value. + is static; + + SetSingleSolutionFlag (me: in out; + theFlag: Boolean) + ---Purpose: Sets single solution flag value. + is static; @@ -139,6 +148,7 @@ fields myECC: ECC from Extrema; myDone: Boolean; myIsPar: Boolean; + myIsFindSingleSolution: Boolean; mypoints: SequenceOfPOnCurv from Extrema; mySqDist: SequenceOfReal from TColStd; mynbext: Integer; diff --git a/src/Extrema/Extrema_ExtCC.cxx b/src/Extrema/Extrema_ExtCC.cxx index 5ee9d5bb30..131d410696 100644 --- a/src/Extrema/Extrema_ExtCC.cxx +++ b/src/Extrema/Extrema_ExtCC.cxx @@ -45,15 +45,14 @@ #include #include - //======================================================================= //function : Extrema_ExtCC //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; @@ -64,15 +63,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); @@ -89,10 +89,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()); @@ -164,6 +165,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(); @@ -725,3 +727,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_ExtCC2d.cdl b/src/Extrema/Extrema_ExtCC2d.cdl index b156e6bd42..342abd8800 100644 --- a/src/Extrema/Extrema_ExtCC2d.cdl +++ b/src/Extrema/Extrema_ExtCC2d.cdl @@ -131,11 +131,21 @@ is Period2 : Real from Standard = 0.0) is static protected; + + GetSingleSolutionFlag (me) returns Boolean + ---Purpose: Returns single solution flag value. + is static; + + SetSingleSolutionFlag (me: in out; + theFlag: Boolean) + ---Purpose: Sets single solution flag value. + is static; fields myDone: Boolean; myIsPar: Boolean; + myIsFindSingleSolution: Boolean; mypoints: SequenceOfPOnCurv2d from Extrema; mySqDist: SequenceOfReal from TColStd; mynbext: Integer; diff --git a/src/Extrema/Extrema_ExtCC2d.cxx b/src/Extrema/Extrema_ExtCC2d.cxx index 8448867d9e..585c02c7e6 100644 --- a/src/Extrema/Extrema_ExtCC2d.cxx +++ b/src/Extrema/Extrema_ExtCC2d.cxx @@ -39,27 +39,30 @@ 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); @@ -135,11 +138,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: { @@ -164,35 +168,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: { @@ -220,34 +228,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: { @@ -275,33 +287,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: { @@ -320,13 +336,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; @@ -359,11 +376,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: { @@ -555,3 +573,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_GenExtCC.cdl b/src/Extrema/Extrema_GenExtCC.cdl index a126b92ecf..e5e9c166c8 100644 --- a/src/Extrema/Extrema_GenExtCC.cdl +++ b/src/Extrema/Extrema_GenExtCC.cdl @@ -94,8 +94,18 @@ is OutOfRange -- if N < 1 or N > NbExt(me) is static; + + GetSingleSolutionFlag (me) returns Boolean + ---Purpose: Returns single solution flag value. + is static; + + SetSingleSolutionFlag (me: in out; + theFlag: Boolean) + ---Purpose: Sets single solution flag value. + is static; fields + myIsFindSingleSolution: Boolean; myCurveMinTol : Real from Standard; myLowBorder : Vector from math; myUppBorder : Vector from math; @@ -103,5 +113,6 @@ fields myPoints2 : SequenceOfReal from TColStd; myC : Address from Standard [2]; myDone : Boolean; + end GenExtCC; diff --git a/src/Extrema/Extrema_GenExtCC.gxx b/src/Extrema/Extrema_GenExtCC.gxx index ba07b73781..61441e40cd 100644 --- a/src/Extrema/Extrema_GenExtCC.gxx +++ b/src/Extrema/Extrema_GenExtCC.gxx @@ -27,7 +27,8 @@ //purpose : //======================================================================= Extrema_GenExtCC::Extrema_GenExtCC() -: myCurveMinTol(Precision::PConfusion()), +: myIsFindSingleSolution(Standard_False), + myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), myDone(Standard_False) @@ -41,7 +42,8 @@ Extrema_GenExtCC::Extrema_GenExtCC() //======================================================================= Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1, const Curve2& C2) -: myCurveMinTol(Precision::PConfusion()), +: myIsFindSingleSolution(Standard_False), + myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), myDone(Standard_False) @@ -64,7 +66,8 @@ Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1, const Standard_Real Usup, const Standard_Real Vinf, const Standard_Real Vsup) -: myCurveMinTol(Precision::PConfusion()), +: myIsFindSingleSolution(Standard_False), + myCurveMinTol(Precision::PConfusion()), myLowBorder(1,2), myUppBorder(1,2), myDone(Standard_False) @@ -117,15 +120,25 @@ void Extrema_GenExtCC::Perform() Curve2 &C2 = *(Curve2*)myC[1]; Standard_Integer aNbInter[2]; - aNbInter[0] = C1.NbIntervals(GeomAbs_C2); - aNbInter[1] = C2.NbIntervals(GeomAbs_C2); + GeomAbs_Shape aContinuity = GeomAbs_C2; + aNbInter[0] = C1.NbIntervals(aContinuity); + aNbInter[1] = C2.NbIntervals(aContinuity); + + if (aNbInter[0] * aNbInter[1] > 100) + { + aContinuity = GeomAbs_C1; + aNbInter[0] = C1.NbIntervals(aContinuity); + aNbInter[1] = C2.NbIntervals(aContinuity); + } + TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1); TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1); - C1.Intervals(anIntervals1, GeomAbs_C2); - C2.Intervals(anIntervals2, GeomAbs_C2); + C1.Intervals(anIntervals1, aContinuity); + C2.Intervals(anIntervals2, aContinuity); Extrema_GlobOptFuncCCC2 aFunc (C1, C2); math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder); + aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1); Standard_Real aDiscTol = 1.0e-2; Standard_Real aValueTol = 1.0e-2; Standard_Real aSameTol = myCurveMinTol / (aDiscTol); @@ -149,7 +162,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(); @@ -242,4 +255,22 @@ 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))); -} \ No newline at end of file +} + +//======================================================================= +//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/ProjLib/ProjLib_CompProjectedCurve.cxx b/src/ProjLib/ProjLib_CompProjectedCurve.cxx index 1d5cc6e470..b4f785b68a 100644 --- a/src/ProjLib/ProjLib_CompProjectedCurve.cxx +++ b/src/ProjLib/ProjLib_CompProjectedCurve.cxx @@ -14,9 +14,15 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. + +#include + #include #include #include +#include +#include +#include #include #include #include @@ -28,6 +34,11 @@ #include #include #include +#include +#include +#include +#include +#include #define FuncTol 1.e-10 @@ -54,6 +65,59 @@ static void ResultChron( OSD_Chronometer & ch, Standard_Real & time) } #endif +// Structure to perform splits computation. +// This structure is not thread-safe since operations under mySplits should be performed in a critical section. +// myPeriodicDir - 0 for U periodicity and 1 for V periodicity. +struct SplitDS +{ + SplitDS(const Handle(Adaptor3d_HCurve) &theCurve, + const Handle(Adaptor3d_HSurface) &theSurface, + NCollection_Vector &theSplits) + : myCurve(theCurve), + mySurface(theSurface), + mySplits(theSplits) + { } + + // Assignment operator is forbidden. + void operator=(const SplitDS &theSplitDS); + + const Handle(Adaptor3d_HCurve) myCurve; + const Handle(Adaptor3d_HSurface) mySurface; + NCollection_Vector &mySplits; + + Standard_Real myPerMinParam; + Standard_Real myPerMaxParam; + Standard_Integer myPeriodicDir; + + Extrema_ExtCC *myExtCC; + Extrema_ExtPS *myExtPS; +}; + + //! Compute split points in the parameter space of the curve. + static void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve, + const Handle(Adaptor3d_HSurface) &theSurface, + const Standard_Real theTolU, + const Standard_Real theTolV, + NCollection_Vector &theSplits); + + //! Perform splitting on a specified direction. Sub-method in BuildCurveSplits. + static void SplitOnDirection(SplitDS & theSplitDS); + + //! Perform recursive search of the split points. + static void FindSplitPoint(SplitDS & theSplitDS, + const Standard_Real theMinParam, + const Standard_Real theMaxParam); + + +//======================================================================= +//function : Comparator +//purpose : used in sort algorithm +//======================================================================= +inline Standard_Boolean Comparator(const Standard_Real theA, + const Standard_Real theB) +{ + return theA < theB; +} //======================================================================= //function : d1 @@ -554,34 +618,36 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve void ProjLib_CompProjectedCurve::Init() { myTabInt.Nullify(); + NCollection_Vector aSplits; Standard_Real Tol;// Tolerance for ExactBound - Standard_Integer i, Nend = 0; - Standard_Boolean FromLastU=Standard_False; - - //new part (to discard far solutions) - Standard_Real TolC = Precision::Confusion(), TolS = Precision::Confusion(); - Extrema_ExtCS CExt(myCurve->Curve(), - mySurface->Surface(), - TolC, - TolS); - if (CExt.IsDone() && CExt.NbExt()) + Standard_Integer i, Nend = 0, aSplitIdx = 0; + Standard_Boolean FromLastU = Standard_False, + isSplitsComputed = Standard_False; + + const Standard_Real aTol3D = Precision::Confusion(); + Extrema_ExtCS CExt(myCurve->Curve(), mySurface->Surface(), aTol3D, aTol3D); + if (CExt.IsDone() && CExt.NbExt()) { - // Search for the minimum solution - Nend = CExt.NbExt(); + // Search for the minimum solution. + // Avoid usage of extrema result that can be wrong for extrusion. if(myMaxDist > 0 && - // Avoid usage of extrema result that can be wrong for extrusion + mySurface->GetType() != GeomAbs_SurfaceOfExtrusion) { Standard_Real min_val2; min_val2 = CExt.SquareDistance(1); + + Nend = CExt.NbExt(); for(i = 2; i <= Nend; i++) - if (CExt.SquareDistance(i) < min_val2) min_val2 = CExt.SquareDistance(i); + { + if (CExt.SquareDistance(i) < min_val2) + min_val2 = CExt.SquareDistance(i); + } if (min_val2 > myMaxDist * myMaxDist) - return; + return; // No near solution -> exit. } } - // end of new part Standard_Real FirstU, LastU, Step, SearchStep, WalkStep, t; @@ -595,12 +661,9 @@ void ProjLib_CompProjectedCurve::Init() SearchStep = 10*MinStep; Step = SearchStep; - //Initialization of aPrjPS - Standard_Real Uinf = mySurface->FirstUParameter(); - Standard_Real Usup = mySurface->LastUParameter(); - Standard_Real Vinf = mySurface->FirstVParameter(); - Standard_Real Vsup = mySurface->LastVParameter(); - + gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter()); + gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter()); + gp_Pnt2d aTol(myTolU, myTolV); ProjLib_PrjResolve aPrjPS(myCurve->Curve(), mySurface->Surface(), 1); t = FirstU; @@ -638,10 +701,8 @@ void ProjLib_CompProjectedCurve::Init() ParT=P1.Parameter(); P2.Parameter(ParU, ParV); - aPrjPS.Perform(ParT, ParU, ParV, gp_Pnt2d(myTolU, myTolV), - gp_Pnt2d(mySurface->FirstUParameter(),mySurface->FirstVParameter()), - gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()), - FuncTol, Standard_True); + aPrjPS.Perform(ParT, ParU, ParV, aTol, aLowBorder, aUppBorder, FuncTol, Standard_True); + if ( aPrjPS.IsDone() && P1.Parameter() > Max(FirstU,t-Step+Precision::PConfusion()) && P1.Parameter() <= t) { @@ -655,7 +716,7 @@ void ProjLib_CompProjectedCurve::Init() } } if (!initpoint) - { + { myCurve->D0(t,CPoint); #ifdef OCCT_DEBUG_CHRONO InitChron(chr_init_point); @@ -674,38 +735,37 @@ void ProjLib_CompProjectedCurve::Init() gp_Vec2d D; if ((mySurface->IsUPeriodic() && - Abs(Usup - Uinf - mySurface->UPeriod()) < Precision::Confusion()) || + Abs(aUppBorder.X() - aLowBorder.X() - mySurface->UPeriod()) < Precision::Confusion()) || (mySurface->IsVPeriodic() && - Abs(Vsup - Vinf - mySurface->VPeriod()) < Precision::Confusion())) + Abs(aUppBorder.Y() - aLowBorder.Y() - mySurface->VPeriod()) < Precision::Confusion())) { - if((Abs(U - Uinf) < mySurface->UResolution(Precision::PConfusion())) && + if((Abs(U - aLowBorder.X()) < mySurface->UResolution(Precision::PConfusion())) && mySurface->IsUPeriodic()) { d1(t, U, V, D, myCurve, mySurface); - if (D.X() < 0 ) U = Usup; + if (D.X() < 0 ) U = aUppBorder.X(); } - else if((Abs(U - Usup) < mySurface->UResolution(Precision::PConfusion())) && + else if((Abs(U - aUppBorder.X()) < mySurface->UResolution(Precision::PConfusion())) && mySurface->IsUPeriodic()) { d1(t, U, V, D, myCurve, mySurface); - if (D.X() > 0) U = Uinf; + if (D.X() > 0) U = aLowBorder.X(); } - if((Abs(V - Vinf) < mySurface->VResolution(Precision::PConfusion())) && + if((Abs(V - aLowBorder.Y()) < mySurface->VResolution(Precision::PConfusion())) && mySurface->IsVPeriodic()) { d1(t, U, V, D, myCurve, mySurface); - if (D.Y() < 0) V = Vsup; + if (D.Y() < 0) V = aUppBorder.Y(); } - else if((Abs(V - Vsup) <= mySurface->VResolution(Precision::PConfusion())) && + else if((Abs(V - aUppBorder.Y()) <= mySurface->VResolution(Precision::PConfusion())) && mySurface->IsVPeriodic()) { d1(t, U, V, D, myCurve, mySurface); - if (D.Y() > 0) V = Vinf; + if (D.Y() > 0) V = aLowBorder.Y(); } } - if (myMaxDist > 0) { // Here we are going to stop if the distance between projection and @@ -755,7 +815,6 @@ void ProjLib_CompProjectedCurve::Init() } if (!new_part) break; - //We have found a new continuous part Handle(TColgp_HSequenceOfPnt) hSeq = new TColgp_HSequenceOfPnt(); mySequence->Append(hSeq); @@ -780,9 +839,7 @@ void ProjLib_CompProjectedCurve::Init() if (t > LastU) t = LastU; Standard_Real prevStep = Step; Standard_Real U0, V0; - gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter()); - gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter()); - gp_Pnt2d aTol(myTolU, myTolV); + //Here we are trying to prolong continuous part while (t <= LastU && new_part) { @@ -869,6 +926,33 @@ void ProjLib_CompProjectedCurve::Init() Triple.SetZ(V); } + // Protection from case when the whole curve lies on a seam. + if (!isSplitsComputed) + { + Standard_Boolean isUPossible = Standard_False; + if (mySurface->IsUPeriodic() && + (Abs(Triple.Y() - mySurface->FirstUParameter() ) > Precision::PConfusion() && + Abs(Triple.Y() - mySurface->LastUParameter() ) > Precision::PConfusion())) + { + isUPossible = Standard_True; + } + + Standard_Boolean isVPossible = Standard_False; + if (mySurface->IsVPeriodic() && + (Abs(Triple.Z() - mySurface->FirstVParameter() ) > Precision::PConfusion() && + Abs(Triple.Z() - mySurface->LastVParameter() ) > Precision::PConfusion())) + { + isVPossible = Standard_True; + } + + if (isUPossible || isVPossible) + { + // When point is good conditioned. + BuildCurveSplits(myCurve, mySurface, myTolU, myTolV, aSplits); + isSplitsComputed = Standard_True; + } + } + if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10) mySequence->Value(myNbCurves)->Append(Triple); if (t == LastU) {t = LastU + 1; break;}//return; @@ -882,15 +966,38 @@ void ProjLib_CompProjectedCurve::Init() Step = WalkStep; t += Step; - if (t > (LastU-MinStep/2) ) + if (t > (LastU-MinStep/2)) { - Step =Step+LastU-t; + Step = Step + LastU - t; t = LastU; - } + } + + // We assume at least one point of cache inside of a split. + const Standard_Integer aSize = aSplits.Size(); + for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx) + { + const Standard_Real aParam = aSplits(anIdx); + if (Abs(aParam - Triple.X() ) < Precision::PConfusion()) + { + // The current point is equal to a split point. + new_part = Standard_False; + + // Move split index to avoid check of the whole list. + ++aSplitIdx; + break; + } + else if (aParam < t + Precision::PConfusion() ) + { + // The next point crosses the split point. + t = aParam; + Step = t - prevTriple.X(); + } + } // for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx) } } } - // Sequence postproceeding + + // Sequence post-proceeding. Standard_Integer j; // 1. Removing poor parts @@ -1613,3 +1720,161 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const { return GeomAbs_OtherCurve; } + +//======================================================================= +//function : BuildCurveSplits +//purpose : +//======================================================================= +void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve, + const Handle(Adaptor3d_HSurface) &theSurface, + const Standard_Real theTolU, + const Standard_Real theTolV, + NCollection_Vector &theSplits) +{ + SplitDS aDS(theCurve, theSurface, theSplits); + + Extrema_ExtPS anExtPS; + anExtPS.Initialize(theSurface->Surface(), + theSurface->FirstUParameter(), theSurface->LastUParameter(), + theSurface->FirstVParameter(), theSurface->LastVParameter(), + theTolU, theTolV); + aDS.myExtPS = &anExtPS; + + if (theSurface->IsUPeriodic()) + { + aDS.myPeriodicDir = 0; + SplitOnDirection(aDS); + } + if (theSurface->IsVPeriodic()) + { + aDS.myPeriodicDir = 1; + SplitOnDirection(aDS); + } + + std::sort(aDS.mySplits.begin(), aDS.mySplits.end(), Comparator); +} + +//======================================================================= +//function : SplitOnDirection +//purpose : This method compute points in the parameter space of the curve +// on which curve should be split since period jump is happen. +//======================================================================= +void SplitOnDirection(SplitDS & theSplitDS) +{ + // Algorithm: + // Create 3D curve which is correspond to the periodic bound in 2d space. + // Run curve / curve extrema and run extrema point / surface to check that + // the point will be projected to the periodic bound. + // In this method assumed that the points cannot be closer to each other that 1% of the parameter space. + + gp_Pnt2d aStartPnt(theSplitDS.mySurface->FirstUParameter(), theSplitDS.mySurface->FirstVParameter()); + gp_Dir2d aDir(theSplitDS.myPeriodicDir, (Standard_Integer)!theSplitDS.myPeriodicDir); + + theSplitDS.myPerMinParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->FirstUParameter(): + theSplitDS.mySurface->FirstVParameter(); + theSplitDS.myPerMaxParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->LastUParameter(): + theSplitDS.mySurface->LastVParameter(); + Standard_Real aLast2DParam = theSplitDS.myPeriodicDir ? + theSplitDS.mySurface->LastUParameter() - theSplitDS.mySurface->FirstUParameter(): + theSplitDS.mySurface->LastVParameter() - theSplitDS.mySurface->FirstVParameter(); + + // Create line which is represent periodic border. + Handle(Geom2d_Curve) aC2GC = new Geom2d_Line(aStartPnt, aDir); + Handle(Geom2dAdaptor_HCurve) aC = new Geom2dAdaptor_HCurve(aC2GC, 0, aLast2DParam); + Adaptor3d_CurveOnSurface aCOnS(aC, theSplitDS.mySurface); + + Extrema_ExtCC anExtCC; + anExtCC.SetCurve(1, aCOnS); + anExtCC.SetCurve(2, theSplitDS.myCurve->Curve()); + anExtCC.SetRange(1, 0, aLast2DParam); + anExtCC.SetSingleSolutionFlag(Standard_True); + theSplitDS.myExtCC = &anExtCC; + + FindSplitPoint(theSplitDS, + theSplitDS.myCurve->FirstParameter(), // Initial curve range. + theSplitDS.myCurve->LastParameter()); +} + + +//======================================================================= +//function : FindSplitPoint +//purpose : +//======================================================================= +void FindSplitPoint(SplitDS &theSplitDS, + const Standard_Real theMinParam, + const Standard_Real theMaxParam) +{ + // Make extrema copy to avoid dependencies between different levels of the recursion. + Extrema_ExtCC anExtCC(*theSplitDS.myExtCC); + anExtCC.SetRange(2, theMinParam, theMaxParam); + anExtCC.Perform(); + + if (anExtCC.IsDone()) + { + const Standard_Integer aNbExt = anExtCC.NbExt(); + for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx) + { + Extrema_POnCurv aPOnC1, aPOnC2; + anExtCC.Points(anIdx, aPOnC1, aPOnC2); + + theSplitDS.myExtPS->Perform(aPOnC2.Value()); + if (!theSplitDS.myExtPS->IsDone()) + return; + + // Find point with the minimal Euclidean distance to avoid + // false positive points detection. + Standard_Integer aMinIdx = -1; + Standard_Real aMinSqDist = RealLast(); + const Standard_Integer aNbPext = theSplitDS.myExtPS->NbExt(); + for(Standard_Integer aPIdx = 1; aPIdx <= aNbPext; ++aPIdx) + { + const Standard_Real aCurrSqDist = theSplitDS.myExtPS->SquareDistance(aPIdx); + + if (aCurrSqDist < aMinSqDist) + { + aMinSqDist = aCurrSqDist; + aMinIdx = aPIdx; + } + } + + // Check that is point will be projected to the periodic border. + const Extrema_POnSurf &aPOnS = theSplitDS.myExtPS->Point(aMinIdx); + Standard_Real U, V, aProjParam; + aPOnS.Parameter(U, V); + aProjParam = theSplitDS.myPeriodicDir ? V : U; + + + if (Abs(aProjParam - theSplitDS.myPerMinParam) < Precision::PConfusion() || + Abs(aProjParam - theSplitDS.myPerMaxParam) < Precision::PConfusion() ) + { + const Standard_Real aParam = aPOnC2.Parameter(); + const Standard_Real aCFParam = theSplitDS.myCurve->FirstParameter(); + const Standard_Real aCLParam = theSplitDS.myCurve->LastParameter(); + + if (aParam > aCFParam + Precision::PConfusion() && + aParam < aCLParam - Precision::PConfusion() ) + { + // Add only inner points. + theSplitDS.mySplits.Append(aParam); + } + + const Standard_Real aDeltaCoeff = 0.01; + const Standard_Real aDelta = (theMaxParam - theMinParam + + aCLParam - aCFParam) * aDeltaCoeff; + + if (aParam - aDelta > theMinParam + Precision::PConfusion()) + { + FindSplitPoint(theSplitDS, + theMinParam, aParam - aDelta); // Curve parameters. + } + + if (aParam + aDelta < theMaxParam - Precision::PConfusion()) + { + FindSplitPoint(theSplitDS, + aParam + aDelta, theMaxParam); // Curve parameters. + } + } + + } // for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx) + } +} diff --git a/src/math/math_GlobOptMin.cxx b/src/math/math_GlobOptMin.cxx index ce474511f3..0ada2da500 100644 --- a/src/math/math_GlobOptMin.cxx +++ b/src/math/math_GlobOptMin.cxx @@ -45,12 +45,14 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc, myTmp(1, myN), myV(1, myN), myMaxV(1, myN), - myExpandCoeff(1, myN) + myExpandCoeff(1, myN), + myCont(2) { Standard_Integer i; myFunc = theFunc; myC = theC; + myIsFindSingleSolution = Standard_False; myZ = -1; mySolCount = 0; @@ -191,7 +193,7 @@ math_GlobOptMin::~math_GlobOptMin() //purpose : Compute Global extremum point //======================================================================= // In this algo indexes started from 1, not from 0. -void math_GlobOptMin::Perform() +void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution) { Standard_Integer i; @@ -221,10 +223,21 @@ void math_GlobOptMin::Perform() myE1 = minLength * myTol; myE2 = maxLength * myTol; - if (myC > 1.0) - myE3 = - maxLength * myTol / 4.0; + + myIsFindSingleSolution = isFindSingleSolution; + if (isFindSingleSolution) + { + // Run local optimization + // if current value better than optimal. + myE3 = 0.0; + } else - myE3 = - maxLength * myTol * myC / 4.0; + { + if (myC > 1.0) + myE3 = - maxLength * myTol / 4.0; + else + myE3 = - maxLength * myTol * myC / 4.0; + } computeGlobalExtremum(myN); @@ -242,7 +255,8 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt Standard_Integer i; //Newton method - if (dynamic_cast(myFunc)) + if (myCont >= 2 && + dynamic_cast(myFunc)) { math_MultipleVarFunctionWithHessian* myTmp = dynamic_cast (myFunc); @@ -259,7 +273,8 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt } else // BFGS method used. - if (dynamic_cast(myFunc)) + if (myCont >= 1 && + dynamic_cast(myFunc)) { math_MultipleVarFunctionWithGradient* myTmp = dynamic_cast (myFunc); @@ -404,8 +419,10 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) aStepBestValue = (isInside && (val < d))? val : d; aStepBestPoint = (isInside && (val < d))? myTmp : myX; - // Solutions are close to each other. - if (Abs(aStepBestValue - myF) < mySameTol * 0.01) + // Solutions are close to each other + // and it is allowed to have more than one solution. + if (Abs(aStepBestValue - myF) < mySameTol * 0.01 && + !myIsFindSingleSolution) { if (!isStored(aStepBestPoint)) { @@ -417,8 +434,12 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j) } } - // New best solution. - if ((aStepBestValue - myF) * myZ > mySameTol * 0.01) + // New best solution: + // new point is out of (mySameTol * 0.01) surrounding or + // new point is better than old + single point search. + Standard_Real aFunctionalDelta = (aStepBestValue - myF) * myZ; + if (aFunctionalDelta > mySameTol * 0.01 || + (aFunctionalDelta > 0.0 && myIsFindSingleSolution)) { mySolCount = 0; myF = aStepBestValue; diff --git a/src/math/math_GlobOptMin.hxx b/src/math/math_GlobOptMin.hxx index 27d4834718..b18f93de88 100644 --- a/src/math/math_GlobOptMin.hxx +++ b/src/math/math_GlobOptMin.hxx @@ -53,7 +53,8 @@ public: Standard_EXPORT ~math_GlobOptMin(); - Standard_EXPORT void Perform(); + //! @param isFindSingleSolution - defines whether to find single solution or all solutions. + Standard_EXPORT void Perform(const Standard_Boolean isFindSingleSolution = Standard_False); //! Get best functional value. Standard_EXPORT Standard_Real GetF(); @@ -66,6 +67,12 @@ public: Standard_Boolean isDone(); + //! Get continuity of local borders splits. + inline Standard_Integer GetContinuity() const { return myCont; } + + //! Set continuity of local borders splits. + inline void SetContinuity(const Standard_Integer theCont) { myCont = theCont; } + private: math_GlobOptMin & operator = (const math_GlobOptMin & theOther); @@ -99,6 +106,7 @@ private: // function values |val1 - val2| * 0.01 < mySameTol is equal, // default value is 1.0e-7. Standard_Real myC; //Lipschitz constant, default 9 + Standard_Boolean myIsFindSingleSolution; // Default value is false. // Output. Standard_Boolean myDone; @@ -117,6 +125,9 @@ private: math_Vector myMaxV; // Max Steps array. math_Vector myExpandCoeff; // Define expand coefficient between neighboring indiced dimensions. + // Continuity of local borders. + Standard_Integer myCont; + Standard_Real myF; // Current value of Global optimum. }; diff --git a/tests/bugs/moddata_3/bug27299_1 b/tests/bugs/moddata_3/bug27299_1 new file mode 100644 index 0000000000..8e50765f92 --- /dev/null +++ b/tests/bugs/moddata_3/bug27299_1 @@ -0,0 +1,20 @@ +puts "================" +puts "0027299" +puts "================" +puts "" +############################################################## +# Incorrect result of the normal projection algorithm +# Exception during the exectuion +############################################################## + +restore [locate_data_file bug27299_1.brep] aShape +explode aShape + +nproject result aShape_1 aShape_2 + +# Visual check. +donly result +smallview +fit +display aShape_2 +xwd ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_3/bug27299_2 b/tests/bugs/moddata_3/bug27299_2 new file mode 100644 index 0000000000..7f49d5c7ec --- /dev/null +++ b/tests/bugs/moddata_3/bug27299_2 @@ -0,0 +1,23 @@ +puts "================" +puts "0027299" +puts "================" +puts "" +############################################################## +# Incorrect result of the normal projection algorithm +# Exception during the exectuion +############################################################## + +restore [locate_data_file bug27299_1.brep] aShape +explode aShape + +# To make task non-symmetry. +ttranslate aShape_1 0 0 135.123 + +nproject result aShape_1 aShape_2 + +# Visual check. +donly result +smallview +fit +display aShape_2 +xwd ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_3/bug27299_3 b/tests/bugs/moddata_3/bug27299_3 new file mode 100644 index 0000000000..703d8c88f3 --- /dev/null +++ b/tests/bugs/moddata_3/bug27299_3 @@ -0,0 +1,20 @@ +puts "================" +puts "0027299" +puts "================" +puts "" +############################################################## +# Incorrect result of the normal projection algorithm +# Exception during the exectuion +############################################################## + +restore [locate_data_file bug27299_2.brep] aShape +explode aShape + +nproject result aShape_1 aShape_2 + +# Visual check. +donly result +smallview +fit +display aShape_2 +xwd ${imagedir}/${test_image}.png