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