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