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