0031682: Visualization - Prs3d_ShadingAspect::SetTransparency() has no effect with...
[occt.git] / src / Extrema / Extrema_GExtPC.gxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified by cma, Fri Dec 10 18:11:56 1993
18
19 #include Extrema_EPC_hxx
20 #include ThePOnC_hxx
21 #include TheSequenceOfPOnC_hxx
22 #include ThePoint_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>
29 #include <ElCLib.hxx>
30 #include <TColStd_Array1OfReal.hxx>
31 #include <TColStd_HArray1OfReal.hxx>
32 #include <NCollection_Array1.hxx>
33
34
35 //=======================================================================
36 //function : Perform
37 //purpose  : 
38 //=======================================================================
39 void Extrema_GExtPC::Perform(const ThePoint& P)
40 {
41   mySqDist.Clear();
42   mypoint.Clear();
43   myismin.Clear();
44   Standard_Integer i, NbExt, n;                     
45   Standard_Real U;
46   mysample = 17;
47   Standard_Real t3d = Precision::Confusion();
48   if (Precision::IsInfinite(myuinf)) mydist1 = RealLast();
49   else {
50     Pf = TheCurveTool::Value(*((TheCurve*)myC), myuinf);
51     mydist1 = P.SquareDistance(Pf);
52   }
53   
54   if (Precision::IsInfinite(myusup)) mydist2 = RealLast();
55   else {
56     Pl = TheCurveTool::Value(*((TheCurve*)myC), myusup);
57     mydist2 = P.SquareDistance(Pl);
58   }
59
60   TheCurve & aCurve = *((TheCurve*)myC);
61
62   switch(type) {
63   case GeomAbs_Circle: 
64     {
65       myExtPElC.Perform(P, TheCurveTool::Circle(aCurve), t3d, myuinf, myusup);
66     }
67     break;
68   case GeomAbs_Ellipse: 
69     {
70       myExtPElC.Perform(P, TheCurveTool::Ellipse(aCurve), t3d, myuinf, myusup);
71     }
72     break;
73   case GeomAbs_Parabola: 
74     {
75       myExtPElC.Perform(P, TheCurveTool::Parabola(aCurve), t3d,myuinf,myusup);
76     }
77     break;
78   case GeomAbs_Hyperbola: 
79     {
80       myExtPElC.Perform(P,TheCurveTool::Hyperbola(aCurve),t3d, myuinf, myusup);
81     }
82     break;
83   case GeomAbs_Line: 
84     {
85       myExtPElC.Perform(P, TheCurveTool::Line(aCurve), t3d, myuinf, myusup);
86     }
87     break;
88   case GeomAbs_BezierCurve:
89     {
90       myintuinf = myuinf;
91       myintusup = myusup;
92       mysample = (TheCurveTool::Bezier(aCurve))->NbPoles() * 2;
93       myExtPC.Initialize(aCurve);
94       IntervalPerform(P);
95       return;
96     }
97   case GeomAbs_BSplineCurve: 
98     {
99       const Standard_Integer 
100         aFirstIdx = TheCurveTool::BSpline(aCurve)->FirstUKnotIndex(),
101         aLastIdx  = TheCurveTool::BSpline(aCurve)->LastUKnotIndex();
102       // const reference can not be used due to implementation of BRep_Adaptor.
103       TColStd_Array1OfReal aKnots(aFirstIdx, aLastIdx);
104       TheCurveTool::BSpline(aCurve)->Knots(aKnots); 
105
106       // Workaround to work with:
107       // blend, where knots may be moved from parameter space.
108       Standard_Real aPeriodJump = 0.0;
109       // Avoid problem with too close knots.
110       const Standard_Real aTolCoeff = (myusup - myuinf) * Precision::PConfusion();
111       if (TheCurveTool::IsPeriodic(aCurve))
112       {
113         Standard_Integer aPeriodShift =
114           Standard_Integer ((myuinf - aKnots(aFirstIdx)) / TheCurveTool::Period(aCurve));
115         
116         if (myuinf < aKnots(aFirstIdx) - aTolCoeff)
117           aPeriodShift--;
118
119         aPeriodJump = TheCurveTool::Period(aCurve) * aPeriodShift;
120       }
121
122       Standard_Integer anIdx;
123
124       // Find first and last used knot.
125       Standard_Integer aFirstUsedKnot = aFirstIdx,
126                         aLastUsedKnot = aLastIdx;
127       for(anIdx = aFirstIdx; anIdx <= aLastIdx; anIdx++)
128       {
129         Standard_Real aKnot = aKnots(anIdx) + aPeriodJump;
130         if (myuinf >= aKnot - aTolCoeff)
131           aFirstUsedKnot = anIdx;
132         else
133           break;
134
135       }
136       for(anIdx = aLastIdx; anIdx >= aFirstIdx; anIdx--)
137       {
138         Standard_Real aKnot = aKnots(anIdx) + aPeriodJump;
139         if (myusup <= aKnot + aTolCoeff)
140           aLastUsedKnot = anIdx;
141         else
142           break;
143       }
144
145       if (aFirstUsedKnot == aLastUsedKnot)
146       {
147         // Degenerated case:
148         // Some bounds lies out of curve param space.
149         // In this case build one interval with [myuinf, myusup].
150         // Parameters of these indexes will be redefined.
151         aFirstUsedKnot = aFirstIdx;
152         aLastUsedKnot  = aFirstIdx + 1;
153       }
154
155       mysample = (TheCurveTool::BSpline(aCurve))->Degree() + 1;
156
157       if (mysample == 2)
158       {
159         //BSpline of first degree, direct seaching extrema for each knot interval
160         ThePoint aPmin;
161         Standard_Real tmin = 0., distmin = RealLast();
162         Standard_Real aMin1 = 0., aMin2 = 0.;
163         myExtPC.Initialize(aCurve);
164         for (anIdx = aFirstUsedKnot; anIdx < aLastUsedKnot; anIdx++)
165         {
166           Standard_Real aF = aKnots(anIdx) + aPeriodJump,
167             aL = aKnots(anIdx + 1) + aPeriodJump;
168
169           if (anIdx == aFirstUsedKnot)
170           {
171             aF = myuinf;
172           }
173           else
174           if (anIdx == aLastUsedKnot - 1)
175           {
176             aL = myusup;
177           }
178
179
180           ThePoint aP1, aP2;
181           TheCurveTool::D0(aCurve, aF, aP1);
182           TheCurveTool::D0(aCurve, aL, aP2);
183           TheVector aBase1(P, aP1), aBase2(P, aP2);
184           TheVector aV(aP2, aP1);
185           Standard_Real aVal1 = aV.Dot(aBase1); // Derivative of (C(u) - P)^2
186           Standard_Real aVal2 = aV.Dot(aBase2); // Derivative of (C(u) - P)^2
187           if (anIdx == aFirstUsedKnot)
188           {
189             aMin1 = P.SquareDistance(aP1);
190           }
191           else
192           {
193             aMin1 = aMin2;          
194             if (distmin > aMin1)
195             {
196               distmin = aMin1;
197               tmin = aF;
198               aPmin = aP1;
199             }
200           }
201           aMin2 = P.SquareDistance(aP2);
202           Standard_Real aMinSqDist = Min(aMin1, aMin2);
203           Standard_Real aMinDer = Min(Abs(aVal1), Abs(aVal2));
204           if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2)))
205           {
206             // Derivatives have opposite signs - min or max inside of interval (sufficient condition).
207             if (aVal1 * aVal2 <= 0.0 ||
208                 aMinSqDist < 100. * Precision::SquareConfusion() ||
209                 2.*aMinDer < Precision::Confusion())
210             {
211               myintuinf = aF;
212               myintusup = aL;
213               IntervalPerform(P);
214             }
215           }
216         }
217         if (!Precision::IsInfinite(distmin))
218         {
219           Standard_Boolean isToAdd = Standard_True;
220           NbExt = mypoint.Length();
221           for (i = 1; i <= NbExt && isToAdd; i++)
222           {
223             Standard_Real t = mypoint.Value(i).Parameter();
224             isToAdd = (distmin < mySqDist(i)) && (Abs(t - tmin) > mytolu);
225           }
226           if (isToAdd)
227           {
228             ThePOnC PC(tmin, aPmin);
229             mySqDist.Append(distmin);
230             myismin.Append(Standard_True);
231             mypoint.Append(PC);
232           }
233         }
234       }
235       else
236       {
237
238         // Fill sample points.
239         Standard_Integer aValIdx = 1;
240         NCollection_Array1<Standard_Real> aVal(1, (mysample)* (aLastUsedKnot - aFirstUsedKnot) + 1);
241         NCollection_Array1<Standard_Real> aParam(1, (mysample)* (aLastUsedKnot - aFirstUsedKnot) + 1);
242         for (anIdx = aFirstUsedKnot; anIdx < aLastUsedKnot; anIdx++)
243         {
244           Standard_Real aF = aKnots(anIdx) + aPeriodJump,
245             aL = aKnots(anIdx + 1) + aPeriodJump;
246
247           if (anIdx == aFirstUsedKnot)
248             aF = myuinf;
249           if (anIdx == aLastUsedKnot - 1)
250             aL = myusup;
251
252           Standard_Real aStep = (aL - aF) / mysample;
253           for (Standard_Integer aPntIdx = 0; aPntIdx < mysample; aPntIdx++)
254           {
255             Standard_Real aCurrentParam = aF + aStep * aPntIdx;
256             aVal(aValIdx) = TheCurveTool::Value(aCurve, aCurrentParam).SquareDistance(P);
257             aParam(aValIdx) = aCurrentParam;
258             aValIdx++;
259           }
260         }
261         // Fill last point.
262         aVal(aValIdx) = TheCurveTool::Value(aCurve, myusup).SquareDistance(P);
263         aParam(aValIdx) = myusup;
264
265         myExtPC.Initialize(aCurve);
266
267         // Find extremas.
268         for (anIdx = aVal.Lower() + 1; anIdx < aVal.Upper(); anIdx++)
269         {
270           if (aVal(anIdx) <= Precision::SquareConfusion())
271           {
272             mySqDist.Append(aVal(anIdx));
273             myismin.Append(Standard_True);
274             mypoint.Append(ThePOnC(aParam(anIdx), TheCurveTool::Value(aCurve, aParam(anIdx))));
275           }
276           if ((aVal(anIdx) >= aVal(anIdx + 1) &&
277             aVal(anIdx) >= aVal(anIdx - 1)) ||
278             (aVal(anIdx) <= aVal(anIdx + 1) &&
279             aVal(anIdx) <= aVal(anIdx - 1)))
280           {
281             myintuinf = aParam(anIdx - 1);
282             myintusup = aParam(anIdx + 1);
283
284             IntervalPerform(P);
285           }
286         }
287
288         // Solve on the first and last intervals.
289         if (mydist1 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist1))
290         {
291           ThePoint aP1, aP2;
292           TheVector aV1, aV2;
293           TheCurveTool::D1(aCurve, aParam.Value(aParam.Lower()), aP1, aV1);
294           TheCurveTool::D1(aCurve, aParam.Value(aParam.Lower() + 1), aP2, aV2);
295           TheVector aBase1(P, aP1), aBase2(P, aP2);
296           Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2
297           Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2
298           if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2)))
299           {
300             // Derivatives have opposite signs - min or max inside of interval (sufficient condition).
301             // Necessary condition - when point lies on curve.
302             // Necessary condition - when derivative of point is too small.
303             if (aVal1 * aVal2 <= 0.0 ||
304               aBase1.Dot(aBase2) <= 0.0 ||
305               2.0 * Abs(aVal1) < Precision::Confusion())
306             {
307               myintuinf = aParam(aVal.Lower());
308               myintusup = aParam(aVal.Lower() + 1);
309               IntervalPerform(P);
310             }
311           }
312         }
313
314         if (mydist2 > Precision::SquareConfusion() && !Precision::IsPositiveInfinite(mydist2))
315         {
316           ThePoint aP1, aP2;
317           TheVector aV1, aV2;
318           TheCurveTool::D1(aCurve, aParam.Value(aParam.Upper() - 1), aP1, aV1);
319           TheCurveTool::D1(aCurve, aParam.Value(aParam.Upper()), aP2, aV2);
320           TheVector aBase1(P, aP1), aBase2(P, aP2);
321           Standard_Real aVal1 = aV1.Dot(aBase1); // Derivative of (C(u) - P)^2
322           Standard_Real aVal2 = aV2.Dot(aBase2); // Derivative of (C(u) - P)^2
323
324           if (!(Precision::IsInfinite(aVal1) || Precision::IsInfinite(aVal2)))
325           {
326             // Derivatives have opposite signs - min or max inside of interval (sufficient condition).
327             // Necessary condition - when point lies on curve.
328             // Necessary condition - when derivative of point is too small.
329             if (aVal1 * aVal2 <= 0.0 ||
330               aBase1.Dot(aBase2) <= 0.0 ||
331               2.0 * Abs(aVal2) < Precision::Confusion())
332             {
333               myintuinf = aParam(aVal.Upper() - 1);
334               myintusup = aParam(aVal.Upper());
335               IntervalPerform(P);
336             }
337           }
338         }
339       }
340       mydone = Standard_True;
341       break;
342     }
343   default:
344     {
345       const Standard_Integer aMaxSample = 17;
346       Standard_Boolean IntExtIsDone = Standard_False;
347       Standard_Boolean IntIsNotValid;
348       Handle(TColStd_HArray1OfReal) theHInter;
349       n = TheCurveTool::NbIntervals(aCurve, GeomAbs_C2);
350       if (n > 1)
351       {
352         theHInter = new TColStd_HArray1OfReal(1, n + 1);
353         TheCurveTool::Intervals(aCurve, theHInter->ChangeArray1(), GeomAbs_C2);
354       }
355       else
356       {
357         theHInter = TheCurveTool::DeflCurvIntervals(aCurve);
358         n = theHInter->Length() - 1;
359       }
360       mysample = Max(mysample / n, aMaxSample);
361       Standard_Real maxint = 0.;
362       for (i = 1; i <= n; ++i)
363       {
364         Standard_Real dt = theHInter->Value(i + 1) - theHInter->Value(i);
365         if (maxint < dt)
366         {
367           maxint = dt;
368         }
369       }
370       Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(aCurve);
371       TheVector V1;
372       ThePoint PP;
373       Standard_Real s1 = 0.0 ;
374       Standard_Real s2 = 0.0;
375       myExtPC.Initialize(aCurve);
376       for (i = 1; i <= n; i++)
377       {
378         myintuinf = theHInter->Value(i);
379         myintusup = theHInter->Value(i+1);
380         mysample = Max(RealToInt(aMaxSample*(myintusup - myintuinf) / maxint), 3);
381         
382         Standard_Real anInfToCheck = myintuinf;
383         Standard_Real aSupToCheck = myintusup;
384         
385         if (isPeriodic) {
386           Standard_Real aPeriod = TheCurveTool::Period(aCurve);
387           anInfToCheck = ElCLib::InPeriod(myintuinf, myuinf, myuinf+aPeriod);
388           aSupToCheck = myintusup+(anInfToCheck-myintuinf);
389         }    
390         IntIsNotValid = (myuinf > aSupToCheck) || (myusup < anInfToCheck);
391
392         if(IntIsNotValid) continue;
393
394         if (myuinf >= anInfToCheck) anInfToCheck = myuinf;
395         if (myusup <= aSupToCheck) aSupToCheck = myusup;
396         if((aSupToCheck - anInfToCheck) <= mytolu) continue;
397         
398         if (i != 1)
399           {
400           TheCurveTool::D1(aCurve, myintuinf, PP, V1);
401           s1 = (TheVector(P, PP))*V1;
402           if (s1*s2 < 0.0) {
403             mySqDist.Append(PP.SquareDistance(P));
404             myismin.Append((s1 < 0.0));
405             mypoint.Append(ThePOnC(myintuinf, PP));
406           }
407         }
408         if (i != n) {
409           TheCurveTool::D1(aCurve, myintusup, PP, V1);
410           s2 = (TheVector(P, PP))*V1;
411         }
412
413         IntervalPerform(P);
414         IntExtIsDone = IntExtIsDone || mydone;
415       }
416
417       mydone = IntExtIsDone;
418       break;
419     }
420   }
421
422   // Postprocessing.
423   if (type == GeomAbs_BSplineCurve ||
424       type == GeomAbs_OffsetCurve ||
425       type == GeomAbs_OtherCurve)
426   {
427     // Additional checking if the point is on the first or last point of the curve
428     // and does not added yet.
429     if (mydist1 < Precision::SquareConfusion() || 
430         mydist2 < Precision::SquareConfusion())
431     {
432       Standard_Boolean isFirstAdded = Standard_False;
433       Standard_Boolean isLastAdded  = Standard_False;
434       Standard_Integer aNbPoints = mypoint.Length();
435       for (i = 1; i <= aNbPoints; i++)
436       {
437         U = mypoint.Value(i).Parameter();
438         if (Abs(U - myuinf) < mytolu)
439           isFirstAdded = Standard_True;
440         else if (Abs(myusup - U) < mytolu)
441           isLastAdded = Standard_True;
442       }
443       if (!isFirstAdded && mydist1 < Precision::SquareConfusion())
444       {
445         mySqDist.Prepend(mydist1);
446         myismin.Prepend(Standard_True);
447         mypoint.Prepend(ThePOnC(myuinf, Pf));
448       }
449       if (!isLastAdded && mydist2 < Precision::SquareConfusion())
450       {
451         mySqDist.Append(mydist2);
452         myismin.Append(Standard_True);
453         mypoint.Append(ThePOnC(myusup, Pl));
454       }
455       mydone = Standard_True;
456     }
457   }
458   else
459   {
460     // In analytical case
461     mydone = myExtPElC.IsDone();
462     if (mydone)
463     {
464       NbExt = myExtPElC.NbExt();
465       for (i = 1; i <= NbExt; i++)
466       {
467         // Verification de la validite des parametres:
468         ThePOnC PC = myExtPElC.Point(i);
469         U = PC.Parameter();
470         if (TheCurveTool::IsPeriodic(aCurve))
471         {
472           U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(aCurve));
473         }
474         if ((U >= myuinf-mytolu) && (U <= myusup+mytolu))
475         {
476           PC.SetValues(U, myExtPElC.Point(i).Value());
477           mySqDist.Append(myExtPElC.SquareDistance(i));
478           myismin.Append(myExtPElC.IsMin(i));
479           mypoint.Append(PC);
480         }
481       }
482     }
483   }
484 }
485
486
487 //=======================================================================
488 //function : Initialize
489 //purpose  : 
490 //=======================================================================
491
492 void Extrema_GExtPC::Initialize(const TheCurve&     C,
493                                 const Standard_Real Uinf,
494                                 const Standard_Real Usup,
495                                 const Standard_Real TolF) 
496 {
497   myC = (Standard_Address)&C;
498   myintuinf = myuinf = Uinf;
499   myintusup = myusup = Usup;
500   mytolf = TolF;
501   mytolu = TheCurveTool::Resolution(*((TheCurve*)myC), Precision::Confusion());
502   type = TheCurveTool::GetType(C);
503   mydone = Standard_False;
504   mydist1 = RealLast();
505   mydist2 = RealLast();
506   mysample = 17;
507 }
508
509
510 //=======================================================================
511 //function : IntervalPerform
512 //purpose  : 
513 //=======================================================================
514
515 void Extrema_GExtPC::IntervalPerform(const ThePoint& P)
516 {
517   Standard_Integer i;
518   Standard_Real U;
519   myExtPC.Initialize(mysample, myintuinf, myintusup, mytolu, mytolf);
520   myExtPC.Perform(P);
521   mydone = myExtPC.IsDone();
522   if (mydone)
523   {
524     Standard_Integer NbExt = myExtPC.NbExt();
525     for (i = 1; i <= NbExt; i++)
526     {
527       // Verification de la validite des parametres pour le cas trimme:
528       ThePOnC PC = myExtPC.Point(i);
529       U = PC.Parameter();
530       if (TheCurveTool::IsPeriodic(*((TheCurve*)myC)))
531       {
532         U = ElCLib::InPeriod(U, myuinf, myuinf+TheCurveTool::Period(*((TheCurve*)myC)));
533       }
534       if ((U >= myuinf - mytolu) && (U <= myusup + mytolu))
535       {
536         AddSol(U, PC.Value(),
537                myExtPC.SquareDistance(i),
538                myExtPC.IsMin(i));
539       }
540     }
541   }
542 }
543
544
545 //=======================================================================
546 //function : AddSol
547 //purpose  : 
548 //=======================================================================
549
550 void Extrema_GExtPC::AddSol(const Standard_Real theU, const ThePoint& theP,
551                             const Standard_Real theSqDist, 
552                             const Standard_Boolean isMin)
553 {
554   Standard_Integer i, NbExt = mypoint.Length();
555   for (i = 1; i <= NbExt; i++)
556   {
557     Standard_Real t = mypoint.Value(i).Parameter();
558     if (Abs(t - theU) <= mytolu)
559     {
560       return;
561     }
562   }
563   ThePOnC PC(theU, theP);
564   mySqDist.Append(theSqDist);
565   myismin.Append(isMin);
566   mypoint.Append(PC);
567
568  }
569
570
571 //=======================================================================
572 //function : Extrema_GExtPC
573 //purpose  : 
574 //=======================================================================
575
576 Extrema_GExtPC::Extrema_GExtPC()
577 {
578   myC = 0;
579   mydone = Standard_False;
580   mydist1 = RealLast();
581   mydist2 = RealLast();
582   mytolu = 0.0;
583   mytolf = 0.0;
584   mysample = 17;
585   myintuinf = myintusup = myuinf = myusup = Precision::Infinite();
586   type = GeomAbs_OtherCurve;
587 }
588
589 //=======================================================================
590 //function : Extrema_GExtPC
591 //purpose  : 
592 //=======================================================================
593
594 Extrema_GExtPC::Extrema_GExtPC(const ThePoint&           P, 
595                                const TheCurve&           C,
596                                const Standard_Real       Uinf,
597                                const Standard_Real       Usup,
598                                const Standard_Real       TolF) 
599 {
600   Initialize(C, Uinf, Usup, TolF);
601   Perform(P);
602 }
603
604 //=======================================================================
605 //function : Extrema_GExtPC
606 //purpose  : 
607 //=======================================================================
608
609 Extrema_GExtPC::Extrema_GExtPC(const ThePoint&     P, 
610                                const TheCurve&     C,
611                                const Standard_Real TolF) 
612 {
613   Initialize(C, TheCurveTool::FirstParameter(C), 
614              TheCurveTool::LastParameter(C), TolF);
615   Perform(P);
616 }
617
618
619 //=======================================================================
620 //function : IsDone
621 //purpose  : 
622 //=======================================================================
623
624 Standard_Boolean Extrema_GExtPC::IsDone() const
625 {
626   return mydone;
627 }
628
629
630 //=======================================================================
631 //function : Value
632 //purpose  : 
633 //=======================================================================
634
635 Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const 
636 {
637   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
638   return mySqDist.Value(N);
639 }
640
641
642 //=======================================================================
643 //function : NbExt
644 //purpose  : 
645 //=======================================================================
646
647 Standard_Integer Extrema_GExtPC::NbExt() const
648 {
649   if (!IsDone()) throw StdFail_NotDone();
650   return mySqDist.Length();
651 }
652
653
654 //=======================================================================
655 //function : IsMin
656 //purpose  : 
657 //=======================================================================
658
659 Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const
660 {
661   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
662   return myismin.Value(N);
663 }
664
665
666
667 //=======================================================================
668 //function : Point
669 //purpose  : 
670 //=======================================================================
671
672 const ThePOnC & Extrema_GExtPC::Point(const Standard_Integer N) const
673 {
674   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
675   return mypoint.Value(N);
676 }
677
678
679 //=======================================================================
680 //function : TrimmedDistances
681 //purpose  : 
682 //=======================================================================
683
684 void Extrema_GExtPC::TrimmedSquareDistances(Standard_Real& dist1, 
685                                       Standard_Real& dist2,
686                                       ThePoint& P1,
687                                       ThePoint& P2) const
688 {
689   dist1 = mydist1;
690   dist2 = mydist2;
691   P1 = Pf;
692   P2 = Pl;
693 }