0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / GccAna / GccAna_Circ2dTanOnRad_3.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 #include <ElCLib.hxx>
17 #include <GccAna_Circ2dTanOnRad.hxx>
18 #include <GccEnt_BadQualifier.hxx>
19 #include <GccEnt_QualifiedCirc.hxx>
20 #include <GccEnt_QualifiedLin.hxx>
21 #include <gp_Circ2d.hxx>
22 #include <gp_Dir2d.hxx>
23 #include <gp_Lin2d.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <IntAna2d_AnaIntersection.hxx>
26 #include <IntAna2d_IntPoint.hxx>
27 #include <Standard_NegativeValue.hxx>
28 #include <Standard_OutOfRange.hxx>
29 #include <StdFail_NotDone.hxx>
30 #include <TColgp_Array1OfDir2d.hxx>
31
32 //=========================================================================
33 //   Circle tangent to a circle   Qualified1 (C1).                        +
34 //          center on a circle  OnCirc.                                   +
35 //          of radius              Radius.                                +
36 //                                                                        +
37 //  Initialize the table of solutions cirsol and all fields.              +
38 //  Eliminate cases not being the solution.                     +
39 //  Create parallel(s) to C1 in the required direction(s).       +
40 //  Intersect parallel(s) with OnCirc and obtain the   +
41 //  center point(s) of found solution(s).       +
42 //  Create solution(s) cirsol.                               +
43 //=========================================================================
44 GccAna_Circ2dTanOnRad::
45    GccAna_Circ2dTanOnRad (const GccEnt_QualifiedCirc& Qualified1,
46                           const gp_Circ2d&            OnCirc    ,
47                           const Standard_Real         Radius    ,
48                           const Standard_Real         Tolerance ):
49    cirsol(1,4)   ,
50    qualifier1(1,4) ,
51    TheSame1(1,4) ,
52    pnttg1sol(1,4),
53    pntcen3(1,4)  ,
54    par1sol(1,4)  ,
55    pararg1(1,4)  ,
56    parcen3(1,4)  
57 {
58      
59    TheSame1.Init(0);
60    gp_Dir2d dirx(1.0,0.0);
61    Standard_Real Tol = Abs(Tolerance);
62    Standard_Integer signe[5];
63    signe[0] = 0;
64    signe[1] = 0;
65    signe[2] = 0;
66    signe[3] = 0;
67    signe[4] = 0;
68    Standard_Real disparal[2];
69    Standard_Integer nparal = 0;
70    Standard_Integer sign = 0;
71    WellDone = Standard_False;
72    NbrSol = 0;
73    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
74          Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
75      throw GccEnt_BadQualifier();
76      return;
77    }
78    gp_Circ2d C1 = Qualified1.Qualified();
79    TColgp_Array1OfPnt2d Center(1,4);
80    TColgp_Array1OfDir2d dir1on(1,4);
81
82    if (Radius < 0.0) { throw Standard_NegativeValue(); }
83    else {
84      Standard_Real R1 = C1.Radius();
85      Standard_Real R2 = OnCirc.Radius();
86      Standard_Real c1x = C1.Location().X();
87      Standard_Real c1y = C1.Location().Y();
88      gp_Pnt2d center1(c1x,c1y);
89      Standard_Real dist = OnCirc.Location().Distance(center1);
90      Standard_Real onx = OnCirc.Location().X();
91      Standard_Real ony = OnCirc.Location().Y();
92      if (Qualified1.IsEnclosed()) {
93 //   ============================
94        if ((Radius-R1 > Tol) || (R1-dist-R2-Radius > Tol)) {
95          WellDone=Standard_True;
96        }
97        else {
98          if (Abs(Radius-R1) < Tol) {
99            if (OnCirc.Distance(center1) < Tol) {
100              cirsol(NbrSol) = C1;
101 //           ==============
102              qualifier1(NbrSol) = Qualified1.Qualifier();
103              NbrSol = 1;
104              TheSame1(NbrSol) = 1;
105              pntcen3(NbrSol) = center1;
106              parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen3(NbrSol));
107              WellDone = Standard_True;
108            }
109            else { WellDone = Standard_False; }
110          }
111          else if (Abs(R1-dist-R2-Radius) <= Tol) {
112            dir1on(1) = gp_Dir2d(c1x-onx,c1y-ony);
113            sign = -1;
114          }
115          else {
116            nparal = 1;
117            disparal[0] = Abs(R1-Radius);
118          }
119        }
120      }
121      else if (Qualified1.IsEnclosing()) {
122 //   ==================================
123        if ((Tol<R1-Radius)||(Tol<R1+dist-R2-Radius)||(Radius-R1-dist-R2>Tol)) {
124          WellDone = Standard_True;
125        }
126        else {
127          if (Abs(Radius-R1) < Tol) {
128            if (OnCirc.Distance(center1) < Tol) {
129              cirsol(NbrSol) = C1;
130 //           ==============
131              qualifier1(NbrSol) = Qualified1.Qualifier();
132              NbrSol = 1;
133              TheSame1(NbrSol) = 1;
134              pntcen3(NbrSol) = center1;
135              parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen3(NbrSol));
136              WellDone = Standard_True;
137            }
138            else { WellDone = Standard_True; }
139          }
140          else if ((Abs(R1+dist-R2-Radius)<Tol)||(Abs(Radius-R1-dist-R2)<Tol)) {
141            dir1on(1) = gp_Dir2d(c1x-onx,c1y-ony);
142            if (Abs(R1+dist-R2-Radius) < Tol) { sign = 1; }
143            else { sign = -1; }
144          }
145          else {
146            nparal = 1;
147            disparal[0] = Abs(R1-Radius);
148          }
149        }
150      }
151      else if (Qualified1.IsOutside()) {
152 //   ================================
153        if ((dist-R2-R1-Radius>Tol)||(Radius-dist-R2+R1>Tol)) { 
154          WellDone=Standard_True;
155        }
156        else {
157          dir1on(1) = gp_Dir2d(c1x-onx,c1y-ony);
158          if (Abs(R1-dist-R2+Radius) < Tol) {
159            sign = -1;
160          }
161          else if (Abs(dist-R1-R2-Radius) < Tol) { sign = 1; }
162          else {
163            nparal = 1;
164            disparal[0] = Abs(R1+Radius);
165          }
166        }
167      }
168      else {
169        if ((dist-R2-R1-Radius>Tol)||(Radius-dist-R1-R2>Tol)) { 
170          WellDone=Standard_True;
171        }
172        else if ((R1-dist-R2>Tol)&&(Tol<R1-R2-dist-Radius)) {
173          WellDone = Standard_True;
174        }
175        else {
176          dir1on(1) = gp_Dir2d(c1x-onx,c1y-ony);
177          if (Abs(dist-R1-R2-Radius) < Tol) {
178            sign = 1;
179          }
180          else if (dist+R1+R2-Radius < 0.0) { sign = -1; }
181          else if ((R1-dist+R2>0.0) && (R1-R2-dist-Radius>0.0)) { sign = -1; }
182          else {
183            nparal = 2;
184            disparal[0] = Abs(R1+Radius);
185            disparal[1] = Abs(R1-Radius);
186          }
187        }
188      }
189      for (Standard_Integer jj = 0 ; jj < nparal ; jj++) {
190        IntAna2d_AnaIntersection Intp(OnCirc,
191                      gp_Circ2d(gp_Ax2d(center1,dirx),disparal[jj]));
192        if (Intp.IsDone()) {
193          if (!Intp.IsEmpty()) {
194            for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
195              NbrSol++;
196              Center(NbrSol) = gp_Pnt2d(Intp.Point(i).Value());
197              cirsol(NbrSol)=gp_Circ2d(gp_Ax2d(Center(NbrSol),dirx),Radius);
198 //           =============================================================
199              Standard_Real distcc1 = Center(NbrSol).Distance(center1);
200              if (!Qualified1.IsUnqualified()) { 
201                qualifier1(NbrSol) = Qualified1.Qualifier();
202              }
203              else if (Abs(distcc1+Radius-R1) < Tol) {
204                qualifier1(NbrSol) = GccEnt_enclosed;
205              }
206              else if (Abs(distcc1-R1-Radius) < Tol) {
207                qualifier1(NbrSol) = GccEnt_outside;
208              }
209              else { qualifier1(NbrSol) = GccEnt_enclosing; }
210              dir1on(NbrSol) = gp_Dir2d(c1x-Center(NbrSol).X(),
211                                        c1y-Center(NbrSol).Y());
212              if ((R1>Radius) && (Center(NbrSol).Distance (center1)<=R1)){
213                signe[NbrSol-1] = -1;
214              }
215              else {
216                signe[NbrSol-1] = 1;
217              }
218            }
219          }
220          WellDone = Standard_True;
221        }
222      }
223      if (sign != 0) {
224        Center(1) = gp_Pnt2d(OnCirc.Location().XY()+sign*R2*dir1on(1).XY());
225        cirsol(1) = gp_Circ2d(gp_Ax2d(Center(1),dirx),Radius); 
226 //     =====================================================
227        Standard_Real distcc1 = Center(1).Distance(center1);
228        if (!Qualified1.IsUnqualified()) { 
229          qualifier1(NbrSol) = Qualified1.Qualifier();
230        }
231        else if (Abs(distcc1+Radius-R1) < Tol) {
232          qualifier1(NbrSol) = GccEnt_enclosed;
233        }
234        else if (Abs(distcc1-R1-Radius) < Tol) {
235          qualifier1(NbrSol) = GccEnt_outside;
236        }
237        else { qualifier1(NbrSol) = GccEnt_enclosing; }
238        NbrSol = 1;
239        signe[NbrSol-1] = 1;
240        WellDone = Standard_True;
241      }
242      Standard_Integer ii = 0;
243      while (signe[ii] != 0) {
244        pnttg1sol(ii+1) = gp_Pnt2d(Center(ii+1).XY()+
245                                   signe[ii]*Radius*dir1on(ii+1).XY());
246        pntcen3(ii+1) = cirsol(ii+1).Location();
247        pararg1(ii+1)=ElCLib::Parameter(C1,pnttg1sol(ii+1));
248        par1sol(ii+1)=ElCLib::Parameter(cirsol(ii+1),pnttg1sol(ii+1));
249        parcen3(ii+1)=ElCLib::Parameter(OnCirc,pntcen3(ii+1));
250        ii++;
251      }
252    }
253  }