0024203: Command "sameparameter" in DRAW on attached edge set tolerance equal to...
[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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
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,
48   const TheCurve&     C,
49   const Standard_Real U0,
50   const Standard_Real TolF)
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,
62   const TheCurve&     C,
63   const Standard_Real U0, 
64   const Standard_Real Umin,
65   const Standard_Real Usup,
66   const Standard_Real TolF)
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, 
80   const Standard_Real Umin,
81   const Standard_Real Usup,
82   const Standard_Real TolF)
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) || 
91     (type == GeomAbs_BezierCurve)  || 
92     (type == GeomAbs_OtherCurve)) {
93       myLocExtPC.Initialize(C, Umin, Usup, tolu);
94   }
95   else {
96     myExtremPC.Initialize(C, Umin, Usup, tolu);
97   }
98 }
99
100
101
102
103 //=======================================================================
104 //function : Perform
105 //purpose  : 
106 //=======================================================================
107
108 void Extrema_GLocateExtPC::Perform(const ThePoint&     P,
109   const Standard_Real U0)
110 {
111   Standard_Integer i, i1, i2, inter;
112   Standard_Real Par, valU, valU2 = RealLast(),
113     local_u0 ;
114   Standard_Real myintuinf=0, myintusup=0;
115   local_u0 = U0 ;
116   switch(type)
117   {
118   case GeomAbs_OtherCurve:
119   case GeomAbs_BSplineCurve:
120     {
121       // La recherche de l extremum est faite intervalle continu C2 par
122       // intervalle continu C2 de la courbe
123       Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
124       TColStd_Array1OfReal theInter(1, n+1);
125       TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
126       //
127       //  be gentle with the caller 
128       //
129       if (local_u0 < myumin) {
130         local_u0 = myumin ; 
131       }
132       else if (local_u0 > myusup) {
133         local_u0  = myusup ;
134       }
135       // Recherche de l intervalle ou se trouve U0
136       Standard_Boolean found = Standard_False;
137       inter = 1;
138       while (!found && inter <= n) {
139         // Intervalle commun a l intervalle C2 courant de la courbe et a
140         // l intervalle total de recherche de l'extremum (hla : au cas ou
141         // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent
142         // pas, mais il n'y avait aucune raison de sortir en "return")
143         myintuinf = Max(theInter(inter), myumin);
144         myintusup = Min(theInter(inter+1), myusup);
145         if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True;
146         inter++;
147       }
148
149       if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
150
151       // Essai sur l intervalle trouve
152       myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
153         myintusup, mytol);
154       myLocExtPC.Perform(P, local_u0);
155       myDone = myLocExtPC.IsDone();
156       if (myDone) {
157         mypp = myLocExtPC.Point();
158         myismin = myLocExtPC.IsMin();
159         mydist2 = myLocExtPC.SquareDistance();
160       }
161       else {
162         Standard_Integer k = 1;
163         // Essai sur les intervalles alentours:
164         i1 = inter;
165         i2 = inter;
166         Standard_Real s1inf, s2inf, s1sup, s2sup;
167         ThePoint P1;
168         TheVector V1;
169         TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
170         s2inf = (TheVector(P, P1)*V1);
171         TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
172         s1sup = (TheVector(P, P1)*V1);
173
174
175         while (!myDone && (i2 > 0) && (i1 <= n))
176         {
177           i1 = inter + k;
178           i2 = inter - k;
179           if (i1 <= n)
180           {
181             myintuinf = Max(theInter(i1), myumin);
182             myintusup = Min(theInter(i1+1), myusup);
183             if (myintuinf < myintusup)
184             {
185               TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
186               s2sup = (TheVector(P, P1)*V1);
187               if (s1sup*s2sup <= RealEpsilon())
188               {
189                 // extremum:
190                 myDone = Standard_True;
191                 mypp.SetValues(myintuinf, P1);
192                 myismin = (s1sup <= 0.0);
193                 mydist2 = P.SquareDistance(P1);
194                 break;
195               }
196
197               TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
198               s1sup = (TheVector(P, P1)*V1);
199               myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
200                 myintusup, mytol);
201               myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
202               myDone = myLocExtPC.IsDone();
203               if (myDone) {
204                 mypp = myLocExtPC.Point();
205                 myismin = myLocExtPC.IsMin();
206                 mydist2 = myLocExtPC.SquareDistance();
207                 break;
208               }
209             }
210           }
211
212           if (i2 > 0)
213           {
214             myintuinf = Max(theInter(i2), myumin);
215             myintusup = Min(theInter(i2+1), myusup);
216             if (myintuinf < myintusup)
217             {
218               TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
219               s1inf = (TheVector(P, P1)*V1);
220               if (s1inf*s2inf <= RealEpsilon())
221               {
222                 // extremum:
223                 myDone = Standard_True;
224                 mypp.SetValues(myintusup, P1);
225                 myismin = (s1inf <= 0.0);
226                 mydist2 = P.SquareDistance(P1);
227                 break;
228               }
229
230               TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
231               s2inf = (TheVector(P, P1)*V1);
232               myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf, 
233                 myintusup, mytol);
234               myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
235               myDone = myLocExtPC.IsDone();
236             
237               if (myDone)
238               {
239                 mypp = myLocExtPC.Point();
240                 myismin = myLocExtPC.IsMin();
241                 mydist2 = myLocExtPC.SquareDistance();
242                 break;
243               }
244             }
245           }
246
247           k++;
248         }
249       }
250     }
251
252     break;
253
254   case GeomAbs_BezierCurve:
255     {
256       myLocExtPC.Perform(P, U0);
257       myDone = myLocExtPC.IsDone();
258     }
259
260     break;
261   default:
262     {
263       myExtremPC.Perform(P);
264       numberext = 0;
265       if (myExtremPC.IsDone())
266       {
267         for (i = 1; i <= myExtremPC.NbExt(); i++)
268         {
269           Par = myExtremPC.Point(i).Parameter();
270           valU = Abs(Par - U0);
271           if (valU <= valU2)
272           {
273             valU2 = valU;
274             numberext = i;
275             myDone = Standard_True;
276           }
277         }
278       }
279
280       if (numberext == 0)
281         myDone = Standard_False;
282
283       break;
284     }
285   }
286 }
287
288
289
290
291 //=======================================================================
292 //function : IsDone
293 //purpose  : 
294 //=======================================================================
295
296 Standard_Boolean Extrema_GLocateExtPC::IsDone () const 
297 {
298   return myDone;
299 }
300
301
302 //=======================================================================
303 //function : Value
304 //purpose  : 
305 //=======================================================================
306
307 Standard_Real Extrema_GLocateExtPC::SquareDistance () const 
308 {
309   if (!myDone) { StdFail_NotDone::Raise(); }
310   Standard_Real d=0;
311   if ((type == GeomAbs_BezierCurve)) {
312     d =  myLocExtPC.SquareDistance();
313   }
314   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
315     d = mydist2;
316   }
317   else {
318     if (numberext != 0) {
319       d = myExtremPC.SquareDistance(numberext);
320     }
321   }
322   return d;
323 }
324
325
326 //=======================================================================
327 //function : IsMin
328 //purpose  : 
329 //=======================================================================
330
331 Standard_Boolean Extrema_GLocateExtPC::IsMin () const 
332 {
333   if (!myDone) { StdFail_NotDone::Raise(); }
334   Standard_Boolean b=0;
335   if ((type == GeomAbs_BezierCurve)) {
336     b = myLocExtPC.IsMin();
337   }
338   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
339     b = myismin;
340   }
341   else {
342     if (numberext != 0) {
343       b = myExtremPC.IsMin(numberext);
344     }
345   }
346   return b;
347 }
348
349
350 //=======================================================================
351 //function : Point
352 //purpose  : 
353 //=======================================================================
354
355 const ThePOnC & Extrema_GLocateExtPC::Point () const 
356 {
357   if (!myDone) { StdFail_NotDone::Raise(); }
358   if (type == GeomAbs_BezierCurve) {
359     return myLocExtPC.Point();
360   }
361   else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
362     return mypp;
363   }
364   return myExtremPC.Point(numberext);
365 }