1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +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 2f23e4e3a5
commit 2ac4e1beee
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()
{
gp_Pnt P, P1, P2;
// gp_Vec V1, V2, VV1, VV2, VV;
gp_Vec V1, V2, VV;
Standard_Real Un1;
Standard_Real NormD1, NormD2;
myIPoint = -1;
myNbPoints = -1;
while ( (myNbPoints<2) && (!myFinish) ) {
myNbPoints = myNbPoints + 1;
const Standard_Real anEspilon = Epsilon(myFirstParam);
while ( (myNbPoints<2) && (!myFinish) )
{
++myNbPoints;
myParams[myNbPoints] = myFirstParam;
if (my3d)
{
D23d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
}
else
{
D22d(myCurve, myFirstParam, myPoints[myNbPoints], V1, V2);
P = myPoints[myNbPoints] ;
}
P = myPoints[myNbPoints];
NormD1 = V1.Magnitude();
if (NormD1 < myTolCur || V2.Magnitude() < myTolCur) {
if (NormD1 < myTolCur || V2.Magnitude() < myTolCur)
{
// singularity on the tangent or null curvature
myDu = Min(myDwmax, 1.5 * myDu);
}
else {
else
{
NormD2 = V2.CrossMagnitude(V1);
if (NormD2 / NormD1 < myDeflection) { // collinearity of derivatives
myDu = Min(myDwmax, 1.5 * myDu);
if (NormD2 / NormD1 < myDeflection)
{
// collinearity of derivatives
myDu = Min(myDwmax, 1.5 * myDu);
}
else {
myDu = Sqrt(8.* myDeflection * NormD1 / NormD2 );
myDu = Min(Max(myDu, myTolCur), myDwmax);
else
{
myDu = Sqrt(8.* myDeflection * NormD1 / NormD2);
myDu = Min(Max(myDu, myTolCur), myDwmax);
}
}
// check if the arrow is observed if WithControl
if (myControl) {
if (myControl)
{
myDu = Min(myDu, myLastParam-myFirstParam);
if (my3d) {
D03d(myCurve, myFirstParam + myDu,P);
D03d(myCurve, myFirstParam + (myDu / 2.0),P1);
if (my3d)
{
D03d(myCurve, myFirstParam + myDu,P);
D03d(myCurve, myFirstParam + (myDu / 2.0), P1);
}
else {
D02d(myCurve, myFirstParam + myDu,P);
D02d(myCurve, myFirstParam + (myDu / 2.0),P1);
else
{
D02d(myCurve, myFirstParam + myDu,P);
D02d(myCurve, myFirstParam + (myDu / 2.0), P1);
}
V1= gp_Vec(myPoints[myNbPoints], P);
NormD1 = V1.Magnitude();
if (NormD1 >= myDeflection) {
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
// from the others) this test does not work on the points of inflexion
if (NormD2 > myDeflection / 5.0) {
NormD2 = Max(NormD2, 1.1 * myDeflection);
myDu = myDu * Sqrt(myDeflection / NormD2);
myDu = Min(Max(myDu, myTolCur), myDwmax);
}
if (NormD1 >= myDeflection)
{
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
// from the others) this test does not work on the points of inflexion
if (NormD2 > myDeflection / 5.0)
{
NormD2 = Max(NormD2, 1.1 * myDeflection);
myDu = myDu * Sqrt(myDeflection / NormD2);
myDu = Min(Max(myDu, myTolCur), myDwmax);
}
}
}
myFirstParam = myFirstParam + myDu;
myFinish = (myLastParam - myFirstParam < myTolCur) || (myDu == 0.);
myFirstParam += myDu;
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
if (myControl && (myNbPoints == 1) ) {
if (myControl && (myNbPoints == 1) )
{
Un1 = myParams[0];
if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam)) {
myFirstParam = (myLastParam + Un1) / 2.0;
myParams[0]= myFirstParam;
myParams[1]= myLastParam;
if (my3d) {
D03d(myCurve, myParams[0], myPoints[0]);
D03d(myCurve, myParams[1], myPoints[1]);
}
else {
D02d(myCurve, myParams[0], myPoints[0]);
if (myLastParam - Un1 < 0.33*(myLastParam-myFirstParam))
{
myFirstParam = (myLastParam + Un1) / 2.0;
myParams[0] = myFirstParam;
myParams[1] = myLastParam;
if (my3d)
{
D03d(myCurve, myParams[0], myPoints[0]);
D03d(myCurve, myParams[1], myPoints[1]);
}
else
{
D02d(myCurve, myParams[0], myPoints[0]);
D02d(myCurve, myParams[1], myPoints[1]);
}
}
}
else {
if (my3d) {
D23d(myCurve, myLastParam, P1, V1, V2);
}
else {
D22d(myCurve, myLastParam, P1, V1, V2);
}
P = myPoints[0] ;
VV = gp_Vec(P1, P);
NormD1 = VV.Magnitude();
if ( NormD1 < myDeflection) {
myParams[1]= myLastParam;
myPoints[1]= P1 ;
}
else {
myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu)
/(myFirstParam -Un1);
if (my3d)
D03d(myCurve, myFirstParam, P2);
else
D02d(myCurve, myFirstParam, P2);
if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) &&
(Un1 >= myLastParam - myDwmax) ) {
// point n is removed
myParams[1]= myLastParam;
myPoints[1] = P1 ;
}
else {
myParams[1]=myFirstParam;
myPoints[1] = P2 ;
myParams[2]=myLastParam;
myPoints[2] = P1 ;
myNbPoints = myNbPoints +1;
}
}
else
{
if (my3d)
{
D23d(myCurve, myLastParam, P1, V1, V2);
}
else
{
D22d(myCurve, myLastParam, P1, V1, V2);
}
P = myPoints[0];
VV = gp_Vec(P1, P);
NormD1 = VV.Magnitude();
if (NormD1 < myDeflection)
{
myParams[1] = myLastParam;
myPoints[1] = P1;
}
else
{
myFirstParam = (myLastParam * (myParams[1] - Un1) + Un1 * myDu) / (myFirstParam - Un1);
if (my3d)
{
D03d(myCurve, myFirstParam, P2);
}
else
{
D02d(myCurve, myFirstParam, P2);
}
if ((VV.CrossMagnitude(gp_Vec(P2, P)) / NormD1 < myDeflection) &&
(Un1 >= myLastParam - myDwmax) )
{
// point n is removed
myParams[1] = myLastParam;
myPoints[1] = P1;
}
else
{
myParams[1] = myFirstParam;
myPoints[1] = P2;
myParams[2] = myLastParam;
myPoints[2] = P1;
++myNbPoints;
}
}
}
}
else {
myNbPoints = myNbPoints +1 ;
if (myNbPoints >= 3) myNbPoints = 2;
myParams[myNbPoints]= myLastParam;
if (my3d) {
D03d(myCurve, myLastParam, myPoints[myNbPoints]);
}
else {
D02d(myCurve, myLastParam, myPoints[myNbPoints]);
}
else
{
++myNbPoints;
if (myNbPoints >= 3)
{
myNbPoints = 2;
}
myParams[myNbPoints] = myLastParam;
if (my3d)
{
D03d(myCurve, myLastParam, myPoints[myNbPoints]);
}
else
{
D02d(myCurve, myLastParam, myPoints[myNbPoints]);
}
}
}
}

View File

@ -4148,6 +4148,41 @@ static Standard_Integer OCC29406 (Draw_Interpretor&, Standard_Integer, const cha
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) {
const char *group = "QABugs";
@ -4234,5 +4269,11 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
theCommands.Add ("OCC29406",
"Tests the case when newly set axis for gp_Ax3 is parallel to one of current axis",
__FILE__, OCC29406, group);
theCommands.Add("OCC32744",
"Tests avoid Endless loop in GCPnts_UniformDeflection",
__FILE__,
OCC32744, group);
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