0024773: Convertation of the generic classes to the non-generic. Part 7
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2d2TanRadGeo.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <Geom2dGcc_Circ2d2TanRadGeo.ixx>
16
17 #include <ElCLib.hxx>
18 #include <gp_Ax2d.hxx>
19 #include <gp_Circ2d.hxx>
20 #include <gp_Lin2d.hxx>
21 #include <Standard_NegativeValue.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #include <StdFail_NotDone.hxx>
24 #include <TColStd_Array1OfReal.hxx>
25 #include <GccEnt_BadQualifier.hxx>
26 #include <IntRes2d_Domain.hxx>
27 #include <IntRes2d_IntersectionPoint.hxx>
28
29 #include <Geom2dGcc_CurveTool.hxx>
30 #include <Adaptor3d_OffsetCurve.hxx>
31 #include <Geom2dAdaptor_HCurve.hxx>
32 #include <Geom2dGcc_CurveToolGeo.hxx>
33 #include <Geom2dInt_GInter.hxx>
34
35 // circulaire tant a une courbe et une droite ,de rayon donne
36 //==============================================================
37
38 //========================================================================
39 // On initialise WellDone a false.                                       +
40 // On recupere la courbe Cu2 et la droite L1.                            +
41 // On sort en erreur dans les cas ou la construction est impossible.     +
42 // On fait la parallele a Cu2 dans le bon sens.                          +
43 // On fait la parallele a L1 dans le bon sens.                           +
44 // On intersecte les paralleles ==> point de centre de la solution.      +
45 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
46 // On remplit les champs.                                                +
47 //========================================================================
48
49 Geom2dGcc_Circ2d2TanRadGeo::
50 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin&  Qualified1,
51                             const Geom2dGcc_QCurve&     Qualified2,
52                             const Standard_Real         Radius    ,
53                             const Standard_Real         Tolerance ):
54
55 //========================================================================
56 // initialisation des champs.                                            +
57 //========================================================================
58
59 cirsol(1,16)   ,
60 qualifier1(1,16),
61 qualifier2(1,16),
62 TheSame1(1,16) ,
63 TheSame2(1,16) ,
64 pnttg1sol(1,16),
65 pnttg2sol(1,16),
66 par1sol(1,16)  ,
67 par2sol(1,16)  ,
68 pararg1(1,16)  ,
69 pararg2(1,16)  
70 {
71
72   //========================================================================
73   // Traitement.                                                           +
74   //========================================================================
75
76   Standard_Real Tol = Abs(Tolerance);
77   Standard_Real thefirst = -100000.;
78   Standard_Real thelast  =  100000.;
79   Standard_Real firstparam;
80   Standard_Real lastparam;
81   gp_Dir2d dirx(1.,0.);
82   TColStd_Array1OfReal cote1(1,2);
83   TColStd_Array1OfReal cote2(1,2);
84   Standard_Integer nbrcote1=0;
85   Standard_Integer nbrcote2=0;
86   WellDone = Standard_False;
87   NbrSol = 0;
88   if (!(Qualified1.IsEnclosed() ||
89     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
90     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
91     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
92
93       GccEnt_BadQualifier::Raise();
94       return;
95   }
96   gp_Lin2d L1 = Qualified1.Qualified();
97   Standard_Real x1dir = (L1.Direction()).X();
98   Standard_Real y1dir = (L1.Direction()).Y();
99   Standard_Real lxloc = (L1.Location()).X();
100   Standard_Real lyloc = (L1.Location()).Y();
101   gp_Pnt2d origin1(lxloc,lyloc);
102   gp_Dir2d normL1(-y1dir,x1dir);
103   Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
104   if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
105   else {
106     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
107       //   =======================================================
108       nbrcote1 = 1;
109       nbrcote2 = 1;
110       cote1(1) = Radius;
111       cote2(1) = Radius;
112     }
113     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
114       //   ==========================================================
115       nbrcote1 = 1;
116       nbrcote2 = 1;
117       cote1(1) = Radius;
118       cote2(1) = -Radius;
119     }
120     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
121       //   ===========================================================
122       nbrcote1 = 1;
123       nbrcote2 = 1;
124       cote1(1) = -Radius;
125       cote2(1) = Radius;
126     }
127     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
128       //   =========================================================
129       nbrcote1 = 1;
130       nbrcote2 = 1;
131       cote1(1) = -Radius;
132       cote2(1) = -Radius;
133     }
134     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
135       //   =========================================================
136       nbrcote1 = 1;
137       nbrcote2 = 2;
138       cote1(1) = Radius;
139       cote2(1) = Radius;
140       cote2(2) = -Radius;
141     }
142     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
143       //   =========================================================
144       nbrcote1 = 2;
145       nbrcote2 = 1;
146       cote1(1) = Radius;
147       cote1(2) = -Radius;
148       cote2(1) = Radius;
149     }
150     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
151       //   =============================================================
152       nbrcote1 = 1;
153       nbrcote2 = 2;
154       cote1(1) = -Radius;
155       cote2(1) = Radius;
156       cote2(2) = -Radius;
157     }
158     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
159       //   ========================================================
160       nbrcote1 = 2;
161       nbrcote2 = 1;
162       cote1(1) = Radius;
163       cote1(2) = -Radius;
164       cote2(1) = -Radius;
165     }
166     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
167       //   =================================================================
168       nbrcote1 = 2;
169       nbrcote2 = 2;
170       cote1(1) = Radius;
171       cote1(2) = -Radius;
172       cote2(1) = Radius;
173       cote2(2) = -Radius;
174     }
175     gp_Dir2d Dir(-y1dir,x1dir);
176     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
177       gp_Pnt2d Point(L1.Location().XY()+cote1(jcote1)*Dir.XY());
178       gp_Lin2d Line(Point,L1.Direction()); // ligne avec deport.
179       IntRes2d_Domain D1;
180       for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
181         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
182         Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
183         firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
184         lastparam  = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
185         IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
186           Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
187         Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
188         if (Intp.IsDone()) {
189           if (!Intp.IsEmpty()) {
190             for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
191               NbrSol++;
192               gp_Pnt2d Center(Intp.Point(i).Value());
193               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
194               //             =======================================================
195               gp_Dir2d dc1(origin1.XY()-Center.XY());
196               qualifier2(NbrSol) = Qualified2.Qualifier();
197               if (!Qualified1.IsUnqualified()) { 
198                 qualifier1(NbrSol) = Qualified1.Qualifier();
199               }
200               else if (dc1.Dot(normL1) > 0.0) {
201                 qualifier1(NbrSol) = GccEnt_outside;
202               }
203               else { qualifier1(NbrSol) = GccEnt_enclosed; }
204               TheSame1(NbrSol) = 0;
205               TheSame2(NbrSol) = 0;
206               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
207               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
208               pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
209               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
210               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
211                 pnttg1sol(NbrSol));
212               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
213                 pnttg2sol(NbrSol));
214             }
215           }
216           WellDone = Standard_True;
217         }
218       }
219     }
220   }
221 }
222
223 // circulaire tant a une courbe et un cercle ,de rayon donne
224 //=============================================================
225
226 //========================================================================
227 // On initialise WellDone a false.                                       +
228 // On recupere la courbe Cu2 et le cercle C1.                            +
229 // On sort en erreur dans les cas ou la construction est impossible.     +
230 // On fait la parallele a Cu2 dans le bon sens.                          +
231 // On fait la parallele a C1 dans le bon sens.                           +
232 // On intersecte les paralleles ==> point de centre de la solution.      +
233 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
234 // On remplit les champs.                                                +
235 //========================================================================
236
237 Geom2dGcc_Circ2d2TanRadGeo::
238 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
239                             const Geom2dGcc_QCurve&     Qualified2,
240                             const Standard_Real         Radius    ,
241                             const Standard_Real         Tolerance ):
242
243 //========================================================================
244 // initialisation des champs.                                            +
245 //========================================================================
246
247 cirsol(1,16)   ,
248 qualifier1(1,16),
249 qualifier2(1,16),
250 TheSame1(1,16) ,
251 TheSame2(1,16) ,
252 pnttg1sol(1,16),
253 pnttg2sol(1,16),
254 par1sol(1,16)  ,
255 par2sol(1,16)  ,
256 pararg1(1,16)  ,
257 pararg2(1,16)  
258 {
259
260   //========================================================================
261   // Traitement.                                                           +
262   //========================================================================
263
264   Standard_Real Tol = Abs(Tolerance);
265   Standard_Real thefirst = -100000.;
266   Standard_Real thelast  =  100000.;
267   Standard_Real firstparam;
268   Standard_Real lastparam;
269   gp_Dir2d dirx(1.,0.);
270   TColStd_Array1OfReal cote1(1,2);
271   TColStd_Array1OfReal cote2(1,2);
272   Standard_Integer nbrcote1=0;
273   Standard_Integer nbrcote2=0;
274   WellDone = Standard_False;
275   NbrSol = 0;
276   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
277     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
278     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
279     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
280       GccEnt_BadQualifier::Raise();
281       return;
282   }
283   gp_Circ2d C1 = Qualified1.Qualified();
284   gp_Pnt2d center1(C1.Location());
285   Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
286   if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
287   else {
288     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
289       //   =======================================================
290       nbrcote1 = 1;
291       nbrcote2 = 1;
292       cote1(1) = Radius;
293       cote2(1) = Radius;
294     }
295     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
296       //   ==========================================================
297       nbrcote1 = 1;
298       nbrcote2 = 1;
299       cote1(1) = Radius;
300       cote2(1) = -Radius;
301     }
302     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
303       //   ===========================================================
304       nbrcote1 = 1;
305       nbrcote2 = 1;
306       cote1(1) = -Radius;
307       cote2(1) = Radius;
308     }
309     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
310       //   =========================================================
311       nbrcote1 = 1;
312       nbrcote2 = 1;
313       cote1(1) = -Radius;
314       cote2(1) = -Radius;
315     }
316     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
317       //   =========================================================
318       nbrcote1 = 1;
319       nbrcote2 = 2;
320       cote1(1) = Radius;
321       cote2(1) = Radius;
322       cote2(2) = -Radius;
323     }
324     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
325       //   =========================================================
326       nbrcote1 = 2;
327       nbrcote2 = 1;
328       cote1(1) = Radius;
329       cote1(2) = -Radius;
330       cote2(1) = Radius;
331     }
332     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
333       //   =============================================================
334       nbrcote1 = 1;
335       nbrcote2 = 2;
336       cote1(1) = -Radius;
337       cote2(1) = Radius;
338       cote2(2) = -Radius;
339     }
340     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
341       //   ========================================================
342       nbrcote1 = 2;
343       nbrcote2 = 1;
344       cote1(1) = Radius;
345       cote1(2) = -Radius;
346       cote2(1) = -Radius;
347     }
348     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
349       //   =================================================================
350       nbrcote1 = 2;
351       nbrcote2 = 2;
352       cote1(1) = Radius;
353       cote1(2) = -Radius;
354       cote2(1) = Radius;
355       cote2(2) = -Radius;
356     }
357     Standard_Real R1 = C1.Radius();
358     Geom2dInt_TheIntConicCurveOfGInter Intp;
359     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
360       gp_Circ2d Circ(C1.XAxis(),R1+cote1(jcote1));
361       IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
362         ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
363       D1.SetEquivalentParameters(0.,2.*M_PI);
364       for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
365         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
366         Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
367         firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
368         lastparam  = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
369         IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
370           Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
371         Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
372         if (Intp.IsDone()) {
373           if (!Intp.IsEmpty()) {
374             for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
375               NbrSol++;
376               gp_Pnt2d Center(Intp.Point(i).Value());
377               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
378               //             =======================================================
379 #ifdef DEB
380               gp_Dir2d dir1(Center.XY()-center1.XY());
381 #else
382               Center.XY() ;
383               center1.XY() ;
384 #endif
385               Standard_Real distcc1 = Center.Distance(center1);
386               if (!Qualified1.IsUnqualified()) { 
387                 qualifier1(NbrSol) = Qualified1.Qualifier();
388               }
389               else if (Abs(distcc1+Radius-R1) < Tol) {
390                 qualifier1(NbrSol) = GccEnt_enclosed;
391               }
392               else if (Abs(distcc1-R1-Radius) < Tol) {
393                 qualifier1(NbrSol) = GccEnt_outside;
394               }
395               else { qualifier1(NbrSol) = GccEnt_enclosing; }
396               qualifier2(NbrSol) = Qualified2.Qualifier();
397               TheSame1(NbrSol) = 0;
398               TheSame2(NbrSol) = 0;
399               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
400               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
401               pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
402               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
403               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
404                 pnttg1sol(NbrSol));
405               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
406                 pnttg2sol(NbrSol));
407             }
408           }
409           WellDone = Standard_True;
410         }
411       }
412     }
413   }
414 }
415
416 // circulaire tant a une courbe et un point ,de rayon donne
417 //============================================================
418
419 //========================================================================
420 // On initialise WellDone a false.                                       +
421 // On recupere la courbe Cu1 et le point P2.                             +
422 // On sort en erreur dans les cas ou la construction est impossible.     +
423 // On fait la parallele a Cu1 dans le bon sens.                          +
424 // On fait la parallele a P2 dans le bon sens.                           +
425 // On intersecte les paralleles ==> point de centre de la solution.      +
426 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
427 // On remplit les champs.                                                +
428 //========================================================================
429
430 Geom2dGcc_Circ2d2TanRadGeo::
431 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
432                             const gp_Pnt2d&     Point2    ,
433                             const Standard_Real Radius    ,
434                             const Standard_Real Tolerance ):
435
436 //========================================================================
437 // initialisation des champs.                                            +
438 //========================================================================
439
440 cirsol(1,16)   ,
441 qualifier1(1,16),
442 qualifier2(1,16),
443 TheSame1(1,16) ,
444 TheSame2(1,16) ,
445 pnttg1sol(1,16),
446 pnttg2sol(1,16),
447 par1sol(1,16)  ,
448 par2sol(1,16)  ,
449 pararg1(1,16)  ,
450 pararg2(1,16)  
451 {
452
453   //========================================================================
454   // Traitement.                                                           +
455   //========================================================================
456
457   Standard_Real Tol = Abs(Tolerance);
458   Standard_Real thefirst = -100000.;
459   Standard_Real thelast  =  100000.;
460   Standard_Real firstparam;
461   Standard_Real lastparam;
462   gp_Dir2d dirx(1.,0.);
463   TColStd_Array1OfReal cote1(1,2);
464   Standard_Integer nbrcote1=0;
465   WellDone = Standard_False;
466   NbrSol = 0;
467   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
468     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
469       GccEnt_BadQualifier::Raise();
470       return;
471   }
472   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
473   if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
474   else {
475     if (Qualified1.IsEnclosed()) {
476       //    ===========================
477       nbrcote1 = 1;
478       cote1(1) = Radius;
479     }
480     else if(Qualified1.IsOutside()) {
481       //   ===============================
482       nbrcote1 = 1;
483       cote1(1) = -Radius;
484     }
485     else if(Qualified1.IsUnqualified()) {
486       //   ===================================
487       nbrcote1 = 2;
488       cote1(1) = Radius;
489       cote1(2) = -Radius;
490     }
491     gp_Circ2d Circ(gp_Ax2d(Point2,gp_Dir2d(1.,0.)),Radius);
492     IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
493       ElCLib::Value(M_PI+M_PI,Circ),M_PI+M_PI,Tol);
494     D1.SetEquivalentParameters(0.,M_PI+M_PI);
495     Geom2dInt_TheIntConicCurveOfGInter Intp;
496     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
497       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
498       Adaptor3d_OffsetCurve Cu2(HCu1,cote1(jcote1));
499       firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(Cu2),thefirst);
500       lastparam  = Min(Geom2dGcc_CurveToolGeo::LastParameter(Cu2),thelast);
501       IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(Cu2,firstparam),firstparam,Tol,
502         Geom2dGcc_CurveToolGeo::Value(Cu2,lastparam),lastparam,Tol);
503       Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
504       if (Intp.IsDone()) {
505         if (!Intp.IsEmpty()) {
506           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
507             NbrSol++;
508             gp_Pnt2d Center(Intp.Point(i).Value());
509             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
510             //           =======================================================
511             qualifier1(NbrSol) = Qualified1.Qualifier();
512             qualifier2(NbrSol) = GccEnt_noqualifier;
513             TheSame1(NbrSol) = 0;
514             TheSame2(NbrSol) = 0;
515             pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
516             pararg2(NbrSol) = 0.;
517             pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
518             pnttg2sol(NbrSol) = Point2;
519             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
520               pnttg1sol(NbrSol));
521             par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
522               pnttg2sol(NbrSol));
523           }
524         }
525         WellDone = Standard_True;
526       }
527     }
528   }
529 }
530
531 static void PrecRoot(const Adaptor3d_OffsetCurve& theC1,
532                      const Adaptor3d_OffsetCurve& theC2,
533                      const Standard_Real theU0,
534                      const Standard_Real theV0,
535                      const Standard_Real theUmin,
536                      const Standard_Real theUmax,
537                      const Standard_Real theVmin,
538                      const Standard_Real theVmax,
539                      Standard_Real& theUfinal,
540                      Standard_Real& theVfinal)
541 {
542   const Standard_Real aInitStepU = (theUmax - theUmin)/2.0,
543     aInitStepV = (theVmax - theVmin)/2.0;
544
545   Standard_Real aStepU = aInitStepU, aStepV = aInitStepV;
546
547   const Standard_Real aTol = Precision::PConfusion() * Precision::PConfusion();
548   const Standard_Integer aNbIterMax = 100;
549
550   gp_Pnt2d aP1, aP2;
551   gp_Vec2d aD1, aD2;
552
553   Geom2dGcc_CurveToolGeo::D1(theC1, theU0, aP1, aD1);
554   Geom2dGcc_CurveToolGeo::D1(theC2, theV0, aP2, aD2);
555
556   gp_Vec2d vP12(aP1.XY() - aP2.XY());
557
558   Standard_Real aU = theU0, aV = theV0;
559   theUfinal = theU0;
560   theVfinal = theV0;
561
562   Standard_Real aSQDistPrev = aP1.SquareDistance(aP2);
563
564   Standard_Integer aNbIter = 1;
565
566   do
567   {
568     Standard_Real aDetH = aD1.Y()*aD2.X() - aD1.X()*aD2.Y();
569     if(aDetH == 0.0)
570       break;
571
572     aU += aStepU*(aD2.Y() * vP12.X() - aD2.X()*vP12.Y())/aDetH;
573     aV += aStepV*(aD1.Y() * vP12.X() - aD1.X()*vP12.Y())/aDetH;
574
575     if(Abs(aU - theUmin) > 1000.0)
576       //method diverges
577       return;
578
579     if(Abs(aU - theUmax) > 1000.0)
580       //method diverges
581       return;
582
583     if(Abs(aV - theVmin) > 1000.0)
584       //method diverges
585       return;
586
587     if(Abs(aV - theVmax) > 1000.0)
588       //method diverges
589       return;
590
591     Geom2dGcc_CurveToolGeo::D1(theC1, aU, aP1, aD1);
592     Geom2dGcc_CurveToolGeo::D1(theC2, aV, aP2, aD2);
593     const Standard_Real aSQDist = aP1.SquareDistance(aP2);
594
595     if(Precision::IsInfinite(aSQDist))
596       //method diverges
597       return;
598
599     vP12.SetXY(aP1.XY() - aP2.XY());
600
601     if(aSQDist < aSQDistPrev)
602     {
603       aSQDistPrev = aSQDist;
604       aStepU = aInitStepU;
605       aStepV = aInitStepV;
606       theUfinal = aU;
607       theVfinal = aV;
608     }
609     else
610     {
611       aStepU /= 2.0;
612       aStepV /= 2.0;
613     }
614   }
615   while((aNbIter++ < aNbIterMax) && ((aStepU > aTol) || (aStepV > aTol)));
616
617   Standard_Boolean isInBound = Standard_True;
618   if(theUfinal < theUmin)
619   {
620     aU = theUfinal;
621     aV = theVfinal;
622
623     theUfinal = theUmin;
624     isInBound = Standard_False;
625   }
626
627   if(theUfinal > theUmax)
628   {
629     aU = theUfinal;
630     aV = theVfinal;
631
632     theUfinal = theUmax;
633     isInBound = Standard_False;
634   }
635
636   if(!isInBound)
637   {
638     Geom2dGcc_CurveToolGeo::D1(theC1, aU, aP1, aD1);
639     Geom2dGcc_CurveToolGeo::D1(theC2, aV, aP2, aD2);
640     Standard_Real aV1 = (aD2.X() == 0.0) ? aV :((theUfinal - aU)*aD1.X() + aV*aD2.X() + (aP1.X() - aP2.X()))/aD2.X();
641     Standard_Real aV2 = (aD2.Y() == 0.0) ? aV :((theUfinal - aU)*aD1.Y() + aV*aD2.Y() + (aP1.Y() - aP2.Y()))/aD2.Y();
642
643     if(aV1 < theVmin)
644       aV1 = theVmin;
645
646     if(aV1 > theVmax)
647       aV1 = theVmax;
648
649     if(aV2 < theVmin)
650       aV2 = theVmin;
651
652     if(aV2 > theVmax)
653       aV2 = theVmax;
654
655     aP1 = Geom2dGcc_CurveToolGeo::Value(theC1,theUfinal);
656     aP2 = Geom2dGcc_CurveToolGeo::Value(theC2,aV1);
657
658     Standard_Real aSQ1 = aP1.SquareDistance(aP2);
659
660     aP2 = Geom2dGcc_CurveToolGeo::Value(theC2,aV2);
661     Standard_Real aSQ2 = aP1.SquareDistance(aP2);
662
663     if(aSQ1 < aSQ2)
664       theVfinal = aV1;
665     else
666       theVfinal = aV2;
667
668     return;
669   }
670
671   if(theVfinal < theVmin)
672   {
673     aU = theUfinal;
674     aV = theVfinal;
675
676     theVfinal = theVmin;
677     isInBound = Standard_False;
678   }
679
680   if(theVfinal > theVmax)
681   {
682     aU = theUfinal;
683     aV = theVfinal;
684
685     theVfinal = theVmax;
686     isInBound = Standard_False;
687   }
688
689   if(isInBound)
690     return;
691
692   Geom2dGcc_CurveToolGeo::D1(theC1, aU, aP1, aD1);
693   Geom2dGcc_CurveToolGeo::D1(theC2, aV, aP2, aD2);
694   Standard_Real aU1 = (aD1.X() == 0.0) ? aU :((theVfinal - aV)*aD2.X() + aU*aD1.X() + (aP2.X() - aP1.X()))/aD1.X();
695   Standard_Real aU2 = (aD1.Y() == 0.0) ? aU :((theVfinal - aV)*aD2.Y() + aU*aD1.Y() + (aP2.Y() - aP1.Y()))/aD1.Y();
696
697   if(aU1 < theUmin)
698     aU1 = theUmin;
699
700   if(aU1 > theUmax)
701     aU1 = theUmax;
702
703   if(aU2 < theUmin)
704     aU2 = theUmin;
705
706   if(aU2 > theUmax)
707     aU2 = theUmax;
708
709   aP2 = Geom2dGcc_CurveToolGeo::Value(theC2,theVfinal);
710   aP1 = Geom2dGcc_CurveToolGeo::Value(theC1,aU1);
711
712   Standard_Real aSQ1 = aP1.SquareDistance(aP2);
713
714   aP1 = Geom2dGcc_CurveToolGeo::Value(theC1,aU2);
715   Standard_Real aSQ2 = aP1.SquareDistance(aP2);
716
717   if(aSQ1 < aSQ2)
718     theUfinal = aU1;
719   else
720     theUfinal = aU2;  
721 }
722
723 // circulaire tant a deux courbes ,de rayon donne
724 //==================================================
725
726 //========================================================================
727 // On initialise WellDone a false.                                       +
728 // On recupere les courbes Cu1 et Cu2.                                   +
729 // On sort en erreur dans les cas ou la construction est impossible.     +
730 // On fait la parallele a Cu1 dans le bon sens.                          +
731 // On fait la parallele a Cu2 dans le bon sens.                          +
732 // On intersecte les paralleles ==> point de centre de la solution.      +
733 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
734 // On remplit les champs.                                                +
735 //========================================================================
736
737 Geom2dGcc_Circ2d2TanRadGeo::
738 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
739                             const Geom2dGcc_QCurve& Qualified2,
740                             const Standard_Real Radius    ,
741                             const Standard_Real Tolerance ):
742
743 //========================================================================
744 // initialisation des champs.                                            +
745 //========================================================================
746
747 cirsol(1,16)   ,
748 qualifier1(1,16),
749 qualifier2(1,16),
750 TheSame1(1,16) ,
751 TheSame2(1,16) ,
752 pnttg1sol(1,16),
753 pnttg2sol(1,16),
754 par1sol(1,16)  ,
755 par2sol(1,16)  ,
756 pararg1(1,16)  ,
757 pararg2(1,16)  
758 {
759
760   //========================================================================
761   // Traitement.                                                           +
762   //========================================================================
763
764   Standard_Real Tol = Abs(Tolerance);
765   Standard_Real thefirst = -100000.;
766   Standard_Real thelast  =  100000.;
767   Standard_Real firstparam;
768   Standard_Real lastparam;
769   gp_Dir2d dirx(1.,0.);
770   TColStd_Array1OfReal cote1(1,2);
771   TColStd_Array1OfReal cote2(1,2);
772   Standard_Integer nbrcote1=0;
773   Standard_Integer nbrcote2=0;
774   WellDone = Standard_False;
775   NbrSol = 0;
776   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
777     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
778     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
779     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
780       GccEnt_BadQualifier::Raise();
781       return;
782   }
783   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
784   Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
785   if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
786   else {
787     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
788       //   =======================================================
789       nbrcote1 = 1;
790       nbrcote2 = 1;
791       cote1(1) = Radius;
792       cote2(1) = Radius;
793     }
794     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
795       //   ==========================================================
796       nbrcote1 = 1;
797       nbrcote2 = 1;
798       cote1(1) = Radius;
799       cote2(1) = -Radius;
800     }
801     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
802       //   ===========================================================
803       nbrcote1 = 1;
804       nbrcote2 = 1;
805       cote1(1) = -Radius;
806       cote2(1) = Radius;
807     }
808     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
809       //   =========================================================
810       nbrcote1 = 1;
811       nbrcote2 = 1;
812       cote1(1) = -Radius;
813       cote2(1) = -Radius;
814     }
815     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
816       //   =========================================================
817       nbrcote1 = 1;
818       nbrcote2 = 2;
819       cote1(1) = Radius;
820       cote2(1) = Radius;
821       cote2(2) = -Radius;
822     }
823     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
824       //   =========================================================
825       nbrcote1 = 2;
826       nbrcote2 = 1;
827       cote1(1) = Radius;
828       cote1(2) = -Radius;
829       cote2(1) = Radius;
830     }
831     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
832       //   =============================================================
833       nbrcote1 = 1;
834       nbrcote2 = 2;
835       cote1(1) = -Radius;
836       cote2(1) = Radius;
837       cote2(2) = -Radius;
838     }
839     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
840       //   ========================================================
841       nbrcote1 = 2;
842       nbrcote2 = 1;
843       cote1(1) = Radius;
844       cote1(2) = -Radius;
845       cote2(1) = -Radius;
846     }
847     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
848       //   =================================================================
849       nbrcote1 = 2;
850       nbrcote2 = 2;
851       cote1(1) = Radius;
852       cote1(2) = -Radius;
853       cote2(1) = Radius;
854       cote2(2) = -Radius;
855     }
856     Geom2dInt_GInter Intp;
857     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
858       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1); 
859       Adaptor3d_OffsetCurve C1(HCu1,cote1(jcote1));
860       firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C1),thefirst);
861       lastparam  = Min(Geom2dGcc_CurveToolGeo::LastParameter(C1),thelast);
862 #ifdef DEB
863       IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C1,firstparam),firstparam,Tol,
864         Geom2dGcc_CurveToolGeo::Value(C1,lastparam),lastparam,Tol);
865 #else
866       Geom2dGcc_CurveToolGeo::Value(C1,firstparam);
867       Geom2dGcc_CurveToolGeo::Value(C1,lastparam);
868 #endif
869       for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
870         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
871         Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
872         firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
873         lastparam  = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
874 #ifdef DEB
875         IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
876           Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
877 #else
878         Geom2dGcc_CurveToolGeo::Value(C2,firstparam);
879         Geom2dGcc_CurveToolGeo::Value(C2,lastparam);
880 #endif
881         Intp.Perform(C1,C2,Tol,Tol);
882         if (Intp.IsDone()) {
883           if (!Intp.IsEmpty()) {
884             for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++)
885             {
886               Standard_Real aU0 = Intp.Point(i).ParamOnFirst();
887               Standard_Real aV0 = Intp.Point(i).ParamOnSecond();
888
889               Standard_Real aU1 = aU0-Precision::PApproximation();
890               Standard_Real aV1 = aV0-Precision::PApproximation();
891
892               Standard_Real aU2 = aU0+Precision::PApproximation();
893               Standard_Real aV2 = aV0+Precision::PApproximation();
894
895               gp_Pnt2d P11 = Geom2dGcc_CurveToolGeo::Value(C1,aU1);
896               gp_Pnt2d P12 = Geom2dGcc_CurveToolGeo::Value(C2,aV1);
897               gp_Pnt2d P21 = Geom2dGcc_CurveToolGeo::Value(C1,aU2);
898               gp_Pnt2d P22 = Geom2dGcc_CurveToolGeo::Value(C2,aV2);
899
900               Standard_Real aDist1112 = P11.Distance(P12);
901               Standard_Real aDist1122 = P11.Distance(P22);
902
903               Standard_Real aDist1221 = P12.Distance(P21);
904               Standard_Real aDist2122 = P21.Distance(P22);
905
906               if( Min(aDist1112, aDist1122) <= Precision::Approximation() &&
907                 Min(aDist1221, aDist2122) <= Precision::Approximation())
908               {
909                 PrecRoot(C1, C2, aU0, aV0,
910                   Max(Geom2dGcc_CurveToolGeo::FirstParameter(C1), aU0 - 10.0),
911                   Min(Geom2dGcc_CurveToolGeo::LastParameter(C1), aU0 + 10.0),
912                   Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2), aV0 - 10.0),
913                   Min(Geom2dGcc_CurveToolGeo::LastParameter(C2), aV0 + 10.0),
914                   aU0, aV0);
915               }
916
917               NbrSol++;
918               gp_Pnt2d Center(Geom2dGcc_CurveToolGeo::Value(C1, aU0));
919               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
920               //             =======================================================
921               qualifier1(NbrSol) = Qualified1.Qualifier();
922               qualifier1(NbrSol) = Qualified1.Qualifier();
923               TheSame1(NbrSol) = 0;
924               TheSame2(NbrSol) = 0;
925               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
926               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
927               pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
928               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
929               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
930                 pnttg1sol(NbrSol));
931               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
932                 pnttg2sol(NbrSol));
933             }
934           }
935
936           WellDone = Standard_True;
937         }
938       }
939     }
940   }
941 }
942
943 //=========================================================================
944
945 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
946 IsDone () const { return WellDone; }
947
948 Standard_Integer Geom2dGcc_Circ2d2TanRadGeo::
949 NbSolutions () const { return NbrSol; }
950
951 gp_Circ2d Geom2dGcc_Circ2d2TanRadGeo::
952 ThisSolution (const Standard_Integer Index) const 
953 {
954   if (!WellDone) { StdFail_NotDone::Raise(); }
955   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
956   return cirsol(Index);
957 }
958
959 void Geom2dGcc_Circ2d2TanRadGeo::
960 WhichQualifier(const Standard_Integer Index   ,
961                GccEnt_Position& Qualif1 ,
962                GccEnt_Position& Qualif2 ) const
963 {
964   if (!WellDone) { StdFail_NotDone::Raise(); }
965   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
966   else {
967     Qualif1 = qualifier1(Index);
968     Qualif2 = qualifier2(Index);
969   }
970 }
971
972 void Geom2dGcc_Circ2d2TanRadGeo::
973 Tangency1 (const Standard_Integer Index,
974            Standard_Real&   ParSol,
975            Standard_Real&   ParArg,
976            gp_Pnt2d&        PntSol) const{
977              if (!WellDone) { StdFail_NotDone::Raise(); }
978              else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
979              else {
980                if (TheSame1(Index) == 0) {
981                  ParSol = par1sol(Index);
982                  ParArg = pararg1(Index);
983                  PntSol = gp_Pnt2d(pnttg1sol(Index));
984                }
985                else { StdFail_NotDone::Raise(); }
986              }
987 }
988
989 void Geom2dGcc_Circ2d2TanRadGeo::
990 Tangency2 (const Standard_Integer Index,
991            Standard_Real&   ParSol,
992            Standard_Real&   ParArg,
993            gp_Pnt2d&        PntSol) const{
994              if (!WellDone) { StdFail_NotDone::Raise(); }
995              else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
996              else {
997                if (TheSame2(Index) == 0) {
998                  ParSol = par2sol(Index);
999                  ParArg = pararg2(Index);
1000                  PntSol = gp_Pnt2d(pnttg2sol(Index));
1001                }
1002                else { StdFail_NotDone::Raise(); }
1003              }
1004 }
1005
1006 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
1007 IsTheSame1 (const Standard_Integer Index) const
1008 {
1009   if (!WellDone) { StdFail_NotDone::Raise(); }
1010   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1011
1012   if (TheSame1(Index) == 0) { return Standard_False; }
1013   return Standard_True;
1014 }
1015
1016 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
1017 IsTheSame2 (const Standard_Integer Index) const
1018 {
1019   if (!WellDone) { StdFail_NotDone::Raise(); }
1020   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
1021
1022   if (TheSame2(Index) == 0) { return Standard_False; }
1023   return Standard_True;
1024 }
1025