0022922: Clean up warnings on uninitialized / unused variables
[occt.git] / src / GCPnts / GCPnts_UniformAbscissa.gxx
1 #include <StdFail_NotDone.hxx>
2 #include <Standard_DomainError.hxx>
3 #include <Standard_OutOfRange.hxx>
4 #include <Standard_ConstructionError.hxx>
5 #include <GCPnts_AbscissaType.hxx>
6 #include <TColStd_HArray1OfReal.hxx>
7 #include <TColStd_Array1OfReal.hxx>
8 #include <GeomAbs_CurveType.hxx>
9 #include <CPnts_AbscissaPoint.hxx>
10 #include <GCPnts_AbscissaPoint.hxx>
11 #include <Precision.hxx>
12 #include <gp_Circ.hxx>
13 #include <gp_Circ2d.hxx>
14 #include <gp_Vec.hxx>
15 #include <gp_Vec2d.hxx>
16
17
18 static Standard_Real GetParameterLengthRatio(TheCurve& C)
19 {
20   switch (C.GetType()) {
21     
22   case GeomAbs_Circle :
23     return C.Circle().Radius();
24     
25   case GeomAbs_Line :
26     return 1.;
27     
28   case GeomAbs_BezierCurve : 
29   case GeomAbs_BSplineCurve :
30     {
31       if (!C.IsRational())
32         return C.DN(0., 1).Magnitude();
33       else
34         return RealLast();
35     }
36     
37     default :
38       return RealLast();
39     
40   }
41 }
42
43
44 static GCPnts_AbscissaType GetAbsType(TheCurve& C)
45 {
46   if (C.NbIntervals(GeomAbs_C1) > 1)
47     return GCPnts_AbsComposite;
48
49   switch (C.GetType()) {
50     
51   case GeomAbs_Line:
52   case GeomAbs_Circle:
53     return GCPnts_LengthParametrized;
54   case GeomAbs_BezierCurve:
55     {
56       Handle_TheBezierCurve  BZ = C.Bezier(); 
57       if (BZ->NbPoles() == 2 && !BZ->IsRational()) 
58         return GCPnts_LengthParametrized;
59       else
60         return GCPnts_Parametrized; 
61     }
62   case GeomAbs_BSplineCurve:
63     {
64       Handle_TheBSplineCurve BS = C.BSpline() ;
65       if (BS->NbPoles() == 2 && !BS->IsRational()) 
66         return GCPnts_LengthParametrized;
67       else
68         return GCPnts_Parametrized; 
69     }
70   default:
71    return GCPnts_Parametrized ;   
72   }
73 }
74
75 static Standard_Boolean Perform(Handle(TColStd_HArray1OfReal)& HParameters,
76                                 TheCurve& C, 
77                                 const Standard_Real Abscissa,
78                                 const Standard_Real U1,
79                                 const Standard_Real U2,
80                                 const Standard_Real TotalLength,
81                                 Standard_Integer &NbPoints,
82                                 const Standard_Real EPSILON) 
83 {
84   Standard_Boolean NotDone = Standard_True;
85   Standard_Boolean LocalDone = Standard_True;
86 //  Standard_Boolean Forward = Standard_True  ;
87   Standard_Real UU1 = Min(U1, U2), UU2 = Max(U1, U2) ;
88   Standard_Integer Index ;
89 //  Standard_Real UCurrent, Delta, Ui;
90   Standard_Real Delta, Ui;
91   NbPoints = 0 ;
92
93 // 
94 // this initialization avoids the computation of the Length
95 // of the curve 
96
97   Delta = (Abscissa/TotalLength) * (UU2 - UU1) ; 
98   Index = 1 ;
99   HParameters->SetValue(Index,UU1)  ;
100   while (NotDone) {
101     Ui = HParameters->Value(Index) + Delta;
102     if (Ui > UU2) {
103       // MSV 21.04.2004: OCC5739 (GCPnts_UniformAbscissa gives incorrect
104       // distribution of points)
105 //       if (UU2 - HParameters->Value(Index) > 0.01*Delta) {
106 //      Index += 1;
107 //       }
108 //       HParameters->SetValue(Index, UU2);
109 //       NotDone = Standard_False;
110 //       break;
111       Ui = UU2;
112     }
113     GCPnts_AbscissaPoint   AbscissaFinder(C,
114                                           Abscissa,
115                                           HParameters->Value(Index),
116                                           Ui,
117                                           EPSILON) ;
118     if (AbscissaFinder.IsDone()) {
119       Index += 1 ;
120       Ui = AbscissaFinder.Parameter();
121       if (Abs(Ui-UU2) <= EPSILON) {
122         HParameters->SetValue(Index, UU2);
123         NotDone = Standard_False;
124       }
125       else if (Ui < UU2) {
126         HParameters->SetValue(Index, Ui);
127       }
128       else {
129         HParameters->SetValue(Index, UU2);
130         NotDone = Standard_False;
131       }
132       NotDone = NotDone && (Index + 1 <= HParameters->Length()) ;
133     }
134     else {
135       
136       LocalDone = Standard_False ;
137       NotDone = Standard_True ;
138       Delta -= Delta/10;
139       if (Delta <= Precision::PConfusion()) break;
140     }
141   }
142   NbPoints = Index ;
143   return (LocalDone) ;
144 }
145
146
147 static Standard_Boolean 
148 PerformLengthParametrized( Handle(TColStd_HArray1OfReal)& HParameters,
149                           TheCurve& C, 
150                           const Standard_Real Abscissa,
151                           const Standard_Real U1,
152                           const Standard_Real U2,
153                           const Standard_Real TotalLength,
154                           Standard_Integer &NbPoints,
155                           const Standard_Real EPSILON) 
156 {
157   Standard_Boolean NotDone = Standard_True;
158 //  Standard_Boolean LocalDone = Standard_True;
159   Standard_Boolean Forward = Standard_True  ;
160   Standard_Real UU1 = Min(U1, U2);
161 //  Standard_Real UCurrent;
162   Standard_Real Delta, Ui;
163   Standard_Real UU2 = Max(U1, U2);
164   Standard_Integer   Index ;
165
166 // Ratio is defined as dl = Ratio * du
167 // for a circle of gp Ratio is equal to the radius of the circle.
168 // for a line of gp ratio is equal to 1.0
169   Standard_Real Ratio = GetParameterLengthRatio(C);
170
171
172   if (Abscissa < 0.0e0)    {
173     Forward = Standard_False ;
174     UU2 = Min(U1, U2);
175     UU1 = Max(U1, U2);
176   }
177   Delta = (Abscissa/TotalLength) * (UU2 - UU1) ; 
178   Index = 1 ;
179   NbPoints = 0 ;
180   HParameters->SetValue(Index,UU1) ;  
181   while  (NotDone) {
182     Index += 1 ;
183     Ui = HParameters->Value(Index-1) + Delta;
184     if (Abs(Ui-UU2) <= EPSILON) {
185       HParameters->SetValue(Index, UU2);
186       NotDone = Standard_False;
187     }
188     else if (Ui < UU2) {
189       HParameters->SetValue(Index, Ui);
190     }
191     else {
192       NotDone = Standard_False;
193       if (Abs(HParameters->Value(Index-1) - UU2)*Ratio/Abscissa < 0.1) {
194         HParameters->SetValue(Index-1, UU2);
195         Index -= 1;
196       }
197       else 
198         HParameters->SetValue(Index, UU2);
199     }
200     NotDone = (Index+1  <= HParameters->Length()) && NotDone ;
201   }
202
203   NbPoints = Index ;
204   return Standard_True ;
205 }
206
207
208 //=======================================================================
209 //function : Initialize
210 //purpose  : 
211 //=======================================================================
212
213 void GCPnts_UniformAbscissa::Initialize  (TheCurve& C, 
214                                           const Standard_Real Abscissa, 
215                                           const Standard_Real Tol)
216 {
217   Initialize(C, Abscissa, C.FirstParameter(), 
218              C.LastParameter(), Tol);
219
220
221 //=======================================================================
222 //function : GCPnts_UniformAbscissa
223 //purpose  : 
224 //=======================================================================
225
226 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa  (TheCurve& C, 
227                                                  const Standard_Real Abscissa,
228                                                  const Standard_Real Tol)
229 {
230   Initialize(C, Abscissa, Tol);
231
232
233 //=======================================================================
234 //function : GCPnts_UniformAbscissa
235 //purpose  : 
236 //=======================================================================
237
238 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa  (TheCurve& C, 
239                                                  const Standard_Real Abscissa, 
240                                                  const Standard_Real U1, 
241                                                  const Standard_Real U2,
242                                                  const Standard_Real Tol)
243 {
244   Initialize(C, Abscissa, U1, U2, Tol);
245 }
246
247 //=======================================================================
248 //function : GCPnts_UniformAbscissa
249 //purpose  : 
250 //=======================================================================
251
252 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa(TheCurve& C, 
253                                                const Standard_Integer NbPoints, 
254                                                const Standard_Real Tol)
255 {
256   Initialize(C, NbPoints, Tol);
257 }
258
259 //=======================================================================
260 //function : GCPnts_UniformAbscissa
261 //purpose  : 
262 //=======================================================================
263
264 GCPnts_UniformAbscissa::GCPnts_UniformAbscissa(TheCurve& C, 
265                                                const Standard_Integer NbPoints,
266                                                const Standard_Real U1, 
267                                                const Standard_Real U2,
268                                                const Standard_Real Tol)
269 {
270   Initialize(C, NbPoints, U1, U2, Tol);
271 }
272
273 //=======================================================================
274 //function : Initialize
275 //purpose  : 
276 //=======================================================================
277
278 void GCPnts_UniformAbscissa::Initialize(TheCurve& C, 
279                                         const Standard_Real Abscissa, 
280                                         const Standard_Real U1,
281                                         const Standard_Real U2,
282                                         const Standard_Real Tol)
283
284   Standard_Real L ;
285   myAbscissa = Abscissa;
286   myNbPoints = 0 ;
287   myDone = Standard_False;
288   Standard_Real EPSILON;
289   
290   if(Tol < Precision::Confusion())
291     EPSILON = C.Resolution(Precision::Confusion());
292   else
293     EPSILON = C.Resolution(Tol);
294   
295   L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON);
296   if (L <= Precision::Confusion()) {
297     return;
298   }
299   Standard_Integer size ;
300
301 // 
302 //  compute the total Length here so that we can 
303 //  guess the number of points instead of letting the
304 //  constructor of CPnts_AbscissaPoint do that and loosing
305 //  the information
306 //
307 //
308
309 // modified by Igor Motchalov 23/04/2001
310 //  size = (Standard_Integer )( (L/Abs(Abscissa)) + 5 );
311   Standard_Real sizeR=L/Abs(Abscissa) + 5; 
312   if (sizeR < IntegerLast()) {
313     size=(Standard_Integer) sizeR; 
314   } else {
315     return; 
316   }
317
318   if (!myParams.IsNull())    {
319     if (myParams->Length() < size)      {
320       myParams.Nullify() ;
321       myParams =  new
322         TColStd_HArray1OfReal(1,size) ;
323     } 
324   }
325   else    {
326     myParams  = new
327       TColStd_HArray1OfReal(1,size) ;
328   }
329
330 //  Standard_Real EPSILON = C.Resolution(Precision::Confusion());
331   GCPnts_AbscissaType Type = GetAbsType(C);
332   switch (Type) {
333   case GCPnts_LengthParametrized : 
334     myDone = PerformLengthParametrized(myParams, 
335                                        C, 
336                                        Abscissa, 
337                                        U1, 
338                                        U2, 
339                                        L, 
340                                        myNbPoints, 
341                                        EPSILON);
342     break;
343   case GCPnts_Parametrized: 
344   case GCPnts_AbsComposite: 
345     myDone = Perform(myParams, 
346                      C, 
347                      Abscissa, 
348                      U1, 
349                      U2, 
350                      L, 
351                      myNbPoints, 
352                      EPSILON);
353     break;
354   }
355 }
356
357
358 //=======================================================================
359 //function : Initialize
360 //purpose  : 
361 //=======================================================================
362
363 void GCPnts_UniformAbscissa::Initialize(TheCurve& C, 
364                                         const Standard_Integer NbPoints,
365                                         const Standard_Real Tol)
366 {
367   Initialize(C, NbPoints, C.FirstParameter(),
368              C.LastParameter(), Tol);
369
370
371
372 //=======================================================================
373 //function : Initialize
374 //purpose  : 
375 //=======================================================================
376
377 void GCPnts_UniformAbscissa::Initialize(TheCurve& C, 
378                                         const Standard_Integer NbPoints,
379                                         const Standard_Real U1, 
380                                         const Standard_Real U2,
381                                         const Standard_Real Tol)
382 {
383   Standard_ConstructionError_Raise_if(NbPoints <= 1, "");
384   Standard_Real Abscissa ;
385   myNbPoints = 0 ;
386   myDone = Standard_False;
387   Standard_Real EPSILON;
388   
389   if(Tol < Precision::Confusion())
390     EPSILON = C.Resolution(Precision::Confusion());
391   else
392     EPSILON = C.Resolution(Tol);
393
394 //
395 // although very similar to Initialize with Abscissa this avoid
396 // the computation of the total length of the curve twice
397 //
398   Standard_Real L = GCPnts_AbscissaPoint::Length(C, U1, U2, EPSILON) ;
399
400   if (L <= Precision::Confusion()) {
401     return;
402   }
403
404   Abscissa = 
405   myAbscissa = L / (NbPoints - 1);
406   
407   Standard_Integer size ;
408
409 // 
410 //  compute the total Length here so that we can 
411 //  guess the number of points instead of letting the
412 //  constructor of CPnts_AbscissaPoint do that and loosing
413 //  the information
414 //
415 //
416
417   size = NbPoints + 5 ;
418
419
420   if (!myParams.IsNull())    {
421     if (myParams->Length() < size)      {
422       myParams.Nullify() ;
423       myParams =  new
424         TColStd_HArray1OfReal(1,size) ;
425     } 
426   }
427   else    {
428     myParams  = new
429       TColStd_HArray1OfReal(1,size) ;
430   }
431   
432
433   myNbPoints = 0 ;
434   GCPnts_AbscissaType Type = GetAbsType(C);
435   switch (Type) {
436   case GCPnts_LengthParametrized: 
437     myDone = PerformLengthParametrized(myParams, 
438                                        C, 
439                                        Abscissa, 
440                                        U1, 
441                                        U2, 
442                                        L, 
443                                        myNbPoints, 
444                                        EPSILON);
445     break;
446   case GCPnts_Parametrized: 
447   case GCPnts_AbsComposite: 
448     myDone = Perform(myParams, 
449                      C, 
450                      Abscissa, 
451                      U1, 
452                      U2, 
453                      L, 
454                      myNbPoints, 
455                      EPSILON);
456     break;
457   }
458 }
459
460
461
462
463
464