0023404: Create SquareConfusion function in Precision package for speed and convenience
[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 #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 }