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