1 // File: GCPnts_TangentialDeflection.gxx
2 // Created: Fri Nov 8 11:26:11 1996
3 // Author: Jean Claude VAUTHIER
4 // <jcv@brunox.paris1.matra-dtv.fr>
6 #include <GCPnts_DeflectionType.hxx>
7 #include <Standard_ConstructionError.hxx>
8 #include <Precision.hxx>
14 #define Us3 0.3333333333333333333333333333
16 void GCPnts_TangentialDeflection::EvaluateDu (
18 const Standard_Real U,
21 Standard_Boolean& NotDone) const {
25 Standard_Real Lt = T.Magnitude ();
26 Standard_Real LTol = Precision::Confusion ();
27 if (Lt > LTol && N.Magnitude () > LTol) {
28 Standard_Real Lc = N.CrossMagnitude (T);
29 Standard_Real Ln = Lc/Lt;
31 Du = sqrt (8.0 * curvatureDeflection / Ln);
32 NotDone = Standard_False;
38 //=======================================================================
39 //function : GCPnts_TangentialDeflection
41 //=======================================================================
43 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
45 const Standard_Real AngularDeflection,
46 const Standard_Real CurvatureDeflection,
47 const Standard_Integer MinimumOfPoints,
48 const Standard_Real UTol)
51 Initialize (C,AngularDeflection,CurvatureDeflection,MinimumOfPoints,UTol);
55 //=======================================================================
56 //function : GCPnts_TangentialDeflection
58 //=======================================================================
60 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
62 const Standard_Real FirstParameter,
63 const Standard_Real LastParameter,
64 const Standard_Real AngularDeflection,
65 const Standard_Real CurvatureDeflection,
66 const Standard_Integer MinimumOfPoints,
67 const Standard_Real UTol)
81 //=======================================================================
82 //function : Initialize
84 //=======================================================================
86 void GCPnts_TangentialDeflection::Initialize (
88 const Standard_Real AngularDeflection,
89 const Standard_Real CurvatureDeflection,
90 const Standard_Integer MinimumOfPoints,
91 const Standard_Real UTol)
104 //=======================================================================
105 //function : Initialize
107 //=======================================================================
109 void GCPnts_TangentialDeflection::Initialize (
111 const Standard_Real FirstParameter,
112 const Standard_Real LastParameter,
113 const Standard_Real AngularDeflection,
114 const Standard_Real CurvatureDeflection,
115 const Standard_Integer MinimumOfPoints,
116 const Standard_Real UTol)
120 Standard_ConstructionError_Raise_if (CurvatureDeflection <= Precision::Confusion () || AngularDeflection <= Precision::Angular (), "GCPnts_TangentialDeflection::Initialize - Zero Deflection")
124 if (FirstParameter < LastParameter) {
125 firstu = FirstParameter;
126 lastu = LastParameter;
129 lastu = FirstParameter;
130 firstu = LastParameter;
133 angularDeflection = AngularDeflection;
134 curvatureDeflection = CurvatureDeflection;
135 minNbPnts = Max (MinimumOfPoints, 2);
137 switch (C.GetType()) {
147 case GeomAbs_BSplineCurve:
149 Handle_TheBSplineCurve BS = C.BSpline() ;
150 if (BS->NbPoles() == 2 ) PerformLinear (C);
151 else PerformCurve (C);
154 case GeomAbs_BezierCurve:
156 Handle_TheBezierCurve BZ = C.Bezier();
157 if (BZ->NbPoles() == 2) PerformLinear (C);
158 else PerformCurve (C);
161 default: PerformCurve (C);
167 //=======================================================================
168 //function : PerformLinear
170 //=======================================================================
172 void GCPnts_TangentialDeflection::PerformLinear (const TheCurve& C) {
176 parameters.Append (firstu);
179 Standard_Real Du = (lastu - firstu) / minNbPnts;
180 Standard_Real U = firstu + Du;
181 for (Standard_Integer i = 2; i <= minNbPnts; i++) {
183 parameters.Append (U);
189 parameters.Append (lastu);
194 //=======================================================================
195 //function : PerformCircular
197 //=======================================================================
199 void GCPnts_TangentialDeflection::PerformCircular (const TheCurve& C)
201 // akm 8/01/02 : check the radius before divide by it
202 Standard_Real dfR = C.Circle().Radius();
203 Standard_Real Du = 0.;
204 if (Abs(dfR) > Precision::Confusion())
205 Du = Max(1.0e0 - (curvatureDeflection/dfR),0.0e0) ;
206 Du = acos (Du); Du+=Du;
207 Du = Min (Du, angularDeflection);
208 Standard_Integer NbPoints = (Standard_Integer )((lastu - firstu) / Du);
209 NbPoints = Max (NbPoints, minNbPnts-1);
210 Du = (lastu - firstu) / NbPoints;
213 Standard_Real U = firstu;
214 for (Standard_Integer i = 1; i <= NbPoints; i++) {
216 parameters.Append (U);
221 parameters.Append (lastu);
227 //=======================================================================
228 //function : PerformCurve
229 //purpose : On respecte ll'angle et la fleche, on peut imposer un nombre
230 // minimum de points sur un element lineaire
231 //=======================================================================
233 void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C)
238 gp_Pnt MiddlePoint, CurrentPoint, LastPoint;
239 Standard_Real Du, Dusave, MiddleU, L1, L2;
241 Standard_Real U1 = firstu;
242 Standard_Real LTol = Precision::Confusion (); //protection longueur nulle
243 Standard_Real ATol = Precision::Angular (); //protection angle nul
245 D0 (C, lastu, LastPoint);
247 //Initialization du calcul
249 Standard_Boolean NotDone = Standard_True;
250 Dusave = (lastu - firstu)*Us3;
252 EvaluateDu (C, U1, CurrentPoint, Du, NotDone);
253 parameters.Append (U1);
254 points .Append (CurrentPoint);
257 //C'est soit une droite, soit une singularite :
258 V1 = LastPoint.XYZ ();
259 V1.Subtract (CurrentPoint.XYZ());
262 //Si c'est une droite on verifie en calculant minNbPoints :
263 Standard_Boolean IsLine = Standard_True;
264 Standard_Integer NbPoints = 3;
265 if (minNbPnts > 3) NbPoints = minNbPnts;
266 Du = (lastu-firstu)/NbPoints;
267 MiddleU = firstu + Du;
268 for (i = 2; i < NbPoints; i++) {
269 D0 (C, MiddleU, MiddlePoint);
270 V2 = MiddlePoint.XYZ();
271 V2.Subtract (CurrentPoint.XYZ());
274 if (((V2.CrossMagnitude (V1))/(L1*L2)) >= ATol) {
275 //C'etait une singularite
276 IsLine = Standard_False;
280 parameters.Append (MiddleU);
281 points .Append (MiddlePoint);
287 //C'etait une droite (plusieurs poles alignes), Calcul termine :
288 parameters.Append (lastu);
289 points .Append (LastPoint);
293 //c'etait une singularite on continue :
294 Standard_Integer pointsLength=points.Length ();
295 for (i = 2; i <= pointsLength; i++) {
297 parameters.Remove (i);
305 Du = (lastu-firstu)/2.1;
306 MiddleU = firstu + Du;
307 D0 (C, MiddleU, MiddlePoint);
308 V1 = MiddlePoint.XYZ ();
309 V1.Subtract (CurrentPoint.XYZ());
312 // L1 < LTol C'est une courbe de longueur nulle, calcul termine :
313 // on renvoi un segment de 2 points (protection)
314 parameters.Append (lastu);
315 points .Append (LastPoint);
321 if (Du > Dusave) Du = Dusave;
327 parameters.Append (lastu);
328 points .Append (LastPoint);
333 //Traitement normal pour une courbe
334 Standard_Boolean MorePoints = Standard_True;
335 Standard_Real U2 = firstu;
336 Standard_Real AngleMax = angularDeflection * 0.5; //car on prend le point milieu
338 gp_Pnt aPrevPoint = points.Last();
344 if (U2 >= lastu) { //Bout de courbe
346 CurrentPoint = LastPoint;
350 else D0 (C, U2, CurrentPoint); //Point suivant
352 Standard_Real Coef, ACoef, FCoef;
353 Standard_Boolean Correction, TooLarge, TooSmall;
354 TooLarge = Standard_False;
355 TooSmall = Standard_False;
356 Correction = Standard_True;
358 Standard_Real lastCoef = 0;
360 while (Correction) { //Ajustement Du
361 MiddleU = (U1+U2)*0.5; //Verif / au point milieu
362 D0 (C, MiddleU, MiddlePoint);
364 V1 = CurrentPoint.XYZ (); //Critere de fleche
365 V1.Subtract (aPrevPoint.XYZ());
366 V2 = MiddlePoint.XYZ ();
367 V2.Subtract (aPrevPoint.XYZ());
369 if (L1 > LTol) FCoef = V1.CrossMagnitude(V2)/(L1*curvatureDeflection);
372 V1 = CurrentPoint.XYZ (); //Critere d'angle
373 V1.Subtract (MiddlePoint.XYZ ());
376 Standard_Real angg = V1.CrossMagnitude(V2)/(L1*L2);
377 if (L1 > LTol && L2 > LTol) ACoef = angg/AngleMax;
380 if (ACoef >= FCoef) Coef = ACoef; //On retient le plus penalisant
385 if (Abs (lastu-U2) < uTol) {
386 parameters.Append (lastu);
387 points .Append (LastPoint);
388 MorePoints = Standard_False;
389 Correction = Standard_False;
392 if (Coef >= 0.55 || TooLarge) {
393 parameters.Append (U2);
394 points .Append (CurrentPoint);
395 aPrevPoint = CurrentPoint;
396 Correction = Standard_False;
399 Correction = Standard_False;
400 aPrevPoint = CurrentPoint;
403 TooSmall = Standard_True;
405 //Standard_Real UUU2 = U2;
406 Du += Min((U2-U1)*(1.-Coef), Du*Us3);
409 //if (U2 >= lastu) U2 = UUU2;
411 parameters.Append (lastu);
412 points .Append (LastPoint);
413 MorePoints = Standard_False;
414 Correction = Standard_False;
416 else D0 (C, U2, CurrentPoint);
425 CurrentPoint = MiddlePoint;
430 D0 (C, U2, CurrentPoint);
431 TooLarge = Standard_True;
442 //La fleche est critere de decoupage
443 EvaluateDu (C, U2, CurrentPoint, Du, NotDone);
445 Du += (Du-Dusave)*(Du/Dusave);
446 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
447 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
451 //L'angle est le critere de decoupage
452 Du += (Du-Dusave)*(Du/Dusave);
453 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
454 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
461 parameters.Append (lastu);
462 points .Append (LastPoint);
463 MorePoints = Standard_False;
465 else if (Du*Us3 > uTol) Du*=Us3;
471 //Recalage avant dernier point :
472 i = points.Length()-1;
473 // Real d = points (i).Distance (points (i+1));
474 // if (Abs(parameters (i) - parameters (i+1))<= 0.000001 || d < Precision::Confusion()) {
475 // cout<<"deux points confondus"<<endl;
476 // parameters.Remove (i+1);
477 // points.Remove (i+1);
482 MiddleU = parameters (i-1);
483 MiddleU = (lastu + MiddleU)*0.5;
484 D0 (C, MiddleU, MiddlePoint);
485 parameters.SetValue (i, MiddleU);
486 points .SetValue (i, MiddlePoint);
489 //-- On rajoute des points aux milieux des segments si le nombre
490 //-- mini de points n'est pas atteint
492 Standard_Integer Nbp = points.Length();
493 Standard_Integer MinNb= (9*minNbPnts)/10;
494 //if(MinNb<4) MinNb=4;
496 //-- if(Nbp < MinNb) { cout<<"\n*"; } else { cout<<"\n."; }
498 //-- cout<<" \nGCPnts TangentialDeflection : Ajout de Points ("<<Nbp<<" "<<minNbPnts<<" )"<<endl;
499 for(i=2; i<=Nbp; i++) {
500 MiddleU = (parameters.Value(i-1)+parameters.Value(i))*0.5;
501 D0 (C, MiddleU, MiddlePoint);
502 parameters.InsertBefore(i,MiddleU);
503 points.InsertBefore(i,MiddlePoint);