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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
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
23 #include Extrema_ELPC_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>
34 //=======================================================================
35 //function : Extrema_GLocateExtPC
37 //=======================================================================
39 Extrema_GLocateExtPC::Extrema_GLocateExtPC() { }
42 //=======================================================================
43 //function : Extrema_GLocateExtPC
45 //=======================================================================
47 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
49 const Standard_Real U0,
50 const Standard_Real TolF)
52 Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF);
56 //=======================================================================
57 //function : Extrema_GLocateExtPC
59 //=======================================================================
61 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
63 const Standard_Real U0,
64 const Standard_Real Umin,
65 const Standard_Real Usup,
66 const Standard_Real TolF)
68 Initialize(C, Umin, Usup, TolF);
74 //=======================================================================
75 //function : Initialize
77 //=======================================================================
79 void Extrema_GLocateExtPC::Initialize(const TheCurve& C,
80 const Standard_Real Umin,
81 const Standard_Real Usup,
82 const Standard_Real TolF)
84 myC = (Standard_Address)&C;
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);
96 myExtremPC.Initialize(C, Umin, Usup, tolu);
103 //=======================================================================
106 //=======================================================================
108 void Extrema_GLocateExtPC::Perform(const ThePoint& P,
109 const Standard_Real U0)
111 Standard_Integer i, i1, i2, inter;
112 Standard_Real Par, valU, valU2 = RealLast(),
114 Standard_Real myintuinf=0, myintusup=0;
118 case GeomAbs_OtherCurve:
119 case GeomAbs_BSplineCurve:
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);
127 // be gentle with the caller
129 if (local_u0 < myumin) {
132 else if (local_u0 > myusup) {
135 // Recherche de l intervalle ou se trouve U0
136 Standard_Boolean found = Standard_False;
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;
149 if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
151 // Essai sur l intervalle trouve
152 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
154 myLocExtPC.Perform(P, local_u0);
155 myDone = myLocExtPC.IsDone();
157 mypp = myLocExtPC.Point();
158 myismin = myLocExtPC.IsMin();
159 mydist2 = myLocExtPC.SquareDistance();
162 Standard_Integer k = 1;
163 // Essai sur les intervalles alentours:
166 Standard_Real s1inf, s2inf, s1sup, s2sup;
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);
175 while (!myDone && (i2 > 0) && (i1 <= n))
181 myintuinf = Max(theInter(i1), myumin);
182 myintusup = Min(theInter(i1+1), myusup);
183 if (myintuinf < myintusup)
185 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
186 s2sup = (TheVector(P, P1)*V1);
187 if (s1sup*s2sup <= RealEpsilon())
190 myDone = Standard_True;
191 mypp.SetValues(myintuinf, P1);
192 myismin = (s1sup <= 0.0);
193 mydist2 = P.SquareDistance(P1);
197 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
198 s1sup = (TheVector(P, P1)*V1);
199 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
201 myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
202 myDone = myLocExtPC.IsDone();
204 mypp = myLocExtPC.Point();
205 myismin = myLocExtPC.IsMin();
206 mydist2 = myLocExtPC.SquareDistance();
214 myintuinf = Max(theInter(i2), myumin);
215 myintusup = Min(theInter(i2+1), myusup);
216 if (myintuinf < myintusup)
218 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
219 s1inf = (TheVector(P, P1)*V1);
220 if (s1inf*s2inf <= RealEpsilon())
223 myDone = Standard_True;
224 mypp.SetValues(myintusup, P1);
225 myismin = (s1inf <= 0.0);
226 mydist2 = P.SquareDistance(P1);
230 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
231 s2inf = (TheVector(P, P1)*V1);
232 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
234 myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
235 myDone = myLocExtPC.IsDone();
239 mypp = myLocExtPC.Point();
240 myismin = myLocExtPC.IsMin();
241 mydist2 = myLocExtPC.SquareDistance();
254 case GeomAbs_BezierCurve:
256 myLocExtPC.Perform(P, U0);
257 myDone = myLocExtPC.IsDone();
263 myExtremPC.Perform(P);
265 if (myExtremPC.IsDone())
267 for (i = 1; i <= myExtremPC.NbExt(); i++)
269 Par = myExtremPC.Point(i).Parameter();
270 valU = Abs(Par - U0);
275 myDone = Standard_True;
281 myDone = Standard_False;
291 //=======================================================================
294 //=======================================================================
296 Standard_Boolean Extrema_GLocateExtPC::IsDone () const
302 //=======================================================================
305 //=======================================================================
307 Standard_Real Extrema_GLocateExtPC::SquareDistance () const
309 if (!myDone) { StdFail_NotDone::Raise(); }
311 if ((type == GeomAbs_BezierCurve)) {
312 d = myLocExtPC.SquareDistance();
314 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
318 if (numberext != 0) {
319 d = myExtremPC.SquareDistance(numberext);
326 //=======================================================================
329 //=======================================================================
331 Standard_Boolean Extrema_GLocateExtPC::IsMin () const
333 if (!myDone) { StdFail_NotDone::Raise(); }
334 Standard_Boolean b=0;
335 if ((type == GeomAbs_BezierCurve)) {
336 b = myLocExtPC.IsMin();
338 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
342 if (numberext != 0) {
343 b = myExtremPC.IsMin(numberext);
350 //=======================================================================
353 //=======================================================================
355 const ThePOnC & Extrema_GLocateExtPC::Point () const
357 if (!myDone) { StdFail_NotDone::Raise(); }
358 if (type == GeomAbs_BezierCurve) {
359 return myLocExtPC.Point();
361 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
364 return myExtremPC.Point(numberext);