322f66cf694bd6016d43c54029377e565561eca1
[occt.git] / src / GccGeo / GccGeo_Circ2d2TanOn.gxx
1 // Created on: 1991-12-13
2 // Created by: Remi GILET
3 // Copyright (c) 1991-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 //=========================================================================
18 //   Creation d un cercle tangent a deux elements : Droite.               +
19 //                                                  Cercle.               +
20 //                                                  Point.                +
21 //                                                  Courbes.              +
22 //                        centre sur un troisieme : Droite.               +
23 //                                                  Cercle.               +
24 //                                                  Courbes.              +
25 //=========================================================================
26
27 #include <ElCLib.hxx>
28 #include <gp_Dir2d.hxx>
29 #include <gp_Ax2d.hxx>
30 #include <GccAna_Circ2dBisec.hxx>
31 #include <GccAna_CircLin2dBisec.hxx>
32 #include <GccAna_Lin2dBisec.hxx>
33 #include <GccAna_CircPnt2dBisec.hxx>
34 #include <GccAna_LinPnt2dBisec.hxx>
35 #include <GccAna_Pnt2dBisec.hxx>
36 #include <GccInt_IType.hxx>
37 #include <GccInt_BCirc.hxx>
38 #include <GccInt_BLine.hxx>
39 #include <GccInt_BElips.hxx>
40 #include <GccInt_BHyper.hxx>
41 #include <IntRes2d_Domain.hxx>
42 #include <IntRes2d_IntersectionPoint.hxx>
43 #include <Standard_OutOfRange.hxx>
44 #include <StdFail_NotDone.hxx>
45 #include <TColStd_Array1OfReal.hxx>
46 #include <GccEnt_BadQualifier.hxx>
47 #include <Standard_ConstructionError.hxx>
48
49
50 GccGeo_Circ2d2TanOn::
51    GccGeo_Circ2d2TanOn (const GccEnt_QualifiedCirc&     Qualified1 , 
52                         const GccEnt_QualifiedCirc&     Qualified2 , 
53                         const TheCurve&                 OnCurv     ,
54                         const Standard_Real             Tolerance  ):
55    cirsol(1,8)    ,
56    qualifier1(1,8),
57    qualifier2(1,8),
58    TheSame1(1,8)  ,
59    TheSame2(1,8)  ,
60    pnttg1sol(1,8) ,
61    pnttg2sol(1,8) ,
62    pntcen(1,8)    ,
63    par1sol(1,8)   ,
64    par2sol(1,8)   ,
65    pararg1(1,8)   ,
66    pararg2(1,8)   ,
67    parcen3(1,8)   
68 {
69
70   WellDone = Standard_False;
71   Standard_Real thefirst = -100000.;
72   Standard_Real thelast  =  100000.;
73   Standard_Real firstparam;
74   Standard_Real lastparam;
75   Standard_Real Tol = Abs(Tolerance);
76   NbrSol = 0;
77   TColStd_Array1OfReal Rbid(1,2);
78   TColStd_Array1OfReal RBid(1,2);
79   TColStd_Array1OfReal Radius(1,2);
80   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
81         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
82       !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
83         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
84     GccEnt_BadQualifier::Raise();
85     return;
86   }
87   gp_Circ2d C1 = Qualified1.Qualified();
88   gp_Circ2d C2 = Qualified2.Qualified();
89   Standard_Real R1 = C1.Radius();
90   Standard_Real R2 = C2.Radius();
91   gp_Dir2d dirx(1.,0.);
92   gp_Pnt2d center1(C1.Location());
93   gp_Pnt2d center2(C2.Location());
94   GccAna_Circ2dBisec Bis(C1,C2);
95   if (Bis.IsDone()) {
96     TheIntConicCurve Intp;
97     Standard_Integer nbsolution = Bis.NbSolutions();
98     Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
99     TheParGenCurve Cu2(HCu2,0.);
100     firstparam = Max(TheCurvePGTool::FirstParameter(Cu2),thefirst);
101     lastparam  = Min(TheCurvePGTool::LastParameter(Cu2),thelast);
102     IntRes2d_Domain D2(TheCurvePGTool::Value(Cu2,firstparam),firstparam,Tol,
103                        TheCurvePGTool::Value(Cu2,lastparam),lastparam,Tol);
104     Standard_Real Tol1 = Abs(Tolerance);
105     Standard_Real Tol2 = Tol1;
106     for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
107       Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
108       GccInt_IType type = Sol->ArcType();
109       switch (type) {
110       case GccInt_Cir:
111         {
112           gp_Circ2d Circ(Sol->Circle());
113           IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol1,
114                              ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol2);
115           D1.SetEquivalentParameters(0.,2.*M_PI);
116           Intp.Perform(Circ,D1,Cu2,D2,Tol1,Tol2);
117         }
118         break;
119       case GccInt_Ell:
120         {
121           gp_Elips2d Elips(Sol->Ellipse());
122           IntRes2d_Domain D1(ElCLib::Value(0.,Elips),   0.,Tol1,
123                              ElCLib::Value(2.*M_PI,Elips),2.*M_PI,Tol2);
124           D1.SetEquivalentParameters(0.,2.*M_PI);
125           Intp.Perform(Elips,D1,Cu2,D2,Tol1,Tol2);
126         }
127         break;
128       case GccInt_Hpr:
129         {
130           gp_Hypr2d Hypr(Sol->Hyperbola());
131           IntRes2d_Domain D1(ElCLib::Value(-4.,Hypr),-4.,Tol1,
132                              ElCLib::Value(4.,Hypr),4.,Tol2);
133           Intp.Perform(Hypr,D1,Cu2,D2,Tol1,Tol2);
134         }
135         break;
136       case GccInt_Lin:
137         {
138           gp_Lin2d Line(Sol->Line());
139           IntRes2d_Domain D1;
140           Intp.Perform(Line,D1,Cu2,D2,Tol1,Tol2);
141         }
142         break;
143       default:
144         {
145           Standard_ConstructionError::Raise();
146         }
147       }
148       if (Intp.IsDone()) {
149         if ((!Intp.IsEmpty())) {
150           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
151             gp_Pnt2d Center(Intp.Point(j).Value());
152             Standard_Real dist1 = Center.Distance(C1.Location());
153             Standard_Real dist2 = Center.Distance(C2.Location());
154             Standard_Integer nbsol = 0;
155             Standard_Integer nnsol = 0;
156             R1 = C1.Radius();
157             R2 = C2.Radius();
158             if (Qualified1.IsEnclosed()) {
159               if (dist1-R1 < Tol) { 
160                 nbsol = 1;
161                 Rbid(1) = Abs(R1-dist1);
162               }
163             }
164             else if (Qualified1.IsOutside()) {
165               if (R1-dist1 < Tol) { 
166                 nbsol = 1;
167                 Rbid(1) = Abs(dist1-R1);
168               }
169             }
170             else if (Qualified1.IsEnclosing()) {
171               nbsol = 1;
172               Rbid(1) = dist1+R1;
173             }
174             else if (Qualified1.IsUnqualified()) {
175               nbsol = 2;
176               Rbid(1) = dist1+R1;
177               Rbid(1) = Abs(dist1-R1);
178             }
179             if (Qualified2.IsEnclosed() && nbsol != 0) {
180               if (dist2-R2 < Tol) {
181                 RBid(1) = Abs(R2-dist2);
182               }
183             }
184             else if (Qualified2.IsOutside() && nbsol != 0) {
185               if (R2-dist2 < Tol) {
186                 RBid(1) = Abs(R2-dist2);
187               }
188             }
189             else if (Qualified2.IsEnclosing() && nbsol != 0) {
190               RBid(1) = dist2+R2;
191             }
192             else if (Qualified2.IsUnqualified() && nbsol != 0) {
193               RBid(1) = dist2+R2;
194               RBid(2) = Abs(R2-dist2);
195             }
196             for (Standard_Integer isol = 1; isol <= nbsol ; isol++) {
197               for (Standard_Integer jsol = 1; jsol <= nbsol ; jsol++) {
198                 if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) {
199                   nnsol++;
200                   Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.;
201                 }
202               }
203             }
204             if (nnsol > 0) {
205               for (Standard_Integer k = 1 ; k <= nnsol ; k++) {
206                 NbrSol++;
207                 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k));
208 //              ==========================================================
209                 Standard_Real distcc1 = Center.Distance(center1);
210                 Standard_Real distcc2 = Center.Distance(center2);
211                 if (!Qualified1.IsUnqualified()) { 
212                   qualifier1(NbrSol) = Qualified1.Qualifier();
213                 }
214                 else if (Abs(distcc1+Radius(i)-R1) < Tol) {
215                   qualifier1(NbrSol) = GccEnt_enclosed;
216                 }
217                 else if (Abs(distcc1-R1-Radius(i)) < Tol) {
218                   qualifier1(NbrSol) = GccEnt_outside;
219                 }
220                 else { qualifier1(NbrSol) = GccEnt_enclosing; }
221                 if (!Qualified2.IsUnqualified()) { 
222                   qualifier2(NbrSol) = Qualified2.Qualifier();
223                 }
224                 else if (Abs(distcc2+Radius(i)-R2) < Tol) {
225                   qualifier2(NbrSol) = GccEnt_enclosed;
226                 }
227                 else if (Abs(distcc2-R2-Radius(i)) < Tol) {
228                   qualifier2(NbrSol) = GccEnt_outside;
229                 }
230                 else { qualifier2(NbrSol) = GccEnt_enclosing; }
231                 if (dist1 <= Tol && Abs(Radius(k)-C1.Radius()) <= Tol) {
232                   TheSame1(NbrSol) = 1;
233                 }
234                 else {
235                   TheSame1(NbrSol) = 0;
236                   gp_Dir2d dc1(C1.Location().XY()-Center.XY());
237                   pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc1.XY());
238                   par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
239                                                     pnttg1sol(NbrSol));
240                   pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
241                 }
242                 if (dist2 <= Tol && Abs(Radius(k)-C2.Radius()) <= Tol) {
243                   TheSame2(NbrSol) = 1;
244                 }
245                 else {
246                   TheSame2(NbrSol) = 0;
247                   gp_Dir2d dc2(C2.Location().XY()-Center.XY());
248                   pnttg2sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc2.XY());
249                   par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
250                                                     pnttg2sol(NbrSol));
251                   pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
252                 }
253                 pntcen(NbrSol) = Center;
254                 parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
255               }
256               WellDone = Standard_True;
257             }
258           }
259         }
260       }
261     }
262   }
263 }
264
265 //=========================================================================
266 //   Creation d un cercle tangent a un Cercle C1 et a une Droite L2.      +
267 //                        centre sur une courbe OnCurv.                   +
268 //  Nous calculons les bissectrices a C1 et L2 qui nous donnent           +
269 //  l ensemble des lieux possibles des centres de tous les cercles        +
270 //  tangents a C1 et L2.                                                  +
271 //  Nous intersectons ces bissectrices avec la courbe OnCurv ce qui nous  +
272 //  donne les points parmis lesquels nous allons choisir les solutions.   +
273 //  Les choix s effectuent a partir des Qualifieurs qualifiant C1 et L2.  +
274 //=========================================================================
275
276 GccGeo_Circ2d2TanOn::
277    GccGeo_Circ2d2TanOn (const GccEnt_QualifiedCirc&     Qualified1 , 
278                         const GccEnt_QualifiedLin&      Qualified2 , 
279                         const TheCurve&                 OnCurv     ,
280                         const Standard_Real             Tolerance  ):
281    cirsol(1,8)    ,
282    qualifier1(1,8),
283    qualifier2(1,8),
284    TheSame1(1,8)  ,
285    TheSame2(1,8)  ,
286    pnttg1sol(1,8) ,
287    pnttg2sol(1,8) ,
288    pntcen(1,8)    ,
289    par1sol(1,8)   ,
290    par2sol(1,8)   ,
291    pararg1(1,8)   ,
292    pararg2(1,8)   ,
293    parcen3(1,8)   
294 {
295
296   WellDone = Standard_False;
297   Standard_Real thefirst = -100000.;
298   Standard_Real thelast  =  100000.;
299   Standard_Real firstparam;
300   Standard_Real lastparam;
301   NbrSol = 0;
302   Standard_Real Tol = Abs(Tolerance);
303   Standard_Real Radius;
304   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
305         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
306       !(Qualified2.IsEnclosed() ||
307         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
308     GccEnt_BadQualifier::Raise();
309       return;
310     }
311   gp_Dir2d dirx(1.,0.);
312   gp_Circ2d C1 = Qualified1.Qualified();
313   gp_Lin2d L2 = Qualified2.Qualified();
314   Standard_Real R1 = C1.Radius();
315   gp_Pnt2d center1(C1.Location());
316   gp_Pnt2d origin2(L2.Location());
317   gp_Dir2d dir2(L2.Direction());
318   gp_Dir2d normL2(-dir2.Y(),dir2.X());
319   
320   GccAna_CircLin2dBisec Bis(C1,L2);
321   if (Bis.IsDone()) {
322     Standard_Real Tol1 = Abs(Tolerance);
323     Standard_Real Tol2 = Tol1;
324     TheIntConicCurve Intp;
325     Standard_Integer nbsolution = Bis.NbSolutions();
326     Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
327     TheParGenCurve C2(HCu2,0.);
328     firstparam = Max(TheCurvePGTool::FirstParameter(C2),thefirst);
329     lastparam  = Min(TheCurvePGTool::LastParameter(C2),thelast);
330     IntRes2d_Domain D2(TheCurvePGTool::Value(C2,firstparam),firstparam,Tol,
331                        TheCurvePGTool::Value(C2,lastparam),lastparam,Tol);
332     for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
333       Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
334       GccInt_IType type = Sol->ArcType();
335       switch (type) {
336       case GccInt_Lin:
337         {
338           gp_Lin2d Line(Sol->Line());
339           IntRes2d_Domain D1;
340           Intp.Perform(Line,D1,C2,D2,Tol1,Tol2);
341         }
342         break;
343       case GccInt_Par:
344         {
345           gp_Parab2d Parab(Sol->Parabola());
346           IntRes2d_Domain D1(ElCLib::Value(-40,Parab),-40,Tol1,
347                              ElCLib::Value(40,Parab),40,Tol1);
348           Intp.Perform(Parab,D1,C2,D2,Tol1,Tol2);
349         }
350         break;
351       default:
352         {
353           Standard_ConstructionError::Raise();
354         }
355       }
356       if (Intp.IsDone()) {
357         if (!Intp.IsEmpty()) {
358           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
359             gp_Pnt2d Center(Intp.Point(j).Value());
360             Standard_Real dist1 = Center.Distance(center1);
361 //          Standard_Integer nbsol = 1;
362             Standard_Boolean ok = Standard_False;
363             if (Qualified1.IsEnclosed()) {
364               if (dist1-R1 < Tol) { ok = Standard_True; }
365             }
366             else if (Qualified1.IsOutside()) {
367               if (R1-dist1 < Tol) { ok = Standard_True; }
368             }
369             else if (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) {
370               ok = Standard_True;
371             }
372             Radius = L2.Distance(Center);
373             if (Qualified2.IsEnclosed() && ok) {
374               ok = Standard_False;
375               if ((((origin2.X()-Center.X())*(-dir2.Y()))+
376                     ((origin2.Y()-Center.Y())*(dir2.X())))<=0){
377                 ok = Standard_True;
378               }
379             }
380             else if (Qualified2.IsOutside() && ok) {
381               ok = Standard_False;
382               if ((((origin2.X()-Center.X())*(-dir2.Y()))+
383                     ((origin2.Y()-Center.Y())*(dir2.X())))>=0){
384                 ok = Standard_True;
385               }
386             }
387             if (Qualified1.IsEnclosing()&&dist1>Radius) { ok=Standard_False; }
388             if (ok) {
389               NbrSol++;
390               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
391 //            =======================================================
392 #ifdef DEB
393               gp_Dir2d dc1(center1.XY()-Center.XY());
394 #endif
395               gp_Dir2d dc2(origin2.XY()-Center.XY());
396               Standard_Real distcc1 = Center.Distance(center1);
397               if (!Qualified1.IsUnqualified()) { 
398                 qualifier1(NbrSol) = Qualified1.Qualifier();
399               }
400               else if (Abs(distcc1+Radius-R1) < Tol) {
401                 qualifier1(NbrSol) = GccEnt_enclosed;
402               }
403               else if (Abs(distcc1-R1-Radius) < Tol) {
404                 qualifier1(NbrSol) = GccEnt_outside;
405               }
406               else { qualifier1(NbrSol) = GccEnt_enclosing; }
407               if (!Qualified2.IsUnqualified()) { 
408                 qualifier2(NbrSol) = Qualified2.Qualifier();
409               }
410               else if (dc2.Dot(normL2) > 0.0) {
411                 qualifier2(NbrSol) = GccEnt_outside;
412               }
413               else { qualifier2(NbrSol) = GccEnt_enclosed; }
414               if (dist1 <= Tol && Abs(Radius-C1.Radius()) <= Tol) {
415                 TheSame1(NbrSol) = 1;
416               }
417               else {
418                 TheSame1(NbrSol) = 0;
419                 gp_Dir2d dc1(center1.XY()-Center.XY());
420                 pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius*dc1.XY());
421                 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
422                                                   pnttg1sol(NbrSol));
423                 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
424               }
425               TheSame2(NbrSol) = 0;
426               Standard_Real sign = dc2.Dot(gp_Dir2d(-dir2.Y(),dir2.X()));
427               dc2 = gp_Dir2d(sign*gp_XY(-dir2.Y(),dir2.X()));
428               pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc2.XY());
429               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
430                                                 pnttg2sol(NbrSol));
431               pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
432               pntcen(NbrSol) = Center;
433               parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
434             }
435           }
436         }
437         WellDone = Standard_True;
438       }
439     }
440   }
441 }
442
443 //=========================================================================
444 //   Creation d un cercle tant a deux Droites L1 et L2.                +
445 //                        centre sur une courbe OnCurv.                   +
446 //  Nous calculons les bissectrices a L1 et L2 qui nous donnent           +
447 //  l ensemble des lieux possibles des centres de tous les cercles        +
448 //  tants a L1 et L2.                                                  +
449 //  Nous intersectons ces bissectrices avec la courbe OnCurv ce qui nous  +
450 //  donne les points parmis lesquels nous allons choisir les solutions.   +
451 //  Les choix s effectuent a partir des Qualifieurs qualifiant L1 et L2.  +
452 //=========================================================================
453
454 GccGeo_Circ2d2TanOn::
455    GccGeo_Circ2d2TanOn (const GccEnt_QualifiedLin&      Qualified1 , 
456                         const GccEnt_QualifiedLin&      Qualified2 , 
457                         const TheCurve&                 OnCurv     ,
458                         const Standard_Real             Tolerance  ):
459    cirsol(1,8)    ,
460    qualifier1(1,8),
461    qualifier2(1,8),
462    TheSame1(1,8)  ,
463    TheSame2(1,8)  ,
464    pnttg1sol(1,8) ,
465    pnttg2sol(1,8) ,
466    pntcen(1,8)    ,
467    par1sol(1,8)   ,
468    par2sol(1,8)   ,
469    pararg1(1,8)   ,
470    pararg2(1,8)   ,
471    parcen3(1,8)   
472 {
473
474   WellDone = Standard_False;
475   Standard_Real thefirst = -100000.;
476   Standard_Real thelast  =  100000.;
477   Standard_Real firstparam;
478   Standard_Real lastparam;
479   NbrSol = 0;
480   if (!(Qualified1.IsEnclosed() || 
481         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
482       !(Qualified2.IsEnclosed() ||
483         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
484     GccEnt_BadQualifier::Raise();
485       return;
486     }
487   Standard_Real Tol = Abs(Tolerance);
488   Standard_Real Radius=0;
489   gp_Dir2d dirx(1.,0.);
490   gp_Lin2d L1 = Qualified1.Qualified();
491   gp_Lin2d L2 = Qualified2.Qualified();
492   gp_Dir2d dir1(L1.Direction());
493   gp_Dir2d dir2(L2.Direction());
494   gp_Dir2d Dnor1(-dir1.Y(),dir1.X());
495   gp_Dir2d Dnor2(-dir2.Y(),dir2.X());
496   gp_Pnt2d origin1(L1.Location());
497   gp_Pnt2d origin2(L2.Location());
498   GccAna_Lin2dBisec Bis(L1,L2);
499   if (Bis.IsDone()) {
500     Standard_Real Tol1 = Abs(Tolerance);
501     Standard_Real Tol2 = Tol1;
502     TheIntConicCurve Intp;
503     Standard_Integer nbsolution = Bis.NbSolutions();
504     Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
505     TheParGenCurve C2(HCu2,0.);
506     firstparam = Max(TheCurvePGTool::FirstParameter(C2),thefirst);
507     lastparam  = Min(TheCurvePGTool::LastParameter(C2),thelast);
508     IntRes2d_Domain D2(TheCurvePGTool::Value(C2,firstparam),firstparam,Tol,
509                        TheCurvePGTool::Value(C2,lastparam),lastparam,Tol);
510     IntRes2d_Domain D1;
511     for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
512       Intp.Perform(Bis.ThisSolution(i),D1,C2,D2,Tol1,Tol2);
513       if (Intp.IsDone()) {
514         if ((!Intp.IsEmpty())) {
515           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
516             gp_Pnt2d Center(Intp.Point(j).Value());
517             Standard_Real dist1 = L1.Distance(Center);
518             Standard_Real dist2 = L2.Distance(Center);
519 //          Standard_Integer nbsol = 1;
520             Standard_Boolean ok = Standard_False;
521             if (Qualified1.IsEnclosed()) {
522               if ((((origin1.X()-Center.X())*(-dir1.Y()))+
523                    ((origin1.Y()-Center.Y())*(dir1.X())))<=0){
524                 ok = Standard_True;
525               }
526             }
527             else if (Qualified1.IsOutside()) {
528               if ((((origin1.X()-Center.X())*(-dir1.Y()))+
529                    ((origin1.Y()-Center.Y())*(dir1.X())))>=0){
530                 ok = Standard_True;
531               }
532             }
533             else if (Qualified1.IsUnqualified()) { ok = Standard_True; }
534             if (Qualified2.IsEnclosed() && ok) {
535               ok = Standard_False;
536               if ((((origin2.X()-Center.X())*(-dir2.Y()))+
537                    ((origin2.Y()-Center.Y())*(dir2.X())))<=0){
538                 ok = Standard_True;
539                 Radius = (dist1+dist2)/2.;
540               }
541             }
542             else if (Qualified2.IsOutside() && ok) {
543               ok = Standard_False;
544               if ((((origin2.X()-Center.X())*(-dir2.Y()))+
545                    ((origin2.Y()-Center.Y())*(dir2.X())))>=0){
546                 ok = Standard_True;
547                 Radius = (dist1+dist2)/2.;
548               }
549             }
550             else if (Qualified2.IsUnqualified() && ok) {
551               Radius = (dist1+dist2)/2.;
552             }
553             if (ok) {
554               NbrSol++;
555               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
556 //            =======================================================
557               gp_Dir2d dc1(origin1.XY()-Center.XY());
558               gp_Dir2d dc2(origin2.XY()-Center.XY());
559               if (!Qualified1.IsUnqualified()) { 
560                 qualifier1(NbrSol) = Qualified1.Qualifier();
561               }
562               else if (dc1.Dot(Dnor1) > 0.0) {
563                 qualifier1(NbrSol) = GccEnt_outside;
564               }
565               else { qualifier1(NbrSol) = GccEnt_enclosed; }
566               if (!Qualified2.IsUnqualified()) { 
567                 qualifier2(NbrSol) = Qualified2.Qualifier();
568               }
569               else if (dc2.Dot(Dnor2) > 0.0) {
570                 qualifier2(NbrSol) = GccEnt_outside;
571               }
572               else { qualifier2(NbrSol) = GccEnt_enclosed; }
573               TheSame1(NbrSol) = 0;
574               TheSame2(NbrSol) = 0;
575               Standard_Real sign = dc1.Dot(Dnor1);
576               dc1 = gp_Dir2d(sign*gp_XY(-dir1.Y(),dir1.X()));
577               pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc1.XY());
578               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
579                                                 pnttg1sol(NbrSol));
580               pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
581               sign = dc2.Dot(gp_Dir2d(-dir2.Y(),dir2.X()));
582               dc2 = gp_Dir2d(sign*gp_XY(-dir2.Y(),dir2.X()));
583               pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc2.XY());
584               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
585                                                 pnttg2sol(NbrSol));
586               pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
587               pntcen(NbrSol) = Center;
588               parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
589             }
590           }
591         }
592         WellDone = Standard_True;
593       }
594     }
595   }
596 }
597
598 //=========================================================================
599 //   Creation d un cercle tant a un Cercle C1, passant par un point P2 +
600 //                        centre sur une courbe OnCurv.                   +
601 //  Nous calculons les bissectrices a C1 et Point2 qui nous donnent       +
602 //  l ensemble des lieux possibles des centres de tous les cercles        +
603 //  tants a C1 et Point2.                                              +
604 //  Nous intersectons ces bissectrices avec la courbe OnCurv ce qui nous  +
605 //  donne les points parmis lesquels nous allons choisir les solutions.   +
606 //  Les choix s effectuent a partir des Qualifieurs qualifiant C1.        +
607 //=========================================================================
608
609 GccGeo_Circ2d2TanOn::
610    GccGeo_Circ2d2TanOn (const GccEnt_QualifiedCirc&     Qualified1 , 
611                         const gp_Pnt2d&                 Point2     , 
612                         const TheCurve&                 OnCurv     ,
613                         const Standard_Real             Tolerance  ):
614    cirsol(1,8)    ,
615    qualifier1(1,8),
616    qualifier2(1,8),
617    TheSame1(1,8)  ,
618    TheSame2(1,8)  ,
619    pnttg1sol(1,8) ,
620    pnttg2sol(1,8) ,
621    pntcen(1,8)    ,
622    par1sol(1,8)   ,
623    par2sol(1,8)   ,
624    pararg1(1,8)   ,
625    pararg2(1,8)   ,
626    parcen3(1,8)   
627 {
628
629   WellDone = Standard_False;
630   Standard_Real thefirst = -100000.;
631   Standard_Real thelast  =  100000.;
632   Standard_Real firstparam;
633   Standard_Real lastparam;
634   NbrSol = 0;
635   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
636         Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
637     GccEnt_BadQualifier::Raise();
638       return;
639     }
640   Standard_Real Tol = Abs(Tolerance);
641   Standard_Real Radius;
642   gp_Dir2d dirx(1.,0.);
643   gp_Circ2d C1 = Qualified1.Qualified();
644   Standard_Real R1 = C1.Radius();
645   gp_Pnt2d center1(C1.Location());
646   GccAna_CircPnt2dBisec Bis(C1,Point2);
647   if (Bis.IsDone()) {
648     Standard_Real Tol1 = Abs(Tolerance);
649     Standard_Real Tol2 = Tol1;
650     TheIntConicCurve Intp;
651     Standard_Integer nbsolution = Bis.NbSolutions();
652     Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
653     TheParGenCurve C2(HCu2,0.);
654     firstparam = Max(TheCurvePGTool::FirstParameter(C2),thefirst);
655     lastparam  = Min(TheCurvePGTool::LastParameter(C2),thelast);
656     IntRes2d_Domain D2(TheCurvePGTool::Value(C2,firstparam),firstparam,Tol,
657                        TheCurvePGTool::Value(C2,lastparam),lastparam,Tol);
658     for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
659       Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
660       GccInt_IType type = Sol->ArcType();
661       switch (type) {
662       case GccInt_Cir:
663         {
664           gp_Circ2d Circ(Sol->Circle());
665           IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol1,
666                              ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol2);
667           D1.SetEquivalentParameters(0.,2.*M_PI);
668           Intp.Perform(Circ,D1,C2,D2,Tol1,Tol2);
669         }
670         break;
671       case GccInt_Lin:
672         {
673           gp_Lin2d Line(Sol->Line());
674           IntRes2d_Domain D1;
675           Intp.Perform(Line,D1,C2,D2,Tol1,Tol2);
676         }
677         break;
678       case GccInt_Ell:
679         {
680           gp_Elips2d Elips(Sol->Ellipse());
681           IntRes2d_Domain D1(ElCLib::Value(0.,Elips),   0.,Tol1,
682                              ElCLib::Value(2.*M_PI,Elips),2.*M_PI,Tol2);
683           D1.SetEquivalentParameters(0.,2.*M_PI);
684           Intp.Perform(Elips,D1,C2,D2,Tol1,Tol2);
685         }
686         break;
687       case GccInt_Hpr:
688         {
689           gp_Hypr2d Hypr(Sol->Hyperbola());
690           IntRes2d_Domain D1(ElCLib::Value(-4.,Hypr),-4.,Tol1,
691                              ElCLib::Value(4.,Hypr),4.,Tol2);
692           Intp.Perform(Hypr,D1,C2,D2,Tol1,Tol2);
693         }
694         break;
695       default:
696         {
697           Standard_ConstructionError::Raise();
698         }
699       }
700       if (Intp.IsDone()) {
701         if ((!Intp.IsEmpty())) {
702           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
703             gp_Pnt2d Center(Intp.Point(j).Value());
704             Radius = Center.Distance(Point2);
705             Standard_Real dist1 = center1.Distance(Center);
706 //          Standard_Integer nbsol = 1;
707             Standard_Boolean ok = Standard_False;
708             if (Qualified1.IsEnclosed()) {
709               if (dist1-R1 <= Tol) { ok = Standard_True; }
710             }
711             else if (Qualified1.IsOutside()) {
712               if (R1-dist1 <= Tol) { ok = Standard_True; }
713             }
714             else if (Qualified1.IsEnclosing()) { ok = Standard_True; }
715             else if (Qualified1.IsUnqualified()) { ok = Standard_True; }
716             if (ok) {
717               NbrSol++;
718               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
719 //            =======================================================
720               Standard_Real distcc1 = Center.Distance(center1);
721               if (!Qualified1.IsUnqualified()) { 
722                 qualifier1(NbrSol) = Qualified1.Qualifier();
723               }
724               else if (Abs(distcc1+Radius-R1) < Tol) {
725                 qualifier1(NbrSol) = GccEnt_enclosed;
726               }
727               else if (Abs(distcc1-R1-Radius) < Tol) {
728                 qualifier1(NbrSol) = GccEnt_outside;
729               }
730               else { qualifier1(NbrSol) = GccEnt_enclosing; }
731               qualifier2(NbrSol) = GccEnt_noqualifier;
732               if (dist1 <= Tol && Abs(Radius-R1) <= Tol) {
733                 TheSame1(NbrSol) = 1;
734               }
735               else {
736                 TheSame1(NbrSol) = 0;
737                 gp_Dir2d dc1(center1.XY()-Center.XY());
738                 pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius*dc1.XY());
739                 par1sol(NbrSol) = 0.;
740                 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
741                                                   pnttg1sol(NbrSol));
742                 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
743               }
744               TheSame2(NbrSol) = 0;
745               pnttg2sol(NbrSol) = Point2;
746               pntcen(NbrSol) = Center;
747               parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
748               pararg2(NbrSol) = 0.;
749               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
750                                                 pnttg2sol(NbrSol));
751             }
752           }
753         }
754         WellDone = Standard_True;
755       }
756     }
757   }
758 }
759
760 //=========================================================================
761 //   Creation d un cercle tant a une ligne L1, passant par un point P2 +
762 //                        centre sur une courbe OnCurv.                   +
763 //  Nous calculons les bissectrices a L1 et Point2 qui nous donnent       +
764 //  l ensemble des lieux possibles des centres de tous les cercles        +
765 //  tants a L1 et passant par Point2.                                  +
766 //  Nous intersectons ces bissectrices avec la courbe OnCurv ce qui nous  +
767 //  donne les points parmis lesquels nous allons choisir les solutions.   +
768 //  Les choix s effectuent a partir des Qualifieurs qualifiant L1.        +
769 //=========================================================================
770
771 GccGeo_Circ2d2TanOn::
772    GccGeo_Circ2d2TanOn (const GccEnt_QualifiedLin&      Qualified1 , 
773                         const gp_Pnt2d&                 Point2     , 
774                         const TheCurve&                 OnCurv     ,
775                         const Standard_Real             Tolerance  ):
776    cirsol(1,8)    ,
777    qualifier1(1,8),
778    qualifier2(1,8),
779    TheSame1(1,8)  ,
780    TheSame2(1,8)  ,
781    pnttg1sol(1,8) ,
782    pnttg2sol(1,8) ,
783    pntcen(1,8)    ,
784    par1sol(1,8)   ,
785    par2sol(1,8)   ,
786    pararg1(1,8)   ,
787    pararg2(1,8)   ,
788    parcen3(1,8)   
789 {
790
791   WellDone = Standard_False;
792   Standard_Real thefirst = -100000.;
793   Standard_Real thelast  =  100000.;
794   Standard_Real firstparam;
795   Standard_Real lastparam;
796   Standard_Real Tol = Abs(Tolerance);
797   NbrSol = 0;
798   if (!(Qualified1.IsEnclosed() ||
799         Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
800     GccEnt_BadQualifier::Raise();
801       return;
802     }
803   gp_Dir2d dirx(1.,0.);
804   gp_Lin2d L1 = Qualified1.Qualified();
805   gp_Pnt2d origin1(L1.Location());
806   gp_Dir2d dir1(L1.Direction());
807   gp_Dir2d normal(-dir1.Y(),dir1.X());
808   GccAna_LinPnt2dBisec Bis(L1,Point2);
809   if (Bis.IsDone()) {
810     Standard_Real Tol1 = Abs(Tolerance);
811     Standard_Real Tol2 = Tol1;
812     TheIntConicCurve Intp;
813     Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
814     TheParGenCurve C2(HCu2,0.);
815     firstparam = Max(TheCurvePGTool::FirstParameter(C2),thefirst);
816     lastparam  = Min(TheCurvePGTool::LastParameter(C2),thelast);
817     IntRes2d_Domain D2(TheCurvePGTool::Value(C2,firstparam),firstparam,Tol,
818                        TheCurvePGTool::Value(C2,lastparam),lastparam,Tol);
819     Handle(GccInt_Bisec) Sol = Bis.ThisSolution();
820     GccInt_IType type = Sol->ArcType();
821     switch (type) {
822     case GccInt_Lin:
823       {
824         gp_Lin2d Line(Sol->Line());
825         IntRes2d_Domain D1;
826         Intp.Perform(Line,D1,C2,D2,Tol1,Tol2);
827       }
828       break;
829     case GccInt_Par:
830       {
831         gp_Parab2d Parab(Sol->Parabola());
832         IntRes2d_Domain D1(ElCLib::Value(-40,Parab),-40,Tol1,
833                            ElCLib::Value(40,Parab),40,Tol1);
834         Intp.Perform(Parab,D1,C2,D2,Tol1,Tol2);
835       }
836       break;
837     default:
838       {
839         Standard_ConstructionError::Raise();
840       }
841     }
842     if (Intp.IsDone()) {
843       if ((!Intp.IsEmpty())) {
844         for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
845           gp_Pnt2d Center(Intp.Point(j).Value());
846           Standard_Real Radius = L1.Distance(Center);
847 //        Standard_Integer nbsol = 1;
848           Standard_Boolean ok = Standard_False;
849           if (Qualified1.IsEnclosed()) {
850             if ((((origin1.X()-Center.X())*(-dir1.Y()))+
851                  ((origin1.Y()-Center.Y())*(dir1.X())))<=0){
852               ok = Standard_True;
853             }
854           }
855           else if (Qualified1.IsOutside()) {
856             if ((((origin1.X()-Center.X())*(-dir1.Y()))+
857                  ((origin1.Y()-Center.Y())*(dir1.X())))>=0){
858               ok = Standard_True;
859             }
860           }
861           else if (Qualified1.IsUnqualified()) { ok = Standard_True; }
862           if (ok) {
863             NbrSol++;
864             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
865 //          =======================================================
866             qualifier2(NbrSol) = GccEnt_noqualifier;
867             gp_Dir2d dc2(origin1.XY()-Center.XY());
868             if (!Qualified1.IsUnqualified()) { 
869               qualifier1(NbrSol) = Qualified1.Qualifier();
870             }
871             else if (dc2.Dot(normal) > 0.0) {
872               qualifier1(NbrSol) = GccEnt_outside;
873             }
874             else { qualifier1(NbrSol) = GccEnt_enclosed; }
875             TheSame1(NbrSol) = 0;
876             TheSame2(NbrSol) = 0;
877             gp_Dir2d dc1(origin1.XY()-Center.XY());
878             Standard_Real sign = dc1.Dot(gp_Dir2d(-dir1.Y(),dir1.X()));
879             dc1=gp_Dir2d(sign*gp_XY(-dir1.Y(),dir1.X()));
880             pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc1.XY());
881             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
882                                               pnttg1sol(NbrSol));
883             pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
884             pnttg2sol(NbrSol) = Point2;
885             par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
886                                               pnttg2sol(NbrSol));
887             pararg2(NbrSol) = 0.;
888             pntcen(NbrSol) = Center;
889             parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
890           }
891         }
892       }
893       WellDone = Standard_True;
894     }
895   }
896 }
897  
898 //=========================================================================
899 //   Creation d un cercle passant par deux point Point1 et Point2         +
900 //                        centre sur une courbe OnCurv.                   +
901 //  Nous calculons les bissectrices a Point1 et Point2 qui nous donnent   +
902 //  l ensemble des lieux possibles des centres de tous les cercles        +
903 //  passant par Point1 et Point2.                                         +
904 //  Nous intersectons ces bissectrices avec la courbe OnCurv ce qui nous  +
905 //  donne les points parmis lesquels nous allons choisir les solutions.   +
906 //=========================================================================
907
908 GccGeo_Circ2d2TanOn::
909    GccGeo_Circ2d2TanOn (const gp_Pnt2d&               Point1    ,
910                         const gp_Pnt2d&               Point2    ,
911                         const TheCurve&               OnCurv    ,
912                         const Standard_Real           Tolerance ):
913    cirsol(1,8)    ,
914    qualifier1(1,8),
915    qualifier2(1,8),
916    TheSame1(1,8)  ,
917    TheSame2(1,8)  ,
918    pnttg1sol(1,8) ,
919    pnttg2sol(1,8) ,
920    pntcen(1,8)    ,
921    par1sol(1,8)   ,
922    par2sol(1,8)   ,
923    pararg1(1,8)   ,
924    pararg2(1,8)   ,
925    parcen3(1,8)   
926 {
927
928    WellDone = Standard_False;
929    Standard_Real thefirst = -100000.;
930    Standard_Real thelast  =  100000.;
931    Standard_Real firstparam;
932    Standard_Real lastparam;
933    Standard_Real Tol = Abs(Tolerance);
934    NbrSol = 0;
935    gp_Dir2d dirx(1.,0.);
936    GccAna_Pnt2dBisec Bis(Point1,Point2);
937    if (Bis.IsDone()) {
938      Standard_Real Tol1 = Abs(Tolerance);
939      Standard_Real Tol2 = Tol1;
940      TheIntConicCurve Intp;
941      Handle(TheHParGenCurve) HCu2 = new TheHParGenCurve(OnCurv); 
942      TheParGenCurve Cu2(HCu2,0.);
943      firstparam = Max(TheCurvePGTool::FirstParameter(Cu2),thefirst);
944      lastparam  = Min(TheCurvePGTool::LastParameter(Cu2),thelast);
945      IntRes2d_Domain D2(TheCurvePGTool::Value(Cu2,firstparam),firstparam,Tol,
946                         TheCurvePGTool::Value(Cu2,lastparam),lastparam,Tol);
947      IntRes2d_Domain D1;
948      if (Bis.HasSolution()) {
949        Intp.Perform(Bis.ThisSolution(),D1,Cu2,D2,Tol1,Tol2);
950        if (Intp.IsDone()) {
951          if ((!Intp.IsEmpty())) {
952            for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
953              gp_Pnt2d Center(Intp.Point(j).Value());
954              Standard_Real Radius = Point2.Distance(Center);
955              NbrSol++;
956              cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
957 //           =======================================================
958              qualifier1(NbrSol) = GccEnt_noqualifier;
959              qualifier2(NbrSol) = GccEnt_noqualifier;
960              TheSame1(NbrSol) = 0;
961              TheSame2(NbrSol) = 0;
962              pntcen(NbrSol) = Center;
963              pnttg1sol(NbrSol) = Point1;
964              pnttg2sol(NbrSol) = Point2;
965              pararg1(NbrSol) = 0.;
966              pararg2(NbrSol) = 0.;
967              par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
968                                               pnttg1sol(NbrSol));
969              par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
970                                               pnttg2sol(NbrSol));
971              parcen3(NbrSol) = Intp.Point(j).ParamOnSecond();
972            }
973          }
974          WellDone = Standard_True;
975        }
976      }
977    }
978  }
979
980 Standard_Boolean GccGeo_Circ2d2TanOn::
981    IsDone () const { return WellDone; }
982
983 Standard_Integer GccGeo_Circ2d2TanOn::
984    NbSolutions () const{ return NbrSol; }
985
986 gp_Circ2d GccGeo_Circ2d2TanOn::
987    ThisSolution (const Standard_Integer Index) const
988 {
989   if (!WellDone) { StdFail_NotDone::Raise(); }
990   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
991  
992   return cirsol(Index);
993 }
994
995 void GccGeo_Circ2d2TanOn::
996   WhichQualifier(const Standard_Integer Index   ,
997                        GccEnt_Position& Qualif1 ,
998                        GccEnt_Position& Qualif2 ) const
999 {
1000   if (!WellDone) { StdFail_NotDone::Raise(); }
1001   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1002   else {
1003     Qualif1 = qualifier1(Index);
1004     Qualif2 = qualifier2(Index);
1005   }
1006 }
1007
1008 void GccGeo_Circ2d2TanOn:: 
1009    Tangency1 (const Standard_Integer    Index          , 
1010                  Standard_Real&      ParSol         ,
1011                  Standard_Real&      ParArg         ,
1012                  gp_Pnt2d&           PntSol         ) const{
1013    if (!WellDone) { StdFail_NotDone::Raise(); }
1014    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1015    else {
1016      if (TheSame1(Index) == 0) {
1017        ParSol = par1sol(Index);
1018        ParArg = pararg1(Index);
1019        PntSol = gp_Pnt2d(pnttg1sol(Index));
1020      }
1021      else { StdFail_NotDone::Raise(); }
1022    }
1023  }
1024
1025 void GccGeo_Circ2d2TanOn:: 
1026    Tangency2 (const Standard_Integer    Index          , 
1027                  Standard_Real&      ParSol         ,
1028                  Standard_Real&      ParArg         ,
1029                  gp_Pnt2d&           PntSol         ) const{
1030    if (!WellDone) { StdFail_NotDone::Raise(); }
1031    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1032    else {
1033      if (TheSame2(Index) == 0) {
1034        ParSol = par2sol(Index);
1035        ParArg = pararg2(Index);
1036        PntSol = gp_Pnt2d(pnttg2sol(Index));
1037      }
1038      else { StdFail_NotDone::Raise(); }
1039    }
1040  }
1041
1042 void GccGeo_Circ2d2TanOn::
1043    CenterOn3 (const Standard_Integer    Index          ,
1044                     Standard_Real&      ParArg         ,
1045                     gp_Pnt2d&           PntSol         ) const{
1046    if (!WellDone) { StdFail_NotDone::Raise(); }
1047    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1048    else {
1049      ParArg = parcen3(Index);
1050      PntSol = gp_Pnt2d(pntcen(Index));
1051    }
1052  }
1053  
1054 Standard_Boolean GccGeo_Circ2d2TanOn::
1055    IsTheSame1 (const Standard_Integer Index) const
1056 {
1057   if (!WellDone) StdFail_NotDone::Raise();
1058   if (Index <= 0 ||Index > NbrSol) Standard_OutOfRange::Raise();
1059
1060   if (TheSame1(Index) == 0) 
1061     return Standard_False;
1062
1063   return Standard_True;
1064 }
1065
1066
1067 Standard_Boolean GccGeo_Circ2d2TanOn::
1068    IsTheSame2 (const Standard_Integer Index) const
1069 {
1070   if (!WellDone) StdFail_NotDone::Raise();
1071   if (Index <= 0 ||Index > NbrSol) Standard_OutOfRange::Raise();
1072   
1073   if (TheSame2(Index) == 0)
1074     return Standard_False;
1075   
1076   return Standard_True;
1077 }