0026674: Performance regression in BRepExtrema_DistShapeShape in OCCT 6.9.0 in compar...
[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 <ElCLib.hxx>
24 #include <Extrema_CurveTool.hxx>
25 #include <Extrema_ECC.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Extrema_ExtElC.hxx>
28 #include <Extrema_ExtPElC.hxx>
29 #include <Extrema_POnCurv.hxx>
30 #include <Extrema_SequenceOfPOnCurv.hxx>
31 #include <Geom_Circle.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Ellipse.hxx>
34 #include <Geom_Hyperbola.hxx>
35 #include <Geom_Line.hxx>
36 #include <Geom_Parabola.hxx>
37 #include <Geom_TrimmedCurve.hxx>
38 #include <GeomAbs_CurveType.hxx>
39 #include <gp_Pnt.hxx>
40 #include <Precision.hxx>
41 #include <Standard_Failure.hxx>
42 #include <Standard_NotImplemented.hxx>
43 #include <Standard_NullObject.hxx>
44 #include <Standard_OutOfRange.hxx>
45 #include <StdFail_InfiniteSolutions.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 {
60   myC[0] = 0; myC[1] = 0;
61   myTol[0] = TolC1; myTol[1] = TolC2;
62 }
63
64 //=======================================================================
65 //function : Extrema_ExtCC
66 //purpose  : 
67 //=======================================================================
68
69 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
70                              const Adaptor3d_Curve& C2,
71                              const Standard_Real      U1,
72                              const Standard_Real      U2,
73                              const Standard_Real      V1,
74                              const Standard_Real      V2,
75                              const Standard_Real      TolC1,
76                              const Standard_Real      TolC2)
77 : myIsFindSingleSolution(Standard_False),
78   myECC(C1, C2, U1, U2, V1, V2),
79   myDone (Standard_False)
80 {
81   SetCurve (1, C1, U1, U2);
82   SetCurve (2, C2, V1, V2);
83   SetTolerance (1, TolC1);
84   SetTolerance (2, TolC2);
85   Perform();
86 }
87
88
89 //=======================================================================
90 //function : Extrema_ExtCC
91 //purpose  : 
92 //=======================================================================
93
94 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
95                              const Adaptor3d_Curve& C2,
96                              const Standard_Real      TolC1,
97                              const Standard_Real      TolC2)
98 : myIsFindSingleSolution(Standard_False),
99   myECC(C1, C2),
100   myDone (Standard_False)
101 {
102   SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
103   SetCurve (2, C2, C2.FirstParameter(), C2.LastParameter());
104   SetTolerance (1, TolC1);
105   SetTolerance (2, TolC2);
106   Perform();
107 }
108
109 //=======================================================================
110 //function : SetCurve
111 //purpose  : 
112 //=======================================================================
113
114 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C)
115 {
116   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetCurve()")
117   Standard_Integer anInd = theRank - 1;
118   myC[anInd] = (Standard_Address)&C;
119 }
120
121 //=======================================================================
122 //function : SetCurve
123 //purpose  : 
124 //=======================================================================
125
126 void Extrema_ExtCC::SetCurve (const Standard_Integer theRank, const Adaptor3d_Curve& C,
127                                const Standard_Real Uinf, const Standard_Real Usup)
128 {
129   SetCurve (theRank, C);
130   SetRange (theRank, Uinf, Usup);
131 }
132
133 //=======================================================================
134 //function : SetRange
135 //purpose  : 
136 //=======================================================================
137
138 void Extrema_ExtCC::SetRange (const Standard_Integer theRank, 
139                                const Standard_Real Uinf, const Standard_Real Usup)
140 {
141   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetRange()")
142   Standard_Integer anInd = theRank - 1;
143   myInf[anInd] = Uinf;
144   mySup[anInd] = Usup;
145 }
146
147 //=======================================================================
148 //function : SetTolerance
149 //purpose  : 
150 //=======================================================================
151
152 void Extrema_ExtCC::SetTolerance (const Standard_Integer theRank, const Standard_Real theTol)
153 {
154   Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_ExtCC::SetTolerance()")
155   Standard_Integer anInd = theRank - 1;
156   myTol[anInd] = theTol;
157 }
158
159
160 //=======================================================================
161 //function : Perform
162 //purpose  : 
163 //=======================================================================
164
165 void Extrema_ExtCC::Perform()
166 {  
167   Standard_NullObject_Raise_if (!myC[0] || !myC[1], "Extrema_ExtCC::Perform()")
168   myECC.SetParams(*((Adaptor3d_Curve*)myC[0]), 
169                   *((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]);
170   myECC.SetTolerance(Min(myTol[0], myTol[1]));
171   myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
172   myDone = Standard_False;
173   mypoints.Clear();
174   mySqDist.Clear();
175   myIsPar = Standard_False;
176
177   GeomAbs_CurveType type1 = (*((Adaptor3d_Curve*)myC[0])).GetType();
178   GeomAbs_CurveType type2 = (*((Adaptor3d_Curve*)myC[1])).GetType();
179   Standard_Real U11, U12, U21, U22, Tol = Min(myTol[0], myTol[1]);
180   mynbext = 0;
181   inverse = Standard_False;
182
183   U11 = myInf[0];
184   U12 = mySup[0];
185   U21 = myInf[1];
186   U22 = mySup[1];
187
188   if (!Precision::IsInfinite(U11)) P1f = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]),  U11); 
189   if (!Precision::IsInfinite(U12)) P1l = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]),  U12);
190   if (!Precision::IsInfinite(U21)) P2f = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), U21);
191   if (!Precision::IsInfinite(U22)) P2l = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), U22);
192   
193
194   if (Precision::IsInfinite(U11) || Precision::IsInfinite(U21)) mydist11 = RealLast();
195   else mydist11 = P1f.SquareDistance(P2f);
196   if (Precision::IsInfinite(U11) || Precision::IsInfinite(U22)) mydist12 = RealLast();
197   else mydist12 = P1f.SquareDistance(P2l);
198   if (Precision::IsInfinite(U12) || Precision::IsInfinite(U21)) mydist21 = RealLast();
199   else mydist21 = P1l.SquareDistance(P2f);
200   if (Precision::IsInfinite(U12) || Precision::IsInfinite(U22)) mydist22 = RealLast();
201   else mydist22 = P1l.SquareDistance(P2l);
202
203   //Depending on the types of curves, the algorithm is chosen:
204   //- _ExtElC, when one of the curves is a line and the other is elementary,
205   //   or there are two circles;
206   //- _GenExtCC, in all other cases
207   if ( (type1 == GeomAbs_Line && type2 <= GeomAbs_Parabola) ||
208        (type2 == GeomAbs_Line && type1 <= GeomAbs_Parabola) ) {
209     //analytical case - one curve is always a line
210     Standard_Integer anInd1 = 0, anInd2 = 1;
211     GeomAbs_CurveType aType2 = type2;
212     inverse = (type1 > type2);
213     if (inverse) {
214       //algorithm uses inverse order of arguments
215       anInd1 = 1;
216       anInd2 = 0;
217       aType2 = type1;
218     }
219     switch (aType2) {
220     case GeomAbs_Line: {
221       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Line(), Tol);
222       Results(Xtrem, U11, U12, U21, U22);
223       break;
224     }
225     case GeomAbs_Circle: {
226       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Circle(), Tol);
227       Results(Xtrem, U11, U12, U21, U22);
228       break;
229     }
230     case GeomAbs_Ellipse: {
231       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Ellipse());
232       Results(Xtrem, U11, U12, U21, U22);
233       break;
234     }
235     case GeomAbs_Hyperbola: {
236       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Hyperbola());
237       Results(Xtrem, U11, U12, U21, U22);
238       break;
239     }
240     case GeomAbs_Parabola: {
241       Extrema_ExtElC Xtrem((*((Adaptor3d_Curve*)myC[anInd1])).Line(), (*((Adaptor3d_Curve*)myC[anInd2])).Parabola());
242       Results(Xtrem, U11, U12, U21, U22);
243       break;
244     }
245     default: break;
246     }
247   } else if (type1 == GeomAbs_Circle && type2 == GeomAbs_Circle) {
248     //analytical case - two circles
249     Standard_Boolean bIsDone;
250     Extrema_ExtElC CCXtrem ((*((Adaptor3d_Curve*)myC[0])).Circle(), (*((Adaptor3d_Curve*)myC[1])).Circle());
251     bIsDone = CCXtrem.IsDone();
252     if(bIsDone) {
253       Results(CCXtrem, U11, U12, U21, U22);
254     }
255     else {
256       myECC.Perform();
257       Results(myECC, U11, U12, U21, U22);
258     }
259   } else {
260     myECC.Perform();
261     Results(myECC, U11, U12, U21, U22);
262   }
263 }
264
265
266 //=======================================================================
267 //function : IsDone
268 //purpose  : 
269 //=======================================================================
270
271 Standard_Boolean Extrema_ExtCC::IsDone() const
272 {
273   return myDone;
274 }
275
276 //=======================================================================
277 //function : IsParallel
278 //purpose  : 
279 //=======================================================================
280
281 Standard_Boolean Extrema_ExtCC::IsParallel() const
282 {
283   return myIsPar;
284 }
285
286
287 //=======================================================================
288 //function : Value
289 //purpose  : 
290 //=======================================================================
291
292 Standard_Real Extrema_ExtCC::SquareDistance(const Standard_Integer N) const 
293 {
294   if(!myDone) StdFail_NotDone::Raise();
295   if ((N <= 0) || (N > mynbext)) Standard_OutOfRange::Raise();
296   return mySqDist.Value(N);
297 }
298
299
300 //=======================================================================
301 //function : NbExt
302 //purpose  : 
303 //=======================================================================
304
305 Standard_Integer Extrema_ExtCC::NbExt() const
306 {
307   if(!myDone) StdFail_NotDone::Raise();
308   return mynbext;
309 }
310
311
312 //=======================================================================
313 //function : Points
314 //purpose  : 
315 //=======================================================================
316
317 void Extrema_ExtCC::Points(const Standard_Integer N, 
318                             Extrema_POnCurv& P1,
319                             Extrema_POnCurv& P2) const
320 {
321   if(!myDone) StdFail_NotDone::Raise();
322   if ((N <= 0) || (N > mynbext)) Standard_OutOfRange::Raise();
323   P1 = mypoints.Value(2*N-1);
324   P2 = mypoints.Value(2*N);
325 }
326
327
328
329 //=======================================================================
330 //function : TrimmedDistances
331 //purpose  : 
332 //=======================================================================
333
334 void Extrema_ExtCC::TrimmedSquareDistances(Standard_Real& dist11,
335                                       Standard_Real& dist12,
336                                       Standard_Real& dist21,
337                                       Standard_Real& dist22,
338                                       gp_Pnt&        P11   ,
339                                       gp_Pnt&        P12   ,
340                                       gp_Pnt&        P21   ,
341                                       gp_Pnt&        P22    ) const {
342                                         
343   dist11 = mydist11;
344   dist12 = mydist12;
345   dist21 = mydist21;
346   dist22 = mydist22;
347   P11 = P1f;
348   P12 = P1l;
349   P21 = P2f;
350   P22 = P2l;
351 }
352
353
354
355 //=======================================================================
356 //function : Results
357 //purpose  : 
358 //=======================================================================
359
360 void Extrema_ExtCC::Results(const Extrema_ExtElC&  AlgExt,
361                              const Standard_Real    Ut11,
362                              const Standard_Real    Ut12,
363                              const Standard_Real    Ut21,
364                              const Standard_Real    Ut22)
365 {
366   Standard_Integer i, NbExt;
367   Standard_Real Val, U, U2;
368   Extrema_POnCurv P1, P2;
369
370   myDone = AlgExt.IsDone();
371   if (myDone) {
372     myIsPar = AlgExt.IsParallel();
373     if (myIsPar) {
374       GeomAbs_CurveType type = Extrema_CurveTool::GetType(*((Adaptor3d_Curve*)myC[0]));
375       GeomAbs_CurveType type2 = Extrema_CurveTool::GetType(*((Adaptor3d_Curve*)myC[1]));
376       // Parallel case is only for line-line, circle-circle and circle-line!!!
377       // But really for trimmed curves extremas can not exist!
378       Extrema_POnCurv dummypoint(0., gp_Pnt(0.,0.,0.));
379       if(type != type2) {
380         mySqDist.Append(AlgExt.SquareDistance(1));
381         if(type == GeomAbs_Circle) {
382           gp_Pnt PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), Ut11);
383           P1.SetValues(Ut11, PonC1);
384           Extrema_ExtPElC ExtPLin(PonC1, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
385           if(ExtPLin.IsDone()) {
386             mynbext = 1;
387             P2 = ExtPLin.Point(1);
388             mypoints.Append(P1);
389             mypoints.Append(P2);
390           }
391           else {
392             myIsPar = Standard_False;
393             mynbext = 0;
394             mypoints.Append(dummypoint);
395             mypoints.Append(dummypoint);
396           }
397         }
398         else {
399           gp_Pnt PonC2 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), Ut21);
400           P2.SetValues(Ut21, PonC2);
401           Extrema_ExtPElC ExtPLin(PonC2, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[0])), Precision::Confusion(), Ut11, Ut12);
402           if(ExtPLin.IsDone()) {
403             mynbext = 1;
404             P1 = ExtPLin.Point(1);
405             mypoints.Append(P1);
406             mypoints.Append(P2);
407           }
408           else {
409             myIsPar = Standard_False;
410             mynbext = 0;
411             mypoints.Append(dummypoint);
412             mypoints.Append(dummypoint);
413           }
414         }
415         return;
416       }
417           
418       if(type == GeomAbs_Line) {
419         Standard_Boolean infinite = Precision::IsInfinite(Ut11) &&
420                                     Precision::IsInfinite(Ut12) &&
421                                     Precision::IsInfinite(Ut21) &&
422                                     Precision::IsInfinite(Ut22);
423
424         if(infinite) {
425           mynbext = 1;
426           mySqDist.Append(AlgExt.SquareDistance(1));
427           gp_Pnt PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), 0.); 
428           P1.SetValues(0., PonC1);
429           Extrema_ExtPElC ExtPLin(PonC1, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
430           if(ExtPLin.IsDone()) {
431             P2 = ExtPLin.Point(1);
432             mypoints.Append(P1);
433             mypoints.Append(P2);
434           }
435           else {
436             myIsPar = Standard_False;
437             mypoints.Append(dummypoint);
438             mypoints.Append(dummypoint);
439           }
440         }
441         else {
442           Standard_Boolean finish = Standard_False;
443           if(!Precision::IsInfinite(Ut11)) {
444             gp_Pnt PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), Ut11);  
445             Extrema_ExtPElC ExtPLin(PonC1, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
446             if(ExtPLin.IsDone() && ExtPLin.NbExt() > 0) {
447               mynbext = 1;
448               mySqDist.Append(AlgExt.SquareDistance(1));
449               P1.SetValues(Ut11, PonC1);
450               P2 = ExtPLin.Point(1);
451               mypoints.Append(P1);
452               mypoints.Append(P2);
453               finish = Standard_True;
454             }
455           }
456           if(!finish) {
457             if(!Precision::IsInfinite(Ut12)) {
458               gp_Pnt PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), Ut12);  
459               Extrema_ExtPElC ExtPLin(PonC1, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
460               if(ExtPLin.IsDone() && ExtPLin.NbExt() > 0) {
461                 mynbext = 1;
462                 mySqDist.Append(AlgExt.SquareDistance(1));
463                 P1.SetValues(Ut12, PonC1);
464                 P2 = ExtPLin.Point(1);
465                 mypoints.Append(P1);
466                 mypoints.Append(P2);
467                 finish = Standard_True;
468               }
469             }
470           }
471           if(!finish) {
472             if(!Precision::IsInfinite(Ut21)) {
473               gp_Pnt PonC2 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), Ut21);  
474               Extrema_ExtPElC ExtPLin(PonC2, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[0])), Precision::Confusion(), Ut11, Ut12);
475               if(ExtPLin.IsDone() && ExtPLin.NbExt() > 0) {
476                 mynbext = 1;
477                 mySqDist.Append(AlgExt.SquareDistance(1));
478                 P2.SetValues(Ut21, PonC2);
479                 P1 = ExtPLin.Point(1);
480                 mypoints.Append(P1);
481                 mypoints.Append(P2);
482                 finish = Standard_True;
483               }
484             }
485           }
486           if(!finish) {
487             if(!Precision::IsInfinite(Ut22)) {
488               gp_Pnt PonC2 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), Ut22);  
489               Extrema_ExtPElC ExtPLin(PonC2, Extrema_CurveTool::Line(*((Adaptor3d_Curve*)myC[0])), Precision::Confusion(), Ut11, Ut12);
490               if(ExtPLin.IsDone() && ExtPLin.NbExt() > 0) {
491                 mynbext = 1;
492                 mySqDist.Append(AlgExt.SquareDistance(1));
493                 P2.SetValues(Ut22, PonC2);
494                 P1 = ExtPLin.Point(1);
495                 mypoints.Append(P1);
496                 mypoints.Append(P2);
497                 finish = Standard_True;
498               }
499             }
500           }
501           if(!finish) {
502             mynbext = 0;
503             myIsPar = Standard_False;
504             mySqDist.Append(AlgExt.SquareDistance(1));
505             mypoints.Append(dummypoint);
506             mypoints.Append(dummypoint);
507           }
508         }
509           
510       }
511       else {
512         Standard_Boolean finish = Standard_False;
513         gp_Pnt PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), Ut11);  
514         P1.SetValues(Ut11, PonC1);
515         Extrema_ExtPElC ExtPCir(PonC1, Extrema_CurveTool::Circle(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
516         if(ExtPCir.IsDone() && ExtPCir.NbExt() > 0) {
517           for(i = 1; i <= ExtPCir.NbExt(); i++) {
518             mynbext++;
519             P2 = ExtPCir.Point(i);
520             mySqDist.Append(ExtPCir.SquareDistance(i));
521             mypoints.Append(P1);
522             mypoints.Append(P2);
523           }
524           if(mynbext == 2)  finish = Standard_True;
525         }
526         if(!finish) {
527           PonC1 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[0]), Ut12);  
528           ExtPCir.Perform(PonC1, Extrema_CurveTool::Circle(*((Adaptor3d_Curve*)myC[1])), Precision::Confusion(), Ut21, Ut22);
529           P1.SetValues(Ut12, PonC1);
530           if(ExtPCir.IsDone() && ExtPCir.NbExt() > 0) {
531             if(mynbext == 0) {
532               for(i = 1; i <= ExtPCir.NbExt(); i++) {
533                 mynbext++;
534                 P2 = ExtPCir.Point(i);
535                 mySqDist.Append(ExtPCir.SquareDistance(i));
536                 mypoints.Append(P1);
537                 mypoints.Append(P2);
538               }
539             }
540             else {
541               for(i = 1; i <= ExtPCir.NbExt(); i++) {
542                 Standard_Real dist = mySqDist(1);
543                 if(Abs(dist - ExtPCir.SquareDistance(i)) > Precision::Confusion()) {
544                   mynbext++;
545                   P2 = ExtPCir.Point(i);
546                   mySqDist.Append(ExtPCir.SquareDistance(i));
547                   mypoints.Append(P1);
548                   mypoints.Append(P2);
549                 }
550               }
551             }
552                 
553             if(mynbext == 2)  finish = Standard_True;
554           }
555         }  
556         if(!finish) {
557           gp_Pnt PonC2 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), Ut21);  
558           ExtPCir.Perform(PonC2, Extrema_CurveTool::Circle(*((Adaptor3d_Curve*)myC[0])), Precision::Confusion(), Ut11, Ut12);
559           P2.SetValues(Ut21, PonC2);
560           if(ExtPCir.IsDone() && ExtPCir.NbExt() > 0) {
561             if(mynbext == 0) {
562               for(i = 1; i <= ExtPCir.NbExt(); i++) {
563                 mynbext++;
564                 P1 = ExtPCir.Point(i);
565                 mySqDist.Append(ExtPCir.SquareDistance(i));
566                 mypoints.Append(P1);
567                 mypoints.Append(P2);
568               }
569             }
570             else {
571               for(i = 1; i <= ExtPCir.NbExt(); i++) {
572                 Standard_Real dist = mySqDist(1);
573                 if(Abs(dist - ExtPCir.SquareDistance(i)) > Precision::Confusion()) {
574                   mynbext++;
575                   P1 = ExtPCir.Point(i);
576                   mySqDist.Append(ExtPCir.SquareDistance(i));
577                   mypoints.Append(P1);
578                   mypoints.Append(P2);
579                 }
580               }
581             }
582                 
583             if(mynbext == 2)  finish = Standard_True;
584           }
585         }  
586         if(!finish) {
587           gp_Pnt PonC2 = Extrema_CurveTool::Value(*((Adaptor3d_Curve*)myC[1]), Ut22);  
588           ExtPCir.Perform(PonC2, Extrema_CurveTool::Circle(*((Adaptor3d_Curve*)myC[0])), Precision::Confusion(), Ut11, Ut12);
589           P2.SetValues(Ut22, PonC2);
590           if(ExtPCir.IsDone() && ExtPCir.NbExt() > 0) {
591             if(mynbext == 0) {
592               for(i = 1; i <= ExtPCir.NbExt(); i++) {
593                 mynbext++;
594                 P1 = ExtPCir.Point(i);
595                 mySqDist.Append(ExtPCir.SquareDistance(i));
596                 mypoints.Append(P1);
597                 mypoints.Append(P2);
598               }
599             }
600             else {
601               for(i = 1; i <= ExtPCir.NbExt(); i++) {
602                 Standard_Real dist = mySqDist(1);
603                 if(Abs(dist - ExtPCir.SquareDistance(i)) > Precision::Confusion()) {
604                   mynbext++;
605                   P1 = ExtPCir.Point(i);
606                   mySqDist.Append(ExtPCir.SquareDistance(i));
607                   mypoints.Append(P1);
608                   mypoints.Append(P2);
609                 }
610               }
611             }
612                 
613             if(mynbext == 2)  finish = Standard_True;
614           }
615         }  
616         if(mynbext == 0) {
617           myIsPar = Standard_False;
618           mySqDist.Append(AlgExt.SquareDistance(1));
619           mypoints.Append(dummypoint);
620           mypoints.Append(dummypoint);
621           mySqDist.Append(AlgExt.SquareDistance(2));
622           mypoints.Append(dummypoint);
623           mypoints.Append(dummypoint);
624         }
625       } 
626     }
627     else {
628       NbExt = AlgExt.NbExt();
629       for (i = 1; i <= NbExt; i++) {
630         // Verification de la validite des parametres
631         AlgExt.Points(i, P1, P2);
632         if (!inverse) {
633           U = P1.Parameter();
634           U2 = P2.Parameter();
635         }
636         else {
637           U2 = P1.Parameter();
638           U = P2.Parameter();
639         }
640
641         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[0]))) {
642           U = ElCLib::InPeriod(U, Ut11, Ut11+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[0])));
643         }
644         if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[1]))) {
645           U2 = ElCLib::InPeriod(U2, Ut21, Ut21+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[1])));
646         }
647
648         if ((U  >= Ut11 - RealEpsilon())  && 
649             (U  <= Ut12 + RealEpsilon())  &&
650             (U2 >= Ut21 - RealEpsilon())  &&
651             (U2 <= Ut22 + RealEpsilon())) {
652           mynbext++;
653           Val = AlgExt.SquareDistance(i);
654           mySqDist.Append(Val);
655           if (!inverse) {
656             P1.SetValues(U, P1.Value());
657             P2.SetValues(U2, P2.Value());
658             mypoints.Append(P1);
659             mypoints.Append(P2);
660           }
661           else {
662             P1.SetValues(U2, P1.Value());
663             P2.SetValues(U, P2.Value());
664             mypoints.Append(P2);
665             mypoints.Append(P1);
666           }
667         }
668       }
669     }
670   }
671
672 }
673
674
675 //=======================================================================
676 //function : Results
677 //purpose  : 
678 //=======================================================================
679
680 void Extrema_ExtCC::Results(const Extrema_ECC&   AlgExt,
681                              const Standard_Real  Ut11,
682                              const Standard_Real  Ut12,
683                              const Standard_Real  Ut21,
684                              const Standard_Real  Ut22)
685 {
686   Standard_Integer i, NbExt;
687   Standard_Real Val, U, U2;
688   Extrema_POnCurv P1, P2;
689
690   myDone = AlgExt.IsDone();
691   if (myDone)
692   {
693     myIsPar = AlgExt.IsParallel();
694     NbExt = AlgExt.NbExt();
695     for (i = 1; i <= NbExt; i++)
696     {
697       AlgExt.Points(i, P1, P2);
698       U = P1.Parameter();
699       U2 = P2.Parameter();
700
701       // Check points to be into param space.
702       if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[0])))
703       {
704         U = ElCLib::InPeriod(U, Ut11, Ut11+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[0])));
705       }
706       if (Extrema_CurveTool::IsPeriodic(*((Adaptor3d_Curve*)myC[1])))
707       {
708         U2 = ElCLib::InPeriod(U2, Ut21, Ut21+Extrema_CurveTool::Period(*((Adaptor3d_Curve*)myC[1])));
709       }
710
711       if ((U  >= Ut11 - RealEpsilon())  &&
712           (U  <= Ut12 + RealEpsilon())  &&
713           (U2 >= Ut21 - RealEpsilon())  &&
714           (U2 <= Ut22 + RealEpsilon())   )
715       {
716         mynbext++;
717         Val = AlgExt.SquareDistance(i);
718         mySqDist.Append(Val);
719         P1.SetValues(U, P1.Value());
720         P2.SetValues(U2, P2.Value());
721         mypoints.Append(P1);
722         mypoints.Append(P2);
723       }
724     }
725   }
726 }
727
728 //=======================================================================
729 //function : SetSingleSolutionFlag
730 //purpose  : 
731 //=======================================================================
732 void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
733 {
734   myIsFindSingleSolution = theFlag;
735 }
736
737 //=======================================================================
738 //function : GetSingleSolutionFlag
739 //purpose  : 
740 //=======================================================================
741 Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
742 {
743   return myIsFindSingleSolution;
744 }