1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +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:
nbv
2016-03-29 16:29:55 +03:00
committed by bugmaster
parent cb120537bf
commit 243505b81b
8 changed files with 109 additions and 52 deletions

View File

@@ -575,6 +575,56 @@ Standard_Integer FillSubIntervals(const Handle(Geom_Curve)& theCurve3d,
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
//purpose : Performs computing minimal value
@@ -590,61 +640,52 @@ Standard_Boolean MinComputing (
{
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();
aParSup(1) = theFunction.LastParameter();
theBestParameter = aParInf(1);
theBestValue = RealLast();
const Standard_Real aDeltaParam = aParSup(1) - aParInf(1);
if(aDeltaParam < Precision::PConfusion())
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())
if(!PSO_Perform(theFunction, aParInf, aParSup, theEpsilon, theNbParticles,
theBestValue, anOutputParam))
{
#ifdef OCCT_DEBUG
cout << "BRepLib_CheckCurveOnSurface::Compute(): No solution found!" << endl;
cout << "BRepLib_CheckCurveOnSurface::Compute(): math_PSO is failed!" << endl;
#endif
return Standard_False;
}
anA.Location(anOutputParam);
theBestParameter = anOutputParam(1);
theBestValue = anA.Minimum();
theBestParameter = anOutputParam(1);
//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)
{