1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-05 18:16:23 +03:00

0027048: BSpline cache is always wrong outside of surface

1. Disable recalculation of B-spline cache when the parameter is out of surface boundary but near the cached span.
2. Rebuild cache each time a curve/surface is loaded into adaptor (B-spline knots may be re-parametrized outside adaptor without changing base curve)
3. Test cases.
This commit is contained in:
azv 2016-01-21 11:35:24 +03:00 committed by bugmaster
parent 4f5ad41656
commit f3a1c0cb60
10 changed files with 111 additions and 4 deletions

View File

@ -73,7 +73,8 @@ Standard_Boolean BSplCLib_Cache::IsCacheValid(Standard_Real theParameter) const
PeriodicNormalization(myFlatKnots->Array1(), aNewParam);
Standard_Real aDelta = aNewParam - mySpanStart;
return (aDelta >= 0.0 && (aDelta < mySpanLength || mySpanIndex == mySpanIndexMax));
return ((aDelta >= 0.0 || mySpanIndex == mySpanIndexMin) &&
(aDelta < mySpanLength || mySpanIndex == mySpanIndexMax));
}
void BSplCLib_Cache::PeriodicNormalization(const TColStd_Array1OfReal& theFlatKnots,
@ -126,6 +127,7 @@ void BSplCLib_Cache::BuildCache(const Standard_Real& theParameter,
aNewParam, thePeriodic, mySpanIndex, aNewParam);
mySpanStart = theFlatKnots.Value(mySpanIndex);
mySpanLength = theFlatKnots.Value(mySpanIndex + 1) - mySpanStart;
mySpanIndexMin = thePeriodic ? 0 : myDegree + 1;
mySpanIndexMax = theFlatKnots.Length() - 1 - theDegree;
// Calculate new cache data
@ -164,6 +166,7 @@ void BSplCLib_Cache::BuildCache(const Standard_Real& theParameter,
aNewParam, thePeriodic, mySpanIndex, aNewParam);
mySpanStart = theFlatKnots.Value(mySpanIndex);
mySpanLength = theFlatKnots.Value(mySpanIndex + 1) - mySpanStart;
mySpanIndexMin = thePeriodic ? 0 : myDegree + 1;
mySpanIndexMax = theFlatKnots.Length() - 1 - theDegree;
// Calculate new cache data

View File

@ -167,6 +167,7 @@ private:
Standard_Real mySpanStart; ///< parameter for the first point of the span
Standard_Real mySpanLength; ///< length of the span
Standard_Integer mySpanIndex; ///< index of the span on Bezier/B-spline curve
Standard_Integer mySpanIndexMin; ///< minimal index of span on Bezier/B-spline curve
Standard_Integer mySpanIndexMax; ///< maximal number of spans on Bezier/B-spline curve
Standard_Integer myDegree; ///< degree of Bezier/B-spline
Handle(TColStd_HArray1OfReal) myFlatKnots; ///< knots of Bezier/B-spline (used for periodic normalization of parameters, exists only for periodical splines)

View File

@ -75,8 +75,10 @@ Standard_Boolean BSplSLib_Cache::IsCacheValid(Standard_Real theParameterU,
Standard_Real aDelta0 = aNewU - mySpanStart[0];
Standard_Real aDelta1 = aNewV - mySpanStart[1];
return (aDelta0 >= -mySpanLength[0] && (aDelta0 < mySpanLength[0] || mySpanIndex[0] == mySpanIndexMax[0]) &&
aDelta1 >= -mySpanLength[1] && (aDelta1 < mySpanLength[1] || mySpanIndex[1] == mySpanIndexMax[1]));
return ((aDelta0 >= -mySpanLength[0] || mySpanIndex[0] == mySpanIndexMin[0]) &&
(aDelta0 < mySpanLength[0] || mySpanIndex[0] == mySpanIndexMax[0]) &&
(aDelta1 >= -mySpanLength[1] || mySpanIndex[1] == mySpanIndexMin[1]) &&
(aDelta1 < mySpanLength[1] || mySpanIndex[1] == mySpanIndexMax[1]));
}
void BSplSLib_Cache::PeriodicNormalization(const Standard_Integer& theDegree,
@ -164,7 +166,9 @@ void BSplSLib_Cache::BuildCache(const Standard_Real& theParameterU,
mySpanLength[1] = (theFlatKnotsV.Value(mySpanIndex[1] + 1) - theFlatKnotsV.Value(mySpanIndex[1])) * 0.5;
mySpanStart[1] = theFlatKnotsV.Value(mySpanIndex[1]) + mySpanLength[1];
mySpanIndexMin[0] = thePeriodicU ? 0 : theDegreeU + 1;
mySpanIndexMax[0] = theFlatKnotsU.Length() - 1 - theDegreeU;
mySpanIndexMin[1] = thePeriodicV ? 0 : theDegreeV + 1;
mySpanIndexMax[1] = theFlatKnotsV.Length() - 1 - theDegreeV;
// Calculate new cache data

View File

@ -144,6 +144,7 @@ private:
Standard_Real mySpanStart[2]; ///< parameters (u, v) for the frst point of the span
Standard_Real mySpanLength[2]; ///< lengths of the span along corresponding parameter
Standard_Integer mySpanIndex[2]; ///< indexes of the span on Bezier/B-spline surface
Standard_Integer mySpanIndexMin[2]; ///< minimal indexes of span
Standard_Integer mySpanIndexMax[2]; ///< maximal indexes of span
Standard_Integer myDegree[2]; ///< degrees of Bezier/B-spline for each parameter
Handle(TColStd_HArray1OfReal) myFlatKnots[2]; ///< arrays of knots of Bezier/B-spline

View File

@ -237,6 +237,8 @@ void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
myTypeCurve = GeomAbs_OtherCurve;
}
}
else // rebuild cache of Bezier and B-spline curve even if the loaded curve is same
RebuildCache(myFirst);
}
// --

View File

@ -194,7 +194,9 @@ void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
myTypeCurve = GeomAbs_OtherCurve;
}
}
}
else // rebuild cache of Bezier and B-spline curve even if the loaded curve is same
RebuildCache(myFirst);
}
// --
// -- Global methods - Apply to the whole curve.

View File

@ -217,6 +217,8 @@ void GeomAdaptor_Surface::load(const Handle(Geom_Surface)& S,
else
mySurfaceType = GeomAbs_OtherSurface;
}
else // rebuild cache of Bezier and B-spline surface even if the loaded surface is same
RebuildCache(myUFirst, myVFirst);
}
// --

View File

@ -5027,6 +5027,32 @@ static Standard_Integer OCC26945_close (Draw_Interpretor& theDI, Standard_Intege
return 0;
}
//=======================================================================
//function : OCC27048
//purpose : Calculate value of B-spline surface N times
//=======================================================================
static Standard_Integer OCC27048(Draw_Interpretor& theDI, Standard_Integer theArgc, const char** theArgv)
{
if (theArgc != 5)
{
std::cout << "Incorrect number of arguments. See usage:" << std::endl;
theDI.PrintHelp(theArgv[0]);
return 1;
}
Handle(Geom_Surface) aSurf = DrawTrSurf::GetSurface(theArgv[1]);
GeomAdaptor_Surface anAdaptor(aSurf);
Standard_Real aU = Draw::Atof(theArgv[2]);
Standard_Real aV = Draw::Atof(theArgv[3]);
Standard_Integer aN = Draw::Atoi(theArgv[4]);
for (; aN > 0; --aN)
anAdaptor.Value(aU, aV);
return 0;
}
void QABugs::Commands_19(Draw_Interpretor& theCommands) {
const char *group = "QABugs";
@ -5132,6 +5158,10 @@ void QABugs::Commands_19(Draw_Interpretor& theCommands) {
"OCC26945 localCtxToClose"
"\n\t\t: Closes local context with the ID localCtxToClose",
__FILE__, OCC26945_close, group);
theCommands.Add ("OCC27048",
"OCC27048 surf U V N\nCalculate value of surface N times in the point (U, V)",
__FILE__, OCC27048, group);
return;
}

View File

@ -0,0 +1,34 @@
puts "============"
puts "OCC27048"
puts "============"
puts ""
############################################################################
# Recalculation of BSpline cache causes a performance problems
############################################################################
pload QAcommands
bsplinesurf surf \
3 4 0 4 1 1 2 1 3 4 \
3 4 0 4 1 1 2 1 3 4 \
0 0 0 1 2 0 0 1 3 0 15 1 5 0 15 1 7 0 0 1 10 0 0 1 \
0 2 0 1 1 3 0 1 4 2 15 1 6 3 15 1 8 2 0 1 10 3 0 1 \
0 4 0 1 3 4 0 1 4 3 15 1 5 3 15 1 7 4 0 1 10 5 0 1 \
0 6 0 1 3 6 0 1 4 6 15 1 5 6 15 1 8 5 0 1 10 7 0 1 \
0 8 0 1 2 8 0 1 4 8 15 1 6 8 15 1 7 7 0 1 10 8 0 1 \
0 10 0 1 2 10 0 1 4 10 15 1 6 10 15 1 7 10 0 1 10 10 0 1
dchrono t reset
dchrono t start
OCC27048 surf -0.1 -0.1 1000000
dchrono t stop
set elapsed [dchrono t show]
regexp {CPU user time: ([-0-9.+eE]+) seconds} $elapsed full cpu_time
set max_time 1
if { $cpu_time > ${max_time} } {
puts "Error: calculating B-spline value takes too long time (greater than ${max_time} sec)"
} else {
puts "OK: performance calculating B-spline is suitable"
}

View File

@ -0,0 +1,28 @@
puts "============"
puts "OCC27048"
puts "============"
puts ""
############################################################################
# Recalculation of BSpline cache causes a performance problems
############################################################################
pload XSDRAW
dchrono t reset
dchrono t start
testreadstep [locate_data_file bug27048.stp] result
dchrono t stop
set elapsed [dchrono t show]
regexp {CPU user time: ([-0-9.+eE]+) seconds} $elapsed full cpu_time
set max_time 40
if { $cpu_time > ${max_time} } {
puts "Error: reading document Doc is too long (greater than ${max_time} sec)"
} else {
puts "OK: performance reading document Doc is suitable"
}
smallview
fit
set only_screen_axo 1