Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2d2TanRad.cxx
1 // File:        Geom2dGcc_Circ2d2TanRad.cxx
2 // Created:     Wed Oct 21 14:49:57 1992
3 // Author:      Remi GILET
4 //              <reg@phobox>
5
6 #include <Geom2dGcc_Circ2d2TanRad.ixx>
7 #include <Geom2dAdaptor_Curve.hxx>
8 #include <GccAna_Circ2d2TanRad.hxx>
9 #include <Geom2dGcc_MyCirc2d2TanRad.hxx>
10 #include <Geom2dGcc_MyQCurve.hxx>
11 #include <GccEnt_BadQualifier.hxx>
12 #include <Geom2d_Circle.hxx>
13 #include <Geom2d_Line.hxx>
14 #include <gp_Circ2d.hxx>
15 #include <gp_Lin2d.hxx>
16 #include <GccEnt_QualifiedCirc.hxx>
17 #include <GccEnt_QualifiedLin.hxx>
18 #include <StdFail_NotDone.hxx>
19 #include <Standard_NegativeValue.hxx>
20 #include <Standard_OutOfRange.hxx>
21
22
23 // circulaire tangent a deux cercles et de rayon donne
24 //====================================================
25 //========================================================================
26 // On initialise WellDone a false.                                       +
27 // On recupere le cercle C1 et le cercle C2.                             +
28 // On sort en erreur dans les cas ou la construction est impossible.     +
29 // On distingue les cas limites pour les triater separement.             +
30 // On fait la parallele a C1 dans le bon sens.                           +
31 // On fait la parallele a C2 dans le bon sens.                           +
32 // On intersecte les paralleles ==> point de centre de la solution.      +
33 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
34 // On remplit les champs.                                                +
35 //========================================================================
36
37 Geom2dGcc_Circ2d2TanRad::
38    Geom2dGcc_Circ2d2TanRad (const Geom2dGcc_QualifiedCurve& Qualified1 ,
39                             const Geom2dGcc_QualifiedCurve& Qualified2 ,
40                             const Standard_Real             Radius     ,
41                             const Standard_Real             Tolerance  ):
42   cirsol(1,16)   ,
43   qualifier1(1,16),
44   qualifier2(1,16),
45   TheSame1(1,16) ,
46   TheSame2(1,16) ,
47   pnttg1sol(1,16),
48   pnttg2sol(1,16),
49   par1sol(1,16)  ,
50   par2sol(1,16)  ,
51   pararg1(1,16)  ,
52   pararg2(1,16)  
53 {
54   if (Radius < 0.) { Standard_NegativeValue::Raise(); }
55   else {
56     Geom2dAdaptor_Curve C1 = Qualified1.Qualified();
57     Geom2dAdaptor_Curve C2 = Qualified2.Qualified();
58     Handle(Geom2d_Curve) CC1 = C1.Curve();
59     Handle(Geom2d_Curve) CC2 = C2.Curve();
60     GeomAbs_CurveType Type1 = C1.GetType();
61     GeomAbs_CurveType Type2 = C2.GetType();
62
63 //=============================================================================
64 //                            Appel a GccAna.                                 +
65 //=============================================================================
66
67     Invert = Standard_False;
68     NbrSol = 0;
69     if ((Type1 == GeomAbs_Line || Type1 == GeomAbs_Circle) &&
70         (Type2 == GeomAbs_Line || Type2 == GeomAbs_Circle)) {
71       if (Type1 == GeomAbs_Circle) {
72         Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
73         gp_Circ2d c1(CCC1->Circ2d());
74         GccEnt_QualifiedCirc Qc1 = GccEnt_QualifiedCirc(c1,
75                                                        Qualified1.Qualifier());
76         if (Type2 == GeomAbs_Circle) {
77           Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
78           gp_Circ2d c2(CCC2->Circ2d());
79           GccAna_Circ2d2TanRad CircAna(Qc1,
80                                GccEnt_QualifiedCirc(c2,Qualified2.Qualifier()),
81                                        Radius,Tolerance);
82           WellDone = CircAna.IsDone();
83           NbrSol = CircAna.NbSolutions();
84           for(Standard_Integer i=1; i<=NbrSol; i++) {
85             CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
86           }
87           Results(CircAna);
88         }
89         else {
90           Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
91           gp_Lin2d l2(LL2->Lin2d());
92           if (!Qualified2.IsEnclosing()) {
93             GccAna_Circ2d2TanRad CircAna(Qc1,
94                                 GccEnt_QualifiedLin(l2,Qualified2.Qualifier()),
95                                          Radius,Tolerance);
96             WellDone = CircAna.IsDone();
97             NbrSol = CircAna.NbSolutions();
98             for(Standard_Integer i=1; i<=NbrSol; i++) {
99               CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
100             }
101             Results(CircAna);
102           }
103           else { 
104             WellDone = Standard_False;
105             GccEnt_BadQualifier::Raise(); 
106           }
107         }
108       }
109       else {
110         Handle(Geom2d_Line) LL1 = Handle(Geom2d_Line)::DownCast(CC1);
111         gp_Lin2d l1(LL1->Lin2d());
112         if (Qualified1.IsEnclosing()) {
113           WellDone = Standard_False;
114           GccEnt_BadQualifier::Raise();
115         }
116         else {
117           GccEnt_QualifiedLin Ql1 = GccEnt_QualifiedLin(l1,
118                                                        Qualified1.Qualifier());
119           if (Type2 == GeomAbs_Circle) {
120             Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
121             gp_Circ2d c2(CCC2->Circ2d());
122             Invert = Standard_True;
123             GccAna_Circ2d2TanRad CircAna(GccEnt_QualifiedCirc(c2,
124                                                        Qualified2.Qualifier()),
125                                          Ql1,Radius,Tolerance);
126             WellDone = CircAna.IsDone();
127             NbrSol = CircAna.NbSolutions();
128             for(Standard_Integer i=1; i<=NbrSol; i++) {
129               CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
130             }
131             Results(CircAna);
132           }
133           else {
134             Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
135             gp_Lin2d l2(LL2->Lin2d());
136             if (!Qualified2.IsEnclosing()) {
137               GccAna_Circ2d2TanRad CircAna(Ql1,
138                                 GccEnt_QualifiedLin(l2,Qualified2.Qualifier()),
139                                            Radius,Tolerance);
140               WellDone = CircAna.IsDone();
141               NbrSol = CircAna.NbSolutions();
142               for(Standard_Integer i=1; i<=NbrSol; i++) {
143                 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
144               }
145               Results(CircAna);
146             }
147             else { 
148               WellDone = Standard_False;
149               GccEnt_BadQualifier::Raise(); 
150             }
151           }
152         }
153       }
154     }
155 //=============================================================================
156 //                            Appel a GccGeo.                                 +
157 //=============================================================================
158     else {
159       if (Type1 == GeomAbs_Line) {
160         Handle(Geom2d_Line) LL1 = Handle(Geom2d_Line)::DownCast(CC1);
161         gp_Lin2d l1(LL1->Lin2d());
162         if (Qualified1.IsEnclosing()) {
163           WellDone = Standard_False;
164           GccEnt_BadQualifier::Raise();
165         }
166         else {
167           GccEnt_QualifiedLin Ql1 = GccEnt_QualifiedLin(l1,
168                                                        Qualified1.Qualifier());
169           Geom2dGcc_MyQCurve Qc2(C2,Qualified2.Qualifier());
170           Geom2dGcc_MyCirc2d2TanRad CircGeo(Ql1,Qc2,Radius,Tolerance);
171           WellDone = CircGeo.IsDone();
172           NbrSol = CircGeo.NbSolutions();
173           for(Standard_Integer i=1; i<=NbrSol; i++) {
174             CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
175           }
176           Results(CircGeo);
177         }
178       }
179       else if (Type1 == GeomAbs_Circle) {
180         Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
181         gp_Circ2d c1(CCC1->Circ2d());
182         GccEnt_QualifiedCirc Qc1 = GccEnt_QualifiedCirc(c1,
183                                                        Qualified1.Qualifier());
184         Geom2dGcc_MyQCurve Qc2(C2,Qualified2.Qualifier());
185         Geom2dGcc_MyCirc2d2TanRad CircGeo(Qc1,Qc2,Radius,Tolerance);
186         WellDone = CircGeo.IsDone();
187         NbrSol = CircGeo.NbSolutions();
188         for(Standard_Integer i=1; i<=NbrSol; i++) {
189           CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
190         }
191         Results(CircGeo);
192       }
193       else if (Type2 == GeomAbs_Line) {
194         Invert = Standard_True;
195         Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
196         gp_Lin2d l2(LL2->Lin2d());
197         if (Qualified2.IsEnclosing()) {
198           WellDone = Standard_False;
199           GccEnt_BadQualifier::Raise();
200         }
201         else {
202           GccEnt_QualifiedLin Ql2 = GccEnt_QualifiedLin(l2,
203                                                        Qualified2.Qualifier());
204           Geom2dGcc_MyQCurve Qc1(C1,Qualified1.Qualifier());
205           Geom2dGcc_MyCirc2d2TanRad CircGeo(Ql2,Qc1,Radius,Tolerance);
206           WellDone = CircGeo.IsDone();
207           NbrSol = CircGeo.NbSolutions();
208           for(Standard_Integer i=1; i<=NbrSol; i++) {
209             CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
210           }
211           Results(CircGeo);
212         }
213       }
214       else if (Type2 == GeomAbs_Circle) {
215         Invert = Standard_True;
216         Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
217         gp_Circ2d c2(CCC2->Circ2d());
218         GccEnt_QualifiedCirc Qc2 = GccEnt_QualifiedCirc(c2,
219                                                        Qualified2.Qualifier());
220         Geom2dGcc_MyQCurve Qc1(C1,Qualified1.Qualifier());
221         Geom2dGcc_MyCirc2d2TanRad CircGeo(Qc2,Qc1,Radius,Tolerance);
222         WellDone = CircGeo.IsDone();
223         NbrSol = CircGeo.NbSolutions();
224         for(Standard_Integer i=1; i<=NbrSol; i++) {
225           CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
226         }
227         Results(CircGeo);
228       }
229       else {
230         Geom2dGcc_MyQCurve Qc1(C1,Qualified1.Qualifier());
231         Geom2dGcc_MyQCurve Qc2(C2,Qualified2.Qualifier());
232         Geom2dGcc_MyCirc2d2TanRad CircGeo(Qc1,Qc2,Radius,Tolerance);
233         WellDone = CircGeo.IsDone();
234         NbrSol = CircGeo.NbSolutions();
235         for(Standard_Integer i=1; i<=NbrSol; i++) {
236           CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
237         }
238         Results(CircGeo);
239       }
240     }
241   }
242 }
243
244 Geom2dGcc_Circ2d2TanRad::
245    Geom2dGcc_Circ2d2TanRad (const Geom2dGcc_QualifiedCurve& Qualified1 ,
246                             const Handle(Geom2d_Point)&     Point      ,
247                             const Standard_Real             Radius     ,
248                             const Standard_Real             Tolerance  ):
249   cirsol(1,8)   ,
250   qualifier1(1,8),
251   qualifier2(1,8),
252   TheSame1(1,8) ,
253   TheSame2(1,8) ,
254   pnttg1sol(1,8),
255   pnttg2sol(1,8),
256   par1sol(1,8)  ,
257   par2sol(1,8)  ,
258   pararg1(1,8)  ,
259   pararg2(1,8)  
260 {
261   if (Radius < 0.) { Standard_NegativeValue::Raise(); }
262   else {
263     Geom2dAdaptor_Curve C1 = Qualified1.Qualified();
264     Handle(Geom2d_Curve) CC1 = C1.Curve();
265     GeomAbs_CurveType Type1 = C1.GetType();
266
267 //=============================================================================
268 //                            Appel a GccAna.                                 +
269 //=============================================================================
270
271     Invert = Standard_False;
272     NbrSol = 0;
273     if (Type1 == GeomAbs_Line || Type1 == GeomAbs_Circle) {
274       if (Type1 == GeomAbs_Circle) {
275         Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
276         gp_Circ2d c1(CCC1->Circ2d());
277         GccEnt_QualifiedCirc Qc1(c1,Qualified1.Qualifier());
278         GccAna_Circ2d2TanRad CircAna(Qc1,Point->Pnt2d(),Radius,Tolerance);
279         WellDone = CircAna.IsDone();
280         NbrSol = CircAna.NbSolutions();
281         for(Standard_Integer i=1; i<=NbrSol; i++) {
282           CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
283         }
284         Results(CircAna);
285       }
286       else {
287         Handle(Geom2d_Line) LLL1 = Handle(Geom2d_Line)::DownCast(CC1);
288         gp_Lin2d l1(LLL1->Lin2d());
289         GccEnt_QualifiedLin Ql1(l1,Qualified1.Qualifier());
290         GccAna_Circ2d2TanRad CircAna(Ql1,Point->Pnt2d(),Radius,Tolerance);
291         WellDone = CircAna.IsDone();
292         NbrSol = CircAna.NbSolutions();
293         for(Standard_Integer i=1; i<=NbrSol; i++) {
294           CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
295         }
296         Results(CircAna);
297       }
298     }
299 //=============================================================================
300 //                            Appel a GccGeo.                                 +
301 //=============================================================================
302     else {
303       Geom2dGcc_MyQCurve Qc1(C1,Qualified1.Qualifier());
304       Geom2dGcc_MyCirc2d2TanRad CircGeo(Qc1,Point->Pnt2d(),Radius,Tolerance);
305       WellDone = CircGeo.IsDone();
306       NbrSol = CircGeo.NbSolutions();
307       for(Standard_Integer i=1; i<=NbrSol; i++) {
308         CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
309       }
310       Results(CircGeo);
311     }
312   }
313 }
314   
315 Geom2dGcc_Circ2d2TanRad::
316    Geom2dGcc_Circ2d2TanRad (const Handle(Geom2d_Point)& Point1     ,
317                             const Handle(Geom2d_Point)& Point2     ,
318                             const Standard_Real         Radius     ,
319                             const Standard_Real         Tolerance  ):
320   cirsol(1,2)   ,
321   qualifier1(1,2),
322   qualifier2(1,2),
323   TheSame1(1,2) ,
324   TheSame2(1,2) ,
325   pnttg1sol(1,2),
326   pnttg2sol(1,2),
327   par1sol(1,2)  ,
328   par2sol(1,2)  ,
329   pararg1(1,2)  ,
330   pararg2(1,2)  
331 {
332   if (Radius < 0.) { Standard_NegativeValue::Raise(); }
333   else {
334
335 //=============================================================================
336 //                            Appel a GccAna.                                 +
337 //=============================================================================
338
339     Invert = Standard_False;
340     NbrSol = 0;
341     GccAna_Circ2d2TanRad CircAna(Point1->Pnt2d(),Point2->Pnt2d(),
342                                  Radius,Tolerance);
343     WellDone = CircAna.IsDone();
344     NbrSol = CircAna.NbSolutions();
345     for(Standard_Integer i=1; i<=NbrSol; i++) {
346       CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
347     }
348     Results(CircAna);
349   }
350 }
351
352 void Geom2dGcc_Circ2d2TanRad::Results(const GccAna_Circ2d2TanRad& Circ)
353 {
354   for (Standard_Integer j = 1; j <= NbrSol; j++) {
355     cirsol(j)   = Circ.ThisSolution(j);
356     if (Circ.IsTheSame1(j)) { TheSame1(j) = 1; }
357     else {TheSame1(j) = 0; }
358     if (Circ.IsTheSame2(j)) { TheSame2(j) = 1; }
359     else {TheSame2(j) = 0; }
360     Circ.Tangency1(j,par1sol(j),pararg1(j),pnttg1sol(j));
361     Circ.Tangency2(j,par2sol(j),pararg2(j),pnttg2sol(j));
362   }
363 }
364
365 void Geom2dGcc_Circ2d2TanRad::Results(const Geom2dGcc_MyCirc2d2TanRad& Circ)
366 {
367   for (Standard_Integer j = 1; j <= NbrSol; j++) {
368     cirsol(j)   = Circ.ThisSolution(j);
369     if (Circ.IsTheSame1(j)) { TheSame1(j) = 1; }
370     else {TheSame1(j) = 0; }
371     if (Circ.IsTheSame2(j)) { TheSame2(j) = 1; }
372     else {TheSame2(j) = 0; }
373     Circ.Tangency1(j,par1sol(j),pararg1(j),pnttg1sol(j));
374     Circ.Tangency2(j,par2sol(j),pararg2(j),pnttg2sol(j));
375   }
376 }
377
378 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
379    IsDone () const { return WellDone; }
380
381 Standard_Integer Geom2dGcc_Circ2d2TanRad::
382   NbSolutions () const 
383
384   return NbrSol;
385 }
386
387 gp_Circ2d Geom2dGcc_Circ2d2TanRad::
388   ThisSolution (const Standard_Integer Index) const 
389 {
390   if (!WellDone) { StdFail_NotDone::Raise(); }
391   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
392   return cirsol(Index);
393 }
394
395 void Geom2dGcc_Circ2d2TanRad::
396   WhichQualifier (const Standard_Integer Index   ,
397                         GccEnt_Position& Qualif1 ,
398                         GccEnt_Position& Qualif2) const
399 {
400   if (!WellDone) { StdFail_NotDone::Raise(); }
401   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
402   else {
403     if (Invert) {
404       Qualif1 = qualifier2(Index);
405       Qualif2 = qualifier1(Index);
406     }
407     else {
408       Qualif1 = qualifier1(Index);
409       Qualif2 = qualifier2(Index);
410     }
411   }
412 }
413
414 void Geom2dGcc_Circ2d2TanRad::
415   Tangency1 (const Standard_Integer Index,
416                    Standard_Real&   ParSol,
417                    Standard_Real&   ParArg,
418                    gp_Pnt2d&        PntSol) const
419 {
420   if (!WellDone) { StdFail_NotDone::Raise(); }
421   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
422   else {
423     if (Invert) {
424       if (TheSame2(Index) == 0) {
425         ParSol = par2sol(Index);
426         ParArg = pararg2(Index);
427         PntSol = pnttg2sol(Index);
428       }
429       else { StdFail_NotDone::Raise(); }
430     }
431     else {
432       if (TheSame1(Index) == 0) {
433         ParSol = par1sol(Index);
434         ParArg = pararg1(Index);
435         PntSol = pnttg1sol(Index);
436       }
437       else { StdFail_NotDone::Raise(); }
438     }
439   }
440 }
441
442 void Geom2dGcc_Circ2d2TanRad::
443    Tangency2 (const Standard_Integer Index,
444               Standard_Real& ParSol,
445               Standard_Real& ParArg,
446               gp_Pnt2d& PntSol) const
447 {
448   if (!WellDone) { StdFail_NotDone::Raise(); }
449   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
450   else {
451     if (!Invert) {
452       if (TheSame2(Index) == 0) {
453         ParSol = par2sol(Index);
454         ParArg = pararg2(Index);
455         PntSol = pnttg2sol(Index);
456       }
457       else { StdFail_NotDone::Raise(); }
458     }
459     else {
460       if (TheSame1(Index) == 0) {
461         ParSol = par1sol(Index);
462         ParArg = pararg1(Index);
463         PntSol = pnttg1sol(Index);
464       }
465       else { StdFail_NotDone::Raise(); }
466     }
467   }
468 }
469
470 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
471    IsTheSame1 (const Standard_Integer Index) const
472 {
473   if (!WellDone) { StdFail_NotDone::Raise(); }
474   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
475   if (Invert) {
476     if (TheSame2(Index) == 0) { return Standard_False; }
477     else { return Standard_True; }
478   }
479   else {
480     if (TheSame1(Index) == 0) { return Standard_False; }
481     else { return Standard_True; }
482   }
483   return Standard_True;
484 }
485
486 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
487    IsTheSame2 (const Standard_Integer Index) const
488 {
489   if (!WellDone) { StdFail_NotDone::Raise(); }
490   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
491   if (!Invert) {
492     if (TheSame2(Index) == 0) { return Standard_False; }
493     else { return Standard_True; }
494   }
495   else {
496     if (TheSame1(Index) == 0) { return Standard_False; }
497     else { return Standard_True; }
498   }
499   return Standard_True;
500 }