1 // Created on: 1992-10-19
2 // Created by: Laurent PAINNOT
3 // Copyright (c) 1992-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 // Modified by cma, Fri Dec 10 18:11:56 1993
19 #include Extrema_EPC_hxx
21 #include TheSequenceOfPOnC_hxx
23 #include TheVector_hxx
24 #include TheExtPElC_hxx
25 #include <StdFail_NotDone.hxx>
26 #include <Standard_Failure.hxx>
27 #include <GeomAbs_CurveType.hxx>
28 #include <Precision.hxx>
30 #include <TColStd_Array1OfReal.hxx>
33 //=======================================================================
36 //=======================================================================
38 void Extrema_GExtPC::Perform(const ThePoint& P)
43 Standard_Integer i, NbExt, n;
46 Standard_Real t3d = Precision::Confusion();
47 if (Precision::IsInfinite(myuinf)) mydist1 = RealLast();
49 Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf);
50 mydist1 = P.SquareDistance(Pf);
53 if (Precision::IsInfinite(myusup)) mydist2 = RealLast();
55 Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup);
56 mydist2 = P.SquareDistance(Pl);
62 myExtPElC.Perform(P, TheCurveTool::Circle(*((TheCurve*)myC)), t3d, myuinf, myusup);
67 myExtPElC.Perform(P, TheCurveTool::Ellipse(*((TheCurve*)myC)), t3d, myuinf, myusup);
70 case GeomAbs_Parabola:
72 myExtPElC.Perform(P, TheCurveTool::Parabola(*((TheCurve*)myC)), t3d,myuinf,myusup);
75 case GeomAbs_Hyperbola:
77 myExtPElC.Perform(P,TheCurveTool::Hyperbola(*((TheCurve*)myC)),t3d, myuinf, myusup);
82 myExtPElC.Perform(P, TheCurveTool::Line(*((TheCurve*)myC)), t3d, myuinf, myusup);
85 case GeomAbs_BezierCurve:
89 mysample = (TheCurveTool::Bezier(*((TheCurve*)myC)))->NbPoles()*2;
93 case GeomAbs_BSplineCurve:
95 mysample = (TheCurveTool::BSpline(*((TheCurve*)myC)))->NbPoles()*2;
97 case GeomAbs_OtherCurve:
99 Standard_Boolean IntExtIsDone = Standard_False;
100 Standard_Boolean IntIsNotValid;
101 n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
102 TColStd_Array1OfReal theInter(1, n+1);
103 Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(*((TheCurve*)myC));
104 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
105 mysample = Max(mysample/n, 17);
108 Standard_Real s1 = 0.0 ;
109 Standard_Real s2 = 0.0;
110 for (i = 1; i <= n; i++) {
111 myintuinf = theInter(i);
112 myintusup = theInter(i+1);
114 Standard_Real anInfToCheck = myintuinf;
115 Standard_Real aSupToCheck = myintusup;
118 Standard_Real aPeriod = TheCurveTool::Period(*((TheCurve*)myC));
119 anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod);
120 aSupToCheck = myintusup+(anInfToCheck-myintuinf);
122 IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck);
124 if(IntIsNotValid) continue;
126 if (myuinf >= anInfToCheck) anInfToCheck = myuinf;
127 if (myusup <= aSupToCheck) aSupToCheck = myusup;
128 if((aSupToCheck - anInfToCheck) <= mytolu) continue;
132 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, PP, V1);
133 s1 = (TheVector(P, PP))*V1;
135 mySqDist.Append(PP.SquareDistance(P));
136 myismin.Append((s1 < 0.0));
137 mypoint.Append(ThePOnC(myintuinf, PP));
141 TheCurveTool::D1(*((TheCurve*)myC), myintusup, PP, V1);
142 s2 = (TheVector(P, PP))*V1;
146 IntExtIsDone = IntExtIsDone || mydone;
148 mydone = IntExtIsDone;
150 // Additional checking if the point is on the first or last point of the curve and does not added yet
151 if (mydist1 < Precision::SquareConfusion() || mydist2 < Precision::SquareConfusion())
153 Standard_Boolean isFirstAdded = Standard_False;
154 Standard_Boolean isLastAdded = Standard_False;
155 Standard_Integer aNbPoints = mypoint.Length();
156 for (i = 1; i <= aNbPoints; i++)
158 U = mypoint.Value(i).Parameter();
159 if (Abs(U - myuinf) < mytolu)
160 isFirstAdded = Standard_True;
161 else if (Abs(myusup - U) < mytolu)
162 isLastAdded = Standard_True;
164 if (!isFirstAdded && mydist1 < Precision::SquareConfusion())
166 mySqDist.Prepend(mydist1);
167 myismin.Prepend(Standard_True);
168 mypoint.Prepend(ThePOnC(myuinf, Pf));
170 if (!isLastAdded && mydist2 < Precision::SquareConfusion())
172 mySqDist.Append(mydist2);
173 myismin.Append(Standard_True);
174 mypoint.Append(ThePOnC(myusup, Pl));
182 mydone = myExtPElC.IsDone();
184 NbExt = myExtPElC.NbExt();
185 for (i = 1; i <= NbExt; i++) {
186 // Verification de la validite des parametres:
187 ThePOnC PC = myExtPElC.Point(i);
189 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
190 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
192 if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)){
193 PC.SetValues(U, myExtPElC.Point(i).Value());
194 mySqDist.Append(myExtPElC.SquareDistance(i));
195 myismin.Append(myExtPElC.IsMin(i));
203 //=======================================================================
204 //function : Initialize
206 //=======================================================================
208 void Extrema_GExtPC::Initialize(const TheCurve& C,
209 const Standard_Real Uinf,
210 const Standard_Real Usup,
211 const Standard_Real TolF)
213 myC = (Standard_Address)&C;
214 myintuinf = myuinf = Uinf;
215 myintusup = myusup = Usup;
217 mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
218 type = TheCurveTool::GetType(C);
219 mydone = Standard_False;
220 mydist1 = RealLast();
221 mydist2 = RealLast();
226 //=======================================================================
227 //function : IntervalPerform
229 //=======================================================================
231 void Extrema_GExtPC::IntervalPerform(const ThePoint& P)
235 myExtPC.Initialize((*((TheCurve*)myC)), mysample,
236 myintuinf, myintusup, mytolu, mytolf);
238 mydone = myExtPC.IsDone();
240 Standard_Integer NbExt = myExtPC.NbExt();
241 for (i = 1; i <= NbExt; i++) {
242 // Verification de la validite des parametres pour le cas trimme:
243 ThePOnC PC = myExtPC.Point(i);
245 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
246 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
248 if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) {
249 PC.SetValues(U, PC.Value());
250 mySqDist.Append(myExtPC.SquareDistance(i));
251 myismin.Append(myExtPC.IsMin(i));
261 //=======================================================================
262 //function : Extrema_GExtPC
264 //=======================================================================
266 Extrema_GExtPC::Extrema_GExtPC()
269 mydone = Standard_False;
270 mydist1 = RealLast();
271 mydist2 = RealLast();
275 myintuinf = myintusup = myuinf = myusup = Precision::Infinite();
276 type = GeomAbs_OtherCurve;
279 //=======================================================================
280 //function : Extrema_GExtPC
282 //=======================================================================
284 Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
286 const Standard_Real Uinf,
287 const Standard_Real Usup,
288 const Standard_Real TolF)
290 Initialize(C, Uinf, Usup, TolF);
294 //=======================================================================
295 //function : Extrema_GExtPC
297 //=======================================================================
299 Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
301 const Standard_Real TolF)
303 Initialize(C, TheCurveTool::FirstParameter(C),
304 TheCurveTool::LastParameter(C), TolF);
309 //=======================================================================
312 //=======================================================================
314 Standard_Boolean Extrema_GExtPC::IsDone() const
320 //=======================================================================
323 //=======================================================================
325 Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const
327 if(!mydone) StdFail_NotDone::Raise();
328 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
329 return mySqDist.Value(N);
333 //=======================================================================
336 //=======================================================================
338 Standard_Integer Extrema_GExtPC::NbExt() const
340 if(!mydone) StdFail_NotDone::Raise();
341 return mySqDist.Length();
345 //=======================================================================
348 //=======================================================================
350 Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const
352 if(!mydone) StdFail_NotDone::Raise();
353 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
354 return myismin.Value(N);
359 //=======================================================================
362 //=======================================================================
364 const ThePOnC & Extrema_GExtPC::Point(const Standard_Integer N) const
366 if(!mydone) StdFail_NotDone::Raise();
367 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
368 return mypoint.Value(N);
372 //=======================================================================
373 //function : TrimmedDistances
375 //=======================================================================
377 void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1,
378 Standard_Real& dist2,