b311480e |
1 | // Created on: 1993-12-14 |
2 | // Created by: Christophe MARION |
3 | // Copyright (c) 1993-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
b311480e |
16 | |
7fd59977 |
17 | // 05-Jun-00 : hla : meme type de corr. que xab : dans la methode "Perform", |
18 | // suppression du test mal a propos "myintuinf > myintusup" avec |
19 | // "return" a la suite. |
20 | // 05-Sep-95 : xab : correction d'un probleme de determination d'intervalle |
21 | // de recherche |
22 | |
23 | #include Extrema_ELPC_hxx |
24 | #include ThePOnC_hxx |
25 | #include ThePoint_hxx |
26 | #include TheVector_hxx |
27 | #include <StdFail_NotDone.hxx> |
28 | #include <Standard_DomainError.hxx> |
29 | #include <GeomAbs_CurveType.hxx> |
30 | #include <Precision.hxx> |
31 | #include <TColStd_Array1OfReal.hxx> |
32 | |
33 | |
34 | //======================================================================= |
35 | //function : Extrema_GLocateExtPC |
36 | //purpose : |
37 | //======================================================================= |
38 | |
d533dafb |
39 | Extrema_GLocateExtPC::Extrema_GLocateExtPC() |
40 | : myC(NULL), |
41 | mydist2(0.0), |
42 | myismin(Standard_False), |
43 | myDone(Standard_False), |
44 | myumin(0.0), |
45 | myusup(0.0), |
46 | mytol(0.0), |
47 | type(GeomAbs_OtherCurve), |
48 | numberext(0) |
49 | { |
50 | } |
7fd59977 |
51 | |
52 | |
53 | //======================================================================= |
54 | //function : Extrema_GLocateExtPC |
55 | //purpose : |
56 | //======================================================================= |
57 | |
58 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
a86d3ec0 |
59 | const TheCurve& C, |
60 | const Standard_Real U0, |
61 | const Standard_Real TolF) |
7fd59977 |
62 | { |
63 | Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF); |
64 | Perform(P, U0); |
65 | } |
66 | |
67 | //======================================================================= |
68 | //function : Extrema_GLocateExtPC |
69 | //purpose : |
70 | //======================================================================= |
71 | |
72 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
a86d3ec0 |
73 | const TheCurve& C, |
74 | const Standard_Real U0, |
75 | const Standard_Real Umin, |
76 | const Standard_Real Usup, |
77 | const Standard_Real TolF) |
7fd59977 |
78 | { |
79 | Initialize(C, Umin, Usup, TolF); |
80 | Perform(P, U0); |
81 | } |
82 | |
83 | |
84 | |
85 | //======================================================================= |
86 | //function : Initialize |
87 | //purpose : |
88 | //======================================================================= |
89 | |
90 | void Extrema_GLocateExtPC::Initialize(const TheCurve& C, |
a86d3ec0 |
91 | const Standard_Real Umin, |
92 | const Standard_Real Usup, |
93 | const Standard_Real TolF) |
7fd59977 |
94 | { |
95 | myC = (Standard_Address)&C; |
96 | mytol = TolF; |
97 | myumin = Umin; |
98 | myusup = Usup; |
99 | type = TheCurveTool::GetType(C); |
100 | Standard_Real tolu = TheCurveTool::Resolution(C, Precision::Confusion()); |
101 | if ((type == GeomAbs_BSplineCurve) || |
1aec3320 |
102 | (type == GeomAbs_BezierCurve) || |
103 | (type == GeomAbs_OffsetCurve) || |
104 | (type == GeomAbs_OtherCurve)) |
105 | { |
a86d3ec0 |
106 | myLocExtPC.Initialize(C, Umin, Usup, tolu); |
7fd59977 |
107 | } |
108 | else { |
109 | myExtremPC.Initialize(C, Umin, Usup, tolu); |
110 | } |
111 | } |
112 | |
113 | |
114 | |
115 | |
116 | //======================================================================= |
117 | //function : Perform |
118 | //purpose : |
119 | //======================================================================= |
120 | |
121 | void Extrema_GLocateExtPC::Perform(const ThePoint& P, |
a86d3ec0 |
122 | const Standard_Real U0) |
7fd59977 |
123 | { |
124 | Standard_Integer i, i1, i2, inter; |
7fd59977 |
125 | Standard_Real Par, valU, valU2 = RealLast(), |
a86d3ec0 |
126 | local_u0 ; |
7fd59977 |
127 | Standard_Real myintuinf=0, myintusup=0; |
128 | local_u0 = U0 ; |
a86d3ec0 |
129 | switch(type) |
130 | { |
131 | case GeomAbs_OtherCurve: |
1aec3320 |
132 | case GeomAbs_OffsetCurve: |
a86d3ec0 |
133 | case GeomAbs_BSplineCurve: |
134 | { |
7fd59977 |
135 | // La recherche de l extremum est faite intervalle continu C2 par |
136 | // intervalle continu C2 de la courbe |
137 | Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2); |
138 | TColStd_Array1OfReal theInter(1, n+1); |
139 | TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2); |
a86d3ec0 |
140 | // |
141 | // be gentle with the caller |
142 | // |
7fd59977 |
143 | if (local_u0 < myumin) { |
a86d3ec0 |
144 | local_u0 = myumin ; |
7fd59977 |
145 | } |
146 | else if (local_u0 > myusup) { |
a86d3ec0 |
147 | local_u0 = myusup ; |
7fd59977 |
148 | } |
149 | // Recherche de l intervalle ou se trouve U0 |
150 | Standard_Boolean found = Standard_False; |
151 | inter = 1; |
152 | while (!found && inter <= n) { |
153 | // Intervalle commun a l intervalle C2 courant de la courbe et a |
154 | // l intervalle total de recherche de l'extremum (hla : au cas ou |
155 | // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent |
156 | // pas, mais il n'y avait aucune raison de sortir en "return") |
157 | myintuinf = Max(theInter(inter), myumin); |
158 | myintusup = Min(theInter(inter+1), myusup); |
a86d3ec0 |
159 | if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True; |
160 | inter++; |
7fd59977 |
161 | } |
162 | |
163 | if( found ) inter--; //IFV 16.06.00 - inter is increased after found! |
164 | |
165 | // Essai sur l intervalle trouve |
166 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
a86d3ec0 |
167 | myintusup, mytol); |
7fd59977 |
168 | myLocExtPC.Perform(P, local_u0); |
169 | myDone = myLocExtPC.IsDone(); |
170 | if (myDone) { |
a86d3ec0 |
171 | mypp = myLocExtPC.Point(); |
172 | myismin = myLocExtPC.IsMin(); |
173 | mydist2 = myLocExtPC.SquareDistance(); |
7fd59977 |
174 | } |
175 | else { |
a86d3ec0 |
176 | Standard_Integer k = 1; |
177 | // Essai sur les intervalles alentours: |
178 | i1 = inter; |
179 | i2 = inter; |
180 | Standard_Real s1inf, s2inf, s1sup, s2sup; |
181 | ThePoint P1; |
182 | TheVector V1; |
183 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
184 | s2inf = (TheVector(P, P1)*V1); |
185 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
186 | s1sup = (TheVector(P, P1)*V1); |
187 | |
188 | |
189 | while (!myDone && (i2 > 0) && (i1 <= n)) |
190 | { |
191 | i1 = inter + k; |
192 | i2 = inter - k; |
193 | if (i1 <= n) |
194 | { |
195 | myintuinf = Max(theInter(i1), myumin); |
196 | myintusup = Min(theInter(i1+1), myusup); |
197 | if (myintuinf < myintusup) |
198 | { |
199 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
200 | s2sup = (TheVector(P, P1)*V1); |
f4dee9bb |
201 | if(Precision::IsInfinite(s2sup) || Precision::IsInfinite(s1sup)) |
202 | { |
203 | break; |
204 | } |
a86d3ec0 |
205 | if (s1sup*s2sup <= RealEpsilon()) |
206 | { |
207 | // extremum: |
208 | myDone = Standard_True; |
209 | mypp.SetValues(myintuinf, P1); |
210 | myismin = (s1sup <= 0.0); |
211 | mydist2 = P.SquareDistance(P1); |
212 | break; |
213 | } |
214 | |
215 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
216 | s1sup = (TheVector(P, P1)*V1); |
217 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
218 | myintusup, mytol); |
219 | myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5); |
220 | myDone = myLocExtPC.IsDone(); |
221 | if (myDone) { |
222 | mypp = myLocExtPC.Point(); |
223 | myismin = myLocExtPC.IsMin(); |
224 | mydist2 = myLocExtPC.SquareDistance(); |
225 | break; |
226 | } |
227 | } |
228 | } |
229 | |
230 | if (i2 > 0) |
231 | { |
232 | myintuinf = Max(theInter(i2), myumin); |
233 | myintusup = Min(theInter(i2+1), myusup); |
234 | if (myintuinf < myintusup) |
235 | { |
236 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
237 | s1inf = (TheVector(P, P1)*V1); |
f4dee9bb |
238 | if(Precision::IsInfinite(s2inf) || Precision::IsInfinite(s1inf)) |
239 | { |
240 | break; |
241 | } |
a86d3ec0 |
242 | if (s1inf*s2inf <= RealEpsilon()) |
243 | { |
244 | // extremum: |
245 | myDone = Standard_True; |
246 | mypp.SetValues(myintusup, P1); |
247 | myismin = (s1inf <= 0.0); |
248 | mydist2 = P.SquareDistance(P1); |
249 | break; |
250 | } |
251 | |
252 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
253 | s2inf = (TheVector(P, P1)*V1); |
254 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
255 | myintusup, mytol); |
256 | myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 ); |
257 | myDone = myLocExtPC.IsDone(); |
258 | |
259 | if (myDone) |
260 | { |
261 | mypp = myLocExtPC.Point(); |
262 | myismin = myLocExtPC.IsMin(); |
263 | mydist2 = myLocExtPC.SquareDistance(); |
264 | break; |
265 | } |
266 | } |
267 | } |
268 | |
269 | k++; |
270 | } |
7fd59977 |
271 | } |
272 | } |
a86d3ec0 |
273 | |
274 | break; |
275 | |
276 | case GeomAbs_BezierCurve: |
277 | { |
7fd59977 |
278 | myLocExtPC.Perform(P, U0); |
279 | myDone = myLocExtPC.IsDone(); |
280 | } |
a86d3ec0 |
281 | |
282 | break; |
283 | default: |
284 | { |
7fd59977 |
285 | myExtremPC.Perform(P); |
286 | numberext = 0; |
a86d3ec0 |
287 | if (myExtremPC.IsDone()) |
288 | { |
289 | for (i = 1; i <= myExtremPC.NbExt(); i++) |
290 | { |
291 | Par = myExtremPC.Point(i).Parameter(); |
292 | valU = Abs(Par - U0); |
293 | if (valU <= valU2) |
294 | { |
295 | valU2 = valU; |
296 | numberext = i; |
297 | myDone = Standard_True; |
298 | } |
299 | } |
7fd59977 |
300 | } |
a86d3ec0 |
301 | |
302 | if (numberext == 0) |
303 | myDone = Standard_False; |
304 | |
7fd59977 |
305 | break; |
306 | } |
307 | } |
308 | } |
309 | |
310 | |
311 | |
312 | |
313 | //======================================================================= |
314 | //function : IsDone |
315 | //purpose : |
316 | //======================================================================= |
317 | |
318 | Standard_Boolean Extrema_GLocateExtPC::IsDone () const |
319 | { |
320 | return myDone; |
321 | } |
322 | |
323 | |
324 | //======================================================================= |
325 | //function : Value |
326 | //purpose : |
327 | //======================================================================= |
328 | |
329 | Standard_Real Extrema_GLocateExtPC::SquareDistance () const |
330 | { |
638ad7f3 |
331 | if (!IsDone()) |
332 | { |
333 | throw StdFail_NotDone(); |
334 | } |
7fd59977 |
335 | Standard_Real d=0; |
336 | if ((type == GeomAbs_BezierCurve)) { |
337 | d = myLocExtPC.SquareDistance(); |
338 | } |
1aec3320 |
339 | else if(type == GeomAbs_BSplineCurve || |
340 | type == GeomAbs_OffsetCurve || |
341 | type == GeomAbs_OtherCurve) { |
7fd59977 |
342 | d = mydist2; |
343 | } |
344 | else { |
345 | if (numberext != 0) { |
346 | d = myExtremPC.SquareDistance(numberext); |
347 | } |
348 | } |
349 | return d; |
350 | } |
351 | |
352 | |
353 | //======================================================================= |
354 | //function : IsMin |
355 | //purpose : |
356 | //======================================================================= |
357 | |
358 | Standard_Boolean Extrema_GLocateExtPC::IsMin () const |
359 | { |
638ad7f3 |
360 | if (!IsDone()) |
361 | { |
362 | throw StdFail_NotDone(); |
363 | } |
364 | Standard_Boolean b = 0; |
7fd59977 |
365 | if ((type == GeomAbs_BezierCurve)) { |
366 | b = myLocExtPC.IsMin(); |
367 | } |
1aec3320 |
368 | else if(type == GeomAbs_BSplineCurve || |
369 | type == GeomAbs_OffsetCurve || |
370 | type == GeomAbs_OtherCurve) { |
7fd59977 |
371 | b = myismin; |
372 | } |
373 | else { |
374 | if (numberext != 0) { |
375 | b = myExtremPC.IsMin(numberext); |
376 | } |
377 | } |
378 | return b; |
379 | } |
380 | |
381 | |
382 | //======================================================================= |
383 | //function : Point |
384 | //purpose : |
385 | //======================================================================= |
386 | |
5d99f2c8 |
387 | const ThePOnC & Extrema_GLocateExtPC::Point () const |
7fd59977 |
388 | { |
638ad7f3 |
389 | if (!IsDone()) |
390 | { |
391 | throw StdFail_NotDone(); |
392 | } |
393 | if (type == GeomAbs_BezierCurve) |
394 | { |
5d99f2c8 |
395 | return myLocExtPC.Point(); |
7fd59977 |
396 | } |
1aec3320 |
397 | else if(type == GeomAbs_BSplineCurve || |
398 | type == GeomAbs_OffsetCurve || |
399 | type == GeomAbs_OtherCurve) { |
5d99f2c8 |
400 | return mypp; |
7fd59977 |
401 | } |
5d99f2c8 |
402 | return myExtremPC.Point(numberext); |
7fd59977 |
403 | } |