0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / Approx / Approx_ComputeCLine.gxx
CommitLineData
b311480e 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
7fd59977 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>
1d47d8d0 31#include <Precision.hxx>
7fd59977 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
41Approx_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
67Approx_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
91void Approx_ComputeCLine::Perform(const MultiLine& Line)
92{
7fd59977 93 Standard_Real UFirst, ULast;
94 Standard_Boolean Finish = Standard_False,
95 begin = Standard_True, Ok = Standard_False;
1d47d8d0 96 Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
7fd59977 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;
1d47d8d0 118 Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
7fd59977 119 Standard_Integer NbWorseDecis = 0, NbAllowedBadDecis = 10;
1d47d8d0 120
7fd59977 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
190Standard_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
200AppParCurves_MultiCurve Approx_ComputeCLine::Value(const Standard_Integer Index)
201const
202{
203 return myMultiCurves.Value(Index);
204}
205
206//=======================================================================
207//function : Compute
208//purpose : is internally used by the algorithms.
209//=======================================================================
210
211Standard_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
259void 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
272void 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
284void 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
296void 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
310Standard_Boolean Approx_ComputeCLine::IsAllApproximated()
311const {
312 return alldone;
313}
314
315//=======================================================================
316//function : IsToleranceReached
317//purpose : returns False if the status NoPointsAdded has been sent.
318//=======================================================================
319
320Standard_Boolean Approx_ComputeCLine::IsToleranceReached()
321const {
322 return tolreached;
323}
324
325//=======================================================================
326//function : Error
327//purpose : returns the tolerances 2d and 3d of the <Index> MultiCurve.
328//=======================================================================
329
330void 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}