892c06a964cdfe6651f0e9f816db8c4113872b40
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2dTanOnRadGeo.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 //========================================================================
16 //       circulaire tangent a un element de type :  - Cercle.            +
17 //                                                  - Ligne.             +
18 //                                                  - Point.             +
19 //                  centre sur un deuxieme element de type :  - Cercle.  +
20 //                                                            - Ligne.   +
21 //                  de rayon donne : Radius.                             +
22 //========================================================================
23
24 #include <Adaptor2d_OffsetCurve.hxx>
25 #include <ElCLib.hxx>
26 #include <GccEnt_BadQualifier.hxx>
27 #include <GccEnt_QualifiedCirc.hxx>
28 #include <GccEnt_QualifiedLin.hxx>
29 #include <Geom2dAdaptor_Curve.hxx>
30 #include <Geom2dAdaptor_HCurve.hxx>
31 #include <Geom2dGcc_Circ2dTanOnRadGeo.hxx>
32 #include <Geom2dGcc_CurveTool.hxx>
33 #include <Geom2dGcc_QCurve.hxx>
34 #include <Geom2dInt_GInter.hxx>
35 #include <gp_Circ2d.hxx>
36 #include <gp_Dir2d.hxx>
37 #include <gp_Lin2d.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <IntRes2d_Domain.hxx>
40 #include <IntRes2d_IntersectionPoint.hxx>
41 #include <math_DirectPolynomialRoots.hxx>
42 #include <Standard_NegativeValue.hxx>
43 #include <Standard_OutOfRange.hxx>
44 #include <StdFail_NotDone.hxx>
45 #include <TColStd_Array1OfReal.hxx>
46
47 static const Standard_Integer aNbSolMAX = 8;
48
49 //=========================================================================
50 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
51 //         centre   :  sur une droite OnLine.                             +
52 //         de rayon :  Radius.                                            +
53 //                                                                        + 
54 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
55 //  champs.                                                               +
56 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
57 //  solutions.                                                            +
58 //  On resoud l equation du second degre indiquant que le point de centre +
59 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
60 //                        sur la droite OnLine.                           +
61 //  Les solutions sont representees par les cercles :                     +
62 //                   - de centre Pntcen(xc,yc)                            +
63 //                   - de rayon Radius.                                   +
64 //=========================================================================
65 Geom2dGcc_Circ2dTanOnRadGeo::
66 Geom2dGcc_Circ2dTanOnRadGeo (const Geom2dGcc_QCurve& Qualified1, 
67                              const gp_Lin2d&     OnLine    ,
68                              const Standard_Real Radius    ,
69                              const Standard_Real Tolerance ):
70
71 //=========================================================================
72 // Initialisation des champs.                                             +
73 //=========================================================================
74
75 cirsol(1,aNbSolMAX)     ,
76 qualifier1(1,aNbSolMAX) ,
77 TheSame1(1,aNbSolMAX)   ,
78 pnttg1sol(1,aNbSolMAX)  ,
79 pntcen3(1,aNbSolMAX)    ,
80 par1sol(1,aNbSolMAX)    ,
81 pararg1(1,aNbSolMAX)    ,
82 parcen3(1,aNbSolMAX)    
83 {
84
85   //=========================================================================
86   // Traitement.                                                            +
87   //=========================================================================
88
89   gp_Dir2d dirx(1.0,0.0);
90   Standard_Real Tol = Abs(Tolerance);
91   Standard_Real thefirst = -100000.;
92   Standard_Real thelast  =  100000.;
93   Standard_Real firstparam;
94   Standard_Real lastparam;
95   WellDone = Standard_False;
96   NbrSol = 0;
97   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
98     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
99       throw GccEnt_BadQualifier();
100       return;
101   }
102   Standard_Integer nbrcote1 = 0;
103   TColStd_Array1OfReal Coef(1,2);
104   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
105
106   if (Radius < 0.0) { throw Standard_NegativeValue(); }
107   else {
108     if (Qualified1.IsEnclosed()) {
109       //    ===========================
110       nbrcote1 = 1;
111       Coef(1) = Radius;
112     }
113     else if(Qualified1.IsOutside()) {
114       //   ===============================
115       nbrcote1 = 1;
116       Coef(1) = -Radius;
117     }
118     else if(Qualified1.IsUnqualified()) {
119       //   ===================================
120       nbrcote1 = 2;
121       Coef(1) = Radius;
122       Coef(2) = -Radius;
123     }
124     IntRes2d_Domain D1;
125     Geom2dInt_TheIntConicCurveOfGInter Intp;
126     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
127       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
128       Adaptor2d_OffsetCurve C2(HCu1,Coef(jcote1));
129       firstparam = Max(C2.FirstParameter(),thefirst);
130       lastparam  = Min(C2.LastParameter(),thelast);
131       IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
132                          C2.Value(lastparam), lastparam, Tol);
133       Intp.Perform(OnLine,D1,C2,D2,Tol,Tol);
134       if (Intp.IsDone()) {
135         if (!Intp.IsEmpty()) {
136           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
137             NbrSol++;
138             gp_Pnt2d Center(Intp.Point(i).Value());
139             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
140             //           =======================================================
141             qualifier1(NbrSol) = Qualified1.Qualifier();
142             TheSame1(NbrSol) = 0;
143             pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
144             parcen3(NbrSol) = Intp.Point(i).ParamOnFirst();
145             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
146               pnttg1sol(NbrSol));
147             pnttg1sol(NbrSol) = gp_Pnt2d(Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol)));
148             pntcen3(NbrSol) = Center;
149           }
150         }
151         WellDone = Standard_True;
152       }
153     }
154   }
155 }
156
157 //=========================================================================
158 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
159 //         centre   :  sur une droite OnLine.                             +
160 //         de rayon :  Radius.                                            +
161 //                                                                        + 
162 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
163 //  champs.                                                               +
164 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
165 //  solutions.                                                            +
166 //  On resoud l equation du second degre indiquant que le point de centre +
167 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
168 //                        sur la droite OnLine.                           +
169 //  Les solutions sont representees par les cercles :                     +
170 //                   - de centre Pntcen(xc,yc)                            +
171 //                   - de rayon Radius.                                   +
172 //=========================================================================
173
174 Geom2dGcc_Circ2dTanOnRadGeo::
175 Geom2dGcc_Circ2dTanOnRadGeo (const Geom2dGcc_QCurve& Qualified1,
176                              const gp_Circ2d&    OnCirc    , 
177                              const Standard_Real Radius    ,
178                              const Standard_Real Tolerance ):
179
180 //=========================================================================
181 // Initialisation des champs.                                             +
182 //=========================================================================
183
184 cirsol(1,aNbSolMAX)     ,
185 qualifier1(1,aNbSolMAX) ,
186 TheSame1(1,aNbSolMAX)   ,
187 pnttg1sol(1,aNbSolMAX)  ,
188 pntcen3(1,aNbSolMAX)    ,
189 par1sol(1,aNbSolMAX)    ,
190 pararg1(1,aNbSolMAX)    ,
191 parcen3(1,aNbSolMAX)    
192 {
193
194   //=========================================================================
195   // Traitement.                                                            +
196   //=========================================================================
197
198   gp_Dir2d dirx(1.0,0.0);
199   Standard_Real thefirst = -100000.;
200   Standard_Real thelast  =  100000.;
201   Standard_Real firstparam;
202   Standard_Real lastparam;
203   Standard_Real Tol = Abs(Tolerance);
204   Standard_Integer nbrcote1=0;
205   WellDone = Standard_False;
206   NbrSol = 0;
207   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
208     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
209       throw GccEnt_BadQualifier();
210       return;
211   }
212   TColStd_Array1OfReal cote1(1,2);
213   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
214
215   if (Radius < 0.0) {
216     throw Standard_NegativeValue();
217   }
218   else {
219     if (Qualified1.IsEnclosed()) {
220       //    ===========================
221       nbrcote1 = 1;
222       cote1(1) = Radius;
223     }
224     else if(Qualified1.IsOutside()) {
225       //   ===============================
226       nbrcote1 = 1;
227       cote1(1) = -Radius;
228     }
229     else if(Qualified1.IsUnqualified()) {
230       //   ===================================
231       nbrcote1 = 2;
232       cote1(1) = Radius;
233       cote1(2) = -Radius;
234     }
235     IntRes2d_Domain D1(ElCLib::Value(0.,OnCirc),   0.,Tol,
236       ElCLib::Value(2.*M_PI,OnCirc),2.*M_PI,Tol);
237     D1.SetEquivalentParameters(0.,2.*M_PI);
238     Geom2dInt_TheIntConicCurveOfGInter Intp;
239     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
240       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
241       Adaptor2d_OffsetCurve C2(HCu1,cote1(jcote1));
242       firstparam = Max(C2.FirstParameter(),thefirst);
243       lastparam  = Min(C2.LastParameter(),thelast);
244       IntRes2d_Domain D2(C2.Value(firstparam),firstparam,Tol,
245                          C2.Value(lastparam),lastparam,Tol);
246       Intp.Perform(OnCirc,D1,C2,D2,Tol,Tol);
247       if (Intp.IsDone()) {
248         if (!Intp.IsEmpty()) {
249           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
250             NbrSol++;
251             gp_Pnt2d Center(Intp.Point(i).Value());
252             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
253             //           =======================================================
254             qualifier1(NbrSol) = Qualified1.Qualifier();
255             TheSame1(NbrSol) = 0;
256             pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
257             parcen3(NbrSol) = Intp.Point(i).ParamOnFirst();
258             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
259               pnttg1sol(NbrSol));
260             pnttg1sol(NbrSol) = gp_Pnt2d(Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol)));
261             pntcen3(NbrSol) = Center;
262           }
263         }
264         WellDone = Standard_True;
265       }
266     }
267   }
268 }
269
270 //=========================================================================
271 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
272 //         centre   :  sur une droite OnLine.                             +
273 //         de rayon :  Radius.                                            +
274 //                                                                        + 
275 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
276 //  champs.                                                               +
277 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
278 //  solutions.                                                            +
279 //  On resoud l equation du second degre indiquant que le point de centre +
280 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
281 //                        sur la droite OnLine.                           +
282 //  Les solutions sont representees par les cercles :                     +
283 //                   - de centre Pntcen(xc,yc)                            +
284 //                   - de rayon Radius.                                   +
285 //=========================================================================
286
287 Geom2dGcc_Circ2dTanOnRadGeo::
288 Geom2dGcc_Circ2dTanOnRadGeo (const GccEnt_QualifiedCirc& Qualified1,
289                              const Geom2dAdaptor_Curve&             OnCurv    ,
290                              const Standard_Real         Radius    ,
291                              const Standard_Real         Tolerance ):
292
293 //=========================================================================
294 // Initialisation des champs.                                             +
295 //=========================================================================
296
297 cirsol(1,aNbSolMAX)     ,
298 qualifier1(1,aNbSolMAX) ,
299 TheSame1(1,aNbSolMAX)   ,
300 pnttg1sol(1,aNbSolMAX)  ,
301 pntcen3(1,aNbSolMAX)    ,
302 par1sol(1,aNbSolMAX)    ,
303 pararg1(1,aNbSolMAX)    ,
304 parcen3(1,aNbSolMAX)    
305 {
306
307   //=========================================================================
308   // Traitement.                                                            +
309   //=========================================================================
310
311   gp_Dir2d dirx(1.0,0.0);
312   Standard_Real thefirst = -100000.;
313   Standard_Real thelast  =  100000.;
314   Standard_Real firstparam;
315   Standard_Real lastparam;
316   Standard_Real Tol = Abs(Tolerance);
317   Standard_Integer nbrcote1=0;
318   WellDone = Standard_False;
319   NbrSol = 0;
320   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
321     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
322       throw GccEnt_BadQualifier();
323       return;
324   }
325   TColStd_Array1OfReal cote1(1,2);
326   gp_Circ2d C1 = Qualified1.Qualified();
327   gp_Pnt2d center1(C1.Location());
328   Standard_Real R1 = C1.Radius();
329
330   if (Radius < 0.0) {
331     throw Standard_NegativeValue();
332   }
333   else {
334     if (Qualified1.IsEnclosed()) {
335       //    ===========================
336       nbrcote1 = 1;
337       cote1(1) = Radius;
338     }
339     else if(Qualified1.IsOutside()) {
340       //   ===============================
341       nbrcote1 = 1;
342       cote1(1) = -Radius;
343     }
344     else if(Qualified1.IsUnqualified()) {
345       //   ===================================
346       nbrcote1 = 2;
347       cote1(1) = Radius;
348       cote1(2) = -Radius;
349     }
350     Geom2dInt_TheIntConicCurveOfGInter Intp;
351     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
352       gp_Circ2d Circ(C1.XAxis(),R1 + cote1(jcote1));
353       IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
354         ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
355       D1.SetEquivalentParameters(0.,2.*M_PI);
356       firstparam = Max(Geom2dGcc_CurveTool::FirstParameter(OnCurv),thefirst);
357       lastparam  = Min(Geom2dGcc_CurveTool::LastParameter(OnCurv),thelast);
358       IntRes2d_Domain D2(Geom2dGcc_CurveTool::Value(OnCurv,firstparam),firstparam,Tol,
359         Geom2dGcc_CurveTool::Value(OnCurv,lastparam),lastparam,Tol);
360       Intp.Perform(Circ,D1,OnCurv,D2,Tol,Tol);
361       if (Intp.IsDone()) {
362         if (!Intp.IsEmpty()) {
363           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
364             NbrSol++;
365             gp_Pnt2d Center(Intp.Point(i).Value());
366             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
367             //           =======================================================
368             Standard_Real distcc1 = Center.Distance(center1);
369             if (!Qualified1.IsUnqualified()) { 
370               qualifier1(NbrSol) = Qualified1.Qualifier();
371             }
372             else if (Abs(distcc1+Radius-R1) < Tol) {
373               qualifier1(NbrSol) = GccEnt_enclosed;
374             }
375             else if (Abs(distcc1-R1-Radius) < Tol) {
376               qualifier1(NbrSol) = GccEnt_outside;
377             }
378             else { qualifier1(NbrSol) = GccEnt_enclosing; }
379             TheSame1(NbrSol) = 0;
380             pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
381             parcen3(NbrSol) = Intp.Point(i).ParamOnSecond();
382             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
383               pnttg1sol(NbrSol));
384             pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
385             pntcen3(NbrSol) = Center;
386           }
387         }
388         WellDone = Standard_True;
389       }
390     }
391   }
392 }
393
394 //=========================================================================
395 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
396 //         centre   :  sur une droite OnLine.                             +
397 //         de rayon :  Radius.                                            +
398 //                                                                        + 
399 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
400 //  champs.                                                               +
401 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
402 //  solutions.                                                            +
403 //  On resoud l equation du second degre indiquant que le point de centre +
404 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
405 //                        sur la droite OnLine.                           +
406 //  Les solutions sont representees par les cercles :                     +
407 //                   - de centre Pntcen(xc,yc)                            +
408 //                   - de rayon Radius.                                   +
409 //=========================================================================
410
411 Geom2dGcc_Circ2dTanOnRadGeo::
412 Geom2dGcc_Circ2dTanOnRadGeo (const GccEnt_QualifiedLin& Qualified1,
413                              const Geom2dAdaptor_Curve&            OnCurv    ,
414                              const Standard_Real        Radius    ,
415                              const Standard_Real        Tolerance ):
416
417 //=========================================================================
418 // Initialisation des champs.                                             +
419 //=========================================================================
420
421 cirsol(1,aNbSolMAX)     ,
422 qualifier1(1,aNbSolMAX) ,
423 TheSame1(1,aNbSolMAX)   ,
424 pnttg1sol(1,aNbSolMAX)  ,
425 pntcen3(1,aNbSolMAX)    ,
426 par1sol(1,aNbSolMAX)    ,
427 pararg1(1,aNbSolMAX)    ,
428 parcen3(1,aNbSolMAX)    
429 {
430
431   //=========================================================================
432   // Traitement.                                                            +
433   //=========================================================================
434
435   gp_Dir2d dirx(1.0,0.0);
436   Standard_Real thefirst = -100000.;
437   Standard_Real thelast  =  100000.;
438   Standard_Real firstparam;
439   Standard_Real lastparam;
440   Standard_Real Tol = Abs(Tolerance);
441   WellDone = Standard_False;
442   NbrSol = 0;
443   if (!(Qualified1.IsEnclosed() ||
444     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
445       throw GccEnt_BadQualifier();
446       return;
447   }
448   Standard_Integer nbrcote1=0;
449   TColStd_Array1OfReal cote1(1,2);
450   gp_Lin2d L1 = Qualified1.Qualified();
451   gp_Pnt2d origin1(L1.Location());
452   gp_Dir2d dir1(L1.Direction());
453   gp_Dir2d norm1(-dir1.Y(),dir1.X());
454
455   if (Radius < 0.0) {
456     throw Standard_NegativeValue();
457   }
458   else {
459     if (Qualified1.IsEnclosed()) {
460       //    ===========================
461       nbrcote1 = 1;
462       cote1(1) = Radius;
463     }
464     else if(Qualified1.IsOutside()) {
465       //   ===============================
466       nbrcote1 = 1;
467       cote1(1) = -Radius;
468     }
469     else if(Qualified1.IsUnqualified()) {
470       //   ===================================
471       nbrcote1 = 2;
472       cote1(1) = Radius;
473       cote1(2) = -Radius;
474     }
475     Geom2dInt_TheIntConicCurveOfGInter Intp;
476     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
477       gp_Pnt2d Point(dir1.XY()+cote1(jcote1)*norm1.XY());
478       gp_Lin2d Line(Point,dir1); // ligne avec deport.
479       IntRes2d_Domain D1;
480       firstparam = Max(Geom2dGcc_CurveTool::FirstParameter(OnCurv),thefirst);
481       lastparam  = Min(Geom2dGcc_CurveTool::LastParameter(OnCurv),thelast);
482       IntRes2d_Domain D2(Geom2dGcc_CurveTool::Value(OnCurv,firstparam),firstparam,Tol,
483         Geom2dGcc_CurveTool::Value(OnCurv,lastparam),lastparam,Tol);
484       Intp.Perform(Line,D1,OnCurv,D2,Tol,Tol);
485       if (Intp.IsDone()) {
486         if (!Intp.IsEmpty()) {
487           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
488             NbrSol++;
489             gp_Pnt2d Center(Intp.Point(i).Value());
490             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
491             //           =======================================================
492             gp_Dir2d dc1(origin1.XY()-Center.XY());
493             if (!Qualified1.IsUnqualified()) { 
494               qualifier1(NbrSol) = Qualified1.Qualifier();
495             }
496             else if (dc1.Dot(norm1) > 0.0) {    
497               qualifier1(NbrSol) = GccEnt_outside; 
498             }
499             else { qualifier1(NbrSol) = GccEnt_enclosed; }
500             TheSame1(NbrSol) = 0;
501             pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
502             parcen3(NbrSol) = Intp.Point(i).ParamOnSecond();
503             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
504               pnttg1sol(NbrSol));
505             pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
506             pntcen3(NbrSol) = Center;
507           }
508         }
509         WellDone = Standard_True;
510       }
511     }
512   }
513 }
514
515 //=========================================================================
516 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
517 //         centre   :  sur une droite OnLine.                             +
518 //         de rayon :  Radius.                                            +
519 //                                                                        + 
520 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
521 //  champs.                                                               +
522 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
523 //  solutions.                                                            +
524 //  On resoud l equation du second degre indiquant que le point de centre +
525 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
526 //                        sur la droite OnLine.                           +
527 //  Les solutions sont representees par les cercles :                     +
528 //                   - de centre Pntcen(xc,yc)                            +
529 //                   - de rayon Radius.                                   +
530 //=========================================================================
531
532 Geom2dGcc_Circ2dTanOnRadGeo::
533 Geom2dGcc_Circ2dTanOnRadGeo (const Geom2dGcc_QCurve& Qualified1,
534                              const Geom2dAdaptor_Curve&     OnCurv    ,
535                              const Standard_Real Radius    ,
536                              const Standard_Real Tolerance ):
537
538 //=========================================================================
539 // Initialisation des champs.                                             +
540 //=========================================================================
541
542 cirsol(1,aNbSolMAX)     ,
543 qualifier1(1,aNbSolMAX) ,
544 TheSame1(1,aNbSolMAX)   ,
545 pnttg1sol(1,aNbSolMAX)  ,
546 pntcen3(1,aNbSolMAX)    ,
547 par1sol(1,aNbSolMAX)    ,
548 pararg1(1,aNbSolMAX)    ,
549 parcen3(1,aNbSolMAX)    
550 {
551
552   //=========================================================================
553   // Traitement.                                                            +
554   //=========================================================================
555
556   gp_Dir2d dirx(1.0,0.0);
557   Standard_Real thefirst = -100000.;
558   Standard_Real thelast  =  100000.;
559   Standard_Real firstparam;
560   Standard_Real lastparam;
561   Standard_Real Tol = Abs(Tolerance);
562   Standard_Integer nbrcote1=0;
563   WellDone = Standard_False;
564   NbrSol = 0;
565   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
566     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
567       throw GccEnt_BadQualifier();
568       return;
569   }
570   TColStd_Array1OfReal cote1(1,2);
571   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
572
573   if (Radius < 0.0) {
574     throw Standard_NegativeValue();
575   }
576   else {
577     if (Qualified1.IsEnclosed()) {
578       //    ===========================
579       nbrcote1 = 1;
580       cote1(1) = Radius;
581     }
582     else if(Qualified1.IsOutside()) {
583       //   ===============================
584       nbrcote1 = 1;
585       cote1(1) = -Radius;
586     }
587     else if(Qualified1.IsUnqualified()) {
588       //   ===================================
589       nbrcote1 = 2;
590       cote1(1) = Radius;
591       cote1(2) = -Radius;
592     }
593     Geom2dInt_GInter Intp;
594     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
595       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
596       Adaptor2d_OffsetCurve C1(HCu1,cote1(jcote1));
597       firstparam = Max(C1.FirstParameter(),thefirst);
598       lastparam  = Min(C1.LastParameter(),thelast);
599       IntRes2d_Domain D1(C1.Value(firstparam), firstparam, Tol,
600                          C1.Value(lastparam), lastparam, Tol);
601       Handle(Geom2dAdaptor_HCurve) HOnCurv = new Geom2dAdaptor_HCurve(OnCurv);
602       Adaptor2d_OffsetCurve C2(HOnCurv);
603       firstparam = Max(C2.FirstParameter(),thefirst);
604       lastparam  = Min(C2.LastParameter(),thelast);
605       IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
606                          C2.Value(lastparam), lastparam, Tol);
607       Intp.Perform(C1,D1,C2,D2,Tol,Tol);
608       if (Intp.IsDone()) {
609         if (!Intp.IsEmpty()) {
610           for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
611             NbrSol++;
612             gp_Pnt2d Center(Intp.Point(i).Value());
613             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
614             //           =======================================================
615             qualifier1(NbrSol) = Qualified1.Qualifier();
616             TheSame1(NbrSol) = 0;
617             pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
618             parcen3(NbrSol) = Intp.Point(i).ParamOnSecond();
619             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
620               pnttg1sol(NbrSol));
621             pnttg1sol(NbrSol) = gp_Pnt2d(Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol)));
622             pntcen3(NbrSol) = Center;
623           }
624         }
625         WellDone = Standard_True;
626       }
627     }
628   }
629 }
630
631 //=========================================================================
632 //  Cercle tangent  :  a un cercle Qualified1 (C1).                       +
633 //         centre   :  sur une droite OnLine.                             +
634 //         de rayon :  Radius.                                            +
635 //                                                                        + 
636 //  On initialise le tableau de solutions cirsol ainsi que tous les       +
637 //  champs.                                                               +
638 //  On elimine en fonction du qualifieur les cas ne presentant pas de     +
639 //  solutions.                                                            +
640 //  On resoud l equation du second degre indiquant que le point de centre +
641 //  recherche (xc,yc) est a une distance Radius du cercle C1 et           +
642 //                        sur la droite OnLine.                           +
643 //  Les solutions sont representees par les cercles :                     +
644 //                   - de centre Pntcen(xc,yc)                            +
645 //                   - de rayon Radius.                                   +
646 //=========================================================================
647
648 Geom2dGcc_Circ2dTanOnRadGeo::
649 Geom2dGcc_Circ2dTanOnRadGeo (const gp_Pnt2d&     Point1    ,
650                              const Geom2dAdaptor_Curve&     OnCurv    ,
651                              const Standard_Real Radius    ,
652                              const Standard_Real Tolerance ):
653
654 //=========================================================================
655 // Initialisation des champs.                                             +
656 //=========================================================================
657
658 cirsol(1,aNbSolMAX)     ,
659 qualifier1(1,aNbSolMAX) ,
660 TheSame1(1,aNbSolMAX)   ,
661 pnttg1sol(1,aNbSolMAX)  ,
662 pntcen3(1,aNbSolMAX)    ,
663 par1sol(1,aNbSolMAX)    ,
664 pararg1(1,aNbSolMAX)    ,
665 parcen3(1,aNbSolMAX)    
666 {
667
668   //=========================================================================
669   // Traitement.                                                            +
670   //=========================================================================
671
672   gp_Dir2d dirx(1.0,0.0);
673   Standard_Real thefirst = -100000.;
674   Standard_Real thelast  =  100000.;
675   Standard_Real firstparam;
676   Standard_Real lastparam;
677   Standard_Real Tol = Abs(Tolerance);
678   WellDone = Standard_False;
679   NbrSol = 0;
680
681   if (Radius < 0.0) {
682     throw Standard_NegativeValue();
683   }
684   else {
685     //     gp_Dir2d Dir(-y1dir,x1dir);
686     gp_Circ2d Circ(gp_Ax2d(Point1,gp_Dir2d(1.,0.)),Radius);
687     IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
688       ElCLib::Value(2.*M_PI,Circ),2*M_PI,Tol);
689     D1.SetEquivalentParameters(0.,2.*M_PI);
690     firstparam = Max(Geom2dGcc_CurveTool::FirstParameter(OnCurv),thefirst);
691     lastparam  = Min(Geom2dGcc_CurveTool::LastParameter(OnCurv),thelast);
692     IntRes2d_Domain D2(Geom2dGcc_CurveTool::Value(OnCurv,firstparam),firstparam,Tol,
693       Geom2dGcc_CurveTool::Value(OnCurv,lastparam),lastparam,Tol);
694     Geom2dInt_TheIntConicCurveOfGInter Intp(Circ,D1,OnCurv,D2,Tol,Tol);
695     if (Intp.IsDone()) {
696       if (!Intp.IsEmpty()) {
697         for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
698           NbrSol++;
699           gp_Pnt2d Center(Intp.Point(i).Value());
700           cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
701           //         =======================================================
702           qualifier1(NbrSol) = GccEnt_noqualifier;
703           TheSame1(NbrSol) = 0;
704           pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
705           parcen3(NbrSol) = Intp.Point(i).ParamOnSecond();
706           par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
707             pnttg1sol(NbrSol));
708           pnttg1sol(NbrSol) = Point1;
709           pntcen3(NbrSol) = Center;
710         }
711         WellDone = Standard_True;
712       }
713     }
714   }
715 }
716
717 //=========================================================================
718
719 Standard_Boolean Geom2dGcc_Circ2dTanOnRadGeo::
720 IsDone () const { return WellDone; }
721
722 Standard_Integer Geom2dGcc_Circ2dTanOnRadGeo::
723 NbSolutions () const { return NbrSol; }
724
725 gp_Circ2d Geom2dGcc_Circ2dTanOnRadGeo::
726 ThisSolution (const Standard_Integer Index) const 
727 {
728
729   if (Index > NbrSol || Index <= 0)
730     throw Standard_OutOfRange();
731
732   return cirsol(Index);
733 }
734
735 void Geom2dGcc_Circ2dTanOnRadGeo::
736 WhichQualifier(const Standard_Integer Index   ,
737                GccEnt_Position& Qualif1 ) const
738 {
739   if (!WellDone) { throw StdFail_NotDone(); }
740   else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
741   else {
742     Qualif1 = qualifier1(Index);
743   }
744 }
745
746 void Geom2dGcc_Circ2dTanOnRadGeo::
747 Tangency1 (const Standard_Integer Index,
748            Standard_Real&   ParSol,
749            Standard_Real&   ParArg,
750            gp_Pnt2d& PntSol) const{
751              if (!WellDone) {
752                throw StdFail_NotDone();
753              }
754              else if (Index <= 0 ||Index > NbrSol) {
755                throw Standard_OutOfRange();
756              }
757              else {
758                ParSol = par1sol(Index);
759                ParArg = pararg1(Index);
760                PntSol = gp_Pnt2d(pnttg1sol(Index));
761              }
762 }
763
764 void Geom2dGcc_Circ2dTanOnRadGeo::
765 CenterOn3 (const Standard_Integer Index,
766            Standard_Real&   ParArg, 
767            gp_Pnt2d&        PntSol) const {
768              if (!WellDone) {
769                throw StdFail_NotDone();
770              }
771              else if (Index <= 0 ||Index > NbrSol) {
772                throw Standard_OutOfRange();
773              }
774              else {
775                ParArg = parcen3(Index);
776                PntSol = pnttg1sol(Index);
777              }
778 }
779
780 Standard_Boolean Geom2dGcc_Circ2dTanOnRadGeo::
781 IsTheSame1 (const Standard_Integer Index) const
782 {
783   if (!WellDone) throw StdFail_NotDone();
784   if (Index <= 0 ||Index > NbrSol) throw Standard_OutOfRange();
785
786   if (TheSame1(Index) == 0) 
787     return Standard_False;
788
789   return Standard_True;
790 }