diff --git a/src/Extrema/Extrema_FuncExtCS.hxx b/src/Extrema/Extrema_FuncExtCS.hxx index 4a07792a3c..aa6f3f9c87 100644 --- a/src/Extrema/Extrema_FuncExtCS.hxx +++ b/src/Extrema/Extrema_FuncExtCS.hxx @@ -84,14 +84,21 @@ public: //! Return the Nth extremum on S. Standard_EXPORT const Extrema_POnSurf& PointOnSurface (const Standard_Integer N) const; - - - -protected: - - - - + //! Change Sequence of SquareDistance + Standard_EXPORT TColStd_SequenceOfReal& SquareDistances() + { + return mySqDist; + } + //! Change Sequence of PointOnCurv + Standard_EXPORT Extrema_SequenceOfPOnCurv& PointsOnCurve() + { + return myPoint1; + } + //! Change Sequence of PointOnSurf + Standard_EXPORT Extrema_SequenceOfPOnSurf& PointsOnSurf() + { + return myPoint2; + } private: diff --git a/src/Extrema/Extrema_GenExtCS.cxx b/src/Extrema/Extrema_GenExtCS.cxx index 0034bb5ac9..e4496b4c63 100644 --- a/src/Extrema/Extrema_GenExtCS.cxx +++ b/src/Extrema/Extrema_GenExtCS.cxx @@ -304,33 +304,84 @@ void Extrema_GenExtCS::Perform (const Adaptor3d_Curve& C, Tol(2) = mytol2; Tol(3) = mytol2; // - TUVinf(1) = mytmin; - TUVinf(2) = trimumin; - TUVinf(3) = trimvmin; - // - TUVsup(1) = mytsup; - TUVsup(2) = trimusup; - TUVsup(3) = trimvsup; - // // Number of particles used in PSO algorithm (particle swarm optimization). const Standard_Integer aNbParticles = 48; - // - if (aNbVar == 3) + + Standard_Integer aNbIntC = 1; + if (C.IsClosed() || C.IsPeriodic()) { - GlobMinGenCS(C, aNbParticles, TUVinf, TUVsup, TUV); - } - else if (aNbVar == 2) - { - GlobMinConicS(C, aNbParticles, TUVinf, TUVsup, TUV); - } - else - { - GlobMinCQuadric(C, aNbParticles, TUVinf, TUVsup, TUV); + Standard_Real aPeriod = C.Period(); + if (C.LastParameter() - C.FirstParameter() > 2. * aPeriod / 3.) + { + aNbIntC = 2; + } } - // Find min approximation - math_FunctionSetRoot anA(myF, Tol); - anA.Perform(myF, TUV, TUVinf, TUVsup); + Standard_Integer anInt; + Standard_Real dT = (mytsup - mytmin) / aNbIntC; + for (anInt = 1; anInt <= aNbIntC; anInt++) + { + TUVinf(1) = mytmin + (anInt - 1) * dT; + TUVinf(2) = trimumin; + TUVinf(3) = trimvmin; + // + TUVsup(1) = TUVinf(1) + dT; // mytsup; + TUVsup(2) = trimusup; + TUVsup(3) = trimvsup; + // + if (aNbVar == 3) + { + GlobMinGenCS(C, aNbParticles, TUVinf, TUVsup, TUV); + } + else if (aNbVar == 2) + { + GlobMinConicS(C, aNbParticles, TUVinf, TUVsup, TUV); + } + else + { + GlobMinCQuadric(C, aNbParticles, TUVinf, TUVsup, TUV); + } + + // Find min approximation + math_FunctionSetRoot anA(myF, Tol); + anA.Perform(myF, TUV, TUVinf, TUVsup); + } + if (aNbIntC > 1 && myF.NbExt() > 1) + { + //Try to remove "false" extrema caused by dividing curve interval + TColStd_SequenceOfReal& aSqDists = myF.SquareDistances(); + Extrema_SequenceOfPOnCurv& aPntsOnCrv = myF.PointsOnCurve(); + Extrema_SequenceOfPOnSurf& aPntsOnSurf = myF.PointsOnSurf(); + TColStd_SequenceOfReal aSqDists1(aSqDists); + Extrema_SequenceOfPOnCurv aPntsOnCrv1(aPntsOnCrv); + Extrema_SequenceOfPOnSurf aPntsOnSurf1(aPntsOnSurf); + + Standard_Real aMinDist = aSqDists(1); + Standard_Integer imin = 1, i; + for (i = 2; i <= aSqDists.Length(); ++i) + { + Standard_Real aDist = aSqDists(i); + if (aDist < aMinDist) + { + aMinDist = aDist; + imin = i; + } + } + aSqDists.Clear(); + aPntsOnCrv.Clear(); + aPntsOnSurf.Clear(); + Standard_Real aTol = Precision::SquareConfusion(); + for (i = 1; i <= aSqDists1.Length(); ++i) + { + Standard_Real aDist = aSqDists1(i); + if (Abs(aDist - aMinDist) <= aTol) + { + aSqDists.Append(aDist); + aPntsOnCrv.Append(aPntsOnCrv1(i)); + aPntsOnSurf.Append(aPntsOnSurf1(i)); + } + } + } myDone = Standard_True; } diff --git a/tests/lowalgos/extcs/bug32225 b/tests/lowalgos/extcs/bug32225 new file mode 100644 index 0000000000..35362be164 --- /dev/null +++ b/tests/lowalgos/extcs/bug32225 @@ -0,0 +1,28 @@ +puts "========" +puts "OCC32225: Modeling Data - Wrong result of extrema curve-surface" +puts "========" +puts "" + +restore [locate_data_file bug32225_curve.draw] c +restore [locate_data_file bug32225_surf.draw] s + +extrema c s + +if {[isdraw ext_1]} { + set ext_dist [lindex [length ext_1] end] + checkreal "Ext_1 min distance" $ext_dist 0. 1.e-10 1.e-10 +} else { + puts "Error: invalid result" +} + +if {[isdraw ext_2]} { + set ext_dist [lindex [length ext_2] end] + checkreal "Ext_2 min distance" $ext_dist 0. 1.e-10 1.e-10 +} else { + puts "Error: invalid result" +} +smallview +donly c ext_1 ext_2 +fit +disp s +checkview -screenshot -2d -path ${imagedir}/${test_image}.png \ No newline at end of file