mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
0027300: Boolean operation produces invalid shape in terms of "bopargcheck" command
1. Check, if value found by math_PSO algorithm cannot be precised by math_NewtonMinimum algorithm. In this case, we call math_PSO algorithm repeatedly, however, with other parameters. 2. Some margin of edge tolerance value has been provided in IntTools_Tools class. 3. Interface of math_NewtonMinimum class has been changed (method GetStatus() has been added). Correction of some test cases according to their new behavior.
This commit is contained in:
parent
cb120537bf
commit
243505b81b
@ -575,6 +575,56 @@ Standard_Integer FillSubIntervals(const Handle(Geom_Curve)& theCurve3d,
|
|||||||
return aNbSubIntervals;
|
return aNbSubIntervals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//class : PSO_Perform
|
||||||
|
//purpose : Searches minimal distance with math_PSO class
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean PSO_Perform(GeomLib_CheckCurveOnSurface_TargetFunc& theFunction,
|
||||||
|
const math_Vector &theParInf,
|
||||||
|
const math_Vector &theParSup,
|
||||||
|
const Standard_Real theEpsilon,
|
||||||
|
const Standard_Integer theNbParticles,
|
||||||
|
Standard_Real& theBestValue,
|
||||||
|
math_Vector &theOutputParam)
|
||||||
|
{
|
||||||
|
const Standard_Real aDeltaParam = theParSup(1) - theParInf(1);
|
||||||
|
if(aDeltaParam < Precision::PConfusion())
|
||||||
|
return Standard_False;
|
||||||
|
|
||||||
|
math_Vector aStepPar(1, 1);
|
||||||
|
aStepPar(1) = theEpsilon*aDeltaParam;
|
||||||
|
|
||||||
|
math_PSOParticlesPool aParticles(theNbParticles, 1);
|
||||||
|
|
||||||
|
//They are used for finding a position of theNbParticles worst places
|
||||||
|
const Standard_Integer aNbControlPoints = 3*theNbParticles;
|
||||||
|
|
||||||
|
const Standard_Real aStep = aDeltaParam/(aNbControlPoints-1);
|
||||||
|
Standard_Integer aCount = 1;
|
||||||
|
for(Standard_Real aPrm = theParInf(1); aCount <= aNbControlPoints; aCount++,
|
||||||
|
aPrm = (aCount == aNbControlPoints)? theParSup(1) : aPrm+aStep)
|
||||||
|
{
|
||||||
|
Standard_Real aVal = RealLast();
|
||||||
|
if(!theFunction.Value(aPrm, aVal))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PSO_Particle* aParticle = aParticles.GetWorstParticle();
|
||||||
|
|
||||||
|
if(aVal > aParticle->BestDistance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
aParticle->Position[0] = aPrm;
|
||||||
|
aParticle->BestPosition[0] = aPrm;
|
||||||
|
aParticle->Distance = aVal;
|
||||||
|
aParticle->BestDistance = aVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
math_PSO aPSO(&theFunction, theParInf, theParSup, aStepPar);
|
||||||
|
aPSO.Perform(aParticles, theNbParticles, theBestValue, theOutputParam);
|
||||||
|
|
||||||
|
return Standard_True;
|
||||||
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
//class : MinComputing
|
//class : MinComputing
|
||||||
//purpose : Performs computing minimal value
|
//purpose : Performs computing minimal value
|
||||||
@ -590,61 +640,52 @@ Standard_Boolean MinComputing (
|
|||||||
{
|
{
|
||||||
OCC_CATCH_SIGNALS
|
OCC_CATCH_SIGNALS
|
||||||
|
|
||||||
//They are used for finding a position of theNbParticles worst places
|
|
||||||
const Standard_Integer aNbControlPoints = 3*theNbParticles;
|
|
||||||
//
|
//
|
||||||
math_Vector aParInf(1, 1), aParSup(1, 1), anOutputParam(1, 1), aStepPar(1,1);
|
math_Vector aParInf(1, 1), aParSup(1, 1), anOutputParam(1, 1);
|
||||||
aParInf(1) = theFunction.FirstParameter();
|
aParInf(1) = theFunction.FirstParameter();
|
||||||
aParSup(1) = theFunction.LastParameter();
|
aParSup(1) = theFunction.LastParameter();
|
||||||
theBestParameter = aParInf(1);
|
theBestParameter = aParInf(1);
|
||||||
theBestValue = RealLast();
|
theBestValue = RealLast();
|
||||||
|
|
||||||
const Standard_Real aDeltaParam = aParSup(1) - aParInf(1);
|
if(!PSO_Perform(theFunction, aParInf, aParSup, theEpsilon, theNbParticles,
|
||||||
if(aDeltaParam < Precision::PConfusion())
|
theBestValue, anOutputParam))
|
||||||
return Standard_False;
|
|
||||||
|
|
||||||
aStepPar(1) = theEpsilon*aDeltaParam;
|
|
||||||
|
|
||||||
math_PSOParticlesPool aParticles(theNbParticles, 1);
|
|
||||||
|
|
||||||
const Standard_Real aStep = aDeltaParam/(aNbControlPoints-1);
|
|
||||||
Standard_Integer aCount = 1;
|
|
||||||
for(Standard_Real aPrm = aParInf(1); aCount <= aNbControlPoints; aCount++,
|
|
||||||
aPrm = (aCount == aNbControlPoints)? aParSup(1) : aPrm+aStep)
|
|
||||||
{
|
|
||||||
Standard_Real aVal = RealLast();
|
|
||||||
theFunction.Value(aPrm, aVal);
|
|
||||||
|
|
||||||
PSO_Particle* aParticle = aParticles.GetWorstParticle();
|
|
||||||
|
|
||||||
if(aVal > aParticle->BestDistance)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
aParticle->Position[0] = aPrm;
|
|
||||||
aParticle->BestPosition[0] = aPrm;
|
|
||||||
aParticle->Distance = aVal;
|
|
||||||
aParticle->BestDistance = aVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
math_PSO aPSO(&theFunction, aParInf, aParSup, aStepPar);
|
|
||||||
aPSO.Perform(aParticles, theNbParticles, theBestValue, anOutputParam);
|
|
||||||
|
|
||||||
//Here, anOutputParam contains parameter, which is near to optimal.
|
|
||||||
//It needs to be more precise. Precision is made by math_NewtonMinimum.
|
|
||||||
math_NewtonMinimum anA(theFunction);
|
|
||||||
anA.Perform(theFunction, anOutputParam);
|
|
||||||
|
|
||||||
if(!anA.IsDone())
|
|
||||||
{
|
{
|
||||||
#ifdef OCCT_DEBUG
|
#ifdef OCCT_DEBUG
|
||||||
cout << "BRepLib_CheckCurveOnSurface::Compute(): No solution found!" << endl;
|
cout << "BRepLib_CheckCurveOnSurface::Compute(): math_PSO is failed!" << endl;
|
||||||
#endif
|
#endif
|
||||||
return Standard_False;
|
return Standard_False;
|
||||||
}
|
}
|
||||||
|
|
||||||
anA.Location(anOutputParam);
|
theBestParameter = anOutputParam(1);
|
||||||
theBestParameter = anOutputParam(1);
|
|
||||||
theBestValue = anA.Minimum();
|
//Here, anOutputParam contains parameter, which is near to optimal.
|
||||||
|
//It needs to be more precise. Precision is made by math_NewtonMinimum.
|
||||||
|
math_NewtonMinimum aMinSol(theFunction);
|
||||||
|
aMinSol.Perform(theFunction, anOutputParam);
|
||||||
|
|
||||||
|
if(aMinSol.IsDone() && (aMinSol.GetStatus() == math_OK))
|
||||||
|
{//math_NewtonMinimum has precised the value. We take it.
|
||||||
|
aMinSol.Location(anOutputParam);
|
||||||
|
theBestParameter = anOutputParam(1);
|
||||||
|
theBestValue = aMinSol.Minimum();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{//Use math_PSO again but on smaller range.
|
||||||
|
const Standard_Real aStep = theEpsilon*(aParSup(1) - aParInf(1));
|
||||||
|
aParInf(1) = theBestParameter - 0.5*aStep;
|
||||||
|
aParSup(1) = theBestParameter + 0.5*aStep;
|
||||||
|
|
||||||
|
Standard_Real aValue = RealLast();
|
||||||
|
if(PSO_Perform(theFunction, aParInf, aParSup, theEpsilon, theNbParticles,
|
||||||
|
aValue, anOutputParam))
|
||||||
|
{
|
||||||
|
if(aValue < theBestValue)
|
||||||
|
{
|
||||||
|
theBestValue = aValue;
|
||||||
|
theBestParameter = anOutputParam(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Standard_Failure)
|
catch(Standard_Failure)
|
||||||
{
|
{
|
||||||
|
@ -797,8 +797,16 @@ Standard_Boolean IntTools_Tools::ComputeTolerance
|
|||||||
if (!aCS.IsDone()) {
|
if (!aCS.IsDone()) {
|
||||||
return Standard_False;
|
return Standard_False;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
theMaxDist = aCS.MaxDistance();
|
//Obtaining precise result is impossible if we use
|
||||||
|
//numeric methods for solution. Therefore, we must provide
|
||||||
|
//some margin. Otherwise, in the future
|
||||||
|
//(when geometrical properties of the curve will be changed,
|
||||||
|
//e.g. after trimming) we will be able to come
|
||||||
|
//to the more precise minimum point. As result, this curve with the
|
||||||
|
//tolerance computed earlier will become invalid.
|
||||||
|
const Standard_Real anEps = (1.0+1.0e-9);
|
||||||
|
theMaxDist = anEps*aCS.MaxDistance();
|
||||||
theMaxPar = aCS.MaxParameter();
|
theMaxPar = aCS.MaxParameter();
|
||||||
//
|
//
|
||||||
return Standard_True;
|
return Standard_True;
|
||||||
|
@ -140,8 +140,9 @@ void math_NewtonMinimum::Perform(math_MultipleVarFunctionWithHessian& F,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TheStatus = math_FunctionError;
|
Done = Standard_False;
|
||||||
return;
|
TheStatus = math_FunctionError;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,11 @@ public:
|
|||||||
//! calculation of the minimum.
|
//! calculation of the minimum.
|
||||||
//! The exception NotDone is raised if an error has occured.
|
//! The exception NotDone is raised if an error has occured.
|
||||||
Standard_Integer NbIterations() const;
|
Standard_Integer NbIterations() const;
|
||||||
|
|
||||||
|
//! Returns the Status of computation.
|
||||||
|
//! The exception NotDone is raised if an error has occured.
|
||||||
|
math_Status GetStatus() const;
|
||||||
|
|
||||||
|
|
||||||
//! Prints on the stream o information on the current state
|
//! Prints on the stream o information on the current state
|
||||||
//! of the object.
|
//! of the object.
|
||||||
|
@ -63,3 +63,7 @@ inline Standard_Integer math_NewtonMinimum::NbIterations() const
|
|||||||
return nbiter;
|
return nbiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline math_Status math_NewtonMinimum::GetStatus() const
|
||||||
|
{
|
||||||
|
return TheStatus;
|
||||||
|
}
|
||||||
|
@ -6,8 +6,8 @@ puts ""
|
|||||||
## Wrong distance found by xdistef command for attached shapes
|
## Wrong distance found by xdistef command for attached shapes
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
set Tol 1.0e-14
|
set Tol 5.0e-14
|
||||||
set dist_good 8.5127062130336385e-006
|
set dist_good 8.512706220911343e-006
|
||||||
|
|
||||||
restore [locate_data_file bug698_f.brep] f
|
restore [locate_data_file bug698_f.brep] f
|
||||||
nexplode f e
|
nexplode f e
|
||||||
|
@ -29,7 +29,7 @@ bsection result b1 f2
|
|||||||
|
|
||||||
regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance result] full MaxTolerance
|
regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance result] full MaxTolerance
|
||||||
|
|
||||||
set expected_MaxTolerance 0.0068942263850054935
|
set expected_MaxTolerance 0.0068942263920076944
|
||||||
set tol_abs_MaxTolerance 0.0
|
set tol_abs_MaxTolerance 0.0
|
||||||
set tol_rel_MaxTolerance 1.0e-4
|
set tol_rel_MaxTolerance 1.0e-4
|
||||||
checkreal "MaxTolerance" ${MaxTolerance} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
|
checkreal "MaxTolerance" ${MaxTolerance} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
puts "TODO OCC27300 ALL: ERROR. result is not valid for BOP"
|
|
||||||
|
|
||||||
puts "============"
|
puts "============"
|
||||||
puts "OCC27282"
|
puts "OCC27282"
|
||||||
puts "============"
|
puts "============"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user