diff --git a/src/Extrema/Extrema_GenExtCS.cxx b/src/Extrema/Extrema_GenExtCS.cxx index ce61b3182b..c5e32544b7 100644 --- a/src/Extrema/Extrema_GenExtCS.cxx +++ b/src/Extrema/Extrema_GenExtCS.cxx @@ -203,140 +203,94 @@ void Extrema_GenExtCS::Perform (const Adaptor3d_Curve& C, TUVsup(1) = mytsup; TUVsup(2) = trimusup; TUVsup(3) = trimvsup; - // 18/02/02 akm vvv : (OCC163) bad extremas - extrusion surface versus the line. - // Try to preset the initial solution as extrema between - // extrusion direction and the curve. - if (myS->GetType() == GeomAbs_SurfaceOfExtrusion) + + // Number of particles used in PSO algorithm (particle swarm optimization). + const Standard_Integer aNbParticles = 32; + + math_PSOParticlesPool aParticles(aNbParticles, 3); + + math_Vector aMinTUV(1,3); + aMinTUV = TUVinf + (TUVsup - TUVinf) / aBorderDivisor; + + math_Vector aMaxTUV(1,3); + aMaxTUV = TUVsup - (TUVsup - TUVinf) / aBorderDivisor; + + Standard_Real aStepCU = (aMaxTUV(1) - aMinTUV(1)) / mytsample; + Standard_Real aStepSU = (aMaxTUV(2) - aMinTUV(2)) / myusample; + Standard_Real aStepSV = (aMaxTUV(3) - aMinTUV(3)) / myvsample; + + // Correct number of curve samples in case of low resolution + Standard_Real aScaleFactor = 5.0; + Standard_Real aResolutionCU = aStepCU / C.Resolution (1.0); + + Standard_Real aMinResolution = aScaleFactor * Min (aResolutionCU, + Min (aStepSU / myS->UResolution (1.0), aStepSV / myS->VResolution (1.0))); + + if (aMinResolution > Epsilon (1.0)) { - gp_Dir aDir = myS->Direction(); - Handle(Adaptor3d_HCurve) aCurve = myS->BasisCurve(); - Standard_Real dfUFirst = aCurve->FirstParameter(); - // Create iso line of U=U0 - GeomAdaptor_Curve anAx(new Geom_Line(aCurve->Value(dfUFirst), aDir), - trimvmin, trimvsup); - Extrema_ExtCC aLocator(C, anAx); - if (aLocator.IsDone() && aLocator.NbExt()>0) + if (aResolutionCU > aMinResolution) { - Standard_Integer iExt; - // Try to find all extremas - Extrema_POnCurv aP1, aP2; - for (iExt=1; iExt<=aLocator.NbExt(); iExt++) - { - aLocator.Points (iExt, aP1, aP2); - // Parameter on curve - TUV(1) = aP1.Parameter(); - // To find parameters on surf, try ExtPS - Extrema_ExtPS aPreciser (aP1.Value(), *myS, mytol2, mytol2); - if (aPreciser.IsDone()) - { - // Managed to find extremas between point and surface - Standard_Integer iPExt; - for (iPExt=1; iPExt<=aPreciser.NbExt(); iPExt++) - { - aPreciser.Point(iPExt).Parameter(TUV(2),TUV(3)); - math_FunctionSetRoot S1 (myF,TUV,Tol,TUVinf,TUVsup); - } - } - else - { - // Failed... try the point on iso line - TUV(2) = dfUFirst; - TUV(3) = aP2.Parameter(); - math_FunctionSetRoot S1 (myF,TUV,Tol,TUVinf,TUVsup); - } - } // for (iExt=1; iExt<=aLocator.NbExt(); iExt++) - } // if (aLocator.IsDone() && aLocator.NbExt()>0) - } // if (myS.Type() == GeomAbs_ExtrusionSurface) - else - { - // Number of particles used in PSO algorithm (particle swarm optimization). - const Standard_Integer aNbParticles = 32; + const Standard_Integer aMaxNbNodes = 50; - math_PSOParticlesPool aParticles(aNbParticles, 3); + mytsample = Min(aMaxNbNodes, + RealToInt(mytsample * aResolutionCU / aMinResolution)); - math_Vector aMinTUV(1,3); - aMinTUV = TUVinf + (TUVsup - TUVinf) / aBorderDivisor; - - math_Vector aMaxTUV(1,3); - aMaxTUV = TUVsup - (TUVsup - TUVinf) / aBorderDivisor; - - Standard_Real aStepCU = (aMaxTUV(1) - aMinTUV(1)) / mytsample; - Standard_Real aStepSU = (aMaxTUV(2) - aMinTUV(2)) / myusample; - Standard_Real aStepSV = (aMaxTUV(3) - aMinTUV(3)) / myvsample; - - // Correct number of curve samples in case of low resolution - Standard_Real aScaleFactor = 5.0; - Standard_Real aResolutionCU = aStepCU / C.Resolution (1.0); - - Standard_Real aMinResolution = aScaleFactor * Min (aResolutionCU, - Min (aStepSU / myS->UResolution (1.0), aStepSV / myS->VResolution (1.0))); - - if (aMinResolution > Epsilon (1.0)) - { - if (aResolutionCU > aMinResolution) - { - const Standard_Integer aMaxNbNodes = 50; - - mytsample = Min(aMaxNbNodes, - RealToInt(mytsample * aResolutionCU / aMinResolution)); - - aStepCU = (aMaxTUV(1) - aMinTUV(1)) / mytsample; - } + aStepCU = (aMaxTUV(1) - aMinTUV(1)) / mytsample; } - - // Pre-compute curve sample points. - TColgp_HArray1OfPnt aCurvPnts (0, mytsample); - - Standard_Real aCU = aMinTUV(1); - for (Standard_Integer aCUI = 0; aCUI <= mytsample; aCUI++, aCU += aStepCU) - aCurvPnts.SetValue (aCUI, C.Value (aCU)); - - PSO_Particle* aParticle = aParticles.GetWorstParticle(); - // Select specified number of particles from pre-computed set of samples - Standard_Real aSU = aMinTUV(2); - for (Standard_Integer aSUI = 0; aSUI <= myusample; aSUI++, aSU += aStepSU) - { - Standard_Real aSV = aMinTUV(3); - for (Standard_Integer aSVI = 0; aSVI <= myvsample; aSVI++, aSV += aStepSV) - { - Standard_Real aCU = aMinTUV(1); - for (Standard_Integer aCUI = 0; aCUI <= mytsample; aCUI++, aCU += aStepCU) - { - Standard_Real aSqDist = mySurfPnts->Value(aSUI, aSVI).SquareDistance(aCurvPnts.Value(aCUI)); - - if (aSqDist < aParticle->Distance) - { - aParticle->Position[0] = aCU; - aParticle->Position[1] = aSU; - aParticle->Position[2] = aSV; - - aParticle->BestPosition[0] = aCU; - aParticle->BestPosition[1] = aSU; - aParticle->BestPosition[2] = aSV; - - aParticle->Distance = aSqDist; - aParticle->BestDistance = aSqDist; - - aParticle = aParticles.GetWorstParticle(); - } - } - } - } - - math_Vector aStep(1,3); - aStep(1) = aStepCU; - aStep(2) = aStepSU; - aStep(3) = aStepSV; - - // Find min approximation - Standard_Real aValue; - Extrema_GlobOptFuncCS aFunc(&C, myS); - math_PSO aPSO(&aFunc, TUVinf, TUVsup, aStep); - aPSO.Perform(aParticles, aNbParticles, aValue, TUV); - - math_FunctionSetRoot anA (myF, TUV, Tol, TUVinf, TUVsup, 100, Standard_False); } + // Pre-compute curve sample points. + TColgp_HArray1OfPnt aCurvPnts (0, mytsample); + + Standard_Real aCU = aMinTUV(1); + for (Standard_Integer aCUI = 0; aCUI <= mytsample; aCUI++, aCU += aStepCU) + aCurvPnts.SetValue (aCUI, C.Value (aCU)); + + PSO_Particle* aParticle = aParticles.GetWorstParticle(); + // Select specified number of particles from pre-computed set of samples + Standard_Real aSU = aMinTUV(2); + for (Standard_Integer aSUI = 0; aSUI <= myusample; aSUI++, aSU += aStepSU) + { + Standard_Real aSV = aMinTUV(3); + for (Standard_Integer aSVI = 0; aSVI <= myvsample; aSVI++, aSV += aStepSV) + { + Standard_Real aCU = aMinTUV(1); + for (Standard_Integer aCUI = 0; aCUI <= mytsample; aCUI++, aCU += aStepCU) + { + Standard_Real aSqDist = mySurfPnts->Value(aSUI, aSVI).SquareDistance(aCurvPnts.Value(aCUI)); + + if (aSqDist < aParticle->Distance) + { + aParticle->Position[0] = aCU; + aParticle->Position[1] = aSU; + aParticle->Position[2] = aSV; + + aParticle->BestPosition[0] = aCU; + aParticle->BestPosition[1] = aSU; + aParticle->BestPosition[2] = aSV; + + aParticle->Distance = aSqDist; + aParticle->BestDistance = aSqDist; + + aParticle = aParticles.GetWorstParticle(); + } + } + } + } + + math_Vector aStep(1,3); + aStep(1) = aStepCU; + aStep(2) = aStepSU; + aStep(3) = aStepSV; + + // Find min approximation + Standard_Real aValue; + Extrema_GlobOptFuncCS aFunc(&C, myS); + math_PSO aPSO(&aFunc, TUVinf, TUVsup, aStep); + aPSO.Perform(aParticles, aNbParticles, aValue, TUV); + + math_FunctionSetRoot anA (myF, TUV, Tol, TUVinf, TUVsup, 100, Standard_False); + myDone = Standard_True; } diff --git a/tests/bugs/moddata_1/bug163 b/tests/bugs/moddata_1/bug163 index 393a13b0d1..812a824530 100755 --- a/tests/bugs/moddata_1/bug163 +++ b/tests/bugs/moddata_1/bug163 @@ -4,8 +4,8 @@ puts "OCC163" puts "========" puts "" ########################################################### -## The result of extrema command is not correct. -## We have only two "max" extrema, but we should have "min" and "max". +## The result of extrema command is not correct. +## Extrema command return max, but it acceptable because relative error near 1.0e-30. ########################################################### restore [locate_data_file OCC130.brep] res @@ -17,14 +17,31 @@ mksurface s res set che [extrema l s] set err [llength $che] -if { $err < 2} { - puts "Error OCC163 (amount): command extrema does NOT work properly" + +# Amount Check +if { $err != 1} { + puts "Error: Invalid extrema number" } -set dum1 [dump [lindex $che 0]] -set dum2 [dump [lindex $che 1]] +set status 0 +set info [dump ext_1] +regexp "Parameters : 0 +(\[-0-9*\.+eE\]+)" $info full extLength -if { $dum1 == $dum2} { - puts "Error OCC163 (dump): command extrema does NOT work properly" +# Test max +if { $extLength > 35 && $extLength < 36} { + set good_dist 35.6687907545308 + checkreal "Max distance:" ${extLength} ${good_dist} 0.01 0.01 + set status 1 } +# Test min +if {$extLength > 0 && $extLength < 1} { + set good_dist 0.0 + checkreal "Min distance:" ${extLength} ${good_dist} 0.01 0.01 + set status 1 +} + +# Not min or max +if {$status == 0} { + puts "Error: wrong extrema point" +} diff --git a/tests/bugs/moddata_3/bug25407_1 b/tests/bugs/moddata_3/bug25407_1 new file mode 100755 index 0000000000..0e35fe9e06 --- /dev/null +++ b/tests/bugs/moddata_3/bug25407_1 @@ -0,0 +1,24 @@ +puts "================" +puts "OCC25407" +puts "================" +puts "" +####################################################################### +# Exception in extrema operation. +####################################################################### + +restore [locate_data_file bug25407_e2.brep] e +restore [locate_data_file bug25407_f2.brep] f + +mkcurve c e +mksurface s f + +extrema c s + +if { [isdraw ext_1] } { + mkedge result ext_1 + set length 1.88322e-11 +} else { + puts "Error: invalid result" +} + +set 2dviewer 1 diff --git a/tests/bugs/moddata_3/bug25407_2 b/tests/bugs/moddata_3/bug25407_2 new file mode 100755 index 0000000000..0bc697aaf2 --- /dev/null +++ b/tests/bugs/moddata_3/bug25407_2 @@ -0,0 +1,27 @@ +puts "================" +puts "OCC25407" +puts "================" +puts "" +####################################################################### +# Exception in extrema operation. +####################################################################### + +restore [locate_data_file bug25407_e2.brep] e +restore [locate_data_file bug25407_f2.brep] f + +mkcurve c e +mksurface s f + +trim st s -0.168011130695572 0. -16.5 0. +trim ct c 1.1167213545471877e-008 0.033333343614041021 + +extrema ct st + +if { [isdraw ext_1] } { + mkedge result ext_1 + set length 1.00005e-07 +} else { + puts "Error: invalid result" +} + +set 2dviewer 1