7fd59977 |
1 | // File: Extrema_GLocateExtPC.gxx |
2 | // Created: Tue Dec 14 16:38:29 1993 |
3 | // Author: Christophe MARION |
4 | // <cma@zerox> |
5 | // 05-Jun-00 : hla : meme type de corr. que xab : dans la methode "Perform", |
6 | // suppression du test mal a propos "myintuinf > myintusup" avec |
7 | // "return" a la suite. |
8 | // 05-Sep-95 : xab : correction d'un probleme de determination d'intervalle |
9 | // de recherche |
10 | |
11 | #include Extrema_ELPC_hxx |
12 | #include ThePOnC_hxx |
13 | #include ThePoint_hxx |
14 | #include TheVector_hxx |
15 | #include <StdFail_NotDone.hxx> |
16 | #include <Standard_DomainError.hxx> |
17 | #include <GeomAbs_CurveType.hxx> |
18 | #include <Precision.hxx> |
19 | #include <TColStd_Array1OfReal.hxx> |
20 | |
21 | |
22 | //======================================================================= |
23 | //function : Extrema_GLocateExtPC |
24 | //purpose : |
25 | //======================================================================= |
26 | |
27 | Extrema_GLocateExtPC::Extrema_GLocateExtPC() { } |
28 | |
29 | |
30 | //======================================================================= |
31 | //function : Extrema_GLocateExtPC |
32 | //purpose : |
33 | //======================================================================= |
34 | |
35 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
36 | const TheCurve& C, |
37 | const Standard_Real U0, |
38 | const Standard_Real TolF) |
39 | { |
40 | Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF); |
41 | Perform(P, U0); |
42 | } |
43 | |
44 | //======================================================================= |
45 | //function : Extrema_GLocateExtPC |
46 | //purpose : |
47 | //======================================================================= |
48 | |
49 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
50 | const TheCurve& C, |
51 | const Standard_Real U0, |
52 | const Standard_Real Umin, |
53 | const Standard_Real Usup, |
54 | const Standard_Real TolF) |
55 | { |
56 | Initialize(C, Umin, Usup, TolF); |
57 | Perform(P, U0); |
58 | } |
59 | |
60 | |
61 | |
62 | //======================================================================= |
63 | //function : Initialize |
64 | //purpose : |
65 | //======================================================================= |
66 | |
67 | void Extrema_GLocateExtPC::Initialize(const TheCurve& C, |
68 | const Standard_Real Umin, |
69 | const Standard_Real Usup, |
70 | const Standard_Real TolF) |
71 | { |
72 | myC = (Standard_Address)&C; |
73 | mytol = TolF; |
74 | myumin = Umin; |
75 | myusup = Usup; |
76 | type = TheCurveTool::GetType(C); |
77 | Standard_Real tolu = TheCurveTool::Resolution(C, Precision::Confusion()); |
78 | if ((type == GeomAbs_BSplineCurve) || |
79 | (type == GeomAbs_BezierCurve) || |
80 | (type == GeomAbs_OtherCurve)) { |
81 | myLocExtPC.Initialize(C, Umin, Usup, tolu); |
82 | } |
83 | else { |
84 | myExtremPC.Initialize(C, Umin, Usup, tolu); |
85 | } |
86 | } |
87 | |
88 | |
89 | |
90 | |
91 | //======================================================================= |
92 | //function : Perform |
93 | //purpose : |
94 | //======================================================================= |
95 | |
96 | void Extrema_GLocateExtPC::Perform(const ThePoint& P, |
97 | const Standard_Real U0) |
98 | { |
99 | Standard_Integer i, i1, i2, inter; |
100 | #ifdef DEB |
101 | Standard_Real Tol = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion()); |
102 | #else |
103 | TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion()); |
104 | #endif |
105 | Standard_Real Par, valU, valU2 = RealLast(), |
106 | local_u0 ; |
107 | Standard_Real myintuinf=0, myintusup=0; |
108 | local_u0 = U0 ; |
109 | switch(type) { |
110 | case GeomAbs_OtherCurve: |
111 | case GeomAbs_BSplineCurve: { |
112 | // La recherche de l extremum est faite intervalle continu C2 par |
113 | // intervalle continu C2 de la courbe |
114 | Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2); |
115 | TColStd_Array1OfReal theInter(1, n+1); |
116 | TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2); |
117 | // |
118 | // be gentle with the caller |
119 | // |
120 | if (local_u0 < myumin) { |
121 | local_u0 = myumin ; |
122 | } |
123 | else if (local_u0 > myusup) { |
124 | local_u0 = myusup ; |
125 | } |
126 | // Recherche de l intervalle ou se trouve U0 |
127 | Standard_Boolean found = Standard_False; |
128 | inter = 1; |
129 | while (!found && inter <= n) { |
130 | // Intervalle commun a l intervalle C2 courant de la courbe et a |
131 | // l intervalle total de recherche de l'extremum (hla : au cas ou |
132 | // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent |
133 | // pas, mais il n'y avait aucune raison de sortir en "return") |
134 | myintuinf = Max(theInter(inter), myumin); |
135 | myintusup = Min(theInter(inter+1), myusup); |
136 | if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True; |
137 | inter++; |
138 | } |
139 | |
140 | if( found ) inter--; //IFV 16.06.00 - inter is increased after found! |
141 | |
142 | // Essai sur l intervalle trouve |
143 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
144 | myintusup, mytol); |
145 | myLocExtPC.Perform(P, local_u0); |
146 | myDone = myLocExtPC.IsDone(); |
147 | if (myDone) { |
148 | mypp = myLocExtPC.Point(); |
149 | myismin = myLocExtPC.IsMin(); |
150 | mydist2 = myLocExtPC.SquareDistance(); |
151 | } |
152 | else { |
153 | Standard_Integer k = 1; |
154 | // Essai sur les intervalles alentours: |
155 | i1 = inter; |
156 | i2 = inter; |
157 | Standard_Real s1inf, s2inf, s1sup, s2sup; |
158 | ThePoint P1; |
159 | TheVector V1; |
160 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
161 | s2inf = (TheVector(P, P1)*V1); |
162 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
163 | s1sup = (TheVector(P, P1)*V1); |
164 | |
165 | |
166 | while (!myDone && (i2 > 0) && (i1 <= n)) { |
167 | i1 = inter + k; |
168 | i2 = inter - k; |
169 | if (i1 <= n) { |
170 | myintuinf = Max(theInter(i1), myumin); |
171 | myintusup = Min(theInter(i1+1), myusup); |
172 | if (myintuinf < myintusup) { |
173 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
174 | s2sup = (TheVector(P, P1)*V1); |
175 | if (s1sup*s2sup <= RealEpsilon()) { |
176 | // extremum: |
177 | myDone = Standard_True; |
178 | mypp.SetValues(myintuinf, P1); |
179 | myismin = (s1sup <= 0.0); |
180 | mydist2 = P.SquareDistance(P1); |
181 | break; |
182 | } |
183 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
184 | s1sup = (TheVector(P, P1)*V1); |
185 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
186 | myintusup, mytol); |
187 | myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5); |
188 | myDone = myLocExtPC.IsDone(); |
189 | if (myDone) { |
190 | mypp = myLocExtPC.Point(); |
191 | myismin = myLocExtPC.IsMin(); |
192 | mydist2 = myLocExtPC.SquareDistance(); |
193 | break; |
194 | } |
195 | } |
196 | } |
197 | if (i2 > 0) { |
198 | myintuinf = Max(theInter(i2), myumin); |
199 | myintusup = Min(theInter(i2+1), myusup); |
200 | if (myintuinf < myintusup) { |
201 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
202 | s1inf = (TheVector(P, P1)*V1); |
203 | if (s1inf*s2inf <= RealEpsilon()) { |
204 | // extremum: |
205 | myDone = Standard_True; |
206 | mypp.SetValues(myintusup, P1); |
207 | myismin = (s1inf <= 0.0); |
208 | mydist2 = P.SquareDistance(P1); |
209 | break; |
210 | } |
211 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
212 | s2inf = (TheVector(P, P1)*V1); |
213 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
214 | myintusup, mytol); |
215 | myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 ); |
216 | myDone = myLocExtPC.IsDone(); |
217 | if (myDone) { |
218 | mypp = myLocExtPC.Point(); |
219 | myismin = myLocExtPC.IsMin(); |
220 | mydist2 = myLocExtPC.SquareDistance(); |
221 | break; |
222 | } |
223 | } |
224 | } |
225 | k++; |
226 | } |
227 | } |
228 | } |
229 | break; |
230 | case GeomAbs_BezierCurve: { |
231 | myLocExtPC.Perform(P, U0); |
232 | myDone = myLocExtPC.IsDone(); |
233 | } |
234 | break; |
235 | default:{ |
236 | myExtremPC.Perform(P); |
237 | numberext = 0; |
238 | if (myExtremPC.IsDone()) { |
239 | for (i = 1; i <= myExtremPC.NbExt(); i++) { |
240 | Par = myExtremPC.Point(i).Parameter(); |
241 | valU = Abs(Par - U0); |
242 | if (valU <= valU2) { |
243 | valU2 = valU; |
244 | numberext = i; |
245 | myDone = Standard_True; |
246 | } |
247 | } |
248 | } |
249 | if (numberext == 0) myDone = Standard_False; |
250 | break; |
251 | } |
252 | } |
253 | } |
254 | |
255 | |
256 | |
257 | |
258 | //======================================================================= |
259 | //function : IsDone |
260 | //purpose : |
261 | //======================================================================= |
262 | |
263 | Standard_Boolean Extrema_GLocateExtPC::IsDone () const |
264 | { |
265 | return myDone; |
266 | } |
267 | |
268 | |
269 | //======================================================================= |
270 | //function : Value |
271 | //purpose : |
272 | //======================================================================= |
273 | |
274 | Standard_Real Extrema_GLocateExtPC::SquareDistance () const |
275 | { |
276 | if (!myDone) { StdFail_NotDone::Raise(); } |
277 | Standard_Real d=0; |
278 | if ((type == GeomAbs_BezierCurve)) { |
279 | d = myLocExtPC.SquareDistance(); |
280 | } |
281 | else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) { |
282 | d = mydist2; |
283 | } |
284 | else { |
285 | if (numberext != 0) { |
286 | d = myExtremPC.SquareDistance(numberext); |
287 | } |
288 | } |
289 | return d; |
290 | } |
291 | |
292 | |
293 | //======================================================================= |
294 | //function : IsMin |
295 | //purpose : |
296 | //======================================================================= |
297 | |
298 | Standard_Boolean Extrema_GLocateExtPC::IsMin () const |
299 | { |
300 | if (!myDone) { StdFail_NotDone::Raise(); } |
301 | Standard_Boolean b=0; |
302 | if ((type == GeomAbs_BezierCurve)) { |
303 | b = myLocExtPC.IsMin(); |
304 | } |
305 | else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) { |
306 | b = myismin; |
307 | } |
308 | else { |
309 | if (numberext != 0) { |
310 | b = myExtremPC.IsMin(numberext); |
311 | } |
312 | } |
313 | return b; |
314 | } |
315 | |
316 | |
317 | //======================================================================= |
318 | //function : Point |
319 | //purpose : |
320 | //======================================================================= |
321 | |
322 | ThePOnC Extrema_GLocateExtPC::Point () const |
323 | { |
324 | if (!myDone) { StdFail_NotDone::Raise(); } |
325 | ThePOnC P; |
326 | if (type == GeomAbs_BezierCurve) { |
327 | P = myLocExtPC.Point(); |
328 | } |
329 | else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) { |
330 | P = mypp; |
331 | } |
332 | else { |
333 | if (numberext != 0) { |
334 | P = myExtremPC.Point(numberext); |
335 | } |
336 | } |
337 | return P; |
338 | } |