0030657: Visualization - misprint in Graphic3d_ZLayerSettings::SetOrigin()
[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//
d5f74e42 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
973c2be1 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>
368cdde6 22#include <AppCont_LeastSquare.hxx>
7fd59977 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
afb3647b 37(const MultiLine& Line,
38const Standard_Integer degreemin,
39const Standard_Integer degreemax,
40const Standard_Real Tolerance3d,
41const Standard_Real Tolerance2d,
42const Standard_Boolean cutting,
43const AppParCurves_Constraint FirstC,
44const AppParCurves_Constraint LastC)
7fd59977 45{
46 mydegremin = degreemin;
47 mydegremax = degreemax;
48 mytol3d = Tolerance3d;
49 mytol2d = Tolerance2d;
50 mycut = cutting;
51 myfirstC = FirstC;
52 mylastC = LastC;
f998596a 53 myMaxSegments = IntegerLast();
7fd59977 54 alldone = Standard_False;
55 Perform(Line);
56}
57
58//=======================================================================
59//function : Approx_ComputeCLine
60//purpose : Initializes the fields of the algorithm.
61//=======================================================================
62
63Approx_ComputeCLine::Approx_ComputeCLine
afb3647b 64(const Standard_Integer degreemin,
65const Standard_Integer degreemax,
66const Standard_Real Tolerance3d,
67const Standard_Real Tolerance2d,
68const Standard_Boolean cutting,
69const AppParCurves_Constraint FirstC,
70const AppParCurves_Constraint LastC)
7fd59977 71{
72 alldone = Standard_False;
73 mydegremin = degreemin;
74 mydegremax = degreemax;
75 mytol3d = Tolerance3d;
76 mytol2d = Tolerance2d;
77 mycut = cutting;
78 myfirstC = FirstC;
79 mylastC = LastC;
f998596a 80 myMaxSegments = IntegerLast();
7fd59977 81}
82
83//=======================================================================
84//function : Perform
85//purpose : runs the algorithm after having initialized the fields.
86//=======================================================================
87
88void Approx_ComputeCLine::Perform(const MultiLine& Line)
89{
7fd59977 90 Standard_Real UFirst, ULast;
afb3647b 91 Standard_Boolean Finish = Standard_False,
92 begin = Standard_True, Ok = Standard_False;
1d47d8d0 93 Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
368cdde6 94 UFirst = Line.FirstParameter();
afb3647b 95 ULast = Line.LastParameter();
96 Standard_Real TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion());
97 Standard_Real myfirstU = UFirst;
7fd59977 98 Standard_Real mylastU = ULast;
f998596a 99 Standard_Integer aMaxSegments = 0;
100 Standard_Integer aMaxSegments1 = myMaxSegments - 1;
afb3647b 101 Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 5;
7fd59977 102
7da00517 103 if (!mycut)
104 {
7fd59977 105 alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
afb3647b 106 if (!alldone)
7da00517 107 {
7fd59977 108 tolreached = Standard_False;
109 myfirstparam.Append(UFirst);
110 mylastparam.Append(ULast);
111 myMultiCurves.Append(TheMultiCurve);
112 Tolers3d.Append(currenttol3d);
113 Tolers2d.Append(currenttol2d);
114 }
115 }
afb3647b 116 else
7da00517 117 {
7fd59977 118
119 // previous decision to be taken if we get worse with next cut (eap)
120 AppParCurves_MultiCurve KeptMultiCurve;
1d47d8d0 121 Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
1d47d8d0 122
afb3647b 123 while (!Finish)
7da00517 124 {
afb3647b 125
7fd59977 126 // Gestion du decoupage de la multiline pour approximer:
afb3647b 127 if (!begin)
7da00517 128 {
afb3647b 129 if (Ok)
7da00517 130 {
131 // Calcul de la partie a approximer.
132 myfirstU = mylastU;
afb3647b 133 mylastU = ULast;
134 aNbCut = 0;
135 aNbImp = 0;
136 if (Abs(ULast - myfirstU) <= RealEpsilon()
f998596a 137 || aMaxSegments >= myMaxSegments)
7da00517 138 {
139 Finish = Standard_True;
140 alldone = Standard_True;
141 return;
142 }
143 KeptT3d = RealLast(); KeptT2d = 0;
144 KeptUfirst = myfirstU;
145 KeptUlast = mylastU;
146 }
147 else
148 {
149 // keep best decison
150 if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
151 {
152 KeptMultiCurve = TheMultiCurve;
afb3647b 153 KeptUfirst = myfirstU;
154 KeptUlast = mylastU;
155 KeptT3d = thetol3d;
156 KeptT2d = thetol2d;
157 aNbImp++;
7da00517 158 }
159
160 // cut an interval
afb3647b 161 mylastU = (myfirstU + mylastU) / 2;
162 aNbCut++;
7da00517 163 }
7fd59977 164 }
165
7fd59977 166 // Calcul des parametres sur ce nouvel intervalle.
167 Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
afb3647b 168 if (Ok)
f998596a 169 {
170 aMaxSegments++;
171 }
7fd59977 172
173 //cout << myfirstU << " - " << mylastU << " tol : " << thetol3d << " " << thetol2d << endl;
afb3647b 174 Standard_Boolean aStopCutting = Standard_False;
175 if (aNbCut >= aNbComp)
176 {
177 if (aNbCut > aNbImp)
178 {
179 aStopCutting = Standard_True;
180 }
181 }
7fd59977 182 // is new decision better?
afb3647b 183 if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting ))
7fd59977 184 {
afb3647b 185 Ok = Standard_True; // stop interval cutting, approx the rest part
3629864d 186
afb3647b 187 if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
188 {
189 KeptMultiCurve = TheMultiCurve;
190 KeptUfirst = myfirstU;
191 KeptUlast = mylastU;
192 KeptT3d = thetol3d;
193 KeptT2d = thetol2d;
194 }
3629864d 195
afb3647b 196 mylastU = KeptUlast;
7da00517 197
afb3647b 198 tolreached = Standard_False; // helas
199 myMultiCurves.Append(KeptMultiCurve);
200 aMaxSegments++;
201 Tolers3d.Append(KeptT3d);
202 Tolers2d.Append(KeptT2d);
203 myfirstparam.Append(KeptUfirst);
204 mylastparam.Append(KeptUlast);
205 }
7fd59977 206
207 begin = Standard_False;
208 } // while (!Finish)
209 }
210}
211
212//=======================================================================
213//function : NbMultiCurves
214//purpose : Returns the number of MultiCurve doing the approximation
215// of the MultiLine.
216//=======================================================================
217
218Standard_Integer Approx_ComputeCLine::NbMultiCurves()const
219{
220 return myMultiCurves.Length();
221}
222
223//=======================================================================
224//function : Value
225//purpose : returns the approximation MultiCurve of range <Index>.
226//=======================================================================
227
228AppParCurves_MultiCurve Approx_ComputeCLine::Value(const Standard_Integer Index)
229const
230{
231 return myMultiCurves.Value(Index);
232}
233
234//=======================================================================
235//function : Compute
236//purpose : is internally used by the algorithms.
237//=======================================================================
238
239Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
afb3647b 240 const Standard_Real Ufirst,
241 const Standard_Real Ulast,
242 Standard_Real& TheTol3d,
243 Standard_Real& TheTol2d)
7fd59977 244{
245
246
247 Standard_Integer deg, NbPoints = 24;
248 Standard_Boolean mydone;
249 Standard_Real Fv;
250
251 for (deg = mydegremin; deg <= mydegremax; deg++) {
252
368cdde6 253 AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
7fd59977 254 mydone = LSquare.IsDone();
255 if (mydone) {
256 LSquare.Error(Fv, TheTol3d, TheTol2d);
257 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
afb3647b 258 // Stockage de la multicurve approximee.
259 tolreached = Standard_True;
3065019c 260 myMultiCurves.Append(LSquare.Value());
afb3647b 261 myfirstparam.Append(Ufirst);
262 mylastparam.Append(Ulast);
263 Tolers3d.Append(TheTol3d);
264 Tolers2d.Append(TheTol2d);
265 return Standard_True;
7fd59977 266 }
267 }
268 if (deg == mydegremax) {
269 TheMultiCurve = LSquare.Value();
270 currenttol3d = TheTol3d;
271 currenttol2d = TheTol2d;
272 }
afb3647b 273
7fd59977 274 }
275 return Standard_False;
276}
277
278//=======================================================================
279//function : Parameters
280//purpose : returns the first and last parameters of the
281// <Index> MultiCurve.
282//=======================================================================
283
284void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
afb3647b 285 Standard_Real& firstpar,
286 Standard_Real& lastpar) const
7fd59977 287{
288 firstpar = myfirstparam.Value(Index);
afb3647b 289 lastpar = mylastparam.Value(Index);
7fd59977 290}
291
292//=======================================================================
293//function : SetDegrees
294//purpose : changes the degrees of the approximation.
295//=======================================================================
296
297void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
afb3647b 298 const Standard_Integer degreemax)
7fd59977 299{
300 mydegremin = degreemin;
301 mydegremax = degreemax;
302}
303
304//=======================================================================
305//function : SetTolerances
306//purpose : Changes the tolerances of the approximation.
307//=======================================================================
308
309void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
afb3647b 310 const Standard_Real Tolerance2d)
7fd59977 311{
312 mytol3d = Tolerance3d;
313 mytol2d = Tolerance2d;
314}
315
316//=======================================================================
317//function : SetConstraints
318//purpose : Changes the constraints of the approximation.
319//=======================================================================
320
321void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
afb3647b 322 const AppParCurves_Constraint LastC)
7fd59977 323{
324 myfirstC = FirstC;
afb3647b 325 mylastC = LastC;
7fd59977 326}
327
328//=======================================================================
f998596a 329//function : SetMaxSegments
330//purpose : Changes the max number of segments, which is allowed for cutting.
331//=======================================================================
332
afb3647b 333void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
f998596a 334{
335 myMaxSegments = theMaxSegments;
336}
337
338//=======================================================================
7fd59977 339//function : IsAllApproximated
340//purpose : returns False if at a moment of the approximation,
341// the status NoApproximation has been sent by the user
342// when more points were needed.
343//=======================================================================
344
345Standard_Boolean Approx_ComputeCLine::IsAllApproximated()
346const {
347 return alldone;
348}
349
350//=======================================================================
351//function : IsToleranceReached
352//purpose : returns False if the status NoPointsAdded has been sent.
353//=======================================================================
354
355Standard_Boolean Approx_ComputeCLine::IsToleranceReached()
356const {
357 return tolreached;
358}
359
360//=======================================================================
361//function : Error
362//purpose : returns the tolerances 2d and 3d of the <Index> MultiCurve.
363//=======================================================================
364
365void Approx_ComputeCLine::Error(const Standard_Integer Index,
afb3647b 366 Standard_Real& tol3d,
367 Standard_Real& tol2d) const
7fd59977 368{
369 tol3d = Tolers3d.Value(Index);
370 tol2d = Tolers2d.Value(Index);
371}