0024510: Remove unused local variables
[occt.git] / src / GccAna / GccAna_Circ2d2TanOn.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 #include <GccAna_Circ2d2TanOn.ixx>
16
17 #include <TColStd_Array1OfReal.hxx>
18 #include <TColStd_SequenceOfReal.hxx>
19 #include <IntAna2d_AnaIntersection.hxx>
20 #include <IntAna2d_IntPoint.hxx>
21 #include <Standard_OutOfRange.hxx>
22 #include <ElCLib.hxx>
23 #include <gp_Dir2d.hxx>
24 #include <gp_Ax2d.hxx>
25 #include <GccInt_IType.hxx>
26 #include <GccInt_BCirc.hxx>
27 #include <GccInt_BLine.hxx>
28 #include <IntAna2d_Conic.hxx>
29 #include <StdFail_NotDone.hxx>
30 #include <GccEnt_BadQualifier.hxx>
31 #include <GccAna_Circ2dBisec.hxx>
32
33 //=========================================================================
34 //  Circles tangent to two circles C1 and C2 and centered on a straight line.   +
35 //  We start by distinguishing various boundary cases that will be processed separately. +
36 //  In the general case:                                                  +
37 //  ====================                                                  +
38 //  We calculate bissectrices to two circles that give us     +
39 //  all possible locations of centers of all circles tangent to C1 and C2.                                                  +
40 //  We intersect these bissectrices with straight line which gives us  +
41 //  points among which we are going to find solutions.   +
42 //  The choices are made basing on Qualifiers of C1 and C2.  +
43 //=========================================================================
44
45 GccAna_Circ2d2TanOn::
46    GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc&  Qualified1 , 
47                         const GccEnt_QualifiedCirc&  Qualified2 , 
48                         const gp_Lin2d&              OnLine     ,
49                         const Standard_Real          Tolerance  ):
50    cirsol(1,4)   ,
51    qualifier1(1,4),
52    qualifier2(1,4) ,
53    TheSame1(1,4) ,
54    TheSame2(1,4) ,
55    pnttg1sol(1,4),
56    pnttg2sol(1,4),
57    pntcen(1,4)   ,
58    par1sol(1,4)  ,
59    par2sol(1,4)  ,
60    pararg1(1,4)  ,
61    pararg2(1,4)  ,
62    parcen3(1,4)  
63 {
64
65   TheSame1.Init(0);
66   TheSame2.Init(0);
67   WellDone = Standard_False;
68   NbrSol = 0;
69   Standard_Integer nbsol = 0;
70   Standard_Real Tol = Abs(Tolerance);
71   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
72         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
73       !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
74         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
75    GccEnt_BadQualifier::Raise();
76      return;
77    }
78   gp_Circ2d C1 = Qualified1.Qualified();
79   gp_Circ2d C2 = Qualified2.Qualified();
80   Standard_Real R1 = C1.Radius();
81   Standard_Real R2 = C2.Radius();
82   gp_Dir2d dirx(1.,0.);
83   gp_Pnt2d center1(C1.Location());
84   gp_Pnt2d center2(C2.Location());
85   TColStd_Array1OfReal Radius(1,2);
86
87   Standard_Real dist1 = OnLine.Distance(center1);
88   Standard_Real dist2 = OnLine.Distance(center2);
89   Standard_Real d1 = dist1+R1;
90   Standard_Real d2 = dist2+R2;
91   Standard_Real d3 = dist1-R1;
92   Standard_Real d4 = dist2-R2;
93
94 //=========================================================================
95 //  Processing of boundary cases.                                           +
96 //=========================================================================
97    
98   if (Abs(d3-d4)<Tol && 
99       (Qualified1.IsEnclosed() || Qualified1.IsOutside() ||
100        Qualified1.IsUnqualified()) && 
101       (Qualified2.IsEnclosed() || Qualified2.IsOutside() ||
102        Qualified2.IsUnqualified())) {
103     nbsol++;
104     Radius(nbsol) = Abs(d3);
105     WellDone = Standard_True;
106   }
107   if (Abs(d1-d2)<Tol &&
108       (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) &&
109       (Qualified2.IsEnclosing() || Qualified2.IsUnqualified())){
110     nbsol++;
111     Radius(nbsol) = Abs(d1);
112     WellDone = Standard_True;
113   }
114   if (Abs(d1-d4)<Tol &&
115       (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) &&
116       (Qualified2.IsEnclosed() || Qualified2.IsOutside() ||
117        Qualified2.IsUnqualified())){
118     nbsol++;
119     Radius(nbsol) = Abs(d1);
120     WellDone = Standard_True;
121   }
122   if (Abs(d3-d2)<Tol &&
123       (Qualified2.IsEnclosing() || Qualified2.IsUnqualified()) &&
124       (Qualified1.IsEnclosed() || Qualified1.IsOutside() ||
125        Qualified1.IsUnqualified())){
126     nbsol++;
127     Radius(nbsol) = Abs(d3);
128     WellDone = Standard_True;
129   }
130   gp_Lin2d L(center1,gp_Dir2d(center2.XY()-center1.XY()));
131   IntAna2d_AnaIntersection Intp(OnLine,L);
132   if (Intp.IsDone()) {
133     if (!Intp.IsEmpty()){
134       for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
135         gp_Pnt2d Center(Intp.Point(j).Value());
136         for (Standard_Integer i = 1 ; i <= nbsol ; i++) {
137           NbrSol++;
138           cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(i));
139 //        ==========================================================
140           WellDone = Standard_True;
141           Standard_Real distcc1 = Center.Distance(center1);
142           Standard_Real distcc2 = Center.Distance(center2);
143           if (!Qualified1.IsUnqualified()) { 
144             qualifier1(NbrSol) = Qualified1.Qualifier();
145           }
146           else if (Abs(distcc1+Radius(i)-R1) < Tol) {
147             qualifier1(NbrSol) = GccEnt_enclosed;
148           }
149           else if (Abs(distcc1-R1-Radius(i)) < Tol) {
150             qualifier1(NbrSol) = GccEnt_outside;
151           }
152           else { qualifier1(NbrSol) = GccEnt_enclosing; }
153           if (!Qualified2.IsUnqualified()) { 
154             qualifier2(NbrSol) = Qualified2.Qualifier();
155           }
156           else if (Abs(distcc2+Radius(i)-R2) < Tol) {
157             qualifier2(NbrSol) = GccEnt_enclosed;
158           }
159           else if (Abs(distcc2-R2-Radius(i)) < Tol) {
160             qualifier2(NbrSol) = GccEnt_outside;
161           }
162           else { qualifier2(NbrSol) = GccEnt_enclosing; }
163           gp_Dir2d dc1(center1.XY()-Center.XY());
164           gp_Dir2d dc2(center2.XY()-Center.XY());
165           pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc1.XY());
166           pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc2.XY());
167           par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
168                                             pnttg1sol(NbrSol));
169           pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
170           par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
171                                             pnttg2sol(NbrSol));
172           pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
173           pntcen(NbrSol) = cirsol(NbrSol).Location();
174           parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
175         }
176       }
177     }
178   }
179   
180 //=========================================================================
181 //   General case.                                                       +
182 //=========================================================================
183
184   if (!WellDone) {
185     GccAna_Circ2dBisec Bis(C1,C2);
186     if (Bis.IsDone()) {
187       TColStd_Array1OfReal Rbid(1,2);
188       TColStd_Array1OfReal RBid(1,2);
189       Standard_Integer nbsolution = Bis.NbSolutions();
190       for (Standard_Integer i = 1 ; i <=  nbsolution ; i++) {
191         Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
192         GccInt_IType typ = Sol->ArcType();
193
194         if (typ == GccInt_Cir) {
195           Intp.Perform(OnLine,Sol->Circle());
196         }
197         else if (typ == GccInt_Lin) {
198           Intp.Perform(OnLine,Sol->Line());
199         }
200         else if (typ == GccInt_Hpr) {
201           Intp.Perform(OnLine,IntAna2d_Conic(Sol->Hyperbola()));
202         }
203         else if (typ == GccInt_Ell) {
204           Intp.Perform(OnLine,IntAna2d_Conic(Sol->Ellipse()));
205         }
206         if (Intp.IsDone()) {
207           if (!Intp.IsEmpty()){
208             for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
209               gp_Pnt2d Center(Intp.Point(j).Value());
210               dist1 = Center.Distance(center1);
211               dist2 = Center.Distance(center2);
212               nbsol = 0;
213               Standard_Integer nsol = 0;
214               Standard_Integer nnsol = 0;
215               R1 = C1.Radius();
216               R2 = C2.Radius();
217               if (Qualified1.IsEnclosed()) {
218                 if (dist1-R1 < Tol) { 
219                   nbsol = 1;
220                   Rbid(1) = Abs(R1-dist1);
221                 }
222               }
223               else if (Qualified1.IsOutside()) {
224                 if (R1-dist1 < Tol) { 
225                   nbsol = 1;
226                   Rbid(1) = Abs(dist1-R1);
227                 }
228               }
229               else if (Qualified1.IsEnclosing()) {
230                 nbsol = 1;
231                 Rbid(1) = dist1+R1;
232               }
233               else if (Qualified1.IsUnqualified()) {
234                 nbsol = 2;
235                 Rbid(1) = dist1+R1;
236                 Rbid(1) = Abs(dist1-R1);
237               }
238               if (Qualified2.IsEnclosed() && nbsol != 0) {
239                 if (dist2-R2 < Tol) {
240                   nsol = 1;
241                   RBid(1) = Abs(R2-dist2);
242                 }
243               }
244               else if (Qualified2.IsOutside() && nbsol != 0) {
245                 if (R2-dist2 < Tol) {
246                   nsol = 1;
247                   RBid(1) = Abs(R2-dist2);
248                 }
249               }
250               else if (Qualified2.IsEnclosing() && nbsol != 0) {
251                 nsol = 1;
252                 RBid(1) = dist2+R2;
253               }
254               else if (Qualified2.IsUnqualified() && nbsol != 0) {
255                 nsol = 2;
256                 RBid(1) = dist2+R2;
257                 RBid(2) = Abs(R2-dist2);
258               }
259               for (Standard_Integer isol = 1; isol <= nbsol ; isol++) {
260                 for (Standard_Integer jsol = 1; jsol <= nsol ; jsol++) {
261                   if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) {
262                     nnsol++;
263                     Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.;
264                   }
265                 }
266               }
267               if (nnsol > 0) {
268                 for (Standard_Integer k = 1 ; k <= nnsol ; k++) {
269                   NbrSol++;
270                   cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k));
271 //                ==========================================================
272                   Standard_Real distcc1 = Center.Distance(center1);
273                   Standard_Real distcc2 = Center.Distance(center2);
274                   if (!Qualified1.IsUnqualified()) { 
275                     qualifier1(NbrSol) = Qualified1.Qualifier();
276                   }
277                   else if (Abs(distcc1+Radius(i)-R1) < Tol) {
278                     qualifier1(NbrSol) = GccEnt_enclosed;
279                   }
280                   else if (Abs(distcc1-R1-Radius(i)) < Tol) {
281                     qualifier1(NbrSol) = GccEnt_outside;
282                   }
283                   else { qualifier1(NbrSol) = GccEnt_enclosing; }
284                   if (!Qualified2.IsUnqualified()) { 
285                     qualifier2(NbrSol) = Qualified2.Qualifier();
286                   }
287                   else if (Abs(distcc2+Radius(i)-R2) < Tol) {
288                     qualifier2(NbrSol) = GccEnt_enclosed;
289                   }
290                   else if (Abs(distcc2-R2-Radius(i)) < Tol) {
291                     qualifier2(NbrSol) = GccEnt_outside;
292                   }
293                   else { qualifier2(NbrSol) = GccEnt_enclosing; }
294                   if (Center.Distance(center1) <= Tol &&
295                       Abs(Radius(k)-C1.Radius()) <= Tol) {TheSame1(NbrSol)=1;}
296                   else {
297                     TheSame1(NbrSol) = 0;
298                     gp_Dir2d dc1(center1.XY()-Center.XY());
299                     pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+
300                                                  Radius(k)*dc1.XY());
301                     par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
302                                                       pnttg1sol(NbrSol));
303                     pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg2sol(NbrSol));
304                   }
305                   if (Center.Distance(center2) <= Tol &&
306                       Abs(Radius(k)-C2.Radius()) <= Tol) {TheSame2(NbrSol)=1;}
307                   else {
308                     TheSame2(NbrSol) = 0;
309                     gp_Dir2d dc2(center2.XY()-Center.XY());
310                     pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+
311                                                  Radius(k)*dc2.XY());
312                     par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
313                                                       pnttg2sol(NbrSol));
314                     pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
315                   }
316                   pntcen(NbrSol) = Center;
317                   parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
318                 }
319               }
320             }
321           }
322           WellDone = Standard_True;
323         }
324       }
325     }
326   }
327 }
328
329 //========================================================================
330
331 Standard_Boolean GccAna_Circ2d2TanOn::
332    IsDone () const{ return WellDone; }
333
334 Standard_Integer GccAna_Circ2d2TanOn::
335    NbSolutions () const{ return NbrSol; }
336
337 gp_Circ2d GccAna_Circ2d2TanOn::
338    ThisSolution (const Standard_Integer Index) const{ return cirsol(Index); }
339
340 void GccAna_Circ2d2TanOn::
341   WhichQualifier(const Standard_Integer Index   ,
342                        GccEnt_Position& Qualif1 ,
343                        GccEnt_Position& Qualif2 ) const
344 {
345   if (!WellDone) { StdFail_NotDone::Raise(); }
346    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
347    else {
348      Qualif1 = qualifier1(Index);
349      Qualif2 = qualifier2(Index);
350    }
351 }
352
353 void GccAna_Circ2d2TanOn:: 
354    Tangency1 (const Standard_Integer    Index  , 
355                     Standard_Real&      ParSol ,
356                     Standard_Real&      ParArg ,
357                     gp_Pnt2d&  PntSol ) const{
358    if (!WellDone) { StdFail_NotDone::Raise(); }
359    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
360    else {
361      if (TheSame1(Index) == 0) {
362        ParSol = par1sol(Index);
363        ParArg = pararg1(Index);
364        PntSol = gp_Pnt2d(pnttg1sol(Index));
365      }
366      else { StdFail_NotDone::Raise(); }
367    }
368  }
369
370 void GccAna_Circ2d2TanOn:: 
371    Tangency2 (const Standard_Integer    Index  , 
372                     Standard_Real&      ParSol ,
373                     Standard_Real&      ParArg ,
374                     gp_Pnt2d&  PntSol ) const{
375    if (!WellDone) { StdFail_NotDone::Raise(); }
376    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
377    else {
378      if (TheSame2(Index) == 0) {
379        ParSol = par2sol(Index);
380        ParArg = pararg2(Index);
381        PntSol = gp_Pnt2d(pnttg2sol(Index));
382      }
383      else { StdFail_NotDone::Raise(); }
384    }
385  }
386
387 void GccAna_Circ2d2TanOn::
388    CenterOn3 (const Standard_Integer    Index  ,
389                     Standard_Real&      ParArg ,
390                     gp_Pnt2d&  PntSol ) const{
391    if (!WellDone) { StdFail_NotDone::Raise(); }
392    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
393    else {
394      ParArg = parcen3(Index);
395      PntSol = pnttg1sol(Index);
396    }
397  }
398  
399 Standard_Boolean GccAna_Circ2d2TanOn::
400    IsTheSame1 (const Standard_Integer Index) const
401 {
402   if (!WellDone) { StdFail_NotDone::Raise(); }
403   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
404
405   if (TheSame1(Index) == 0) { return Standard_False; }
406   return Standard_True;
407 }
408
409 Standard_Boolean GccAna_Circ2d2TanOn::
410    IsTheSame2 (const Standard_Integer Index) const
411 {
412   if (!WellDone) { StdFail_NotDone::Raise(); }
413   else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
414
415   if (TheSame2(Index) == 0) { return Standard_False; }
416   return Standard_True;
417 }