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