From fa89e0828b99764234d9f69d0079c81f346b34d3 Mon Sep 17 00:00:00 2001 From: aml Date: Fri, 12 Dec 2014 13:40:06 +0300 Subject: [PATCH] 0025596: GCPnts_TangentialDeflection creates wrong point distribution for visualization Added check to small step after adding new point to prevent possible jump over local splash. If check failed then old step restored. --- src/GCPnts/GCPnts_TangentialDeflection.cxx | 22 +++++++-- src/GCPnts/GCPnts_TangentialDeflection.gxx | 53 ++++++++++++++++------ 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/GCPnts/GCPnts_TangentialDeflection.cxx b/src/GCPnts/GCPnts_TangentialDeflection.cxx index 7b06efe7ce..da67dc9a9a 100644 --- a/src/GCPnts/GCPnts_TangentialDeflection.cxx +++ b/src/GCPnts/GCPnts_TangentialDeflection.cxx @@ -21,6 +21,7 @@ #include #include #include +#include inline static void D0 (const Adaptor3d_Curve& C, const Standard_Real U, gp_Pnt& P) { @@ -58,6 +59,23 @@ static void D2 (const Adaptor2d_Curve2d& C, const Standard_Real U, VV2.SetCoord (X, Y, 0.0); } +// Return number of interval of continuity on which theParam is located. +// Last parameter is used to increase search speed. +static Standard_Integer getIntervalIdx(const Standard_Real theParam, + TColStd_Array1OfReal& theIntervs, + const Standard_Integer thePreviousIdx) +{ + Standard_Integer anIdx; + for(anIdx = thePreviousIdx; anIdx < theIntervs.Upper(); anIdx++) + { + if (theParam >= theIntervs(anIdx) && + theParam <= theIntervs(anIdx + 1)) // Inside of anIdx interval. + { + break; + } + } + return anIdx; +} //======================================================================= //function : CPnts_TangentialDeflection @@ -157,7 +175,3 @@ Standard_Real GCPnts_TangentialDeflection::ArcAngularStep( #undef Handle_TheBezierCurve #undef Handle_TheBSplineCurve #undef TheCurve - - - - diff --git a/src/GCPnts/GCPnts_TangentialDeflection.gxx b/src/GCPnts/GCPnts_TangentialDeflection.gxx index bd1353193a..124ba3c37b 100644 --- a/src/GCPnts/GCPnts_TangentialDeflection.gxx +++ b/src/GCPnts/GCPnts_TangentialDeflection.gxx @@ -21,7 +21,6 @@ #include #include #include -#include #define Us3 0.3333333333333333333333333333 @@ -239,13 +238,11 @@ void GCPnts_TangentialDeflection::PerformCircular (const TheCurve& C) } - //======================================================================= //function : PerformCurve //purpose : On respecte ll'angle et la fleche, on peut imposer un nombre // minimum de points sur un element lineaire //======================================================================= - void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) { @@ -269,8 +266,12 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) parameters.Append (U1); points .Append (CurrentPoint); - if (NotDone) - { + // Used to detect "isLine" current bspline and in Du computation in general handling. + Standard_Integer NbInterv = const_cast(&C)->NbIntervals(GeomAbs_CN); + TColStd_Array1OfReal Intervs(1, NbInterv+1); + const_cast(&C)->Intervals(Intervs, GeomAbs_CN); + + if (NotDone) { //C'est soit une droite, soit une singularite : V1 = (LastPoint.XYZ() - CurrentPoint.XYZ()); L1 = V1.Modulus (); @@ -280,9 +281,6 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) Standard_Boolean IsLine = Standard_True; Standard_Integer NbPoints = (minNbPnts > 3) ? minNbPnts : 3; //// - Standard_Integer NbInterv = const_cast(&C)->NbIntervals(GeomAbs_CN); - TColStd_Array1OfReal Intervs(1, NbInterv+1); - const_cast(&C)->Intervals(Intervs, GeomAbs_CN); Standard_Real param = 0.; for (i = 1; i <= NbInterv && IsLine; ++i) { @@ -368,12 +366,13 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) Standard_Boolean MorePoints = Standard_True; Standard_Real U2 = firstu; Standard_Real AngleMax = angularDeflection * 0.5; //car on prend le point milieu - + Standard_Integer aIdx[2] = {Intervs.Lower(), Intervs.Lower()}; // Indexes of intervals of U1 and U2, used to handle non-uniform case. + Standard_Boolean isNeedToCheck = Standard_False; gp_Pnt aPrevPoint = points.Last(); while (MorePoints) { - - U2 += Du; + aIdx[0] = getIntervalIdx(U1, Intervs, aIdx[0]); + U2 += Du; if (U2 >= lastu) { //Bout de courbe U2 = lastu; @@ -383,13 +382,28 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) } else D0 (C, U2, CurrentPoint); //Point suivant - Standard_Real Coef, ACoef = 0., FCoef = 0.; + Standard_Real Coef = 0.0, ACoef = 0., FCoef = 0.; Standard_Boolean Correction, TooLarge, TooSmall; TooLarge = Standard_False; - TooSmall = Standard_False; Correction = Standard_True; + TooSmall = Standard_False; while (Correction) { //Ajustement Du + if (isNeedToCheck) + { + aIdx[1] = getIntervalIdx(U2, Intervs, aIdx[0]); + if (aIdx[1] > aIdx[0]) // Jump to another polynom. + { + if (Du > (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3) // Set Du to the smallest value and check deflection on it. + { + Du = (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3; + U2 = U1 + Du; + if (U2 > lastu) + U2 = lastu; + D0 (C, U2, CurrentPoint); + } + } + } MiddleU = (U1+U2)*0.5; //Verif / au point milieu D0 (C, MiddleU, MiddlePoint); @@ -414,6 +428,17 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) //On retient le plus penalisant Coef = Max(ACoef, FCoef); + if (isNeedToCheck && Coef < 0.55) + { + isNeedToCheck = Standard_False; + Du = Dusave; + U2 = U1 + Du; + if (U2 > lastu) + U2 = lastu; + D0 (C, U2, CurrentPoint); + continue; + } + if (Coef <= 1.0) { if (Abs (lastu-U2) < uTol) { parameters.Append (lastu); @@ -427,6 +452,7 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) points .Append (CurrentPoint); aPrevPoint = CurrentPoint; Correction = Standard_False; + isNeedToCheck = Standard_True; } else if (TooSmall) { Correction = Standard_False; @@ -504,7 +530,6 @@ void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C) // points.Remove (i+1); // i--; // } - if (i >= 2) { MiddleU = parameters (i-1); MiddleU = (lastu + MiddleU)*0.5;