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