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 | |
39 | Extrema_GLocateExtPC::Extrema_GLocateExtPC() { } |
40 | |
41 | |
42 | //======================================================================= |
43 | //function : Extrema_GLocateExtPC |
44 | //purpose : |
45 | //======================================================================= |
46 | |
47 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
a86d3ec0 |
48 | const TheCurve& C, |
49 | const Standard_Real U0, |
50 | const Standard_Real TolF) |
7fd59977 |
51 | { |
52 | Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF); |
53 | Perform(P, U0); |
54 | } |
55 | |
56 | //======================================================================= |
57 | //function : Extrema_GLocateExtPC |
58 | //purpose : |
59 | //======================================================================= |
60 | |
61 | Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P, |
a86d3ec0 |
62 | const TheCurve& C, |
63 | const Standard_Real U0, |
64 | const Standard_Real Umin, |
65 | const Standard_Real Usup, |
66 | const Standard_Real TolF) |
7fd59977 |
67 | { |
68 | Initialize(C, Umin, Usup, TolF); |
69 | Perform(P, U0); |
70 | } |
71 | |
72 | |
73 | |
74 | //======================================================================= |
75 | //function : Initialize |
76 | //purpose : |
77 | //======================================================================= |
78 | |
79 | void Extrema_GLocateExtPC::Initialize(const TheCurve& C, |
a86d3ec0 |
80 | const Standard_Real Umin, |
81 | const Standard_Real Usup, |
82 | const Standard_Real TolF) |
7fd59977 |
83 | { |
84 | myC = (Standard_Address)&C; |
85 | mytol = TolF; |
86 | myumin = Umin; |
87 | myusup = Usup; |
88 | type = TheCurveTool::GetType(C); |
89 | Standard_Real tolu = TheCurveTool::Resolution(C, Precision::Confusion()); |
90 | if ((type == GeomAbs_BSplineCurve) || |
1aec3320 |
91 | (type == GeomAbs_BezierCurve) || |
92 | (type == GeomAbs_OffsetCurve) || |
93 | (type == GeomAbs_OtherCurve)) |
94 | { |
a86d3ec0 |
95 | myLocExtPC.Initialize(C, Umin, Usup, tolu); |
7fd59977 |
96 | } |
97 | else { |
98 | myExtremPC.Initialize(C, Umin, Usup, tolu); |
99 | } |
100 | } |
101 | |
102 | |
103 | |
104 | |
105 | //======================================================================= |
106 | //function : Perform |
107 | //purpose : |
108 | //======================================================================= |
109 | |
110 | void Extrema_GLocateExtPC::Perform(const ThePoint& P, |
a86d3ec0 |
111 | const Standard_Real U0) |
7fd59977 |
112 | { |
113 | Standard_Integer i, i1, i2, inter; |
7fd59977 |
114 | Standard_Real Par, valU, valU2 = RealLast(), |
a86d3ec0 |
115 | local_u0 ; |
7fd59977 |
116 | Standard_Real myintuinf=0, myintusup=0; |
117 | local_u0 = U0 ; |
a86d3ec0 |
118 | switch(type) |
119 | { |
120 | case GeomAbs_OtherCurve: |
1aec3320 |
121 | case GeomAbs_OffsetCurve: |
a86d3ec0 |
122 | case GeomAbs_BSplineCurve: |
123 | { |
7fd59977 |
124 | // La recherche de l extremum est faite intervalle continu C2 par |
125 | // intervalle continu C2 de la courbe |
126 | Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2); |
127 | TColStd_Array1OfReal theInter(1, n+1); |
128 | TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2); |
a86d3ec0 |
129 | // |
130 | // be gentle with the caller |
131 | // |
7fd59977 |
132 | if (local_u0 < myumin) { |
a86d3ec0 |
133 | local_u0 = myumin ; |
7fd59977 |
134 | } |
135 | else if (local_u0 > myusup) { |
a86d3ec0 |
136 | local_u0 = myusup ; |
7fd59977 |
137 | } |
138 | // Recherche de l intervalle ou se trouve U0 |
139 | Standard_Boolean found = Standard_False; |
140 | inter = 1; |
141 | while (!found && inter <= n) { |
142 | // Intervalle commun a l intervalle C2 courant de la courbe et a |
143 | // l intervalle total de recherche de l'extremum (hla : au cas ou |
144 | // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent |
145 | // pas, mais il n'y avait aucune raison de sortir en "return") |
146 | myintuinf = Max(theInter(inter), myumin); |
147 | myintusup = Min(theInter(inter+1), myusup); |
a86d3ec0 |
148 | if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True; |
149 | inter++; |
7fd59977 |
150 | } |
151 | |
152 | if( found ) inter--; //IFV 16.06.00 - inter is increased after found! |
153 | |
154 | // Essai sur l intervalle trouve |
155 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
a86d3ec0 |
156 | myintusup, mytol); |
7fd59977 |
157 | myLocExtPC.Perform(P, local_u0); |
158 | myDone = myLocExtPC.IsDone(); |
159 | if (myDone) { |
a86d3ec0 |
160 | mypp = myLocExtPC.Point(); |
161 | myismin = myLocExtPC.IsMin(); |
162 | mydist2 = myLocExtPC.SquareDistance(); |
7fd59977 |
163 | } |
164 | else { |
a86d3ec0 |
165 | Standard_Integer k = 1; |
166 | // Essai sur les intervalles alentours: |
167 | i1 = inter; |
168 | i2 = inter; |
169 | Standard_Real s1inf, s2inf, s1sup, s2sup; |
170 | ThePoint P1; |
171 | TheVector V1; |
172 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
173 | s2inf = (TheVector(P, P1)*V1); |
174 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
175 | s1sup = (TheVector(P, P1)*V1); |
176 | |
177 | |
178 | while (!myDone && (i2 > 0) && (i1 <= n)) |
179 | { |
180 | i1 = inter + k; |
181 | i2 = inter - k; |
182 | if (i1 <= n) |
183 | { |
184 | myintuinf = Max(theInter(i1), myumin); |
185 | myintusup = Min(theInter(i1+1), myusup); |
186 | if (myintuinf < myintusup) |
187 | { |
188 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
189 | s2sup = (TheVector(P, P1)*V1); |
f4dee9bb |
190 | if(Precision::IsInfinite(s2sup) || Precision::IsInfinite(s1sup)) |
191 | { |
192 | break; |
193 | } |
a86d3ec0 |
194 | if (s1sup*s2sup <= RealEpsilon()) |
195 | { |
196 | // extremum: |
197 | myDone = Standard_True; |
198 | mypp.SetValues(myintuinf, P1); |
199 | myismin = (s1sup <= 0.0); |
200 | mydist2 = P.SquareDistance(P1); |
201 | break; |
202 | } |
203 | |
204 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
205 | s1sup = (TheVector(P, P1)*V1); |
206 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
207 | myintusup, mytol); |
208 | myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5); |
209 | myDone = myLocExtPC.IsDone(); |
210 | if (myDone) { |
211 | mypp = myLocExtPC.Point(); |
212 | myismin = myLocExtPC.IsMin(); |
213 | mydist2 = myLocExtPC.SquareDistance(); |
214 | break; |
215 | } |
216 | } |
217 | } |
218 | |
219 | if (i2 > 0) |
220 | { |
221 | myintuinf = Max(theInter(i2), myumin); |
222 | myintusup = Min(theInter(i2+1), myusup); |
223 | if (myintuinf < myintusup) |
224 | { |
225 | TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1); |
226 | s1inf = (TheVector(P, P1)*V1); |
f4dee9bb |
227 | if(Precision::IsInfinite(s2inf) || Precision::IsInfinite(s1inf)) |
228 | { |
229 | break; |
230 | } |
a86d3ec0 |
231 | if (s1inf*s2inf <= RealEpsilon()) |
232 | { |
233 | // extremum: |
234 | myDone = Standard_True; |
235 | mypp.SetValues(myintusup, P1); |
236 | myismin = (s1inf <= 0.0); |
237 | mydist2 = P.SquareDistance(P1); |
238 | break; |
239 | } |
240 | |
241 | TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1); |
242 | s2inf = (TheVector(P, P1)*V1); |
243 | myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, |
244 | myintusup, mytol); |
245 | myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 ); |
246 | myDone = myLocExtPC.IsDone(); |
247 | |
248 | if (myDone) |
249 | { |
250 | mypp = myLocExtPC.Point(); |
251 | myismin = myLocExtPC.IsMin(); |
252 | mydist2 = myLocExtPC.SquareDistance(); |
253 | break; |
254 | } |
255 | } |
256 | } |
257 | |
258 | k++; |
259 | } |
7fd59977 |
260 | } |
261 | } |
a86d3ec0 |
262 | |
263 | break; |
264 | |
265 | case GeomAbs_BezierCurve: |
266 | { |
7fd59977 |
267 | myLocExtPC.Perform(P, U0); |
268 | myDone = myLocExtPC.IsDone(); |
269 | } |
a86d3ec0 |
270 | |
271 | break; |
272 | default: |
273 | { |
7fd59977 |
274 | myExtremPC.Perform(P); |
275 | numberext = 0; |
a86d3ec0 |
276 | if (myExtremPC.IsDone()) |
277 | { |
278 | for (i = 1; i <= myExtremPC.NbExt(); i++) |
279 | { |
280 | Par = myExtremPC.Point(i).Parameter(); |
281 | valU = Abs(Par - U0); |
282 | if (valU <= valU2) |
283 | { |
284 | valU2 = valU; |
285 | numberext = i; |
286 | myDone = Standard_True; |
287 | } |
288 | } |
7fd59977 |
289 | } |
a86d3ec0 |
290 | |
291 | if (numberext == 0) |
292 | myDone = Standard_False; |
293 | |
7fd59977 |
294 | break; |
295 | } |
296 | } |
297 | } |
298 | |
299 | |
300 | |
301 | |
302 | //======================================================================= |
303 | //function : IsDone |
304 | //purpose : |
305 | //======================================================================= |
306 | |
307 | Standard_Boolean Extrema_GLocateExtPC::IsDone () const |
308 | { |
309 | return myDone; |
310 | } |
311 | |
312 | |
313 | //======================================================================= |
314 | //function : Value |
315 | //purpose : |
316 | //======================================================================= |
317 | |
318 | Standard_Real Extrema_GLocateExtPC::SquareDistance () const |
319 | { |
9775fa61 |
320 | if (!myDone) { throw StdFail_NotDone(); } |
7fd59977 |
321 | Standard_Real d=0; |
322 | if ((type == GeomAbs_BezierCurve)) { |
323 | d = myLocExtPC.SquareDistance(); |
324 | } |
1aec3320 |
325 | else if(type == GeomAbs_BSplineCurve || |
326 | type == GeomAbs_OffsetCurve || |
327 | type == GeomAbs_OtherCurve) { |
7fd59977 |
328 | d = mydist2; |
329 | } |
330 | else { |
331 | if (numberext != 0) { |
332 | d = myExtremPC.SquareDistance(numberext); |
333 | } |
334 | } |
335 | return d; |
336 | } |
337 | |
338 | |
339 | //======================================================================= |
340 | //function : IsMin |
341 | //purpose : |
342 | //======================================================================= |
343 | |
344 | Standard_Boolean Extrema_GLocateExtPC::IsMin () const |
345 | { |
9775fa61 |
346 | if (!myDone) { throw StdFail_NotDone(); } |
7fd59977 |
347 | Standard_Boolean b=0; |
348 | if ((type == GeomAbs_BezierCurve)) { |
349 | b = myLocExtPC.IsMin(); |
350 | } |
1aec3320 |
351 | else if(type == GeomAbs_BSplineCurve || |
352 | type == GeomAbs_OffsetCurve || |
353 | type == GeomAbs_OtherCurve) { |
7fd59977 |
354 | b = myismin; |
355 | } |
356 | else { |
357 | if (numberext != 0) { |
358 | b = myExtremPC.IsMin(numberext); |
359 | } |
360 | } |
361 | return b; |
362 | } |
363 | |
364 | |
365 | //======================================================================= |
366 | //function : Point |
367 | //purpose : |
368 | //======================================================================= |
369 | |
5d99f2c8 |
370 | const ThePOnC & Extrema_GLocateExtPC::Point () const |
7fd59977 |
371 | { |
9775fa61 |
372 | if (!myDone) { throw StdFail_NotDone(); } |
7fd59977 |
373 | if (type == GeomAbs_BezierCurve) { |
5d99f2c8 |
374 | return myLocExtPC.Point(); |
7fd59977 |
375 | } |
1aec3320 |
376 | else if(type == GeomAbs_BSplineCurve || |
377 | type == GeomAbs_OffsetCurve || |
378 | type == GeomAbs_OtherCurve) { |
5d99f2c8 |
379 | return mypp; |
7fd59977 |
380 | } |
5d99f2c8 |
381 | return myExtremPC.Point(numberext); |
7fd59977 |
382 | } |