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