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 under
9 // the terms of the GNU Lesser General Public License 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 myismin(Standard_False),
43 myDone(Standard_False),
47 type(GeomAbs_OtherCurve),
53 //=======================================================================
54 //function : Extrema_GLocateExtPC
56 //=======================================================================
58 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
60 const Standard_Real U0,
61 const Standard_Real TolF)
63 Initialize(C, TheCurveTool::FirstParameter(C), TheCurveTool::LastParameter(C), TolF);
67 //=======================================================================
68 //function : Extrema_GLocateExtPC
70 //=======================================================================
72 Extrema_GLocateExtPC::Extrema_GLocateExtPC (const ThePoint& P,
74 const Standard_Real U0,
75 const Standard_Real Umin,
76 const Standard_Real Usup,
77 const Standard_Real TolF)
79 Initialize(C, Umin, Usup, TolF);
85 //=======================================================================
86 //function : Initialize
88 //=======================================================================
90 void Extrema_GLocateExtPC::Initialize(const TheCurve& C,
91 const Standard_Real Umin,
92 const Standard_Real Usup,
93 const Standard_Real TolF)
95 myC = (Standard_Address)&C;
99 type = TheCurveTool::GetType(C);
100 Standard_Real tolu = TheCurveTool::Resolution(C, Precision::Confusion());
101 if ((type == GeomAbs_BSplineCurve) ||
102 (type == GeomAbs_BezierCurve) ||
103 (type == GeomAbs_OffsetCurve) ||
104 (type == GeomAbs_OtherCurve))
106 myLocExtPC.Initialize(C, Umin, Usup, tolu);
109 myExtremPC.Initialize(C, Umin, Usup, tolu);
116 //=======================================================================
119 //=======================================================================
121 void Extrema_GLocateExtPC::Perform(const ThePoint& P,
122 const Standard_Real U0)
124 Standard_Integer i, i1, i2, inter;
125 Standard_Real Par, valU, valU2 = RealLast(),
127 Standard_Real myintuinf=0, myintusup=0;
131 case GeomAbs_OtherCurve:
132 case GeomAbs_OffsetCurve:
133 case GeomAbs_BSplineCurve:
135 // La recherche de l extremum est faite intervalle continu C2 par
136 // intervalle continu C2 de la courbe
137 Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
138 TColStd_Array1OfReal theInter(1, n+1);
139 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
141 // be gentle with the caller
143 if (local_u0 < myumin) {
146 else if (local_u0 > myusup) {
149 // Recherche de l intervalle ou se trouve U0
150 Standard_Boolean found = Standard_False;
152 while (!found && inter <= n) {
153 // Intervalle commun a l intervalle C2 courant de la courbe et a
154 // l intervalle total de recherche de l'extremum (hla : au cas ou
155 // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent
156 // pas, mais il n'y avait aucune raison de sortir en "return")
157 myintuinf = Max(theInter(inter), myumin);
158 myintusup = Min(theInter(inter+1), myusup);
159 if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True;
163 if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
165 // Essai sur l intervalle trouve
166 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
168 myLocExtPC.Perform(P, local_u0);
169 myDone = myLocExtPC.IsDone();
171 mypp = myLocExtPC.Point();
172 myismin = myLocExtPC.IsMin();
173 mydist2 = myLocExtPC.SquareDistance();
176 Standard_Integer k = 1;
177 // Essai sur les intervalles alentours:
180 Standard_Real s1inf, s2inf, s1sup, s2sup;
183 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
184 s2inf = (TheVector(P, P1)*V1);
185 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
186 s1sup = (TheVector(P, P1)*V1);
189 while (!myDone && (i2 > 0) && (i1 <= n))
195 myintuinf = Max(theInter(i1), myumin);
196 myintusup = Min(theInter(i1+1), myusup);
197 if (myintuinf < myintusup)
199 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
200 s2sup = (TheVector(P, P1)*V1);
201 if(Precision::IsInfinite(s2sup) || Precision::IsInfinite(s1sup))
205 if (s1sup*s2sup <= RealEpsilon())
208 myDone = Standard_True;
209 mypp.SetValues(myintuinf, P1);
210 myismin = (s1sup <= 0.0);
211 mydist2 = P.SquareDistance(P1);
215 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
216 s1sup = (TheVector(P, P1)*V1);
217 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
219 myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
220 myDone = myLocExtPC.IsDone();
222 mypp = myLocExtPC.Point();
223 myismin = myLocExtPC.IsMin();
224 mydist2 = myLocExtPC.SquareDistance();
232 myintuinf = Max(theInter(i2), myumin);
233 myintusup = Min(theInter(i2+1), myusup);
234 if (myintuinf < myintusup)
236 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
237 s1inf = (TheVector(P, P1)*V1);
238 if(Precision::IsInfinite(s2inf) || Precision::IsInfinite(s1inf))
242 if (s1inf*s2inf <= RealEpsilon())
245 myDone = Standard_True;
246 mypp.SetValues(myintusup, P1);
247 myismin = (s1inf <= 0.0);
248 mydist2 = P.SquareDistance(P1);
252 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
253 s2inf = (TheVector(P, P1)*V1);
254 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
256 myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
257 myDone = myLocExtPC.IsDone();
261 mypp = myLocExtPC.Point();
262 myismin = myLocExtPC.IsMin();
263 mydist2 = myLocExtPC.SquareDistance();
276 case GeomAbs_BezierCurve:
278 myLocExtPC.Perform(P, U0);
279 myDone = myLocExtPC.IsDone();
285 myExtremPC.Perform(P);
287 if (myExtremPC.IsDone())
289 for (i = 1; i <= myExtremPC.NbExt(); i++)
291 Par = myExtremPC.Point(i).Parameter();
292 valU = Abs(Par - U0);
297 myDone = Standard_True;
303 myDone = Standard_False;
313 //=======================================================================
316 //=======================================================================
318 Standard_Boolean Extrema_GLocateExtPC::IsDone () const
324 //=======================================================================
327 //=======================================================================
329 Standard_Real Extrema_GLocateExtPC::SquareDistance () const
333 throw StdFail_NotDone();
336 if ((type == GeomAbs_BezierCurve)) {
337 d = myLocExtPC.SquareDistance();
339 else if(type == GeomAbs_BSplineCurve ||
340 type == GeomAbs_OffsetCurve ||
341 type == GeomAbs_OtherCurve) {
345 if (numberext != 0) {
346 d = myExtremPC.SquareDistance(numberext);
353 //=======================================================================
356 //=======================================================================
358 Standard_Boolean Extrema_GLocateExtPC::IsMin () const
362 throw StdFail_NotDone();
364 Standard_Boolean b = 0;
365 if ((type == GeomAbs_BezierCurve)) {
366 b = myLocExtPC.IsMin();
368 else if(type == GeomAbs_BSplineCurve ||
369 type == GeomAbs_OffsetCurve ||
370 type == GeomAbs_OtherCurve) {
374 if (numberext != 0) {
375 b = myExtremPC.IsMin(numberext);
382 //=======================================================================
385 //=======================================================================
387 const ThePOnC & Extrema_GLocateExtPC::Point () const
391 throw StdFail_NotDone();
393 if (type == GeomAbs_BezierCurve)
395 return myLocExtPC.Point();
397 else if(type == GeomAbs_BSplineCurve ||
398 type == GeomAbs_OffsetCurve ||
399 type == GeomAbs_OtherCurve) {
402 return myExtremPC.Point(numberext);