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;
117 Standard_Real Tol = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
119 TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
121 Standard_Real Par, valU, valU2 = RealLast(),
123 Standard_Real myintuinf=0, myintusup=0;
126 case GeomAbs_OtherCurve:
127 case GeomAbs_BSplineCurve: {
128 // La recherche de l extremum est faite intervalle continu C2 par
129 // intervalle continu C2 de la courbe
130 Standard_Integer n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
131 TColStd_Array1OfReal theInter(1, n+1);
132 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
134 // be gentle with the caller
136 if (local_u0 < myumin) {
139 else if (local_u0 > myusup) {
142 // Recherche de l intervalle ou se trouve U0
143 Standard_Boolean found = Standard_False;
145 while (!found && inter <= n) {
146 // Intervalle commun a l intervalle C2 courant de la courbe et a
147 // l intervalle total de recherche de l'extremum (hla : au cas ou
148 // myintuinf > myintusup, c est que les 2 intervalles ne s intersectent
149 // pas, mais il n'y avait aucune raison de sortir en "return")
150 myintuinf = Max(theInter(inter), myumin);
151 myintusup = Min(theInter(inter+1), myusup);
152 if ((local_u0 >= myintuinf) && (local_u0 < myintusup)) found = Standard_True;
156 if( found ) inter--; //IFV 16.06.00 - inter is increased after found!
158 // Essai sur l intervalle trouve
159 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
161 myLocExtPC.Perform(P, local_u0);
162 myDone = myLocExtPC.IsDone();
164 mypp = myLocExtPC.Point();
165 myismin = myLocExtPC.IsMin();
166 mydist2 = myLocExtPC.SquareDistance();
169 Standard_Integer k = 1;
170 // Essai sur les intervalles alentours:
173 Standard_Real s1inf, s2inf, s1sup, s2sup;
176 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
177 s2inf = (TheVector(P, P1)*V1);
178 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
179 s1sup = (TheVector(P, P1)*V1);
182 while (!myDone && (i2 > 0) && (i1 <= n)) {
186 myintuinf = Max(theInter(i1), myumin);
187 myintusup = Min(theInter(i1+1), myusup);
188 if (myintuinf < myintusup) {
189 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
190 s2sup = (TheVector(P, P1)*V1);
191 if (s1sup*s2sup <= RealEpsilon()) {
193 myDone = Standard_True;
194 mypp.SetValues(myintuinf, P1);
195 myismin = (s1sup <= 0.0);
196 mydist2 = P.SquareDistance(P1);
199 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
200 s1sup = (TheVector(P, P1)*V1);
201 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
203 myLocExtPC.Perform(P, (myintuinf + myintusup)*0.5);
204 myDone = myLocExtPC.IsDone();
206 mypp = myLocExtPC.Point();
207 myismin = myLocExtPC.IsMin();
208 mydist2 = myLocExtPC.SquareDistance();
214 myintuinf = Max(theInter(i2), myumin);
215 myintusup = Min(theInter(i2+1), myusup);
216 if (myintuinf < myintusup) {
217 TheCurveTool::D1(*((TheCurve*)myC), myintusup, P1, V1);
218 s1inf = (TheVector(P, P1)*V1);
219 if (s1inf*s2inf <= RealEpsilon()) {
221 myDone = Standard_True;
222 mypp.SetValues(myintusup, P1);
223 myismin = (s1inf <= 0.0);
224 mydist2 = P.SquareDistance(P1);
227 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, P1, V1);
228 s2inf = (TheVector(P, P1)*V1);
229 myLocExtPC.Initialize((*((TheCurve*)myC)), myintuinf,
231 myLocExtPC.Perform(P, (myintuinf+myintusup)*0.5 );
232 myDone = myLocExtPC.IsDone();
234 mypp = myLocExtPC.Point();
235 myismin = myLocExtPC.IsMin();
236 mydist2 = myLocExtPC.SquareDistance();
246 case GeomAbs_BezierCurve: {
247 myLocExtPC.Perform(P, U0);
248 myDone = myLocExtPC.IsDone();
252 myExtremPC.Perform(P);
254 if (myExtremPC.IsDone()) {
255 for (i = 1; i <= myExtremPC.NbExt(); i++) {
256 Par = myExtremPC.Point(i).Parameter();
257 valU = Abs(Par - U0);
261 myDone = Standard_True;
265 if (numberext == 0) myDone = Standard_False;
274 //=======================================================================
277 //=======================================================================
279 Standard_Boolean Extrema_GLocateExtPC::IsDone () const
285 //=======================================================================
288 //=======================================================================
290 Standard_Real Extrema_GLocateExtPC::SquareDistance () const
292 if (!myDone) { StdFail_NotDone::Raise(); }
294 if ((type == GeomAbs_BezierCurve)) {
295 d = myLocExtPC.SquareDistance();
297 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
301 if (numberext != 0) {
302 d = myExtremPC.SquareDistance(numberext);
309 //=======================================================================
312 //=======================================================================
314 Standard_Boolean Extrema_GLocateExtPC::IsMin () const
316 if (!myDone) { StdFail_NotDone::Raise(); }
317 Standard_Boolean b=0;
318 if ((type == GeomAbs_BezierCurve)) {
319 b = myLocExtPC.IsMin();
321 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
325 if (numberext != 0) {
326 b = myExtremPC.IsMin(numberext);
333 //=======================================================================
336 //=======================================================================
338 ThePOnC Extrema_GLocateExtPC::Point () const
340 if (!myDone) { StdFail_NotDone::Raise(); }
342 if (type == GeomAbs_BezierCurve) {
343 P = myLocExtPC.Point();
345 else if(type == GeomAbs_BSplineCurve || type == GeomAbs_OtherCurve) {
349 if (numberext != 0) {
350 P = myExtremPC.Point(numberext);