1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-21 10:13:43 +03:00

0032744: Modeling Algorithms - Endless loop in GCPnts_UniformDeflection

fixed finish criteria in CPnts_UniformDeflection::Perform()
This commit is contained in:
asuraven 2021-12-20 19:27:09 +03:00 committed by smoskvin
parent a3e117be2c
commit 1955914e73
3 changed files with 181 additions and 97 deletions

View File

@ -89,139 +89,173 @@ static void D22d(const Standard_Address C, const Standard_Real U,
void CPnts_UniformDeflection::Perform() void CPnts_UniformDeflection::Perform()
{ {
gp_Pnt P, P1, P2; gp_Pnt P, P1, P2;
// gp_Vec V1, V2, VV1, VV2, VV;
gp_Vec V1, V2, VV; gp_Vec V1, V2, VV;
Standard_Real Un1; Standard_Real Un1;
Standard_Real NormD1, NormD2; Standard_Real NormD1, NormD2;
myIPoint = -1; myIPoint = -1;
myNbPoints = -1; myNbPoints = -1;
while ( (myNbPoints<2) && (!myFinish) ) { const Standard_Real anEspilon = Epsilon(myFirstParam);
myNbPoints = myNbPoints + 1; while ( (myNbPoints<2) && (!myFinish) )
{
++myNbPoints;
myParams[myNbPoints] = myFirstParam; myParams[myNbPoints] = myFirstParam;
if (my3d) if (my3d)
{
D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2); D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
}
else else
{
D22d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2); D22d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
P = myPoints[myNbPoints] ; }
P = myPoints[myNbPoints];
NormD1 = V1.Magnitude(); NormD1 = V1.Magnitude();
if (NormD1 < myTolCur || V2.Magnitude() < myTolCur) { if (NormD1 < myTolCur || V2.Magnitude() < myTolCur)
{
// singularity on the tangent or null curvature // singularity on the tangent or null curvature
myDu = Min(myDwmax, 1.5 * myDu); myDu = Min(myDwmax, 1.5 * myDu);
} }
else { else
{
NormD2 = V2.CrossMagnitude(V1); NormD2 = V2.CrossMagnitude(V1);
if (NormD2 / NormD1 < myDeflection) { // collinearity of derivatives if (NormD2 / NormD1 < myDeflection)
myDu = Min(myDwmax, 1.5 * myDu); {
// collinearity of derivatives
myDu = Min(myDwmax, 1.5 * myDu);
} }
else { else
myDu = Sqrt(8.* myDeflection * NormD1 / NormD2 ); {
myDu = Min(Max(myDu, myTolCur), myDwmax); myDu = Sqrt(8.* myDeflection * NormD1 / NormD2);
myDu = Min(Max(myDu, myTolCur), myDwmax);
} }
} }
// check if the arrow is observed if WithControl // check if the arrow is observed if WithControl
if (myControl)
if (myControl) { {
myDu = Min(myDu, myLastParam-myFirstParam); myDu = Min(myDu, myLastParam-myFirstParam);
if (my3d) { if (my3d)
{
D03d(myCurve, myFirstParam + myDu,P); D03d(myCurve, myFirstParam + myDu,P);
D03d(myCurve, myFirstParam + (myDu / 2.0),P1); D03d(myCurve, myFirstParam + (myDu / 2.0), P1);
} }
else { else
{
D02d(myCurve, myFirstParam + myDu,P); D02d(myCurve, myFirstParam + myDu,P);
D02d(myCurve, myFirstParam + (myDu / 2.0),P1); D02d(myCurve, myFirstParam + (myDu / 2.0), P1);
} }
V1= gp_Vec(myPoints[myNbPoints], P); V1= gp_Vec(myPoints[myNbPoints], P);
NormD1 = V1.Magnitude(); NormD1 = V1.Magnitude();
if (NormD1 >= myDeflection) { if (NormD1 >= myDeflection)
V2 = gp_Vec(myPoints[myNbPoints], P1); {
NormD2 = V2.CrossMagnitude(V1) / NormD1; V2 = gp_Vec(myPoints[myNbPoints], P1);
NormD2 = V2.CrossMagnitude(V1) / NormD1;
// passing of arrow starting from which the redivision is done is arbitrary
// probably it will be necessary to readjust it (differentiate the first point // passing of arrow starting from which the redivision is done is arbitrary
// from the others) this test does not work on the points of inflexion // probably it will be necessary to readjust it (differentiate the first point
// from the others) this test does not work on the points of inflexion
if (NormD2 > myDeflection / 5.0) { if (NormD2 > myDeflection / 5.0)
NormD2 = Max(NormD2, 1.1 * myDeflection); {
myDu = myDu * Sqrt(myDeflection / NormD2); NormD2 = Max(NormD2, 1.1 * myDeflection);
myDu = Min(Max(myDu, myTolCur), myDwmax); myDu = myDu * Sqrt(myDeflection / NormD2);
} myDu = Min(Max(myDu, myTolCur), myDwmax);
}
} }
} }
myFirstParam = myFirstParam + myDu; myFirstParam += myDu;
myFinish = (myLastParam - myFirstParam < myTolCur) || (myDu == 0.); myFinish = myLastParam - myFirstParam < myTolCur ||
Abs(myDu) < myTolCur ||
// to avoid less than double precision endless increment
myDu < anEspilon;
} }
if (myFinish) { if (myFinish)
{
// the last point is corrected if control // the last point is corrected if control
if (myControl && (myNbPoints == 1) ) { if (myControl && (myNbPoints == 1) )
{
Un1 = myParams[0]; Un1 = myParams[0];
if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) { if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam))
myFirstParam = (myLastParam + Un1) / 2.0; {
myParams[0]= myFirstParam; myFirstParam = (myLastParam + Un1) / 2.0;
myParams[1]= myLastParam; myParams[0] = myFirstParam;
if (my3d) { myParams[1] = myLastParam;
D03d(myCurve, myParams[0], myPoints[0]); if (my3d)
D03d(myCurve, myParams[1], myPoints[1]); {
} D03d(myCurve, myParams[0], myPoints[0]);
else { D03d(myCurve, myParams[1], myPoints[1]);
D02d(myCurve, myParams[0], myPoints[0]); }
else
{
D02d(myCurve, myParams[0], myPoints[0]);
D02d(myCurve, myParams[1], myPoints[1]); D02d(myCurve, myParams[1], myPoints[1]);
} }
} }
else { else
if (my3d) { {
D23d(myCurve, myLastParam, P1, V1, V2); if (my3d)
} {
else { D23d(myCurve, myLastParam, P1, V1, V2);
D22d(myCurve, myLastParam, P1, V1, V2); }
} else
P = myPoints[0] ; {
VV = gp_Vec(P1, P); D22d(myCurve, myLastParam, P1, V1, V2);
NormD1 = VV.Magnitude(); }
if ( NormD1 < myDeflection) { P = myPoints[0];
myParams[1]= myLastParam; VV = gp_Vec(P1, P);
myPoints[1]= P1 ; NormD1 = VV.Magnitude();
} if (NormD1 < myDeflection)
else { {
myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu) myParams[1] = myLastParam;
/(myFirstParam -Un1); myPoints[1] = P1;
if (my3d) }
D03d(myCurve, myFirstParam, P2); else
else {
D02d(myCurve, myFirstParam, P2); myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu) / (myFirstParam - Un1);
if (my3d)
if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) && {
(Un1 >= myLastParam - myDwmax) ) { D03d(myCurve, myFirstParam, P2);
// point n is removed }
myParams[1]= myLastParam; else
myPoints[1] = P1 ; {
} D02d(myCurve, myFirstParam, P2);
else { }
myParams[1]=myFirstParam; if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) &&
myPoints[1] = P2 ; (Un1 >= myLastParam - myDwmax) )
myParams[2]=myLastParam; {
myPoints[2] = P1 ; // point n is removed
myNbPoints = myNbPoints +1; myParams[1] = myLastParam;
} myPoints[1] = P1;
} }
else
{
myParams[1] = myFirstParam;
myPoints[1] = P2;
myParams[2] = myLastParam;
myPoints[2] = P1;
++myNbPoints;
}
}
} }
} }
else { else
myNbPoints = myNbPoints +1 ; {
if (myNbPoints >= 3) myNbPoints = 2; ++myNbPoints;
myParams[myNbPoints]= myLastParam; if (myNbPoints >= 3)
if (my3d) { {
D03d(myCurve, myLastParam, myPoints[myNbPoints]); myNbPoints = 2;
} }
else { myParams[myNbPoints] = myLastParam;
D02d(myCurve, myLastParam, myPoints[myNbPoints]); if (my3d)
} {
D03d(myCurve, myLastParam, myPoints[myNbPoints]);
}
else
{
D02d(myCurve, myLastParam, myPoints[myNbPoints]);
}
} }
} }
} }

View File

@ -4172,6 +4172,41 @@ static Standard_Integer OCC29406 (Draw_Interpretor&, Standard_Integer, const cha
return 0; return 0;
} }
#include <BRepCheck_Analyzer.hxx>
#include <GCPnts_UniformDeflection.hxx>
static Standard_Integer OCC32744(Draw_Interpretor& theDi, Standard_Integer theNbArgs, const char** theArgVec)
{
if (theNbArgs != 2)
{
theDi << "Syntax error: wrong number of arguments!\n";
return 1;
}
const TopoDS_Shape& aShape = DBRep::Get(theArgVec[1]);
if (aShape.IsNull())
{
theDi << " Null Shape is not allowed here\n";
return 1;
}
else if (aShape.ShapeType() != TopAbs_EDGE)
{
theDi << " Shape type must be EDGE\n";
return 1;
}
const TopoDS_Edge& anEdge = TopoDS::Edge(aShape);
BRepCheck_Analyzer analyzer(anEdge);
if (analyzer.IsValid())
{
Standard_Real firstParam = 0., lastParam = 0.;
Handle(Geom_Curve) pCurve = BRep_Tool::Curve(anEdge, firstParam, lastParam);
GeomAdaptor_Curve curveAdaptor(pCurve, firstParam, lastParam);
GCPnts_UniformDeflection uniformAbs(curveAdaptor, 0.001, firstParam, lastParam);
}
return 0;
}
void QABugs::Commands_20(Draw_Interpretor& theCommands) { void QABugs::Commands_20(Draw_Interpretor& theCommands) {
const char *group = "QABugs"; const char *group = "QABugs";
@ -4258,5 +4293,11 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
theCommands.Add ("OCC29406", theCommands.Add ("OCC29406",
"Tests the case when newly set axis for gp_Ax3 is parallel to one of current axis", "Tests the case when newly set axis for gp_Ax3 is parallel to one of current axis",
__FILE__, OCC29406, group); __FILE__, OCC29406, group);
theCommands.Add("OCC32744",
"Tests avoid Endless loop in GCPnts_UniformDeflection",
__FILE__,
OCC32744, group);
return; return;
} }

View File

@ -0,0 +1,9 @@
puts "================================================="
puts "0032744: Modeling Algorithms -Endless loop in GCPnts_UniformDeflection"
puts "================================================="
puts ""
pload QAcommands
# test execution time must be within the cpulimit
restore [locate_data_file bug32744.brep] s
OCC32744 s