0024059: Eliminate compiler warning C4701 in MSVC++ with warning level 4
[occt.git] / src / Approx / Approx_ComputeCLine.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 //  modified by Edward AGAPOV (eap) Tue Apr 2 2002 (occ265)
21 //  -- stop cutting an interval to approximate if next decisions
22 //  -- get worse on and on
23
24
25
26 #include <Approx_ParametrizationType.hxx>
27 #include Approx_MyLeastSquare_hxx
28 #include <TColStd_Array1OfReal.hxx>
29 #include <AppParCurves_Constraint.hxx>
30 #include <Approx_Status.hxx>
31 #include <Precision.hxx>
32
33 //=======================================================================
34 //function : Approx_ComputeCLine
35 //purpose  : The MultiLine <Line> will be approximated until tolerances
36 //           will be reached.
37 //           The approximation will be done from degreemin to degreemax
38 //           with a cutting if the corresponding boolean is True.
39 //=======================================================================
40
41 Approx_ComputeCLine::Approx_ComputeCLine
42                     (const MultiLine& Line,
43                      const Standard_Integer degreemin,
44                      const Standard_Integer degreemax,
45                      const Standard_Real Tolerance3d,
46                      const Standard_Real Tolerance2d,
47                      const Standard_Boolean cutting,
48                      const AppParCurves_Constraint FirstC,
49                      const AppParCurves_Constraint LastC)
50 {
51   mydegremin = degreemin;
52   mydegremax = degreemax;
53   mytol3d = Tolerance3d;
54   mytol2d = Tolerance2d;
55   mycut = cutting;
56   myfirstC = FirstC;
57   mylastC = LastC;
58   alldone = Standard_False;
59   Perform(Line);
60 }
61
62 //=======================================================================
63 //function : Approx_ComputeCLine
64 //purpose  : Initializes the fields of the algorithm.
65 //=======================================================================
66
67 Approx_ComputeCLine::Approx_ComputeCLine
68                     (const Standard_Integer degreemin,
69                      const Standard_Integer degreemax,
70                      const Standard_Real Tolerance3d,
71                      const Standard_Real Tolerance2d,
72                      const Standard_Boolean cutting,
73                      const AppParCurves_Constraint FirstC,
74                      const AppParCurves_Constraint LastC)
75 {
76   alldone = Standard_False;
77   mydegremin = degreemin;
78   mydegremax = degreemax;
79   mytol3d = Tolerance3d;
80   mytol2d = Tolerance2d;
81   mycut = cutting;
82   myfirstC = FirstC;
83   mylastC = LastC;
84 }
85
86 //=======================================================================
87 //function : Perform
88 //purpose  : runs the algorithm after having initialized the fields.
89 //=======================================================================
90
91 void Approx_ComputeCLine::Perform(const MultiLine& Line)
92 {
93   Standard_Real UFirst, ULast;
94   Standard_Boolean Finish = Standard_False, 
95           begin = Standard_True, Ok = Standard_False;
96   Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
97   UFirst = LineTool::FirstParameter(Line);
98   ULast  = LineTool::LastParameter(Line);
99   Standard_Real TolU = (ULast-UFirst)*1.e-05;
100   Standard_Real myfirstU = UFirst; 
101   Standard_Real mylastU = ULast;
102
103   if (!mycut) {
104     alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
105     if (!alldone) {
106       tolreached = Standard_False;
107       myfirstparam.Append(UFirst);
108       mylastparam.Append(ULast);
109       myMultiCurves.Append(TheMultiCurve);
110       Tolers3d.Append(currenttol3d);
111       Tolers2d.Append(currenttol2d);
112     }
113   }
114   else {
115
116     // previous decision to be taken if we get worse with next cut (eap)
117     AppParCurves_MultiCurve KeptMultiCurve;
118     Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
119     Standard_Integer NbWorseDecis = 0, NbAllowedBadDecis = 10;
120
121     while (!Finish) {
122       
123       // Gestion du decoupage de la multiline pour approximer:
124       if (!begin) {
125         if (Ok) {
126           // Calcul de la partie a approximer.
127           myfirstU = mylastU;
128           mylastU  = ULast;
129           if (Abs(ULast-myfirstU) <= RealEpsilon()) {
130             Finish = Standard_True;
131             alldone = Standard_True;
132             return;
133           }
134           KeptT3d = RealLast(); KeptT2d = 0; 
135           NbWorseDecis = 0;
136         }
137         else {
138           // keep best decison
139           if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d)) {
140             KeptMultiCurve = TheMultiCurve;
141             KeptUfirst     = myfirstU;
142             KeptUlast      = mylastU;
143             KeptT3d        = thetol3d;
144             KeptT2d        = thetol2d;
145           }
146           
147           // cut an interval
148           mylastU = (myfirstU + mylastU)/2;
149         }
150       }
151
152       if (Abs(myfirstU-mylastU) <= TolU) /*break;*/ // pour ne pas planter
153         NbAllowedBadDecis /= 2;                     // la station.
154       
155       // Calcul des parametres sur ce nouvel intervalle.
156       Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
157
158       //cout << myfirstU << " - " << mylastU << "  tol : " << thetol3d << " " << thetol2d << endl;
159
160       // is new decision better?
161       if ( !Ok && (thetol3d + thetol2d) > (KeptT3d + KeptT2d) )
162       {
163         NbWorseDecis++;
164
165         if (NbWorseDecis > NbAllowedBadDecis) {
166           
167           Ok = Standard_True; // stop interval cutting, approx the rest part
168           mylastU = KeptUlast;
169           
170           tolreached = Standard_False; // helas
171           myMultiCurves.Append(KeptMultiCurve);
172           Tolers3d.Append     (KeptT3d);
173           Tolers2d.Append     (KeptT2d);
174           myfirstparam.Append (KeptUfirst);
175           mylastparam.Append  (KeptUlast);
176         }
177       }
178
179       begin = Standard_False;
180     } // while (!Finish)
181   }
182 }
183
184 //=======================================================================
185 //function : NbMultiCurves
186 //purpose  : Returns the number of MultiCurve doing the approximation
187 //           of the MultiLine.
188 //=======================================================================
189
190 Standard_Integer Approx_ComputeCLine::NbMultiCurves()const
191 {
192   return myMultiCurves.Length();
193 }
194
195 //=======================================================================
196 //function : Value
197 //purpose  : returns the approximation MultiCurve of range <Index>.
198 //=======================================================================
199
200 AppParCurves_MultiCurve Approx_ComputeCLine::Value(const Standard_Integer Index)
201 const
202 {
203   return myMultiCurves.Value(Index);
204 }
205
206 //=======================================================================
207 //function : Compute
208 //purpose  : is internally used by the algorithms.
209 //=======================================================================
210
211 Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
212                                              const Standard_Real Ufirst,
213                                              const Standard_Real Ulast,
214                                              Standard_Real&   TheTol3d,
215                                              Standard_Real&   TheTol2d)
216 {
217
218
219   Standard_Integer deg, NbPoints = 24;
220   Standard_Boolean mydone;
221   Standard_Real Fv;
222
223   for (deg = mydegremin; deg <= mydegremax; deg++) {
224
225     AppParCurves_MultiCurve mySCU(deg+1);
226     Approx_MyLeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, 
227                                  deg, NbPoints);
228     mydone = LSquare.IsDone();
229     if (mydone) {
230       LSquare.Error(Fv, TheTol3d, TheTol2d);
231       if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
232         mySCU = LSquare.Value();
233         // Stockage de la multicurve approximee.
234         tolreached = Standard_True;
235         myMultiCurves.Append(mySCU);
236         myfirstparam.Append(Ufirst);
237         mylastparam.Append(Ulast);
238         Tolers3d.Append(TheTol3d);
239         Tolers2d.Append(TheTol2d);
240         return Standard_True;
241       }
242     }
243     if (deg == mydegremax) {
244       TheMultiCurve = LSquare.Value();
245       currenttol3d = TheTol3d;
246       currenttol2d = TheTol2d;
247     }
248     
249   }
250   return Standard_False;
251 }
252
253 //=======================================================================
254 //function : Parameters
255 //purpose  : returns the first and last parameters of the 
256 //           <Index> MultiCurve.
257 //=======================================================================
258
259 void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
260                                      Standard_Real& firstpar,
261                                      Standard_Real& lastpar) const
262 {
263   firstpar = myfirstparam.Value(Index);
264   lastpar  = mylastparam.Value(Index);
265 }
266
267 //=======================================================================
268 //function : SetDegrees
269 //purpose  : changes the degrees of the approximation.
270 //=======================================================================
271
272 void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
273                                      const Standard_Integer degreemax)
274 {
275   mydegremin = degreemin;
276   mydegremax = degreemax;
277 }
278
279 //=======================================================================
280 //function : SetTolerances
281 //purpose  : Changes the tolerances of the approximation.
282 //=======================================================================
283
284 void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
285                                        const Standard_Real Tolerance2d)
286 {
287   mytol3d = Tolerance3d;
288   mytol2d = Tolerance2d;
289 }
290
291 //=======================================================================
292 //function : SetConstraints
293 //purpose  : Changes the constraints of the approximation.
294 //=======================================================================
295
296 void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
297                                          const AppParCurves_Constraint LastC)
298 {
299   myfirstC = FirstC;
300   mylastC  = LastC;
301 }
302
303 //=======================================================================
304 //function : IsAllApproximated
305 //purpose  : returns False if at a moment of the approximation,
306 //           the status NoApproximation has been sent by the user
307 //           when more points were needed.
308 //=======================================================================
309
310 Standard_Boolean Approx_ComputeCLine::IsAllApproximated()
311 const {
312   return alldone;
313 }
314
315 //=======================================================================
316 //function : IsToleranceReached
317 //purpose  : returns False if the status NoPointsAdded has been sent.
318 //=======================================================================
319
320 Standard_Boolean Approx_ComputeCLine::IsToleranceReached()
321 const {
322   return tolreached;
323 }
324
325 //=======================================================================
326 //function : Error
327 //purpose  : returns the tolerances 2d and 3d of the <Index> MultiCurve.
328 //=======================================================================
329
330 void Approx_ComputeCLine::Error(const Standard_Integer Index,
331                                Standard_Real& tol3d,
332                                Standard_Real& tol2d) const
333 {
334   tol3d = Tolers3d.Value(Index);
335   tol2d = Tolers2d.Value(Index);
336 }