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
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.
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.
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.
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
27 #include Extrema_ELPC_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>
38 //=======================================================================
39 //function : Extrema_GLocateExtPC
41 //=======================================================================
43 Extrema_GLocateExtPC::Extrema_GLocateExtPC() { }
46 //=======================================================================
47 //function : Extrema_GLocateExtPC
49 //=======================================================================
51 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
53 const Standard_Real U0,
54 const Standard_Real TolF)
56 Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF);
60 //=======================================================================
61 //function : Extrema_GLocateExtPC
63 //=======================================================================
65 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
67 const Standard_Real U0,
68 const Standard_Real Umin,
69 const Standard_Real Usup,
70 const Standard_Real TolF)
72 Initialize(C, Umin, Usup, TolF);
78 //=======================================================================
79 //function : Initialize
81 //=======================================================================
83 void Extrema_GLocateExtPC::Initialize(const TheCurve& C,
84 const Standard_Real Umin,
85 const Standard_Real Usup,
86 const Standard_Real TolF)
88 myC = (Standard_Address)&C;
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);
100 myExtremPC.Initialize(C, Umin, Usup, tolu);
107 //=======================================================================
110 //=======================================================================
112 void Extrema_GLocateExtPC::Perform(const ThePoint& P,
113 const Standard_Real U0)
115 Standard_Integer i, i1, i2, inter;
116 Standard_Real Par, valU, valU2 = RealLast(),
118 Standard_Real myintuinf=0, myintusup=0;
121 case GeomAbs_OtherCurve:
122 case GeomAbs_BSplineCurve: {
123 // La recherche de l extremum est faite intervalle continu C2 par
124 // intervalle continu C2 de la courbe
125 Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
126 TColStd_Array1OfReal theInter(1, n+1);
127 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
129 // be gentle with the caller
131 if (local_u0 < myumin) {
134 else if (local_u0 > myusup) {
137 // Recherche de l intervalle ou se trouve U0
138 Standard_Boolean found = Standard_False;
140 while (!found && inter <= n) {
141 // Intervalle commun a l intervalle C2 courant de la courbe et a
142 // l intervalle total de recherche de l'extremum (hla : au cas ou
143 // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent
144 // pas, mais il n'y avait aucune raison de sortir en "return")
145 myintuinf = Max(theInter(inter), myumin);
146 myintusup = Min(theInter(inter+1), myusup);
147 if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True;
151 if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
153 // Essai sur l intervalle trouve
154 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
156 myLocExtPC.Perform(P, local_u0);
157 myDone = myLocExtPC.IsDone();
159 mypp = myLocExtPC.Point();
160 myismin = myLocExtPC.IsMin();
161 mydist2 = myLocExtPC.SquareDistance();
164 Standard_Integer k = 1;
165 // Essai sur les intervalles alentours:
168 Standard_Real s1inf, s2inf, s1sup, s2sup;
171 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
172 s2inf = (TheVector(P, P1)*V1);
173 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
174 s1sup = (TheVector(P, P1)*V1);
177 while (!myDone && (i2 > 0) && (i1 <= n)) {
181 myintuinf = Max(theInter(i1), myumin);
182 myintusup = Min(theInter(i1+1), myusup);
183 if (myintuinf < myintusup) {
184 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
185 s2sup = (TheVector(P, P1)*V1);
186 if (s1sup*s2sup <= RealEpsilon()) {
188 myDone = Standard_True;
189 mypp.SetValues(myintuinf, P1);
190 myismin = (s1sup <= 0.0);
191 mydist2 = P.SquareDistance(P1);
194 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
195 s1sup = (TheVector(P, P1)*V1);
196 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
198 myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
199 myDone = myLocExtPC.IsDone();
201 mypp = myLocExtPC.Point();
202 myismin = myLocExtPC.IsMin();
203 mydist2 = myLocExtPC.SquareDistance();
209 myintuinf = Max(theInter(i2), myumin);
210 myintusup = Min(theInter(i2+1), myusup);
211 if (myintuinf < myintusup) {
212 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
213 s1inf = (TheVector(P, P1)*V1);
214 if (s1inf*s2inf <= RealEpsilon()) {
216 myDone = Standard_True;
217 mypp.SetValues(myintusup, P1);
218 myismin = (s1inf <= 0.0);
219 mydist2 = P.SquareDistance(P1);
222 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
223 s2inf = (TheVector(P, P1)*V1);
224 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
226 myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
227 myDone = myLocExtPC.IsDone();
229 mypp = myLocExtPC.Point();
230 myismin = myLocExtPC.IsMin();
231 mydist2 = myLocExtPC.SquareDistance();
241 case GeomAbs_BezierCurve: {
242 myLocExtPC.Perform(P, U0);
243 myDone = myLocExtPC.IsDone();
247 myExtremPC.Perform(P);
249 if (myExtremPC.IsDone()) {
250 for (i = 1; i <= myExtremPC.NbExt(); i++) {
251 Par = myExtremPC.Point(i).Parameter();
252 valU = Abs(Par - U0);
256 myDone = Standard_True;
260 if (numberext == 0) myDone = Standard_False;
269 //=======================================================================
272 //=======================================================================
274 Standard_Boolean Extrema_GLocateExtPC::IsDone () const
280 //=======================================================================
283 //=======================================================================
285 Standard_Real Extrema_GLocateExtPC::SquareDistance () const
287 if (!myDone) { StdFail_NotDone::Raise(); }
289 if ((type == GeomAbs_BezierCurve)) {
290 d = myLocExtPC.SquareDistance();
292 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
296 if (numberext != 0) {
297 d = myExtremPC.SquareDistance(numberext);
304 //=======================================================================
307 //=======================================================================
309 Standard_Boolean Extrema_GLocateExtPC::IsMin () const
311 if (!myDone) { StdFail_NotDone::Raise(); }
312 Standard_Boolean b=0;
313 if ((type == GeomAbs_BezierCurve)) {
314 b = myLocExtPC.IsMin();
316 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
320 if (numberext != 0) {
321 b = myExtremPC.IsMin(numberext);
328 //=======================================================================
331 //=======================================================================
333 ThePOnC Extrema_GLocateExtPC::Point () const
335 if (!myDone) { StdFail_NotDone::Raise(); }
337 if (type == GeomAbs_BezierCurve) {
338 P = myLocExtPC.Point();
340 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
344 if (numberext != 0) {
345 P = myExtremPC.Point(numberext);