0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / Extrema / Extrema_ExtCC.cxx
1 // Created on: 1994-07-06
2 // Created by: Laurent PAINNOT
3 // Copyright (c) 1994-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 MPS (june 96) : correction du trap dans le cas droite/Bezier 
18 // Modified by MPS (mai 97) : PRO 7598 
19 //                            tri des solutions pour eviter de rendre plusieurs
20 //                            fois la meme solution 
21
22 #include <Adaptor3d_Curve.hxx>
23 #include <Bnd_Range.hxx>
24 #include <ElCLib.hxx>
25 #include <Extrema_CurveTool.hxx>
26 #include <Extrema_ECC.hxx>
27 #include <Extrema_ExtCC.hxx>
28 #include <Extrema_ExtElC.hxx>
29 #include <Extrema_ExtPElC.hxx>
30 #include <Extrema_POnCurv.hxx>
31 #include <Extrema_SequenceOfPOnCurv.hxx>
32 #include <Geom_Circle.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_Ellipse.hxx>
35 #include <Geom_Hyperbola.hxx>
36 #include <Geom_Line.hxx>
37 #include <Geom_Parabola.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <GeomAbs_CurveType.hxx>
40 #include <gp_Pnt.hxx>
41 #include <Precision.hxx>
42 #include <Standard_Failure.hxx>
43 #include <Standard_NotImplemented.hxx>
44 #include <Standard_NullObject.hxx>
45 #include <Standard_OutOfRange.hxx>
46 #include <StdFail_NotDone.hxx>
47 #include <TColStd_Array1OfReal.hxx>
48 #include <TColStd_ListIteratorOfListOfTransient.hxx>
49 #include <TColStd_SequenceOfReal.hxx>
50
51 //=======================================================================
52 //function : Extrema_ExtCC
53 //purpose  : 
54 //=======================================================================
55 Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
56                               const Standard_Real TolC2)
57 : myIsFindSingleSolution(Standard_False),
58   myDone (Standard_False),
59   myIsPar(Standard_False)
60 {
61   myC[0] = 0; myC[1] = 0;
62   myInf[0] = myInf[1] = -Precision::Infinite();
63   mySup[0] = mySup[1] = Precision::Infinite();
64   myTol[0] = TolC1; myTol[1] = TolC2;
65   mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
66 }
67
68 //=======================================================================
69 //function : Extrema_ExtCC
70 //purpose  : 
71 //=======================================================================
72
73 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
74                              const Adaptor3d_Curve& C2,
75                              const Standard_Real      U1,
76                              const Standard_Real      U2,
77                              const Standard_Real      V1,
78                              const Standard_Real      V2,
79                              const Standard_Real      TolC1,
80                              const Standard_Real      TolC2)
81 : myIsFindSingleSolution(Standard_False),
82   myECC(C1, C2, U1, U2, V1, V2),
83   myDone (Standard_False)
84 {
85   SetCurve (1, C1, U1, U2);
86   SetCurve (2, C2, V1, V2);
87   SetTolerance (1, TolC1);
88   SetTolerance (2, TolC2);
89   mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
90   Perform();
91 }
92
93
94 //=======================================================================
95 //function : Extrema_ExtCC
96 //purpose  : 
97 //=======================================================================
98
99 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
100                              const Adaptor3d_Curve& C2,
101                              const Standard_Real      TolC1,
102                              const Standard_Real      TolC2)
103 : myIsFindSingleSolution(Standard_False),
104   myECC(C1, C2),
105   myDone (Standard_False)
106 {
107   SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
108   SetCurve (2, C2, C2.FirstParameter(), C2.LastParameter());
109   SetTolerance (1, TolC1);
110   SetTolerance (2, TolC2);
111   mydist11 = mydist12 = mydist21 = mydist22 = RealFirst();
112   Perform();
113 }
114
115 //=======================================================================
116 //function : SetCurve
117 //purpose  : 
118 //=======================================================================
119
120 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C)
121 {
122   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetCurve()")
123   Standard_Integer anInd = theRank - 1;
124   myC[anInd] = (Standard_Address)&C;
125 }
126
127 //=======================================================================
128 //function : SetCurve
129 //purpose  : 
130 //=======================================================================
131
132 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C,
133                                const Standard_Real Uinf, const Standard_Real Usup)
134 {
135   SetCurve (theRank, C);
136   SetRange (theRank, Uinf, Usup);
137 }
138
139 //=======================================================================
140 //function : SetRange
141 //purpose  : 
142 //=======================================================================
143
144 void Extrema_ExtCC::SetRange (const Standard_Integer theRank, 
145                                const Standard_Real Uinf, const Standard_Real Usup)
146 {
147   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetRange()")
148   Standard_Integer anInd = theRank - 1;
149   myInf[anInd] = Uinf;
150   mySup[anInd] = Usup;
151 }
152
153 //=======================================================================
154 //function : SetTolerance
155 //purpose  : 
156 //=======================================================================
157
158 void Extrema_ExtCC::SetTolerance (const Standard_Integer theRank, const Standard_Real theTol)
159 {
160   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetTolerance()")
161   Standard_Integer anInd = theRank - 1;
162   myTol[anInd] = theTol;
163 }
164
165
166 //=======================================================================
167 //function : Perform
168 //purpose  : 
169 //=======================================================================
170
171 void Extrema_ExtCC::Perform()
172 {  
173   Standard_NullObject_Raise_if (!myC[0] || !myC[1], "Extrema_ExtCC::Perform()")
174   myECC.SetParams(*((Adaptor3d_Curve*)myC[0]), 
175                   *((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]);
176   myECC.SetTolerance(Min(myTol[0], myTol[1]));
177   myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
178   myDone = Standard_False;
179   mypoints.Clear();
180   mySqDist.Clear();
181   myIsPar = Standard_False;
182
183   GeomAbs_CurveType type1 = (*((Adaptor3d_Curve*)myC[0])).GetType();
184   GeomAbs_CurveType type2 = (*((Adaptor3d_Curve*)myC[1])).GetType();
185   Standard_Real U11, U12, U21, U22, Tol = Min(myTol[0], myTol[1]);
186
187   U11 = myInf[0];
188   U12 = mySup[0];
189   U21 = myInf[1];
190   U22 = mySup[1];
191
192   if (!Precision::IsInfinite(U11)) P1f = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]),  U11); 
193   if (!Precision::IsInfinite(U12)) P1l = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]),  U12);
194   if (!Precision::IsInfinite(U21)) P2f = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), U21);
195   if (!Precision::IsInfinite(U22)) P2l = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), U22);
196   
197
198   if (Precision::IsInfinite(U11) || Precision::IsInfinite(U21)) mydist11 = RealLast();
199   else mydist11 = P1f.SquareDistance(P2f);
200   if (Precision::IsInfinite(U11) || Precision::IsInfinite(U22)) mydist12 = RealLast();
201   else mydist12 = P1f.SquareDistance(P2l);
202   if (Precision::IsInfinite(U12) || Precision::IsInfinite(U21)) mydist21 = RealLast();
203   else mydist21 = P1l.SquareDistance(P2f);
204   if (Precision::IsInfinite(U12) || Precision::IsInfinite(U22)) mydist22 = RealLast();
205   else mydist22 = P1l.SquareDistance(P2l);
206
207   //Depending on the types of curves, the algorithm is chosen:
208   //- _ExtElC, when one of the curves is a line and the other is elementary,
209   //   or there are two circles;
210   //- _GenExtCC, in all other cases
211   if ( (type1 == GeomAbs_Line && type2 <= GeomAbs_Parabola) ||
212        (type2 == GeomAbs_Line && type1 <= GeomAbs_Parabola) ) {
213     //analytical case - one curve is always a line
214     Standard_Integer anInd1 = 0, anInd2 = 1;
215     GeomAbs_CurveType aType2 = type2;
216     Standard_Boolean isInverse = (type1 > type2);
217     if (isInverse)
218     {
219       //algorithm uses inverse order of arguments
220       anInd1 = 1;
221       anInd2 = 0;
222       aType2 = type1;
223     }
224     switch (aType2) {
225     case GeomAbs_Line: {
226       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Line(), Tol);
227       PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
228       break;
229     }
230     case GeomAbs_Circle: {
231       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Circle(), Tol);
232       PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
233       break;
234     }
235     case GeomAbs_Ellipse: {
236       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Ellipse());
237       PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
238       break;
239     }
240     case GeomAbs_Hyperbola: {
241       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Hyperbola());
242       PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
243       break;
244     }
245     case GeomAbs_Parabola: {
246       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Parabola());
247       PrepareResults(Xtrem, isInverse, U11, U12, U21, U22);
248       break;
249     }
250     default: break;
251     }
252   } else if (type1 == GeomAbs_Circle && type2 == GeomAbs_Circle) {
253     //analytical case - two circles
254     Standard_Boolean bIsDone;
255     Extrema_ExtElC CCXtrem ((*((Adaptor3d_Curve*)myC[0])).Circle(), (*((Adaptor3d_Curve*)myC[1])).Circle());
256     bIsDone = CCXtrem.IsDone();
257     if(bIsDone) {
258       PrepareResults(CCXtrem, Standard_False, U11, U12, U21, U22);
259     }
260     else {
261       myECC.Perform();
262       PrepareResults(myECC, U11, U12, U21, U22);
263     }
264   } else {
265     myECC.Perform();
266     PrepareResults(myECC, U11, U12, U21, U22);
267   }
268 }
269
270
271 //=======================================================================
272 //function : IsDone
273 //purpose  : 
274 //=======================================================================
275
276 Standard_Boolean Extrema_ExtCC::IsDone() const
277 {
278   return myDone;
279 }
280
281 //=======================================================================
282 //function : IsParallel
283 //purpose  : 
284 //=======================================================================
285
286 Standard_Boolean Extrema_ExtCC::IsParallel() const
287 {
288   if (!IsDone())
289   {
290     throw StdFail_NotDone();
291   }
292
293   return myIsPar;
294 }
295
296
297 //=======================================================================
298 //function : Value
299 //purpose  : 
300 //=======================================================================
301
302 Standard_Real Extrema_ExtCC::SquareDistance(const Standard_Integer N) const 
303 {
304   if ((N < 1) || (N > NbExt())) throw Standard_OutOfRange();
305   return mySqDist.Value(N);
306 }
307
308
309 //=======================================================================
310 //function : NbExt
311 //purpose  : 
312 //=======================================================================
313
314 Standard_Integer Extrema_ExtCC::NbExt() const
315 {
316   if(!myDone) throw StdFail_NotDone();
317   return mySqDist.Length();
318 }
319
320
321 //=======================================================================
322 //function : Points
323 //purpose  : 
324 //=======================================================================
325
326 void Extrema_ExtCC::Points(const Standard_Integer N, 
327                             Extrema_POnCurv& P1,
328                             Extrema_POnCurv& P2) const
329 {
330   if (N < 1 || N > NbExt())
331   {
332     throw Standard_OutOfRange();
333   }
334
335   P1 = mypoints.Value(2 * N - 1);
336   P2 = mypoints.Value(2 * N);
337 }
338
339
340
341 //=======================================================================
342 //function : TrimmedDistances
343 //purpose  : 
344 //=======================================================================
345
346 void Extrema_ExtCC::TrimmedSquareDistances(Standard_Real& dist11,
347                                       Standard_Real& dist12,
348                                       Standard_Real& dist21,
349                                       Standard_Real& dist22,
350                                       gp_Pnt&        P11   ,
351                                       gp_Pnt&        P12   ,
352                                       gp_Pnt&        P21   ,
353                                       gp_Pnt&        P22    ) const {
354                                         
355   dist11 = mydist11;
356   dist12 = mydist12;
357   dist21 = mydist21;
358   dist22 = mydist22;
359   P11 = P1f;
360   P12 = P1l;
361   P21 = P2f;
362   P22 = P2l;
363 }
364
365 //=======================================================================
366 //function : ParallelResult
367 //purpose  : 
368 //=======================================================================
369 void Extrema_ExtCC::PrepareParallelResult(const Standard_Real theUt11,
370                                           const Standard_Real theUt12,
371                                           const Standard_Real theUt21,
372                                           const Standard_Real theUt22,
373                                           const Standard_Real theSqDist)
374 {
375   if (!myIsPar)
376     return;
377
378   const GeomAbs_CurveType aType1 = Extrema_CurveTool::GetType(*((Adaptor3d_Curve*) myC[0]));
379   const GeomAbs_CurveType aType2 = Extrema_CurveTool::GetType(*((Adaptor3d_Curve*) myC[1]));
380   
381   if (((aType1 != GeomAbs_Line) && (aType1 != GeomAbs_Circle)) ||
382       ((aType2 != GeomAbs_Line) && (aType2 != GeomAbs_Circle)))
383   {
384     mySqDist.Append(theSqDist);
385     myDone = Standard_True;
386     myIsPar = Standard_True;
387     return;
388   }
389   
390   // Parallel case is only for line-line, circle-circle and circle-line!!!
391   // But really for trimmed curves extremas can not exist!
392   if (aType1 != aType2)
393   {
394     //The projection of the circle's location to the trimmed line must exist.
395     const Standard_Boolean isReversed = (aType1 != GeomAbs_Circle);
396     const gp_Pnt aPonC = !isReversed ?
397                       Extrema_CurveTool::Value(*((Adaptor3d_Curve*) myC[0]), theUt11) :
398                       Extrema_CurveTool::Value(*((Adaptor3d_Curve*) myC[1]), theUt21);
399
400     const gp_Lin aL = !isReversed ? ((Adaptor3d_Curve*) myC[1])->Line() :
401                                     ((Adaptor3d_Curve*) myC[0])->Line();
402     const Extrema_ExtPElC ExtPLin(aPonC, aL, Precision::Confusion(),
403                                   !isReversed ? theUt21 : theUt11,
404                                   !isReversed ? theUt22 : theUt12);
405
406     if (ExtPLin.IsDone())
407     {
408       mySqDist.Append(theSqDist);
409     }
410     else
411     {
412       myIsPar = Standard_False;
413     }
414
415     return;
416   }
417
418   if (aType1 == GeomAbs_Line)
419   {
420     // Line - Line
421
422     const Standard_Real isFirstInfinite = (Precision::IsInfinite(theUt11) &&
423                                            Precision::IsInfinite(theUt12));
424     const Standard_Real isLastInfinite = (Precision::IsInfinite(theUt21) &&
425                                           Precision::IsInfinite(theUt22));
426
427     if (isFirstInfinite || isLastInfinite)
428     {
429       // Infinite number of solution
430
431       mySqDist.Append(theSqDist);
432     }
433     else
434     {
435       // The range created by projection of both ends of the 1st line
436       // to the 2nd one must intersect the (native) trimmed range of
437       // the 2nd line.
438
439       myIsPar = Standard_False;
440
441       const gp_Lin aLin1 = ((Adaptor3d_Curve*) myC[0])->Line();
442       const gp_Lin aLin2 = ((Adaptor3d_Curve*) myC[1])->Line();
443       const Standard_Boolean isOpposite(aLin1.Direction().Dot(aLin2.Direction()) < 0.0);
444
445       Bnd_Range aRange2(theUt21, theUt22);
446       Bnd_Range aProjRng12;
447
448       if (Precision::IsInfinite(theUt11))
449       {
450         if (isOpposite)
451           aProjRng12.Add(Precision::Infinite());
452         else
453           aProjRng12.Add(-Precision::Infinite());
454       }
455       else
456       {
457         const gp_Pnt aPonC1 = ElCLib::Value(theUt11, aLin1);
458         const Standard_Real aPar = ElCLib::Parameter(aLin2, aPonC1);
459         aProjRng12.Add(aPar);
460       }
461
462       if (Precision::IsInfinite(theUt12))
463       {
464         if (isOpposite)
465           aProjRng12.Add(-Precision::Infinite());
466         else
467           aProjRng12.Add(Precision::Infinite());
468       }
469       else
470       {
471         const gp_Pnt aPonC1 = ElCLib::Value(theUt12, aLin1);
472         const Standard_Real aPar = ElCLib::Parameter(aLin2, aPonC1);
473         aProjRng12.Add(aPar);
474       }
475
476       aRange2.Common(aProjRng12);
477       if (aRange2.Delta() > Precision::Confusion())
478       {
479         ClearSolutions();
480         mySqDist.Append(theSqDist);
481         myIsPar = Standard_True;
482       }
483       else if (!aRange2.IsVoid())
484       {
485         //Case like this:
486
487         //  **************     aLin1
488         //               o
489         //               o
490         //               ***************  aLin2
491
492         ClearSolutions();
493         Standard_Real aPar1 = 0.0, aPar2 = 0.0;
494         aRange2.GetBounds(aPar1, aPar2);
495         aPar2 = 0.5*(aPar1 + aPar2);
496         gp_Pnt aP = ElCLib::Value(aPar2, aLin2);
497         const Extrema_POnCurv aP2(aPar2, aP);
498         aPar1 = ElCLib::Parameter(aLin1, aP);
499         aP = ElCLib::Value(aPar1, aLin1);
500         const Extrema_POnCurv aP1(aPar1, aP);
501         mypoints.Append(aP1);
502         mypoints.Append(aP2);
503         mySqDist.Append(theSqDist);
504       }
505     }
506   }
507   else
508   {
509     // Circle - Circle
510     myIsPar = Standard_False;
511
512     //Two arcs with ranges [U1, U2] and [V1, V2] correspondingly are
513     //considered to be parallel in the following case:
514     //  The range created by projection both points U1 and U2 of the
515     //  1st circle to the 2nd one intersects either the range [V1, V2] or
516     //  the range [V1-PI, V2-PI]. All ranges must be adjusted to correspond
517     //  periodic range before checking of intersection.
518
519     const gp_Circ aWorkCirc = ((Adaptor3d_Curve*) myC[1])->Circle();
520     const Standard_Real aPeriod = M_PI + M_PI;
521     gp_Vec aVTg1;
522     gp_Pnt aP11;
523     const gp_Pnt aP12 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*) myC[0]), theUt12);
524     Extrema_CurveTool::D1(*((Adaptor3d_Curve*) myC[0]), theUt11, aP11, aVTg1);
525
526     const Bnd_Range aRange(theUt21, theUt22);
527     Bnd_Range aProjRng1;
528
529     // Project arc of the 1st circle between points theUt11 and theUt12 to the
530     // 2nd circle. It is necessary to chose correct arc from two possible ones.
531
532     Standard_Real aPar1 = ElCLib::InPeriod(ElCLib::Parameter(aWorkCirc, aP11),
533                                            theUt21, theUt21 + aPeriod);
534     const gp_Vec aVTg2 = Extrema_CurveTool::DN(*((Adaptor3d_Curve*) myC[1]), aPar1, 1);
535     
536     // Check if circles have same/opposite directions
537     const Standard_Boolean isOpposite(aVTg1.Dot(aVTg2) < 0.0);
538
539     Standard_Real aPar2 = ElCLib::InPeriod(ElCLib::Parameter(aWorkCirc, aP12),
540                                            theUt21, theUt21 + aPeriod);
541
542     if (isOpposite)
543     {
544       // Must be aPar2 < aPar1
545       if ((aRange.Delta() > Precision::Angular()) &&
546           ((aPar1 - aPar2) < Precision::Angular()))
547       {
548         aPar2 -= aPeriod;
549       }
550     }
551     else
552     {
553       // Must be aPar2 > aPar1
554       if ((aRange.Delta() > Precision::Angular()) &&
555           ((aPar2 - aPar1) < Precision::Angular()))
556       {
557         aPar2 += aPeriod;
558       }
559     }
560
561     // Now the projection result is the range [aPar1, aPar2]
562     // if aPar1 < aPar2 or the range [aPar2, aPar1], otherwise.
563
564     Standard_Real aMinSquareDist = RealLast();
565
566     aProjRng1.Add(aPar1 - aPeriod);
567     aProjRng1.Add(aPar2 - aPeriod);
568     for (Standard_Integer i = 0; i < 3; i++)
569     {
570       // Repeat computation three times, shifting the range to PI on each step,
571       // to be able to find if the concentric arcs ranges are intersected in just one parameter
572       // (lower or upper boundary).
573
574       Bnd_Range aRng = aProjRng1;
575       aRng.Common(aRange);
576
577       //Cases are possible and processed below:
578       //1. Extrema does not exist. In this case all common ranges are VOID.
579       //2. Arcs are parallel and distance between them is equal to sqrt(theSqDist).
580       //    In this case myIsPar = TRUE definitely.
581       //3. Arcs are parallel and distance between them is equal to (sqrt(theSqDist) + R),
582       //    where R is the least radius of the both circles. In this case myIsPar flag
583       //    will temporary be set to TRUE but check will be continued until less
584       //    distance will be found. At that, region with the least distance can be
585       //    either a local point or continuous range. In 1st case myIsPar = FALSE and
586       //    several (or single) extremas will be returned. In the 2nd one
587       //    myIsPar = TRUE and only the least distance will be returned.
588       //4. Arcs are not parallel. Then several (or single) extremas will be returned.
589
590       if (aRng.Delta() > Precision::Angular())
591       {
592         Standard_Real aPar = 0.0;
593         aRng.GetIntermediatePoint(0.5, aPar);
594         const gp_Pnt aPCirc2 = ElCLib::Value(aPar, aWorkCirc);
595         Extrema_ExtPElC ExtPCir(aPCirc2,
596                                 Extrema_CurveTool::Circle(*((Adaptor3d_Curve*) myC[0])),
597                                 Precision::Confusion(), theUt11, theUt12);
598
599         Standard_Real aMinSqD = ExtPCir.SquareDistance(1);
600         for (Standard_Integer anExtID = 2; anExtID <= ExtPCir.NbExt(); anExtID++)
601         {
602           aMinSqD = Min(aMinSqD, ExtPCir.SquareDistance(anExtID));
603         }
604
605         if (aMinSqD <= aMinSquareDist)
606         {
607           ClearSolutions();
608           mySqDist.Append(aMinSqD);
609           myIsPar = Standard_True;
610
611           const Standard_Real aDeltaSqDist = aMinSqD - theSqDist;
612           const Standard_Real aSqD = Max(aMinSqD, theSqDist);
613
614           //  0 <= Dist1-Dist2 <= Eps
615           //  0 <= Dist1^2 - Dist2^2 < Eps*(Dist1+Dist2)
616
617           //If Dist1 ~= Dist2 ==> Dist1+Dist2 ~= 2*Dist2.
618           //Consequently,
619           //  0 <= Dist1^2 - Dist2^2 <= 2*Dist2*Eps
620
621           //Or
622           //  (Dist1^2 - Dist2^2)^2 <= 4*Dist2^2*Eps^2
623
624           if (aDeltaSqDist*aDeltaSqDist < 4.0*aSqD*Precision::SquareConfusion())
625           {
626             // New solution is found
627             break;
628           }
629         }
630
631         //Nearer solution can be found
632       }
633       else if (!aRng.IsVoid())
634       {
635         //Check cases like this:
636
637         //  **************     aCirc1
638         //               o
639         //               o
640         //               ***************  aCirc2
641
642         Standard_Real aPar = 0.0;
643         aRng.GetIntermediatePoint(0.5, aPar);
644         const gp_Pnt aPCirc2 = ElCLib::Value(aPar, aWorkCirc);
645         const Extrema_POnCurv aP2(aPar, aPCirc2);
646
647         Extrema_ExtPElC ExtPCir(aPCirc2,
648                                 Extrema_CurveTool::Circle(*((Adaptor3d_Curve*) myC[0])),
649                                 Precision::Confusion(), theUt11, theUt12);
650
651         Standard_Boolean isFound = !myIsPar;
652
653         if (!isFound)
654         {
655           //If the flag myIsPar was set earlier then it does not mean that
656           //we have found the minimal distance. Here we check it. If there is
657           //a pair of points, which are in less distance then myIsPar flag
658           //was unset and the algorithm will return these nearest points.
659
660           for (Standard_Integer anExtID = 1; anExtID <= ExtPCir.NbExt(); anExtID++)
661           {
662             if (ExtPCir.SquareDistance(anExtID) < aMinSquareDist)
663             {
664               isFound = Standard_True;
665               break;
666             }
667           }
668         }
669
670         if (isFound)
671         {
672           ClearSolutions();
673           myIsPar = Standard_False;
674           for (Standard_Integer anExtID = 1; anExtID <= ExtPCir.NbExt(); anExtID++)
675           {
676             mypoints.Append(ExtPCir.Point(anExtID));
677             mypoints.Append(aP2);
678             mySqDist.Append(ExtPCir.SquareDistance(anExtID));
679             aMinSquareDist = Min(aMinSquareDist, ExtPCir.SquareDistance(anExtID));
680           }
681         }
682       }
683
684       aProjRng1.Shift(M_PI);
685     }
686   }
687 }
688
689 //=======================================================================
690 //function : Results
691 //purpose  : 
692 //=======================================================================
693
694 void Extrema_ExtCC::PrepareResults(const Extrema_ExtElC&  AlgExt,
695                                    const Standard_Boolean theIsInverse,
696                                    const Standard_Real    Ut11,
697                                    const Standard_Real    Ut12,
698                                    const Standard_Real    Ut21,
699                                    const Standard_Real    Ut22)
700 {
701   Standard_Integer i, NbExt;
702   Standard_Real Val, U, U2;
703   Extrema_POnCurv P1, P2;
704
705   myDone = AlgExt.IsDone();
706   if (myDone) {
707     myIsPar = AlgExt.IsParallel();
708     if (myIsPar) {
709       PrepareParallelResult(Ut11, Ut12, Ut21, Ut22, AlgExt.SquareDistance());
710     }
711     else {
712       NbExt = AlgExt.NbExt();
713       for (i = 1; i <= NbExt; i++) {
714         // Verification de la validite des parametres
715         AlgExt.Points(i, P1, P2);
716         if (!theIsInverse)
717         {
718           U = P1.Parameter();
719           U2 = P2.Parameter();
720         }
721         else {
722           U2 = P1.Parameter();
723           U = P2.Parameter();
724         }
725
726         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[0]))) {
727           U = ElCLib::InPeriod(U, Ut11, Ut11+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[0])));
728         }
729         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[1]))) {
730           U2 = ElCLib::InPeriod(U2, Ut21, Ut21+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[1])));
731         }
732
733         if ((U  >= Ut11 - RealEpsilon())  && 
734             (U  <= Ut12 + RealEpsilon())  &&
735             (U2 >= Ut21 - RealEpsilon())  &&
736             (U2 <= Ut22 + RealEpsilon())) {
737           Val = AlgExt.SquareDistance(i);
738           mySqDist.Append(Val);
739           if (!theIsInverse)
740           {
741             P1.SetValues(U, P1.Value());
742             P2.SetValues(U2, P2.Value());
743             mypoints.Append(P1);
744             mypoints.Append(P2);
745           }
746           else {
747             P1.SetValues(U2, P1.Value());
748             P2.SetValues(U, P2.Value());
749             mypoints.Append(P2);
750             mypoints.Append(P1);
751           }
752         }
753       }
754     }
755   }
756
757 }
758
759
760 //=======================================================================
761 //function : Results
762 //purpose  : 
763 //=======================================================================
764
765 void Extrema_ExtCC::PrepareResults(const Extrema_ECC&   AlgExt,
766                                    const Standard_Real  Ut11,
767                                    const Standard_Real  Ut12,
768                                    const Standard_Real  Ut21,
769                                    const Standard_Real  Ut22)
770 {
771   Standard_Integer i, NbExt;
772   Standard_Real Val, U, U2;
773   Extrema_POnCurv P1, P2;
774
775   myDone = AlgExt.IsDone();
776   if (myDone)
777   {
778     myIsPar = AlgExt.IsParallel();
779     if (myIsPar)
780     {
781       PrepareParallelResult(Ut11, Ut12, Ut21, Ut22, AlgExt.SquareDistance());
782     }
783     else
784     {
785       NbExt = AlgExt.NbExt();
786       for (i = 1; i <= NbExt; i++)
787       {
788         AlgExt.Points(i, P1, P2);
789         U = P1.Parameter();
790         U2 = P2.Parameter();
791
792         // Check points to be into param space.
793         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*) myC[0])))
794         {
795           U = ElCLib::InPeriod(U, Ut11, Ut11 + Extrema_CurveTool::Period(*((Adaptor3d_Curve*) myC[0])));
796         }
797         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*) myC[1])))
798         {
799           U2 = ElCLib::InPeriod(U2, Ut21, Ut21 + Extrema_CurveTool::Period(*((Adaptor3d_Curve*) myC[1])));
800         }
801
802         if ((U >= Ut11 - RealEpsilon()) &&
803             (U <= Ut12 + RealEpsilon()) &&
804             (U2 >= Ut21 - RealEpsilon()) &&
805             (U2 <= Ut22 + RealEpsilon()))
806         {
807           Val = AlgExt.SquareDistance(i);
808           mySqDist.Append(Val);
809           P1.SetValues(U, P1.Value());
810           P2.SetValues(U2, P2.Value());
811           mypoints.Append(P1);
812           mypoints.Append(P2);
813         }
814       }
815     }
816   }
817 }
818
819 //=======================================================================
820 //function : SetSingleSolutionFlag
821 //purpose  : 
822 //=======================================================================
823 void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
824 {
825   myIsFindSingleSolution = theFlag;
826 }
827
828 //=======================================================================
829 //function : GetSingleSolutionFlag
830 //purpose  : 
831 //=======================================================================
832 Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
833 {
834   return myIsFindSingleSolution;
835 }