0024510: Remove unused local variables
[occt.git] / src / GccAna / GccAna_Circ2dTanOnRad.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
7 // under the terms of the GNU Lesser General Public 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 // PRO12736 : bug quand OnLine // Ox, JCT 20/03/98
16
17 //========================================================================
18 //       circular tangent to element of type :      - Circle.            +
19 //                                                  - Line.             +
20 //                                                  - Point.             +
21 //              center on second element of type :  - Circle.  +
22 //                                                  - Line.   +
23 //              of given radius : Radius.                             +
24 //========================================================================
25
26 #include <GccAna_Circ2dTanOnRad.ixx>
27
28 #include <ElCLib.hxx>
29 #include <math_DirectPolynomialRoots.hxx>
30 #include <TColStd_Array1OfReal.hxx>
31 #include <Standard_NegativeValue.hxx>
32 #include <gp_Dir2d.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
35 #include <GccEnt_BadQualifier.hxx>
36
37 typedef math_DirectPolynomialRoots Roots;
38
39 //=========================================================================
40 //  Circle tangent  :  to circle Qualified1 (C1).                         +
41 //         center   :  on straight line OnLine.                           +
42 //         of radius :  Radius.                                           +
43 //                                                                        + 
44 //  Initialise the table of solutions cirsol and all fields.              +
45 //  Eliminate depending on the qualifier the cases not being solutions.   +
46 //  Solve the equation of the second degree indicating that the found center +
47 //  point (xc,yc) is at a distance Radius from circle C1 and              +
48 //                     on straight line OnLine.                           +
49 //  The solutions aret represented by circles :                           +
50 //                   - with center Pntcen(xc,yc)                          +
51 //                   - with radius Radius.                                +
52 //=========================================================================
53
54 GccAna_Circ2dTanOnRad::
55    GccAna_Circ2dTanOnRad (const GccEnt_QualifiedCirc& Qualified1,
56                           const gp_Lin2d&             OnLine    ,
57                           const Standard_Real         Radius    ,
58                           const Standard_Real         Tolerance ) :
59    cirsol(1,4)     ,
60    qualifier1(1,4) ,
61    TheSame1(1,4)   ,
62    pnttg1sol(1,4)  ,
63    pntcen3(1,4)    ,
64    par1sol(1,4)    ,
65    pararg1(1,4)    ,
66    parcen3(1,4)    
67 {
68
69    TheSame1.Init(0);
70    gp_Dir2d dirx(1.0,0.0);
71    Standard_Real Tol = Abs(Tolerance);
72    WellDone = Standard_False;
73    NbrSol = 0;
74    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
75          Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
76      GccEnt_BadQualifier::Raise();
77      return;
78    }
79    TColStd_Array1OfReal Coef(1,2);
80    gp_Circ2d C1 = Qualified1.Qualified();
81
82    if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
83    else {
84      Standard_Integer nbsol = 0;
85      Standard_Integer signe = 0;
86      gp_Pnt2d Center;
87      Standard_Real xc;
88      Standard_Real yc;
89      Standard_Real R1 = C1.Radius();
90      Standard_Real dist = OnLine.Distance(C1.Location());
91      Standard_Real xdir = (OnLine.Direction()).X();
92      Standard_Real ydir = (OnLine.Direction()).Y();
93      Standard_Real lxloc = (OnLine.Location()).X();
94      Standard_Real lyloc = (OnLine.Location()).Y();
95      gp_Pnt2d center1(C1.Location());
96      Standard_Real x1 = center1.X();
97      Standard_Real y1 = center1.Y();
98      if (Qualified1.IsEnclosed()) {
99 //   ============================
100        if (Tol < Radius-R1+dist) { WellDone = Standard_True; }
101        else {
102          if (Abs(Radius-R1+dist) < Tol) {
103            WellDone = Standard_True;
104            NbrSol = 1;
105            if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
106              Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
107            }
108            else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
109            signe = 1;
110          }
111          else {
112            Coef(1) = (R1-Radius)*(R1-Radius);
113            nbsol = 1;
114          }
115        }
116      }
117      else if (Qualified1.IsEnclosing()) {
118 //   ==================================
119        if (R1+dist-Radius > Tol) { WellDone = Standard_True; }
120        else {
121          if (R1+dist-Radius > 0.0) {
122            WellDone = Standard_True;
123            NbrSol = 1;
124            if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
125              Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
126            }
127            else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
128            signe = -1;
129          }
130          else {
131            Coef(1) = (Radius-R1)*(Radius-R1);
132            nbsol = 1;
133          }
134        }
135      }
136      else {
137 //   ====
138        if (dist-R1-Radius > Tol) { WellDone = Standard_False; }
139        else {
140          if (Abs(dist-R1-Radius) < Tol) {
141            WellDone = Standard_True;
142            NbrSol = 1;
143            if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
144              Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
145            }
146            else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
147            signe = -1;
148          }
149          else {
150            if (Qualified1.IsOutside()) {
151 //         ===========================
152              Coef(1) = (Radius+R1)*(Radius+R1);
153              nbsol = 1;
154            }
155            else {
156 //         ====
157              Coef(1) = (Radius-R1)*(Radius-R1);
158              Coef(2) = (Radius+R1)*(Radius+R1);
159              nbsol = 2;
160            }
161          }
162        }
163      }
164      if (signe != 0) {
165        cirsol(1) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
166 //     ==================================================
167        Standard_Real distcc1 = Center.Distance(center1);
168        if (!Qualified1.IsUnqualified()) { 
169          qualifier1(1) = Qualified1.Qualifier();
170        }
171        else if (Abs(distcc1+Radius-R1) < Tol) {
172          qualifier1(1) = GccEnt_enclosed;
173        }
174        else if (Abs(distcc1-R1-Radius) < Tol) {
175          qualifier1(1) = GccEnt_outside;
176        }
177        else { qualifier1(1) = GccEnt_enclosing; }
178        if (Abs(Radius-R1) <= Tol) { TheSame1(1) = 1; }
179        else {
180          gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
181          pnttg1sol(1) = gp_Pnt2d(Center.XY()+signe*Radius*dir1cen.XY());
182          par1sol(1)=ElCLib::Parameter(cirsol(1),pnttg1sol(1));
183          pararg1(1)=ElCLib::Parameter(C1,pnttg1sol(1));
184        }
185        pntcen3(1) = cirsol(NbrSol).Location();
186        parcen3(1)=ElCLib::Parameter(OnLine,pntcen3(1));
187      }
188      else if (nbsol > 0) {
189        for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
190          Standard_Real A,B,C;
191          OnLine.Coefficients(A,B,C);
192          Standard_Real D = A;
193          Standard_Real x0,y0;
194          if ( Abs(D) <= Tol ) {
195            A = B;
196            B = D;
197            x0 = y1;
198            y0 = x1;
199          }
200          else{
201            x0 = x1;
202            y0 = y1;
203          }
204          Roots Sol((B*B+A*A)/(A*A),
205                    2.0*(B*C/(A*A)+(B/A)*x0-y0),
206                    x0*x0+y0*y0+C*C/(A*A)-Coef(j)+2.0*C*x0/A);
207          if (Sol.IsDone()) {
208            for (Standard_Integer i = 1 ; i <= Sol.NbSolutions() ; i++) {
209
210              if ( Abs(D) > Tol ) {
211                yc = Sol.Value(i);
212                xc = -(B/A)*yc-C/A;
213              }
214              else {
215                xc = Sol.Value(i);
216                yc = -(B/A)*xc-C/A;
217              }
218              Center = gp_Pnt2d(xc,yc);
219              if (OnLine.Distance(Center)>Tol)
220                continue;
221              NbrSol++;
222              cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
223 //           =======================================================
224              Standard_Real distcc1 = Center.Distance(center1);
225              if (!Qualified1.IsUnqualified()) { 
226                qualifier1(NbrSol) = Qualified1.Qualifier();
227              }
228              else if (Abs(distcc1+Radius-R1) < Tol) {
229                qualifier1(NbrSol) = GccEnt_enclosed;
230              }
231              else if (Abs(distcc1-R1-Radius) < Tol) {
232                qualifier1(NbrSol) = GccEnt_outside;
233              }
234              else { qualifier1(NbrSol) = GccEnt_enclosing; }
235              gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
236              if ((Radius > R1) || (Center.Distance(center1) > R1)) {
237                pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1cen.XY());
238              }
239              else {
240                pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1cen.XY());
241              }
242              pntcen3(NbrSol) = cirsol(NbrSol).Location();
243              par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
244                                               pnttg1sol(NbrSol));
245              pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
246              parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen3(NbrSol));
247            }
248            WellDone = Standard_True;
249          }
250        }
251      }
252    }
253  }
254
255 Standard_Boolean GccAna_Circ2dTanOnRad::
256    IsDone () const { return WellDone; }
257
258 Standard_Integer GccAna_Circ2dTanOnRad::
259    NbSolutions () const { return NbrSol; }
260
261 gp_Circ2d GccAna_Circ2dTanOnRad::ThisSolution (const Standard_Integer Index) const 
262 {
263   if (Index > NbrSol || Index <= 0) {
264     Standard_OutOfRange::Raise();
265   }
266   return cirsol(Index);
267 }
268
269 void GccAna_Circ2dTanOnRad::
270   WhichQualifier(const Standard_Integer Index   ,
271                        GccEnt_Position& Qualif1 ) const
272 {
273   if (!WellDone) { StdFail_NotDone::Raise(); }
274    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
275    else {
276      Qualif1 = qualifier1(Index);
277    }
278 }
279
280 void GccAna_Circ2dTanOnRad::
281    Tangency1 (const Standard_Integer Index,
282               Standard_Real& ParSol,
283               Standard_Real& ParArg,
284               gp_Pnt2d& PntSol) const{
285    if (!WellDone) {
286      StdFail_NotDone::Raise();
287    }
288    else if (Index <= 0 ||Index > NbrSol) {
289      Standard_OutOfRange::Raise();
290    }
291    else {
292      ParSol = par1sol(Index);
293      ParArg = pararg1(Index);
294      PntSol = gp_Pnt2d(pnttg1sol(Index));
295    }
296  }
297
298
299 void GccAna_Circ2dTanOnRad::
300    CenterOn3 (const Standard_Integer Index,
301               Standard_Real& ParArg,
302               gp_Pnt2d& PntSol) const{
303    if (!WellDone) {
304      StdFail_NotDone::Raise();
305    }
306    else if (Index <= 0 ||Index > NbrSol) {
307      Standard_OutOfRange::Raise();
308    }
309    else {
310      ParArg = parcen3(Index);
311      PntSol = pnttg1sol(Index);
312    }
313  }
314
315 Standard_Boolean GccAna_Circ2dTanOnRad::IsTheSame1 (const Standard_Integer Index) const
316 {
317   if (!WellDone)
318     StdFail_NotDone::Raise();
319   
320   if (Index <= 0 ||Index > NbrSol)
321     Standard_OutOfRange::Raise();
322   
323   if (TheSame1(Index) == 0)
324     return Standard_False;
325   
326   return Standard_True;
327 }