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