1 // File: Extrema_GLocateExtPC.gxx
2 // Created: Tue Dec 14 16:38:29 1993
3 // Author: Christophe MARION
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
11 #include Extrema_ELPC_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>
22 //=======================================================================
23 //function : Extrema_GLocateExtPC
25 //=======================================================================
27 Extrema_GLocateExtPC::Extrema_GLocateExtPC() { }
30 //=======================================================================
31 //function : Extrema_GLocateExtPC
33 //=======================================================================
35 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
37 const Standard_Real U0,
38 const Standard_Real TolF)
40 Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF);
44 //=======================================================================
45 //function : Extrema_GLocateExtPC
47 //=======================================================================
49 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
51 const Standard_Real U0,
52 const Standard_Real Umin,
53 const Standard_Real Usup,
54 const Standard_Real TolF)
56 Initialize(C, Umin, Usup, TolF);
62 //=======================================================================
63 //function : Initialize
65 //=======================================================================
67 void Extrema_GLocateExtPC::Initialize(const TheCurve& C,
68 const Standard_Real Umin,
69 const Standard_Real Usup,
70 const Standard_Real TolF)
72 myC = (Standard_Address)&C;
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);
84 myExtremPC.Initialize(C, Umin, Usup, tolu);
91 //=======================================================================
94 //=======================================================================
96 void Extrema_GLocateExtPC::Perform(const ThePoint& P,
97 const Standard_Real U0)
99 Standard_Integer i, i1, i2, inter;
101 Standard_Real Tol = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
103 TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
105 Standard_Real Par, valU, valU2 = RealLast(),
107 Standard_Real myintuinf=0, myintusup=0;
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);
118 // be gentle with the caller
120 if (local_u0 < myumin) {
123 else if (local_u0 > myusup) {
126 // Recherche de l intervalle ou se trouve U0
127 Standard_Boolean found = Standard_False;
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;
140 if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
142 // Essai sur l intervalle trouve
143 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
145 myLocExtPC.Perform(P, local_u0);
146 myDone = myLocExtPC.IsDone();
148 mypp = myLocExtPC.Point();
149 myismin = myLocExtPC.IsMin();
150 mydist2 = myLocExtPC.SquareDistance();
153 Standard_Integer k = 1;
154 // Essai sur les intervalles alentours:
157 Standard_Real s1inf, s2inf, s1sup, s2sup;
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);
166 while (!myDone && (i2 > 0) && (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()) {
177 myDone = Standard_True;
178 mypp.SetValues(myintuinf, P1);
179 myismin = (s1sup <= 0.0);
180 mydist2 = P.SquareDistance(P1);
183 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
184 s1sup = (TheVector(P, P1)*V1);
185 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
187 myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
188 myDone = myLocExtPC.IsDone();
190 mypp = myLocExtPC.Point();
191 myismin = myLocExtPC.IsMin();
192 mydist2 = myLocExtPC.SquareDistance();
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()) {
205 myDone = Standard_True;
206 mypp.SetValues(myintusup, P1);
207 myismin = (s1inf <= 0.0);
208 mydist2 = P.SquareDistance(P1);
211 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
212 s2inf = (TheVector(P, P1)*V1);
213 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
215 myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
216 myDone = myLocExtPC.IsDone();
218 mypp = myLocExtPC.Point();
219 myismin = myLocExtPC.IsMin();
220 mydist2 = myLocExtPC.SquareDistance();
230 case GeomAbs_BezierCurve: {
231 myLocExtPC.Perform(P, U0);
232 myDone = myLocExtPC.IsDone();
236 myExtremPC.Perform(P);
238 if (myExtremPC.IsDone()) {
239 for (i = 1; i <= myExtremPC.NbExt(); i++) {
240 Par = myExtremPC.Point(i).Parameter();
241 valU = Abs(Par - U0);
245 myDone = Standard_True;
249 if (numberext == 0) myDone = Standard_False;
258 //=======================================================================
261 //=======================================================================
263 Standard_Boolean Extrema_GLocateExtPC::IsDone () const
269 //=======================================================================
272 //=======================================================================
274 Standard_Real Extrema_GLocateExtPC::SquareDistance () const
276 if (!myDone) { StdFail_NotDone::Raise(); }
278 if ((type == GeomAbs_BezierCurve)) {
279 d = myLocExtPC.SquareDistance();
281 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
285 if (numberext != 0) {
286 d = myExtremPC.SquareDistance(numberext);
293 //=======================================================================
296 //=======================================================================
298 Standard_Boolean Extrema_GLocateExtPC::IsMin () const
300 if (!myDone) { StdFail_NotDone::Raise(); }
301 Standard_Boolean b=0;
302 if ((type == GeomAbs_BezierCurve)) {
303 b = myLocExtPC.IsMin();
305 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
309 if (numberext != 0) {
310 b = myExtremPC.IsMin(numberext);
317 //=======================================================================
320 //=======================================================================
322 ThePOnC Extrema_GLocateExtPC::Point () const
324 if (!myDone) { StdFail_NotDone::Raise(); }
326 if (type == GeomAbs_BezierCurve) {
327 P = myLocExtPC.Point();
329 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
333 if (numberext != 0) {
334 P = myExtremPC.Point(numberext);