0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / Approx / Approx_ComputeCLine.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 under
7 // the terms of the GNU Lesser General Public License 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 //  modified by Edward AGAPOV (eap) Tue Apr 2 2002 (occ265)
16 //  -- stop cutting an interval to approximate if next decisions
17 //  -- get worse on and on
18
19
20
21 #include <Approx_ParametrizationType.hxx>
22 #include <AppCont_LeastSquare.hxx>
23 #include <TColStd_Array1OfReal.hxx>
24 #include <AppParCurves_Constraint.hxx>
25 #include <Approx_Status.hxx>
26 #include <Precision.hxx>
27
28 const static Standard_Integer MAXSEGM = 1000;
29
30 //=======================================================================
31 //function : Approx_ComputeCLine
32 //purpose  : The MultiLine <Line> will be approximated until tolerances
33 //           will be reached.
34 //           The approximation will be done from degreemin to degreemax
35 //           with a cutting if the corresponding boolean is True.
36 //=======================================================================
37
38 Approx_ComputeCLine::Approx_ComputeCLine
39 (const MultiLine& Line,
40 const Standard_Integer degreemin,
41 const Standard_Integer degreemax,
42 const Standard_Real Tolerance3d,
43 const Standard_Real Tolerance2d,
44 const Standard_Boolean cutting,
45 const AppParCurves_Constraint FirstC,
46 const AppParCurves_Constraint LastC)
47 {
48   mydegremin = degreemin;
49   mydegremax = degreemax;
50   mytol3d = Tolerance3d;
51   mytol2d = Tolerance2d;
52   mycut = cutting;
53   myfirstC = FirstC;
54   mylastC = LastC;
55   myMaxSegments = MAXSEGM;
56   myInvOrder = Standard_True;
57   myHangChecking = Standard_True;
58   alldone = Standard_False;
59   tolreached = Standard_False;
60   currenttol3d = 0.0;
61   currenttol2d = 0.0;
62   Perform(Line);
63 }
64
65 //=======================================================================
66 //function : Approx_ComputeCLine
67 //purpose  : Initializes the fields of the algorithm.
68 //=======================================================================
69
70 Approx_ComputeCLine::Approx_ComputeCLine
71 (const Standard_Integer degreemin,
72 const Standard_Integer degreemax,
73 const Standard_Real Tolerance3d,
74 const Standard_Real Tolerance2d,
75 const Standard_Boolean cutting,
76 const AppParCurves_Constraint FirstC,
77 const AppParCurves_Constraint LastC)
78 {
79   alldone = Standard_False;
80   mydegremin = degreemin;
81   mydegremax = degreemax;
82   mytol3d = Tolerance3d;
83   mytol2d = Tolerance2d;
84   mycut = cutting;
85   myfirstC = FirstC;
86   mylastC = LastC;
87   myMaxSegments = MAXSEGM;
88   myInvOrder = Standard_True;
89   myHangChecking = Standard_True;
90   tolreached = Standard_False;
91   currenttol3d = 0.0;
92   currenttol2d = 0.0;
93 }
94
95 //=======================================================================
96 //function : Perform
97 //purpose  : runs the algorithm after having initialized the fields.
98 //=======================================================================
99
100 void Approx_ComputeCLine::Perform(const MultiLine& Line)
101 {
102   Standard_Real UFirst, ULast;
103   Standard_Boolean Finish = Standard_False,
104     begin = Standard_True, Ok = Standard_False;
105   Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
106   UFirst = Line.FirstParameter();
107   ULast = Line.LastParameter();
108   Standard_Real TolU = 0.;
109   if (myHangChecking)
110   {
111     TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion());
112   }
113   else
114   {
115     TolU = Max((ULast - UFirst)*1.e-05, Precision::PApproximation());
116   }
117   Standard_Real myfirstU = UFirst;
118   Standard_Real mylastU = ULast;
119   Standard_Integer aMaxSegments = 0;
120   Standard_Integer aMaxSegments1 = myMaxSegments - 1;
121   Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 10;
122
123   if (!mycut)
124   {
125     alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
126     if (!alldone)
127     {
128       tolreached = Standard_False;
129       myfirstparam.Append(UFirst);
130       mylastparam.Append(ULast);
131       myMultiCurves.Append(TheMultiCurve);
132       Tolers3d.Append(currenttol3d);
133       Tolers2d.Append(currenttol2d);
134     }
135   }
136   else
137   {
138
139     // previous decision to be taken if we get worse with next cut (eap)
140     AppParCurves_MultiCurve KeptMultiCurve;
141     Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
142
143     while (!Finish)
144     {
145
146       // Gestion du decoupage de la multiline pour approximer:
147       if (!begin)
148       {
149         if (Ok)
150         {
151           // Calcul de la partie a approximer.
152           myfirstU = mylastU;
153           mylastU = ULast;
154           aNbCut = 0;
155           aNbImp = 0;
156           if (Abs(ULast - myfirstU) <= RealEpsilon()
157               || aMaxSegments >= myMaxSegments)
158           {
159             Finish = Standard_True;
160             alldone = Standard_True;
161             return;
162           }
163           KeptT3d = RealLast(); KeptT2d = 0;
164           KeptUfirst = myfirstU;
165           KeptUlast = mylastU;
166         }
167         else
168         {
169           // keep best decison
170           if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
171           {
172             KeptMultiCurve = TheMultiCurve;
173             KeptUfirst = myfirstU;
174             KeptUlast = mylastU;
175             KeptT3d = thetol3d;
176             KeptT2d = thetol2d;
177             aNbImp++;
178           }
179
180           // cut an interval
181           mylastU = (myfirstU + mylastU) / 2;
182           aNbCut++;
183         }
184       }
185
186       // Calcul des parametres sur ce nouvel intervalle.
187       Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
188       if (Ok)
189       {
190         aMaxSegments++;
191       }
192
193       //cout << myfirstU << " - " << mylastU << "  tol : " << thetol3d << " " << thetol2d << endl;
194       Standard_Boolean aStopCutting = Standard_False;
195       if (myHangChecking && aNbCut >= aNbComp)
196       {
197         if (aNbCut > aNbImp + 1)
198         {
199           aStopCutting = Standard_True;
200         }
201         aNbCut = 0;
202         aNbImp = 0;
203       }
204       // is new decision better?
205       if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting ))
206       {
207         Ok = Standard_True; // stop interval cutting, approx the rest part
208
209         if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
210         {
211           KeptMultiCurve = TheMultiCurve;
212           KeptUfirst = myfirstU;
213           KeptUlast = mylastU;
214           KeptT3d = thetol3d;
215           KeptT2d = thetol2d;
216         }
217
218         mylastU = KeptUlast;
219
220         tolreached = Standard_False; // helas
221         myMultiCurves.Append(KeptMultiCurve);
222         aMaxSegments++;
223         Tolers3d.Append(KeptT3d);
224         Tolers2d.Append(KeptT2d);
225         myfirstparam.Append(KeptUfirst);
226         mylastparam.Append(KeptUlast);
227       }
228
229       begin = Standard_False;
230     } // while (!Finish)
231   }
232 }
233
234 //=======================================================================
235 //function : NbMultiCurves
236 //purpose  : Returns the number of MultiCurve doing the approximation
237 //           of the MultiLine.
238 //=======================================================================
239
240 Standard_Integer Approx_ComputeCLine::NbMultiCurves()const
241 {
242   return myMultiCurves.Length();
243 }
244
245 //=======================================================================
246 //function : Value
247 //purpose  : returns the approximation MultiCurve of range <Index>.
248 //=======================================================================
249
250 AppParCurves_MultiCurve Approx_ComputeCLine::Value(const Standard_Integer Index)
251 const
252 {
253   return myMultiCurves.Value(Index);
254 }
255
256 //=======================================================================
257 //function : Compute
258 //purpose  : is internally used by the algorithms.
259 //=======================================================================
260
261 Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
262   const Standard_Real Ufirst,
263   const Standard_Real Ulast,
264   Standard_Real&   TheTol3d,
265   Standard_Real&   TheTol2d)
266 {
267
268
269   const Standard_Integer NbPointsMax = 24;
270   const Standard_Real aMinRatio = 0.05;
271   const Standard_Integer aMaxDeg = 8;
272   //
273   Standard_Integer deg, NbPoints;
274   Standard_Boolean mydone;
275   Standard_Real Fv;
276
277   AppParCurves_MultiCurve aPrevCurve;
278   Standard_Real aPrevTol3d = RealLast(), aPrevTol2d = RealLast();
279   Standard_Boolean aPrevIsOk = Standard_False;
280   Standard_Boolean anInvOrder = myInvOrder;
281   if (anInvOrder && mydegremax > aMaxDeg)
282   {
283     if ((Ulast - Ufirst) / (Line.LastParameter() - Line.FirstParameter()) < aMinRatio)
284     {
285       anInvOrder = Standard_False;
286     }
287   }
288   if (anInvOrder)
289   {
290     for (deg = mydegremax; deg >= mydegremin; deg--) {
291       NbPoints = Min(2 * deg + 1, NbPointsMax);
292       AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
293       mydone = LSquare.IsDone();
294       if (mydone)
295       {
296         LSquare.Error(Fv, TheTol3d, TheTol2d);
297         if (TheTol3d <= mytol3d && TheTol2d <= mytol2d)
298         {
299           if (deg == mydegremin)
300           {
301             // Stockage de la multicurve approximee.
302             tolreached = Standard_True;
303             myMultiCurves.Append(LSquare.Value());
304             myfirstparam.Append(Ufirst);
305             mylastparam.Append(Ulast);
306             Tolers3d.Append(TheTol3d);
307             Tolers2d.Append(TheTol2d);
308             return Standard_True;
309           }
310           aPrevTol3d = TheTol3d;
311           aPrevTol2d = TheTol2d;
312           aPrevCurve = LSquare.Value();
313           aPrevIsOk = Standard_True;
314           continue;
315         }
316         else if (aPrevIsOk)
317         {
318           // Stockage de la multicurve approximee.
319           tolreached = Standard_True;
320           TheTol3d = aPrevTol3d;
321           TheTol2d = aPrevTol2d;
322           myMultiCurves.Append(aPrevCurve);
323           myfirstparam.Append(Ufirst);
324           mylastparam.Append(Ulast);
325           Tolers3d.Append(aPrevTol3d);
326           Tolers2d.Append(aPrevTol2d);
327           return Standard_True;
328         }
329       }
330       else if (aPrevIsOk)
331       {
332         // Stockage de la multicurve approximee.
333         tolreached = Standard_True;
334         TheTol3d = aPrevTol3d;
335         TheTol2d = aPrevTol2d;
336         myMultiCurves.Append(aPrevCurve);
337         myfirstparam.Append(Ufirst);
338         mylastparam.Append(Ulast);
339         Tolers3d.Append(aPrevTol3d);
340         Tolers2d.Append(aPrevTol2d);
341         return Standard_True;
342       }
343       if (!aPrevIsOk && deg == mydegremax)
344       {
345         TheMultiCurve = LSquare.Value();
346         currenttol3d = TheTol3d;
347         currenttol2d = TheTol2d;
348         aPrevTol3d = TheTol3d;
349         aPrevTol2d = TheTol2d;
350         aPrevCurve = TheMultiCurve;
351         break;
352       }
353     }
354   }
355   else
356   {
357     for (deg = mydegremin; deg <= mydegremax; deg++) {
358       NbPoints = Min(2 * deg + 1, NbPointsMax);
359       AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
360       mydone = LSquare.IsDone();
361       if (mydone) {
362         LSquare.Error(Fv, TheTol3d, TheTol2d);
363         if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
364           // Stockage de la multicurve approximee.
365           tolreached = Standard_True;
366           myMultiCurves.Append(LSquare.Value());
367           myfirstparam.Append(Ufirst);
368           mylastparam.Append(Ulast);
369           Tolers3d.Append(TheTol3d);
370           Tolers2d.Append(TheTol2d);
371           return Standard_True;
372         }
373       }
374       if (deg == mydegremax) {
375         TheMultiCurve = LSquare.Value();
376         currenttol3d = TheTol3d;
377         currenttol2d = TheTol2d;
378       }
379     }
380   }
381   return Standard_False;
382 }
383
384 //=======================================================================
385 //function : Parameters
386 //purpose  : returns the first and last parameters of the 
387 //           <Index> MultiCurve.
388 //=======================================================================
389
390 void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
391   Standard_Real& firstpar,
392   Standard_Real& lastpar) const
393 {
394   firstpar = myfirstparam.Value(Index);
395   lastpar = mylastparam.Value(Index);
396 }
397
398 //=======================================================================
399 //function : SetDegrees
400 //purpose  : changes the degrees of the approximation.
401 //=======================================================================
402
403 void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
404   const Standard_Integer degreemax)
405 {
406   mydegremin = degreemin;
407   mydegremax = degreemax;
408 }
409
410 //=======================================================================
411 //function : SetTolerances
412 //purpose  : Changes the tolerances of the approximation.
413 //=======================================================================
414
415 void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
416   const Standard_Real Tolerance2d)
417 {
418   mytol3d = Tolerance3d;
419   mytol2d = Tolerance2d;
420 }
421
422 //=======================================================================
423 //function : SetConstraints
424 //purpose  : Changes the constraints of the approximation.
425 //=======================================================================
426
427 void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
428   const AppParCurves_Constraint LastC)
429 {
430   myfirstC = FirstC;
431   mylastC = LastC;
432 }
433
434 //=======================================================================
435 //function : SetMaxSegments
436 //purpose  : Changes the max number of segments, which is allowed for cutting.
437 //=======================================================================
438
439 void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
440 {
441   myMaxSegments = theMaxSegments;
442 }
443
444 //=======================================================================
445 //function : SetInvOrder
446 //purpose  : 
447 //=======================================================================
448 void Approx_ComputeCLine::SetInvOrder(const Standard_Boolean theInvOrder)
449 {
450   myInvOrder = theInvOrder;
451 }
452
453 //=======================================================================
454 //function : SetHangChecking
455 //purpose  : 
456 //=======================================================================
457 void Approx_ComputeCLine::SetHangChecking(const Standard_Boolean theHangChecking)
458 {
459   myHangChecking = theHangChecking;
460 }
461
462 //=======================================================================
463 //function : IsAllApproximated
464 //purpose  : returns False if at a moment of the approximation,
465 //           the status NoApproximation has been sent by the user
466 //           when more points were needed.
467 //=======================================================================
468
469 Standard_Boolean Approx_ComputeCLine::IsAllApproximated()
470 const {
471   return alldone;
472 }
473
474 //=======================================================================
475 //function : IsToleranceReached
476 //purpose  : returns False if the status NoPointsAdded has been sent.
477 //=======================================================================
478
479 Standard_Boolean Approx_ComputeCLine::IsToleranceReached()
480 const {
481   return tolreached;
482 }
483
484 //=======================================================================
485 //function : Error
486 //purpose  : returns the tolerances 2d and 3d of the <Index> MultiCurve.
487 //=======================================================================
488
489 void Approx_ComputeCLine::Error(const Standard_Integer Index,
490   Standard_Real& tol3d,
491   Standard_Real& tol2d) const
492 {
493   tol3d = Tolers3d.Value(Index);
494   tol2d = Tolers2d.Value(Index);
495 }