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