1 // Created on: 1992-10-19
2 // Created by: Laurent PAINNOT
3 // Copyright (c) 1992-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 // Modified by cma, Fri Dec 10 18:11:56 1993
23 #include Extrema_EPC_hxx
25 #include TheSequenceOfPOnC_hxx
27 #include TheVector_hxx
28 #include TheExtPElC_hxx
29 #include <StdFail_NotDone.hxx>
30 #include <Standard_Failure.hxx>
31 #include <GeomAbs_CurveType.hxx>
32 #include <Precision.hxx>
34 #include <TColStd_Array1OfReal.hxx>
37 //=======================================================================
40 //=======================================================================
42 void Extrema_GExtPC::Perform(const ThePoint& P)
47 Standard_Integer i, NbExt, n;
50 Standard_Real t3d = Precision::Confusion();
51 if (Precision::IsInfinite(myuinf)) mydist1 = RealLast();
53 Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf);
54 mydist1 = P.SquareDistance(Pf);
57 if (Precision::IsInfinite(myusup)) mydist2 = RealLast();
59 Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup);
60 mydist2 = P.SquareDistance(Pl);
66 myExtPElC.Perform(P, TheCurveTool::Circle(*((TheCurve*)myC)), t3d, myuinf, myusup);
71 myExtPElC.Perform(P, TheCurveTool::Ellipse(*((TheCurve*)myC)), t3d, myuinf, myusup);
74 case GeomAbs_Parabola:
76 myExtPElC.Perform(P, TheCurveTool::Parabola(*((TheCurve*)myC)), t3d,myuinf,myusup);
79 case GeomAbs_Hyperbola:
81 myExtPElC.Perform(P,TheCurveTool::Hyperbola(*((TheCurve*)myC)),t3d, myuinf, myusup);
86 myExtPElC.Perform(P, TheCurveTool::Line(*((TheCurve*)myC)), t3d, myuinf, myusup);
89 case GeomAbs_BezierCurve:
93 mysample = (TheCurveTool::Bezier(*((TheCurve*)myC)))->NbPoles()*2;
97 case GeomAbs_BSplineCurve:
99 mysample = (TheCurveTool::BSpline(*((TheCurve*)myC)))->NbPoles()*2;
101 case GeomAbs_OtherCurve:
103 Standard_Boolean IntExtIsDone = Standard_False;
104 Standard_Boolean IntIsNotValid;
105 n = TheCurveTool::NbIntervals(*((TheCurve*)myC), GeomAbs_C2);
106 TColStd_Array1OfReal theInter(1, n+1);
107 Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(*((TheCurve*)myC));
108 Standard_Real aPeriodicShift = 0.;
109 TheCurveTool::Intervals(*((TheCurve*)myC), theInter, GeomAbs_C2);
110 mysample = Max(mysample/n, 17);
113 Standard_Real s1 = 0.0 ;
114 Standard_Real s2 = 0.0;
115 for (i = 1; i <= n; i++) {
116 myintuinf = theInter(i);
117 myintusup = theInter(i+1);
119 Standard_Real anInfToCheck = myintuinf;
120 Standard_Real aSupToCheck = myintusup;
123 Standard_Real aPeriod = TheCurveTool::Period(*((TheCurve*)myC));
124 anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod);
125 aSupToCheck = myintusup+(anInfToCheck-myintuinf);
127 IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck);
129 if(IntIsNotValid) continue;
131 if (myuinf >= anInfToCheck) anInfToCheck = myuinf;
132 if (myusup <= aSupToCheck) aSupToCheck = myusup;
133 if((aSupToCheck - anInfToCheck) <= mytolu) continue;
137 TheCurveTool::D1(*((TheCurve*)myC), myintuinf, PP, V1);
138 s1 = (TheVector(P, PP))*V1;
140 mySqDist.Append(PP.SquareDistance(P));
141 myismin.Append((s1 < 0.0));
142 mypoint.Append(ThePOnC(myintuinf, PP));
146 TheCurveTool::D1(*((TheCurve*)myC), myintusup, PP, V1);
147 s2 = (TheVector(P, PP))*V1;
151 IntExtIsDone = IntExtIsDone || mydone;
153 mydone = IntExtIsDone;
159 mydone = myExtPElC.IsDone();
161 NbExt = myExtPElC.NbExt();
162 for (i = 1; i <= NbExt; i++) {
163 // Verification de la validite des parametres:
164 ThePOnC PC = myExtPElC.Point(i);
166 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
167 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
169 if ((U >= myuinf-mytolu) && (U <= myusup+mytolu)){
170 PC.SetValues(U, myExtPElC.Point(i).Value());
171 mySqDist.Append(myExtPElC.SquareDistance(i));
172 myismin.Append(myExtPElC.IsMin(i));
180 //=======================================================================
181 //function : Initialize
183 //=======================================================================
185 void Extrema_GExtPC::Initialize(const TheCurve& C,
186 const Standard_Real Uinf,
187 const Standard_Real Usup,
188 const Standard_Real TolF)
190 myC = (Standard_Address)&C;
191 myintuinf = myuinf = Uinf;
192 myintusup = myusup = Usup;
194 mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
195 type = TheCurveTool::GetType(C);
196 mydone = Standard_False;
197 mydist1 = RealLast();
198 mydist2 = RealLast();
203 //=======================================================================
204 //function : IntervalPerform
206 //=======================================================================
208 void Extrema_GExtPC::IntervalPerform(const ThePoint& P)
212 myExtPC.Initialize((*((TheCurve*)myC)), mysample,
213 myintuinf, myintusup, mytolu, mytolf);
215 mydone = myExtPC.IsDone();
217 Standard_Integer NbExt = myExtPC.NbExt();
218 for (i = 1; i <= NbExt; i++) {
219 // Verification de la validite des parametres pour le cas trimme:
220 ThePOnC PC = myExtPC.Point(i);
222 if (TheCurveTool::IsPeriodic(*((TheCurve*)myC))) {
223 U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
225 if ((U >= myuinf - mytolu) && (U <= myusup + mytolu)) {
226 PC.SetValues(U, PC.Value());
227 mySqDist.Append(myExtPC.SquareDistance(i));
228 myismin.Append(myExtPC.IsMin(i));
238 //=======================================================================
239 //function : Extrema_GExtPC
241 //=======================================================================
243 Extrema_GExtPC::Extrema_GExtPC()
246 mydone = Standard_False;
247 mydist1 = RealLast();
248 mydist2 = RealLast();
252 myintuinf = myintusup = myuinf = myusup = Precision::Infinite();
253 type = GeomAbs_OtherCurve;
256 //=======================================================================
257 //function : Extrema_GExtPC
259 //=======================================================================
261 Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
263 const Standard_Real Uinf,
264 const Standard_Real Usup,
265 const Standard_Real TolF)
267 Initialize(C, Uinf, Usup, TolF);
271 //=======================================================================
272 //function : Extrema_GExtPC
274 //=======================================================================
276 Extrema_GExtPC::Extrema_GExtPC(const ThePoint& P,
278 const Standard_Real TolF)
280 Initialize(C, TheCurveTool::FirstParameter(C),
281 TheCurveTool::LastParameter(C), TolF);
286 //=======================================================================
289 //=======================================================================
291 Standard_Boolean Extrema_GExtPC::IsDone() const
297 //=======================================================================
300 //=======================================================================
302 Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const
304 if(!mydone) StdFail_NotDone::Raise();
305 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
306 return mySqDist.Value(N);
310 //=======================================================================
313 //=======================================================================
315 Standard_Integer Extrema_GExtPC::NbExt() const
317 if(!mydone) StdFail_NotDone::Raise();
318 return mySqDist.Length();
322 //=======================================================================
325 //=======================================================================
327 Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const
329 if(!mydone) StdFail_NotDone::Raise();
330 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
331 return myismin.Value(N);
336 //=======================================================================
339 //=======================================================================
341 ThePOnC Extrema_GExtPC::Point(const Standard_Integer N) const
343 if(!mydone) StdFail_NotDone::Raise();
344 if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise();
345 return mypoint.Value(N);
349 //=======================================================================
350 //function : TrimmedDistances
352 //=======================================================================
354 void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1,
355 Standard_Real& dist2,