1 // Created on: 1996-11-08
2 // Created by: Jean Claude VAUTHIER
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <GCPnts_DeflectionType.hxx>
23 #include <Standard_ConstructionError.hxx>
24 #include <Precision.hxx>
30 #define Us3 0.3333333333333333333333333333
32 void GCPnts_TangentialDeflection::EvaluateDu (
34 const Standard_Real U,
37 Standard_Boolean& NotDone) const {
41 Standard_Real Lt = T.Magnitude ();
42 Standard_Real LTol = Precision::Confusion ();
43 if (Lt > LTol && N.Magnitude () > LTol) {
44 Standard_Real Lc = N.CrossMagnitude (T);
45 Standard_Real Ln = Lc/Lt;
47 Du = sqrt (8.0 * curvatureDeflection / Ln);
48 NotDone = Standard_False;
54 //=======================================================================
55 //function : GCPnts_TangentialDeflection
57 //=======================================================================
59 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
61 const Standard_Real AngularDeflection,
62 const Standard_Real CurvatureDeflection,
63 const Standard_Integer MinimumOfPoints,
64 const Standard_Real UTol)
67 Initialize (C,AngularDeflection,CurvatureDeflection,MinimumOfPoints,UTol);
71 //=======================================================================
72 //function : GCPnts_TangentialDeflection
74 //=======================================================================
76 GCPnts_TangentialDeflection::GCPnts_TangentialDeflection (
78 const Standard_Real FirstParameter,
79 const Standard_Real LastParameter,
80 const Standard_Real AngularDeflection,
81 const Standard_Real CurvatureDeflection,
82 const Standard_Integer MinimumOfPoints,
83 const Standard_Real UTol)
97 //=======================================================================
98 //function : Initialize
100 //=======================================================================
102 void GCPnts_TangentialDeflection::Initialize (
104 const Standard_Real AngularDeflection,
105 const Standard_Real CurvatureDeflection,
106 const Standard_Integer MinimumOfPoints,
107 const Standard_Real UTol)
120 //=======================================================================
121 //function : Initialize
123 //=======================================================================
125 void GCPnts_TangentialDeflection::Initialize (
127 const Standard_Real FirstParameter,
128 const Standard_Real LastParameter,
129 const Standard_Real AngularDeflection,
130 const Standard_Real CurvatureDeflection,
131 const Standard_Integer MinimumOfPoints,
132 const Standard_Real UTol)
136 Standard_ConstructionError_Raise_if (CurvatureDeflection <= Precision::Confusion () || AngularDeflection <= Precision::Angular (), "GCPnts_TangentialDeflection::Initialize - Zero Deflection")
140 if (FirstParameter < LastParameter) {
141 firstu = FirstParameter;
142 lastu = LastParameter;
145 lastu = FirstParameter;
146 firstu = LastParameter;
149 angularDeflection = AngularDeflection;
150 curvatureDeflection = CurvatureDeflection;
151 minNbPnts = Max (MinimumOfPoints, 2);
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);
210 //=======================================================================
211 //function : PerformCircular
213 //=======================================================================
215 void GCPnts_TangentialDeflection::PerformCircular (const TheCurve& C)
217 // akm 8/01/02 : check the radius before divide by it
218 Standard_Real dfR = C.Circle().Radius();
219 Standard_Real Du = 0.;
220 if (Abs(dfR) > Precision::Confusion())
221 Du = Max(1.0e0 - (curvatureDeflection/dfR),0.0e0) ;
222 Du = acos (Du); Du+=Du;
223 Du = Min (Du, angularDeflection);
224 Standard_Integer NbPoints = (Standard_Integer )((lastu - firstu) / Du);
225 NbPoints = Max (NbPoints, minNbPnts-1);
226 Du = (lastu - firstu) / NbPoints;
229 Standard_Real U = firstu;
230 for (Standard_Integer i = 1; i <= NbPoints; i++) {
232 parameters.Append (U);
237 parameters.Append (lastu);
243 //=======================================================================
244 //function : PerformCurve
245 //purpose : On respecte ll'angle et la fleche, on peut imposer un nombre
246 // minimum de points sur un element lineaire
247 //=======================================================================
249 void GCPnts_TangentialDeflection::PerformCurve (const TheCurve& C)
254 gp_Pnt MiddlePoint, CurrentPoint, LastPoint;
255 Standard_Real Du, Dusave, MiddleU, L1, L2;
257 Standard_Real U1 = firstu;
258 Standard_Real LTol = Precision::Confusion (); //protection longueur nulle
259 Standard_Real ATol = Precision::Angular (); //protection angle nul
261 D0 (C, lastu, LastPoint);
263 //Initialization du calcul
265 Standard_Boolean NotDone = Standard_True;
266 Dusave = (lastu - firstu)*Us3;
268 EvaluateDu (C, U1, CurrentPoint, Du, NotDone);
269 parameters.Append (U1);
270 points .Append (CurrentPoint);
273 //C'est soit une droite, soit une singularite :
274 V1 = LastPoint.XYZ ();
275 V1.Subtract (CurrentPoint.XYZ());
278 //Si c'est une droite on verifie en calculant minNbPoints :
279 Standard_Boolean IsLine = Standard_True;
280 Standard_Integer NbPoints = 3;
281 if (minNbPnts > 3) NbPoints = minNbPnts;
282 Du = (lastu-firstu)/NbPoints;
283 MiddleU = firstu + Du;
284 for (i = 2; i < NbPoints; i++) {
285 D0 (C, MiddleU, MiddlePoint);
286 V2 = MiddlePoint.XYZ();
287 V2.Subtract (CurrentPoint.XYZ());
290 if (((V2.CrossMagnitude (V1))/(L1*L2)) >= ATol) {
291 //C'etait une singularite
292 IsLine = Standard_False;
296 parameters.Append (MiddleU);
297 points .Append (MiddlePoint);
303 //C'etait une droite (plusieurs poles alignes), Calcul termine :
304 parameters.Append (lastu);
305 points .Append (LastPoint);
309 //c'etait une singularite on continue :
310 Standard_Integer pointsLength=points.Length ();
311 for (i = 2; i <= pointsLength; i++) {
313 parameters.Remove (i);
321 Du = (lastu-firstu)/2.1;
322 MiddleU = firstu + Du;
323 D0 (C, MiddleU, MiddlePoint);
324 V1 = MiddlePoint.XYZ ();
325 V1.Subtract (CurrentPoint.XYZ());
328 // L1 < LTol C'est une courbe de longueur nulle, calcul termine :
329 // on renvoi un segment de 2 points (protection)
330 parameters.Append (lastu);
331 points .Append (LastPoint);
337 if (Du > Dusave) Du = Dusave;
343 parameters.Append (lastu);
344 points .Append (LastPoint);
349 //Traitement normal pour une courbe
350 Standard_Boolean MorePoints = Standard_True;
351 Standard_Real U2 = firstu;
352 Standard_Real AngleMax = angularDeflection * 0.5; //car on prend le point milieu
354 gp_Pnt aPrevPoint = points.Last();
360 if (U2 >= lastu) { //Bout de courbe
362 CurrentPoint = LastPoint;
366 else D0 (C, U2, CurrentPoint); //Point suivant
368 Standard_Real Coef, ACoef, FCoef;
369 Standard_Boolean Correction, TooLarge, TooSmall;
370 TooLarge = Standard_False;
371 TooSmall = Standard_False;
372 Correction = Standard_True;
374 Standard_Real lastCoef = 0;
376 while (Correction) { //Ajustement Du
377 MiddleU = (U1+U2)*0.5; //Verif / au point milieu
378 D0 (C, MiddleU, MiddlePoint);
380 V1 = CurrentPoint.XYZ (); //Critere de fleche
381 V1.Subtract (aPrevPoint.XYZ());
382 V2 = MiddlePoint.XYZ ();
383 V2.Subtract (aPrevPoint.XYZ());
385 if (L1 > LTol) FCoef = V1.CrossMagnitude(V2)/(L1*curvatureDeflection);
388 V1 = CurrentPoint.XYZ (); //Critere d'angle
389 V1.Subtract (MiddlePoint.XYZ ());
392 Standard_Real angg = V1.CrossMagnitude(V2)/(L1*L2);
393 if (L1 > LTol && L2 > LTol) ACoef = angg/AngleMax;
396 if (ACoef >= FCoef) Coef = ACoef; //On retient le plus penalisant
401 if (Abs (lastu-U2) < uTol) {
402 parameters.Append (lastu);
403 points .Append (LastPoint);
404 MorePoints = Standard_False;
405 Correction = Standard_False;
408 if (Coef >= 0.55 || TooLarge) {
409 parameters.Append (U2);
410 points .Append (CurrentPoint);
411 aPrevPoint = CurrentPoint;
412 Correction = Standard_False;
415 Correction = Standard_False;
416 aPrevPoint = CurrentPoint;
419 TooSmall = Standard_True;
421 //Standard_Real UUU2 = U2;
422 Du += Min((U2-U1)*(1.-Coef), Du*Us3);
425 //if (U2 >= lastu) U2 = UUU2;
427 parameters.Append (lastu);
428 points .Append (LastPoint);
429 MorePoints = Standard_False;
430 Correction = Standard_False;
432 else D0 (C, U2, CurrentPoint);
441 CurrentPoint = MiddlePoint;
446 D0 (C, U2, CurrentPoint);
447 TooLarge = Standard_True;
458 //La fleche est critere de decoupage
459 EvaluateDu (C, U2, CurrentPoint, Du, NotDone);
461 Du += (Du-Dusave)*(Du/Dusave);
462 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
463 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
467 //L'angle est le critere de decoupage
468 Du += (Du-Dusave)*(Du/Dusave);
469 if (Du > 1.5 * Dusave) Du = 1.5 * Dusave;
470 if (Du < 0.75* Dusave) Du = 0.75 * Dusave;
477 parameters.Append (lastu);
478 points .Append (LastPoint);
479 MorePoints = Standard_False;
481 else if (Du*Us3 > uTol) Du*=Us3;
487 //Recalage avant dernier point :
488 i = points.Length()-1;
489 // Real d = points (i).Distance (points (i+1));
490 // if (Abs(parameters (i) - parameters (i+1))<= 0.000001 || d < Precision::Confusion()) {
491 // cout<<"deux points confondus"<<endl;
492 // parameters.Remove (i+1);
493 // points.Remove (i+1);
498 MiddleU = parameters (i-1);
499 MiddleU = (lastu + MiddleU)*0.5;
500 D0 (C, MiddleU, MiddlePoint);
501 parameters.SetValue (i, MiddleU);
502 points .SetValue (i, MiddlePoint);
505 //-- On rajoute des points aux milieux des segments si le nombre
506 //-- mini de points n'est pas atteint
508 Standard_Integer Nbp = points.Length();
509 Standard_Integer MinNb= (9*minNbPnts)/10;
510 //if(MinNb<4) MinNb=4;
512 //-- if(Nbp < MinNb) { cout<<"\n*"; } else { cout<<"\n."; }
514 //-- cout<<" \nGCPnts TangentialDeflection : Ajout de Points ("<<Nbp<<" "<<minNbPnts<<" )"<<endl;
515 for(i=2; i<=Nbp; i++) {
516 MiddleU = (parameters.Value(i-1)+parameters.Value(i))*0.5;
517 D0 (C, MiddleU, MiddlePoint);
518 parameters.InsertBefore(i,MiddleU);
519 points.InsertBefore(i,MiddlePoint);