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