1 // Created on: 1996-11-08
2 // Created by: Jean Claude VAUTHIER
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <GCPnts_DeflectionType.hxx>
18 #include <Standard_ConstructionError.hxx>
19 #include <Precision.hxx>
25 #define Us3 0.3333333333333333333333333333
27 void GCPnts_TangentialDeflection::EvaluateDu (
29 const Standard_Real U,
32 Standard_Boolean& NotDone) const {
36 Standard_Real Lt = T.Magnitude ();
37 Standard_Real LTol = Precision::Confusion ();
38 if (Lt > LTol && N.Magnitude () > LTol) {
39 Standard_Real Lc = N.CrossMagnitude (T);
40 Standard_Real Ln = Lc/Lt;
42 Du = sqrt (8.0 * Max(curvatureDeflection, myMinLen) / Ln);
43 NotDone = Standard_False;
49 //=======================================================================
50 //function : GCPnts_TangentialDeflection
52 //=======================================================================
54 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
56 const Standard_Real AngularDeflection,
57 const Standard_Real CurvatureDeflection,
58 const Standard_Integer MinimumOfPoints,
59 const Standard_Real UTol,
60 const Standard_Real theMinLen)
63 Initialize (C,AngularDeflection,CurvatureDeflection,MinimumOfPoints,UTol,theMinLen);
67 //=======================================================================
68 //function : GCPnts_TangentialDeflection
70 //=======================================================================
72 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
74 const Standard_Real FirstParameter,
75 const Standard_Real LastParameter,
76 const Standard_Real AngularDeflection,
77 const Standard_Real CurvatureDeflection,
78 const Standard_Integer MinimumOfPoints,
79 const Standard_Real UTol,
80 const Standard_Real theMinLen)
94 //=======================================================================
95 //function : Initialize
97 //=======================================================================
99 void GCPnts_TangentialDeflection::Initialize (
101 const Standard_Real AngularDeflection,
102 const Standard_Real CurvatureDeflection,
103 const Standard_Integer MinimumOfPoints,
104 const Standard_Real UTol,
105 const Standard_Real theMinLen)
118 //=======================================================================
119 //function : Initialize
121 //=======================================================================
123 void GCPnts_TangentialDeflection::Initialize (
125 const Standard_Real FirstParameter,
126 const Standard_Real LastParameter,
127 const Standard_Real AngularDeflection,
128 const Standard_Real CurvatureDeflection,
129 const Standard_Integer MinimumOfPoints,
130 const Standard_Real UTol,
131 const Standard_Real theMinLen)
135 Standard_ConstructionError_Raise_if (CurvatureDeflection <= Precision::Confusion () || AngularDeflection <= Precision::Angular (), "GCPnts_TangentialDeflection::Initialize - Zero Deflection")
139 if (FirstParameter < LastParameter) {
140 firstu = FirstParameter;
141 lastu = LastParameter;
144 lastu = FirstParameter;
145 firstu = LastParameter;
148 angularDeflection = AngularDeflection;
149 curvatureDeflection = CurvatureDeflection;
150 minNbPnts = Max (MinimumOfPoints, 2);
151 myMinLen = Max(theMinLen, Precision::Confusion());
153 switch (C.GetType()) {
163 case GeomAbs_BSplineCurve:
165 Handle_TheBSplineCurve BS = C.BSpline() ;
166 if (BS->NbPoles() == 2 ) PerformLinear (C);
167 else PerformCurve (C);
170 case GeomAbs_BezierCurve:
172 Handle_TheBezierCurve BZ = C.Bezier();
173 if (BZ->NbPoles() == 2) PerformLinear (C);
174 else PerformCurve (C);
177 default: PerformCurve (C);
183 //=======================================================================
184 //function : PerformLinear
186 //=======================================================================
188 void GCPnts_TangentialDeflection::PerformLinear (const TheCurve& C) {
192 parameters.Append (firstu);
195 Standard_Real Du = (lastu - firstu) / minNbPnts;
196 Standard_Real U = firstu + Du;
197 for (Standard_Integer i = 2; i <= minNbPnts; i++) {
199 parameters.Append (U);
205 parameters.Append (lastu);
209 //=======================================================================
210 //function : PerformCircular
212 //=======================================================================
214 void GCPnts_TangentialDeflection::PerformCircular (const TheCurve& C)
216 // akm 8/01/02 : check the radius before divide by it
217 Standard_Real dfR = C.Circle().Radius();
218 Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep(
219 dfR, curvatureDeflection, angularDeflection, myMinLen);
221 const Standard_Real aDiff = lastu - firstu;
222 // Round up number of points to satisfy curvatureDeflection more precisely
223 Standard_Integer NbPoints = (Standard_Integer)Ceiling(aDiff / Du);
224 NbPoints = Max(NbPoints, minNbPnts - 1);
225 Du = aDiff / NbPoints;
228 Standard_Real U = firstu;
229 for (Standard_Integer i = 1; i <= NbPoints; i++)
232 parameters.Append (U);
237 parameters.Append (lastu);
242 //=======================================================================
243 //function : PerformCurve
244 //purpose : On respecte ll'angle et la fleche, on peut imposer un nombre
245 // minimum de points sur un element lineaire
246 //=======================================================================
247 void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C)
250 Standard_Integer i, j;
252 gp_Pnt MiddlePoint, CurrentPoint, LastPoint;
253 Standard_Real Du, Dusave, MiddleU, L1, L2;
255 Standard_Real U1 = firstu;
256 Standard_Real LTol = Precision::Confusion (); //protection longueur nulle
257 Standard_Real ATol = Precision::Angular (); //protection angle nul
259 D0 (C, lastu, LastPoint);
261 //Initialization du calcul
263 Standard_Boolean NotDone = Standard_True;
264 Dusave = (lastu - firstu)*Us3;
266 EvaluateDu (C, U1, CurrentPoint, Du, NotDone);
267 parameters.Append (U1);
268 points .Append (CurrentPoint);
270 // Used to detect "isLine" current bspline and in Du computation in general handling.
271 Standard_Integer NbInterv = C.NbIntervals(GeomAbs_CN);
272 TColStd_Array1OfReal Intervs(1, NbInterv+1);
273 C.Intervals(Intervs, GeomAbs_CN);
276 //C'est soit une droite, soit une singularite :
277 V1 = (LastPoint.XYZ() - CurrentPoint.XYZ());
281 //Si c'est une droite on verifie en calculant minNbPoints :
282 Standard_Boolean IsLine = Standard_True;
283 Standard_Integer NbPoints = (minNbPnts > 3) ? minNbPnts : 3;
285 Standard_Real param = 0.;
286 for (i = 1; i <= NbInterv && IsLine; ++i)
288 // Avoid usage intervals out of [firstu, lastu].
289 if ((Intervs(i+1) < firstu) ||
290 (Intervs(i) > lastu))
294 // Fix border points in applicable intervals, to avoid be out of target interval.
295 if ((Intervs(i) < firstu) &&
296 (Intervs(i+1) > firstu))
300 if ((Intervs(i) < lastu) &&
301 (Intervs(i+1) > lastu))
303 Intervs(i + 1) = lastu;
306 Standard_Real delta = (Intervs(i+1) - Intervs(i))/NbPoints;
307 for (j = 1; j <= NbPoints && IsLine; ++j)
309 param = Intervs(i) + j*delta;
310 D0 (C, param, MiddlePoint);
311 V2 = (MiddlePoint.XYZ() - CurrentPoint.XYZ());
315 const Standard_Real aAngle = V2.CrossMagnitude(V1)/(L1*L2);
316 IsLine = (aAngle < ATol);
331 //c'etait une singularite on continue :
333 EvaluateDu (C, param, MiddlePoint, Du, NotDone);
338 Du = (lastu-firstu)/2.1;
339 MiddleU = firstu + Du;
340 D0 (C, MiddleU, MiddlePoint);
341 V1 = (MiddlePoint.XYZ() - CurrentPoint.XYZ());
345 // L1 < LTol C'est une courbe de longueur nulle, calcul termine :
346 // on renvoi un segment de 2 points (protection)
347 parameters.Append (lastu);
348 points .Append (LastPoint);
354 if (Du > Dusave) Du = Dusave;
360 parameters.Append (lastu);
361 points .Append (LastPoint);
366 //Traitement normal pour une courbe
367 Standard_Boolean MorePoints = Standard_True;
368 Standard_Real U2 = firstu;
369 Standard_Real AngleMax = angularDeflection * 0.5; //car on prend le point milieu
370 Standard_Integer aIdx[2] = {Intervs.Lower(), Intervs.Lower()}; // Indexes of intervals of U1 and U2, used to handle non-uniform case.
371 Standard_Boolean isNeedToCheck = Standard_False;
372 gp_Pnt aPrevPoint = points.Last();
375 aIdx[0] = getIntervalIdx(U1, Intervs, aIdx[0]);
378 if (U2 >= lastu) { //Bout de courbe
380 CurrentPoint = LastPoint;
384 else D0 (C, U2, CurrentPoint); //Point suivant
386 Standard_Real Coef = 0.0, ACoef = 0., FCoef = 0.;
387 Standard_Boolean Correction, TooLarge, TooSmall;
388 TooLarge = Standard_False;
389 Correction = Standard_True;
390 TooSmall = Standard_False;
392 while (Correction) { //Ajustement Du
395 aIdx[1] = getIntervalIdx(U2, Intervs, aIdx[0]);
396 if (aIdx[1] > aIdx[0]) // Jump to another polynom.
398 if (Du > (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3) // Set Du to the smallest value and check deflection on it.
400 Du = (Intervs(aIdx[0] + 1) - Intervs(aIdx[0]) ) * Us3;
404 D0 (C, U2, CurrentPoint);
408 MiddleU = (U1+U2)*0.5; //Verif / au point milieu
409 D0 (C, MiddleU, MiddlePoint);
411 V1 = (CurrentPoint.XYZ() - aPrevPoint.XYZ()); //Critere de fleche
412 V2 = (MiddlePoint.XYZ() - aPrevPoint.XYZ());
415 FCoef = (L1 > myMinLen) ?
416 V1.CrossMagnitude(V2)/(L1*curvatureDeflection) : 0.0;
418 V1 = (CurrentPoint.XYZ() - MiddlePoint.XYZ()); //Critere d'angle
421 if (L1 > myMinLen && L2 > myMinLen)
423 Standard_Real angg = V1.CrossMagnitude(V2) / (L1 * L2);
424 ACoef = angg / AngleMax;
429 //On retient le plus penalisant
430 Coef = Max(ACoef, FCoef);
432 if (isNeedToCheck && Coef < 0.55)
434 isNeedToCheck = Standard_False;
439 D0 (C, U2, CurrentPoint);
444 if (Abs (lastu-U2) < uTol) {
445 parameters.Append (lastu);
446 points .Append (LastPoint);
447 MorePoints = Standard_False;
448 Correction = Standard_False;
451 if (Coef >= 0.55 || TooLarge) {
452 parameters.Append (U2);
453 points .Append (CurrentPoint);
454 aPrevPoint = CurrentPoint;
455 Correction = Standard_False;
456 isNeedToCheck = Standard_True;
459 Correction = Standard_False;
460 aPrevPoint = CurrentPoint;
463 TooSmall = Standard_True;
464 //Standard_Real UUU2 = U2;
465 Du += Min((U2-U1)*(1.-Coef), Du*Us3);
470 D0 (C, U2, CurrentPoint);
477 if (!aPrevPoint.IsEqual(points.Last(), Precision::Confusion()))
479 parameters.Append (U1);
480 points .Append (aPrevPoint);
484 CurrentPoint = MiddlePoint;
489 D0 (C, U2, CurrentPoint);
490 TooLarge = Standard_True;
501 //La fleche est critere de decoupage
502 EvaluateDu (C, U2, CurrentPoint, Du, NotDone);
504 Du += (Du-Dusave)*(Du/Dusave);
505 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
506 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
510 //L'angle est le critere de decoupage
511 Du += (Du-Dusave)*(Du/Dusave);
512 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
513 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
520 parameters.Append (lastu);
521 points .Append (LastPoint);
522 MorePoints = Standard_False;
524 else if (Du*Us3 > uTol) Du*=Us3;
530 //Recalage avant dernier point :
531 i = points.Length()-1;
532 // Real d = points (i).Distance (points (i+1));
533 // if (Abs(parameters (i) - parameters (i+1))<= 0.000001 || d < Precision::Confusion()) {
534 // cout<<"deux points confondus"<<endl;
535 // parameters.Remove (i+1);
536 // points.Remove (i+1);
540 MiddleU = parameters (i-1);
541 MiddleU = (lastu + MiddleU)*0.5;
542 D0 (C, MiddleU, MiddlePoint);
543 parameters.SetValue (i, MiddleU);
544 points .SetValue (i, MiddlePoint);
547 //-- On rajoute des points aux milieux des segments si le nombre
548 //-- mini de points n'est pas atteint
550 Standard_Integer Nbp = points.Length();
551 Standard_Integer MinNb= (9*minNbPnts)/10;
552 //if(MinNb<4) MinNb=4;
554 //-- if(Nbp < MinNb) { cout<<"\n*"; } else { cout<<"\n."; }
556 //-- cout<<" \nGCPnts TangentialDeflection : Ajout de Points ("<<Nbp<<" "<<minNbPnts<<" )"<<endl;
557 for(i=2; i<=Nbp; i++) {
558 MiddleU = (parameters.Value(i-1)+parameters.Value(i))*0.5;
559 D0 (C, MiddleU, MiddlePoint);
560 parameters.InsertBefore(i,MiddleU);
561 points.InsertBefore(i,MiddlePoint);