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