// Created on: 1996-11-08 // Created by: Jean Claude VAUTHIER // Copyright (c) 1996-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #include namespace { static const Standard_Real Us3 = 0.3333333333333333333333333333; inline static void D0 (const Adaptor3d_Curve& C, const Standard_Real U, gp_Pnt& P) { C.D0 (U, P); } inline static void D2 (const Adaptor3d_Curve& C, const Standard_Real U, gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) { C.D2 (U, P, V1, V2); } static void D0 (const Adaptor2d_Curve2d& C, const Standard_Real U, gp_Pnt& PP) { Standard_Real X, Y; gp_Pnt2d P; C.D0 (U, P); P.Coord (X, Y); PP.SetCoord (X, Y, 0.0); } static void D2 (const Adaptor2d_Curve2d& C, const Standard_Real U, gp_Pnt& PP, gp_Vec& VV1, gp_Vec& VV2) { Standard_Real X, Y; gp_Pnt2d P; gp_Vec2d V1,V2; C.D2 (U, P, V1, V2); P.Coord (X, Y); PP.SetCoord (X, Y, 0.0); V1.Coord (X, Y); VV1.SetCoord (X, Y, 0.0); V2.Coord (X, Y); VV2.SetCoord (X, Y, 0.0); } static Standard_Real EstimAngl (const gp_Pnt& P1, const gp_Pnt& Pm, const gp_Pnt& P2) { gp_Vec V1(P1, Pm), V2(Pm, P2); Standard_Real L = V1.Magnitude() * V2.Magnitude(); if (L > gp::Resolution()) { return V1.CrossMagnitude(V2)/L; } else { return 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 : GCPnts_TangentialDeflection //purpose : //======================================================================= GCPnts_TangentialDeflection::GCPnts_TangentialDeflection() : myAngularDeflection (0.0), myCurvatureDeflection (0.0), myUTol (0.0), myMinNbPnts (0), myMinLen(0.0), myLastU (0.0), myFirstu (0.0) { } //======================================================================= //function : GCPnts_TangentialDeflection //purpose : //======================================================================= GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (const Adaptor3d_Curve& theC, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) : myAngularDeflection (0.0), myCurvatureDeflection (0.0), myUTol (0.0), myMinNbPnts (0), myMinLen(0.0), myLastU (0.0), myFirstu (0.0) { Initialize (theC, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : GCPnts_TangentialDeflection //purpose : //======================================================================= GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (const Adaptor3d_Curve& theC, const Standard_Real theFirstParameter, const Standard_Real theLastParameter, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) : myAngularDeflection (0.0), myCurvatureDeflection (0.0), myUTol (0.0), myMinNbPnts (0), myMinLen(0.0), myLastU (0.0), myFirstu (0.0) { Initialize (theC, theFirstParameter, theLastParameter, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : GCPnts_TangentialDeflection //purpose : //======================================================================= GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (const Adaptor2d_Curve2d& theC, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) : myAngularDeflection (0.0), myCurvatureDeflection (0.0), myUTol (0.0), myMinNbPnts (0), myMinLen(0.0), myLastU (0.0), myFirstu (0.0) { Initialize (theC, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : GCPnts_TangentialDeflection //purpose : //======================================================================= GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (const Adaptor2d_Curve2d& theC, const Standard_Real theFirstParameter, const Standard_Real theLastParameter, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) : myAngularDeflection (0.0), myCurvatureDeflection (0.0), myUTol (0.0), myMinNbPnts (0), myMinLen(0.0), myLastU (0.0), myFirstu (0.0) { Initialize (theC, theFirstParameter, theLastParameter, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : Initialize //purpose : //======================================================================= void GCPnts_TangentialDeflection::Initialize (const Adaptor3d_Curve& theC, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) { Initialize (theC, theC.FirstParameter(), theC.LastParameter(), theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : Initialize //purpose : //======================================================================= void GCPnts_TangentialDeflection::Initialize (const Adaptor2d_Curve2d& theC, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) { Initialize (theC, theC.FirstParameter(), theC.LastParameter(), theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : Initialize //purpose : //======================================================================= void GCPnts_TangentialDeflection::Initialize (const Adaptor3d_Curve& theC, const Standard_Real theFirstParameter, const Standard_Real theLastParameter, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) { initialize (theC, theFirstParameter, theLastParameter, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : Initialize //purpose : //======================================================================= void GCPnts_TangentialDeflection::Initialize (const Adaptor2d_Curve2d& theC, const Standard_Real theFirstParameter, const Standard_Real theLastParameter, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) { initialize (theC, theFirstParameter, theLastParameter, theAngularDeflection, theCurvatureDeflection, theMinimumOfPoints, theUTol, theMinLen); } //======================================================================= //function : EvaluateDu //purpose : //======================================================================= template void GCPnts_TangentialDeflection::EvaluateDu (const TheCurve& theC, const Standard_Real theU, gp_Pnt& theP, Standard_Real& theDu, Standard_Boolean& theNotDone) const { gp_Vec T, N; D2 (theC, theU, theP, T, N); Standard_Real Lt = T.Magnitude(); constexpr Standard_Real LTol = Precision::Confusion(); if (Lt > LTol && N.Magnitude () > LTol) { Standard_Real Lc = N.CrossMagnitude (T); Standard_Real Ln = Lc/Lt; if (Ln > LTol) { theDu = sqrt (8.0 * Max (myCurvatureDeflection, myMinLen) / Ln); theNotDone = Standard_False; } } } //======================================================================= //function : PerformLinear //purpose : //======================================================================= template void GCPnts_TangentialDeflection::PerformLinear (const TheCurve& theC) { gp_Pnt P; D0 (theC, myFirstu, P); myParameters.Append (myFirstu); myPoints .Append (P); if (myMinNbPnts > 2) { Standard_Real Du = (myLastU - myFirstu) / myMinNbPnts; Standard_Real U = myFirstu + Du; for (Standard_Integer i = 2; i < myMinNbPnts; i++) { D0 (theC, U, P); myParameters.Append (U); myPoints .Append (P); U += Du; } } D0 (theC, myLastU, P); myParameters.Append (myLastU); myPoints .Append (P); } //======================================================================= //function : PerformCircular //purpose : //======================================================================= template void GCPnts_TangentialDeflection::PerformCircular (const TheCurve& theC) { // akm 8/01/02 : check the radius before divide by it Standard_Real dfR = theC.Circle().Radius(); Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep (dfR, myCurvatureDeflection, myAngularDeflection, myMinLen); const Standard_Real aDiff = myLastU - myFirstu; // Round up number of points to satisfy curvatureDeflection more precisely Standard_Integer NbPoints = (Standard_Integer)Min(Ceiling(aDiff / Du), 1.0e+6); NbPoints = Max(NbPoints, myMinNbPnts - 1); Du = aDiff / NbPoints; gp_Pnt P; Standard_Real U = myFirstu; for (Standard_Integer i = 1; i <= NbPoints; i++) { D0 (theC, U, P); myParameters.Append (U); myPoints .Append (P); U += Du; } D0 (theC, myLastU, P); myParameters.Append (myLastU); myPoints .Append (P); } //======================================================================= //function : initialize //purpose : //======================================================================= template void GCPnts_TangentialDeflection::initialize (const TheCurve& theC, const Standard_Real theFirstParameter, const Standard_Real theLastParameter, const Standard_Real theAngularDeflection, const Standard_Real theCurvatureDeflection, const Standard_Integer theMinimumOfPoints, const Standard_Real theUTol, const Standard_Real theMinLen) { Standard_ConstructionError_Raise_if (theCurvatureDeflection < Precision::Confusion() || theAngularDeflection < Precision::Angular(), "GCPnts_TangentialDeflection::Initialize - Zero Deflection") myParameters.Clear(); myPoints .Clear(); if (theFirstParameter < theLastParameter) { myFirstu = theFirstParameter; myLastU = theLastParameter; } else { myLastU = theFirstParameter; myFirstu = theLastParameter; } myUTol = theUTol; myAngularDeflection = theAngularDeflection; myCurvatureDeflection = theCurvatureDeflection; myMinNbPnts = Max (theMinimumOfPoints, 2); myMinLen = Max (theMinLen, Precision::Confusion()); switch (theC.GetType()) { case GeomAbs_Line: { PerformLinear (theC); break; } case GeomAbs_Circle: { PerformCircular (theC); break; } case GeomAbs_BSplineCurve: { Handle(typename GCPnts_TCurveTypes::BSplineCurve) aBS = theC.BSpline(); if (aBS->NbPoles() == 2) PerformLinear (theC); else PerformCurve (theC); break; } case GeomAbs_BezierCurve: { Handle(typename GCPnts_TCurveTypes::BezierCurve) aBZ = theC.Bezier(); if (aBZ->NbPoles() == 2) PerformLinear (theC); else PerformCurve (theC); break; } default: { PerformCurve (theC); break; } } } //======================================================================= //function : AddPoint //purpose : //======================================================================= Standard_Integer GCPnts_TangentialDeflection::AddPoint (const gp_Pnt& thePnt, const Standard_Real theParam, const Standard_Boolean theIsReplace) { constexpr Standard_Real tol = Precision::PConfusion(); Standard_Integer index = -1; const Standard_Integer nb = myParameters.Length(); for ( Standard_Integer i = 1; index == -1 && i <= nb; i++ ) { Standard_Real dist = myParameters.Value( i ) - theParam; if ( fabs( dist ) <= tol ) { index = i; if ( theIsReplace ) { myPoints .ChangeValue (i) = thePnt; myParameters.ChangeValue (i) = theParam; } } else if ( dist > tol ) { myPoints .InsertBefore (i, thePnt); myParameters.InsertBefore (i, theParam); index = i; } } if (index == -1) { myPoints .Append (thePnt); myParameters.Append (theParam); index = myParameters.Length(); } return index; } //======================================================================= //function : ArcAngularStep //purpose : //======================================================================= Standard_Real GCPnts_TangentialDeflection::ArcAngularStep( const Standard_Real theRadius, const Standard_Real theLinearDeflection, const Standard_Real theAngularDeflection, const Standard_Real theMinLength) { Standard_ConstructionError_Raise_if(theRadius < 0.0, "Negative radius"); constexpr Standard_Real aPrecision = Precision::Confusion(); Standard_Real Du = 0.0, aMinSizeAng = 0.0; if (theRadius > aPrecision) { Du = Max(1.0 - (theLinearDeflection / theRadius), 0.0); // It is not suitable to consider min size greater than 1/4 arc len. if (theMinLength > aPrecision) aMinSizeAng = Min(theMinLength / theRadius, M_PI_2); } Du = 2.0 * ACos(Du); Du = Max(Min(Du, theAngularDeflection), aMinSizeAng); return Du; } //======================================================================= //function : PerformCurve //purpose : //======================================================================= template void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& theC) { Standard_Integer i, j; gp_XYZ V1, V2; gp_Pnt MiddlePoint, CurrentPoint, LastPoint; Standard_Real Du, Dusave, MiddleU, L1, L2; Standard_Real U1 = myFirstu; constexpr Standard_Real LTol = Precision::Confusion(); // protection longueur nulle Standard_Real ATol = 1.e-2 * myAngularDeflection; if (ATol > 1.e-2) { ATol = 1.e-2; } else if (ATol < 1.e-7) { ATol = 1.e-7; } D0 (theC, myLastU, LastPoint); // Initialization du calcul Standard_Boolean NotDone = Standard_True; Dusave = (myLastU - myFirstu) * Us3; Du = Dusave; EvaluateDu (theC, U1, CurrentPoint, Du, NotDone); myParameters.Append (U1); myPoints .Append (CurrentPoint); // Used to detect "isLine" current bspline and in Du computation in general handling. const Standard_Integer NbInterv = theC.NbIntervals (GeomAbs_CN); TColStd_Array1OfReal Intervs (1, NbInterv + 1); theC.Intervals (Intervs, GeomAbs_CN); if (NotDone || Du > 5. * Dusave) { //C'est soit une droite, soit une singularite : V1 = (LastPoint.XYZ() - CurrentPoint.XYZ()); L1 = V1.Modulus (); if (L1 > LTol) { // Si c'est une droite on verifie en calculant minNbPoints : Standard_Boolean IsLine = Standard_True; Standard_Integer NbPoints = (myMinNbPnts > 3) ? myMinNbPnts : 3; switch (theC.GetType()) { case GeomAbs_BSplineCurve: { Handle(typename GCPnts_TCurveTypes::BSplineCurve) BS = theC.BSpline(); NbPoints = Max(BS->Degree() + 1, NbPoints); break; } case GeomAbs_BezierCurve: { Handle(typename GCPnts_TCurveTypes::BezierCurve) BZ = theC.Bezier(); NbPoints = Max(BZ->Degree() + 1, NbPoints); break; } default: { break; } } //// Standard_Real param = 0.; for (i = 1; i <= NbInterv && IsLine; ++i) { // Avoid usage intervals out of [myFirstu, myLastU]. if ((Intervs(i + 1) < myFirstu) || (Intervs(i) > myLastU)) { continue; } // Fix border points in applicable intervals, to avoid be out of target interval. if ((Intervs(i) < myFirstu) && (Intervs(i+1) > myFirstu)) { Intervs(i) = myFirstu; } if ((Intervs(i) < myLastU) && (Intervs(i+1) > myLastU)) { Intervs(i + 1) = myLastU; } const Standard_Real delta = (Intervs(i+1) - Intervs(i))/NbPoints; for (j = 1; j <= NbPoints && IsLine; ++j) { param = Intervs(i) + j*delta; D0 (theC, param, MiddlePoint); V2 = (MiddlePoint.XYZ() - CurrentPoint.XYZ()); L2 = V2.Modulus (); if (L2 > LTol) { const Standard_Real aAngle = V2.CrossMagnitude(V1)/(L1*L2); IsLine = (aAngle < ATol); } } } if (IsLine) { myParameters.Clear(); myPoints .Clear(); PerformLinear (theC); return; } else { // c'etait une singularite on continue: //Du = Dusave; EvaluateDu (theC, param, MiddlePoint, Du, NotDone); } } else { Du = (myLastU - myFirstu) / 2.1; MiddleU = myFirstu + Du; D0 (theC, MiddleU, MiddlePoint); V1 = (MiddlePoint.XYZ() - CurrentPoint.XYZ()); L1 = V1.Modulus (); if (L1 < LTol) { // L1 < LTol C'est une courbe de longueur nulle, calcul termine : // on renvoi un segment de 2 points (protection) myParameters.Append (myLastU); myPoints .Append (LastPoint); return; } } } if (Du > Dusave) Du = Dusave; else Dusave = Du; if (Du < myUTol) { Du = myLastU - myFirstu; if (Du < myUTol) { myParameters.Append (myLastU); myPoints .Append (LastPoint); return; } } // Traitement normal pour une courbe Standard_Boolean MorePoints = Standard_True; Standard_Real U2 = myFirstu; Standard_Real AngleMax = myAngularDeflection * 0.5; // car on prend le point milieu // Indexes of intervals of U1 and U2, used to handle non-uniform case. Standard_Integer aIdx[2] = {Intervs.Lower(), Intervs.Lower()}; Standard_Boolean isNeedToCheck = Standard_False; gp_Pnt aPrevPoint = myPoints.Last(); while (MorePoints) { aIdx[0] = getIntervalIdx(U1, Intervs, aIdx[0]); U2 += Du; if (U2 >= myLastU) // Bout de courbe { U2 = myLastU; CurrentPoint = LastPoint; Du = U2-U1; Dusave = Du; } else { D0 (theC, U2, CurrentPoint); // Point suivant } Standard_Real Coef = 0.0, ACoef = 0., FCoef = 0.; Standard_Boolean Correction, TooLarge, TooSmall; TooLarge = 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. { // Set Du to the smallest value and check deflection on it. if (Du > (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3) { Du = (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3; U2 = U1 + Du; if (U2 > myLastU) { U2 = myLastU; } D0 (theC, U2, CurrentPoint); } } } MiddleU = (U1+U2)*0.5; // Verif / au point milieu D0 (theC, MiddleU, MiddlePoint); V1 = (CurrentPoint.XYZ() - aPrevPoint.XYZ()); // Critere de fleche V2 = (MiddlePoint.XYZ() - aPrevPoint.XYZ()); L1 = V1.Modulus (); FCoef = (L1 > myMinLen) ? V1.CrossMagnitude(V2) / (L1 * myCurvatureDeflection) : 0.0; V1 = (CurrentPoint.XYZ() - MiddlePoint.XYZ()); // Critere d'angle L1 = V1.Modulus (); L2 = V2.Modulus (); if (L1 > myMinLen && L2 > myMinLen) { Standard_Real angg = V1.CrossMagnitude(V2) / (L1 * L2); ACoef = angg / AngleMax; } else { ACoef = 0.0; } // On retient le plus penalisant Coef = Max (ACoef, FCoef); if (isNeedToCheck && Coef < 0.55) { isNeedToCheck = Standard_False; Du = Dusave; U2 = U1 + Du; if (U2 > myLastU) { U2 = myLastU; } D0 (theC, U2, CurrentPoint); continue; } if (Coef <= 1.0) { if (Abs (myLastU - U2) < myUTol) { myParameters.Append (myLastU); myPoints .Append (LastPoint); MorePoints = Standard_False; Correction = Standard_False; } else { if (Coef >= 0.55 || TooLarge) { myParameters.Append (U2); myPoints .Append (CurrentPoint); aPrevPoint = CurrentPoint; Correction = Standard_False; isNeedToCheck = Standard_True; } else if (TooSmall) { Correction = Standard_False; aPrevPoint = CurrentPoint; } else { TooSmall = Standard_True; //Standard_Real UUU2 = U2; Du += Min((U2-U1)*(1.-Coef), Du*Us3); U2 = U1 + Du; if (U2 > myLastU) { U2 = myLastU; } D0 (theC, U2, CurrentPoint); } } } else { if (Coef >= 1.5) { if (!aPrevPoint.IsEqual (myPoints.Last(), Precision::Confusion())) { myParameters.Append (U1); myPoints .Append (aPrevPoint); } U2 = MiddleU; Du = U2-U1; CurrentPoint = MiddlePoint; } else { Du*=0.9; U2 = U1 + Du; D0 (theC, U2, CurrentPoint); TooLarge = Standard_True; } } } Du = U2-U1; if (MorePoints) { if (U1 > myFirstu) { if (FCoef > ACoef) { // La fleche est critere de decoupage EvaluateDu (theC, U2, CurrentPoint, Du, NotDone); if (NotDone) { Du += (Du-Dusave)*(Du/Dusave); if (Du > 1.5 * Dusave) Du = 1.5 * Dusave; if (Du < 0.75* Dusave) Du = 0.75 * Dusave; } } else { //L'angle est le critere de decoupage Du += (Du-Dusave)*(Du/Dusave); if (Du > 1.5 * Dusave) Du = 1.5 * Dusave; if (Du < 0.75* Dusave) Du = 0.75 * Dusave; } } if (Du < myUTol) { Du = myLastU - U2; if (Du < myUTol) { myParameters.Append (myLastU); myPoints .Append (LastPoint); MorePoints = Standard_False; } else if (Du*Us3 > myUTol) { Du*=Us3; } } U1 = U2; Dusave = Du; } } // Recalage avant dernier point : i = myPoints.Length() - 1; // Real d = myPoints (i).Distance (myPoints (i+1)); // if (Abs(myParameters (i) - myParameters (i+1))<= 0.000001 || d < Precision::Confusion()) { // cout<<"deux points confondus"<= 2) { MiddleU = myParameters (i-1); MiddleU = (myLastU + MiddleU)*0.5; D0 (theC, MiddleU, MiddlePoint); myParameters.SetValue (i, MiddleU); myPoints .SetValue (i, MiddlePoint); } //-- On rajoute des points aux milieux des segments si le nombre //-- mini de points n'est pas atteint //-- Standard_Integer Nbp = myPoints.Length(); //std::cout << "GCPnts_TangentialDeflection: Number of Points (" << Nbp << " " << myMinNbPnts << " )" << std::endl; while (Nbp < myMinNbPnts) { for (i = 2; i <= Nbp; i += 2) { MiddleU = (myParameters.Value(i-1) + myParameters.Value(i)) * 0.5; D0 (theC, MiddleU, MiddlePoint); myParameters.InsertBefore (i, MiddleU); myPoints .InsertBefore (i, MiddlePoint); Nbp++; } } // Additional check for intervals const Standard_Real MinLen2 = myMinLen * myMinLen; const Standard_Integer MaxNbp = 10 * Nbp; for (i = 1; i < Nbp; ++i) { U1 = myParameters (i); U2 = myParameters (i + 1); if (U2 - U1 <= myUTol) { continue; } // Check maximal deflection on interval; Standard_Real dmax = 0.; Standard_Real umax = 0.; Standard_Real amax = 0.; EstimDefl (theC, U1, U2, dmax, umax); const gp_Pnt& P1 = myPoints (i); const gp_Pnt& P2 = myPoints (i + 1); D0 (theC, umax, MiddlePoint); amax = EstimAngl(P1, MiddlePoint, P2); if (dmax > myCurvatureDeflection || amax > AngleMax) { if (umax - U1 > myUTol && U2 - umax > myUTol) { if (P1.SquareDistance(MiddlePoint) > MinLen2 && P2.SquareDistance(MiddlePoint) > MinLen2) { myParameters.InsertAfter (i, umax); myPoints .InsertAfter (i, MiddlePoint); ++Nbp; --i; //To compensate ++i in loop header: i must point to first part of split interval if (Nbp > MaxNbp) { break; } } } } } } //======================================================================= //function : EstimDefl //purpose : //======================================================================= template void GCPnts_TangentialDeflection::EstimDefl (const TheCurve& theC, const Standard_Real theU1, const Standard_Real theU2, Standard_Real& theMaxDefl, Standard_Real& theUMax) { const Standard_Real Du = (myLastU - myFirstu); // typename GCPnts_TCurveTypes::DistFunction aFunc (theC, theU1, theU2); // const Standard_Integer aNbIter = 100; const Standard_Real aRelTol = Max (1.e-3, 2. * myUTol / (Abs(theU1) + Abs(theU2))); // math_BrentMinimum anOptLoc (aRelTol, aNbIter, myUTol); anOptLoc.Perform (aFunc, theU1, (theU1 + theU2) / 2., theU2); if (anOptLoc.IsDone()) { theMaxDefl = Sqrt(-anOptLoc.Minimum()); theUMax = anOptLoc.Location(); return; } // math_Vector aLowBorder (1, 1), aUppBorder (1, 1), aSteps (1, 1); aSteps (1) = Max (0.1 * Du, 100. * myUTol); const Standard_Integer aNbParticles = Max(8, RealToInt(32 * (theU2 - theU1) / Du)); aLowBorder (1) = theU1; aUppBorder (1) = theU2; // // Standard_Real aValue = 0.0; math_Vector aT (1, 1); typename GCPnts_TCurveTypes::DistFunctionMV aFuncMV(aFunc); math_PSO aFinder (&aFuncMV, aLowBorder, aUppBorder, aSteps, aNbParticles); aFinder.Perform (aSteps, aValue, aT); // anOptLoc.Perform (aFunc, Max (aT(1) - aSteps(1), theU1), aT (1), Min (aT(1) + aSteps(1), theU2)); if (anOptLoc.IsDone()) { theMaxDefl = Sqrt(-anOptLoc.Minimum()); theUMax = anOptLoc.Location(); return; } theMaxDefl = Sqrt(-aValue); theUMax = aT (1); }