21c0055262aaf133c4ab34e5f4f634e727bea449
[occt.git] / src / Extrema / Extrema_GLocateExtPC.gxx
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
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   Standard_Real Par, valU, valU2 = RealLast(),
117   local_u0 ;
118   Standard_Real myintuinf=0, myintusup=0;
119   local_u0 = U0 ;
120   switch(type) {
121     case GeomAbs_OtherCurve:
122     case GeomAbs_BSplineCurve: {
123       // La recherche de l extremum est faite intervalle continu C2 par
124       // intervalle continu C2 de la courbe
125       Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
126       TColStd_Array1OfReal theInter(1, n+1);
127       TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
128 //
129 //  be gentle with the caller 
130 //
131       if (local_u0 < myumin) {
132         local_u0 = myumin ; 
133       }
134       else if (local_u0 > myusup) {
135         local_u0  = myusup ;
136       }
137       // Recherche de l intervalle ou se trouve U0
138       Standard_Boolean found = Standard_False;
139       inter = 1;
140       while (!found && inter <= n) {
141         // Intervalle commun a l intervalle C2 courant de la courbe et a
142         // l intervalle total de recherche de l'extremum (hla : au cas ou
143         // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent
144         // pas, mais il n'y avait aucune raison de sortir en "return")
145         myintuinf = Max(theInter(inter), myumin);
146         myintusup = Min(theInter(inter+1), myusup);
147         if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True;
148         inter++;
149       }
150
151       if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
152
153       // Essai sur l intervalle trouve
154       myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
155                             myintusup, mytol);
156       myLocExtPC.Perform(P, local_u0);
157       myDone = myLocExtPC.IsDone();
158       if (myDone) {
159         mypp = myLocExtPC.Point();
160         myismin = myLocExtPC.IsMin();
161         mydist2 = myLocExtPC.SquareDistance();
162       }
163       else {
164         Standard_Integer k = 1;
165         // Essai sur les intervalles alentours:
166         i1 = inter;
167         i2 = inter;
168         Standard_Real s1inf, s2inf, s1sup, s2sup;
169         ThePoint P1;
170         TheVector V1;
171         TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
172         s2inf = (TheVector(P, P1)*V1);
173         TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
174         s1sup = (TheVector(P, P1)*V1);
175         
176
177         while (!myDone && (i2 > 0) && (i1 <= n)) {
178           i1 = inter + k;
179           i2 = inter - k;
180           if (i1 <= n) {
181             myintuinf = Max(theInter(i1), myumin);
182             myintusup = Min(theInter(i1+1), myusup);
183             if (myintuinf < myintusup) {
184               TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
185               s2sup = (TheVector(P, P1)*V1);
186               if (s1sup*s2sup <= RealEpsilon()) {
187                 // extremum:
188                 myDone = Standard_True;
189                 mypp.SetValues(myintuinf, P1);
190                 myismin = (s1sup <= 0.0);
191                 mydist2 = P.SquareDistance(P1);
192                 break;
193               }
194               TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
195               s1sup = (TheVector(P, P1)*V1);
196               myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
197                                     myintusup, mytol);
198               myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
199               myDone = myLocExtPC.IsDone();
200               if (myDone) {
201                 mypp = myLocExtPC.Point();
202                 myismin = myLocExtPC.IsMin();
203                 mydist2 = myLocExtPC.SquareDistance();
204                 break;
205               }
206             }
207           }
208           if (i2 > 0) {
209             myintuinf = Max(theInter(i2), myumin);
210             myintusup = Min(theInter(i2+1), myusup);
211             if (myintuinf < myintusup) {
212               TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
213               s1inf = (TheVector(P, P1)*V1);
214               if (s1inf*s2inf <= RealEpsilon()) {
215                 // extremum:
216                 myDone = Standard_True;
217                 mypp.SetValues(myintusup, P1);
218                 myismin = (s1inf <= 0.0);
219                 mydist2 = P.SquareDistance(P1);
220                 break;
221               }
222               TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
223               s2inf = (TheVector(P, P1)*V1);
224               myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
225                                     myintusup, mytol);
226               myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
227               myDone = myLocExtPC.IsDone();
228               if (myDone) {
229                 mypp = myLocExtPC.Point();
230                 myismin = myLocExtPC.IsMin();
231                 mydist2 = myLocExtPC.SquareDistance();
232                 break;
233               }
234             }
235           }
236           k++;
237         }
238       }
239     }
240       break;
241     case GeomAbs_BezierCurve: {
242       myLocExtPC.Perform(P, U0);
243       myDone = myLocExtPC.IsDone();
244     }
245       break;
246     default:{
247       myExtremPC.Perform(P);
248       numberext = 0;
249       if (myExtremPC.IsDone()) {
250         for (i = 1; i <= myExtremPC.NbExt(); i++) {
251           Par = myExtremPC.Point(i).Parameter();
252           valU = Abs(Par - U0);
253           if (valU <= valU2) {
254             valU2 = valU;
255             numberext = i;
256             myDone = Standard_True;
257           }
258         }
259       }
260       if (numberext == 0) myDone = Standard_False;
261       break;
262     }
263   }
264 }
265
266
267
268
269 //=======================================================================
270 //function : IsDone
271 //purpose  : 
272 //=======================================================================
273
274 Standard_Boolean Extrema_GLocateExtPC::IsDone () const 
275 {
276   return myDone;
277 }
278
279
280 //=======================================================================
281 //function : Value
282 //purpose  : 
283 //=======================================================================
284
285 Standard_Real Extrema_GLocateExtPC::SquareDistance () const 
286 {
287   if (!myDone) { StdFail_NotDone::Raise(); }
288   Standard_Real d=0;
289   if ((type == GeomAbs_BezierCurve)) {
290     d =  myLocExtPC.SquareDistance();
291   }
292   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
293     d = mydist2;
294   }
295   else {
296     if (numberext != 0) {
297       d = myExtremPC.SquareDistance(numberext);
298     }
299   }
300   return d;
301 }
302
303
304 //=======================================================================
305 //function : IsMin
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Boolean Extrema_GLocateExtPC::IsMin () const 
310 {
311   if (!myDone) { StdFail_NotDone::Raise(); }
312   Standard_Boolean b=0;
313   if ((type == GeomAbs_BezierCurve)) {
314     b = myLocExtPC.IsMin();
315   }
316   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
317     b = myismin;
318   }
319   else {
320     if (numberext != 0) {
321       b = myExtremPC.IsMin(numberext);
322     }
323   }
324   return b;
325 }
326
327
328 //=======================================================================
329 //function : Point
330 //purpose  : 
331 //=======================================================================
332
333 ThePOnC Extrema_GLocateExtPC::Point () const 
334 {
335   if (!myDone) { StdFail_NotDone::Raise(); }
336   ThePOnC P;
337   if (type == GeomAbs_BezierCurve) {
338     P = myLocExtPC.Point();
339   }
340   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
341     P =  mypp;
342   }
343   else {
344     if (numberext != 0) {
345       P = myExtremPC.Point(numberext);
346     }
347   }
348   return P;
349 }