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