ca2d35a265f494c650a775d0206089d3f531fcb9
[occt.git] / src / GccAna / GccAna_Circ2d2TanOn_6.cxx
1 // File:        GccAna_Circ2d2TanOn_6.cxx
2 // Created:     Thu Jan  2 15:56:04 1992
3 // Author:      Remi GILET
4 //              <reg@topsn3>
5
6 #include <GccAna_Circ2d2TanOn.jxx>
7
8 #include <ElCLib.hxx>
9 #include <gp_Dir2d.hxx>
10 #include <gp_Ax2d.hxx>
11 #include <IntAna2d_AnaIntersection.hxx>
12 #include <IntAna2d_IntPoint.hxx>
13 #include <GccAna_Circ2dBisec.hxx>
14 #include <GccInt_IType.hxx>
15 #include <GccInt_BCirc.hxx>
16 #include <GccInt_BLine.hxx>
17 #include <IntAna2d_Conic.hxx>
18 #include <TColStd_Array1OfReal.hxx>
19 #include <GccEnt_BadQualifier.hxx>
20
21 //=========================================================================
22 //   Creation of a circle tangent to two circles C1 and C2.               +
23 //                        centered on a circle.                           +
24 //  We start with distinguishing various boundary cases that will be      +
25 //  processed separately.                                            +
26 //  In the general case:                                                  +
27 //  ====================                                                  +
28 //  We calculate bissectrices to C1 and C2 that give us all           +
29 //  possible locations of centers of all circles tangent to C1 and C2.                                                   +
30 //  We intersect these bissectrices with circle OnCirc which gives us   +
31 //  points among which we choose the solutions.   +
32 //  The choice is made basing in Qualifiers of C1 and C2.  +
33 //=========================================================================
34
35 GccAna_Circ2d2TanOn::
36    GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1 ,
37                         const GccEnt_QualifiedCirc& Qualified2 ,
38                         const gp_Circ2d&            OnCirc     ,
39                         const Standard_Real         Tolerance  ):
40    cirsol(1,8)     ,
41    qualifier1(1,8) ,
42    qualifier2(1,8) ,
43    TheSame1(1,8) ,
44    TheSame2(1,8) ,
45    pnttg1sol(1,8)  ,
46    pnttg2sol(1,8)  ,
47    pntcen(1,8)     ,
48    par1sol(1,8)    ,
49    par2sol(1,8)    ,
50    pararg1(1,8)    ,
51    pararg2(1,8)    ,
52    parcen3(1,8)    
53 {
54   TheSame1.Init(0);
55   TheSame2.Init(0);
56   WellDone = Standard_False;
57   NbrSol = 0;
58   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
59         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
60       !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
61         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
62     GccEnt_BadQualifier::Raise();
63     return;
64   }
65   Standard_Real Tol= Abs(Tolerance);
66   gp_Circ2d C1 = Qualified1.Qualified();
67   gp_Circ2d C2 = Qualified2.Qualified();
68   gp_Dir2d dirx(1.,0.);
69   TColStd_Array1OfReal Radius(1,2);
70   TColStd_Array1OfReal Rradius(1,2);
71   gp_Pnt2d center1(C1.Location());
72   gp_Pnt2d center2(C2.Location());
73 #ifdef DEB
74   Standard_Real distance = center1.Distance(center2);
75 #else
76   center1.Distance(center2);
77 #endif
78   Standard_Real R1 = C1.Radius();
79   Standard_Real R2 = C2.Radius();
80
81 //=========================================================================
82 //   Processing of boundary cases.                                          +
83 //=========================================================================
84
85   Standard_Integer nbsol1 = 1;
86   Standard_Integer nbsol2 = 0;
87   Standard_Real Ron = OnCirc.Radius();
88   Standard_Real distcco = OnCirc.Location().Distance(center1);
89   gp_Dir2d dircc(OnCirc.Location().XY()-center1.XY());
90   gp_Pnt2d pinterm(center1.XY()+(distcco-Ron)*dircc.XY());
91   Standard_Real distcc2 =pinterm.Distance(center2);
92   Standard_Real distcc1 =pinterm.Distance(center1);
93   Standard_Real d1 = Abs(distcc2-R2-Abs(distcc1-R1));
94   Standard_Real d2 = Abs(distcc2+R2-Abs(distcc1-R1));
95   Standard_Real d3 = Abs(distcc2-R2-(distcc1+R1));
96   Standard_Real d4 = Abs(distcc2+R2-(distcc1+R1));
97   if ( d1 > Tol || d2 > Tol || d3 > Tol || d4 > Tol) {
98     pinterm = gp_Pnt2d(center1.XY()+(distcco+Ron)*dircc.XY());
99     distcc2 =pinterm.Distance(center2);
100     distcc1 =pinterm.Distance(center1);
101     d1 = Abs(distcc2-R2-Abs(distcc1-R1));
102     d2 = Abs(distcc2+R2-Abs(distcc1-R1));
103     d3 = Abs(distcc2-R2-(distcc1+R1));
104     d4 = Abs(distcc2+R2-(distcc1+R1));
105     if ( d1 > Tol || d2 > Tol || d3 > Tol || d4 > Tol) { nbsol1 = 0; }
106   }
107   if (nbsol1 > 0) {
108     if (Qualified1.IsEnclosed() || Qualified1.IsOutside()) {
109       nbsol1 = 1;
110       Radius(1) = Abs(distcc1-R1);
111     }
112     else if (Qualified1.IsEnclosing()) {
113       nbsol1 = 1;
114       Radius(1) = R1+distcc1;
115     }
116     else if (Qualified1.IsUnqualified()) {
117       nbsol1 = 2;
118       Radius(1) = Abs(distcc1-R1);
119       Radius(2) = R1+distcc1;
120     }
121     if (Qualified2.IsEnclosed() || Qualified2.IsOutside()) {
122       nbsol2 = 1;
123       Rradius(1) = Abs(distcc2-R2);
124     }
125     else if (Qualified2.IsEnclosing()) {
126       nbsol2 = 1;
127       Rradius(1) = R2+distcc2;
128     }
129     else if (Qualified2.IsUnqualified()) {
130       nbsol2 = 2;
131       Rradius(1) = Abs(distcc2-R2);
132       Rradius(2) = R2+distcc2;
133     }
134     for (Standard_Integer i = 1 ; i <= nbsol1 ; i++) {
135       for (Standard_Integer j = 1 ; j <= nbsol2 ; j++) {
136         if (Abs(Radius(i)-Rradius(j)) <= Tol) {
137           WellDone = Standard_True;
138           NbrSol++;
139           cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),Radius(i));
140 //        ===========================================================
141           gp_Dir2d dc1(center1.XY()-pinterm.XY());
142           gp_Dir2d dc2(center2.XY()-pinterm.XY());
143           distcc1 = pinterm.Distance(center1);
144           distcc2 = pinterm.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           pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+Radius(i)*dc1.XY());
166           pnttg2sol(NbrSol) = gp_Pnt2d(pinterm.XY()+Radius(i)*dc2.XY());
167           pntcen(NbrSol) = cirsol(NbrSol).Location();
168           par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol));
169           pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
170           par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol));
171           pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
172           parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol));
173         }
174       }
175     }
176     if (WellDone) { return; }
177   }
178   
179 //=========================================================================
180 //   General case.                                                         +
181 //=========================================================================
182
183   GccAna_Circ2dBisec Bis(C1,C2);
184   if (Bis.IsDone()) {
185     TColStd_Array1OfReal Rbid(1,2);
186     TColStd_Array1OfReal RBid(1,2);
187     Standard_Integer nbsolution = Bis.NbSolutions();
188     for (Standard_Integer i = 1 ; i <=  nbsolution ; i++) {
189       Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
190       GccInt_IType typ = Sol->ArcType();
191       IntAna2d_AnaIntersection Intp;
192       if (typ == GccInt_Cir) {
193         Intp.Perform(OnCirc,Sol->Circle());
194       }
195       else if (typ == GccInt_Lin) {
196         Intp.Perform(Sol->Line(),OnCirc);
197       }
198       else if (typ == GccInt_Hpr) {
199         Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Hyperbola()));
200       }
201       else if (typ == GccInt_Ell) {
202         Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Ellipse()));
203       }
204       if (Intp.IsDone()) {
205         if ((!Intp.IsEmpty())&&(!Intp.ParallelElements())&&
206             (!Intp.IdenticalElements())) {
207           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
208             gp_Pnt2d Center(Intp.Point(j).Value());
209             Standard_Real dist1 = Center.Distance(center1);
210             Standard_Real dist2 = Center.Distance(center2);
211             Standard_Integer nbsol = 0;
212             Standard_Integer nsol = 0;
213             Standard_Integer nnsol = 0;
214             R1 = C1.Radius();
215             R2 = C2.Radius();
216             if (Qualified1.IsEnclosed()) {
217               if (dist1-R1 < Tol) { 
218                 nbsol = 1;
219                 Rbid(1) = Abs(R1-dist1);
220               }
221             }
222             else if (Qualified1.IsOutside()) {
223               if (R1-dist1 < Tol) { 
224                 nbsol = 1;
225                 Rbid(1) = Abs(dist1-R1);
226               }
227             }
228             else if (Qualified1.IsEnclosing()) {
229               nbsol = 1;
230               Rbid(1) = dist1+R1;
231             }
232             else if (Qualified1.IsUnqualified()) {
233               nbsol = 2;
234               Rbid(1) = dist1+R1;
235               Rbid(1) = Abs(dist1-R1);
236             }
237             if (Qualified2.IsEnclosed() && nbsol != 0) {
238               if (dist2-R2 < Tol) {
239                 nsol = 1;
240                 RBid(1) = Abs(R2-dist2);
241               }
242             }
243             else if (Qualified2.IsOutside() && nbsol != 0) {
244               if (R2-dist2 < Tol) {
245                 nsol = 1;
246                 RBid(1) = Abs(R2-dist2);
247               }
248             }
249             else if (Qualified2.IsEnclosing() && nbsol != 0) {
250               nsol = 1;
251               RBid(1) = dist2+R2;
252             }
253             else if (Qualified2.IsUnqualified() && nbsol != 0) {
254               nsol = 2;
255               RBid(1) = dist2+R2;
256               RBid(2) = Abs(R2-dist2);
257             }
258             for (Standard_Integer isol = 1; isol <= nbsol ; isol++) {
259               for (Standard_Integer jsol = 1; jsol <= nsol ; jsol++) {
260                 if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) {
261                   nnsol++;
262                   Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.;
263                 }
264               }
265             }
266             if (nnsol > 0) {
267               for (Standard_Integer k = 1 ; k <= nnsol ; k++) {
268                 NbrSol++;
269                 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k));
270 //              ==========================================================
271                 distcc1 = Center.Distance(center1);
272                 distcc2 = Center.Distance(center2);
273                 if (!Qualified1.IsUnqualified()) { 
274                   qualifier1(NbrSol) = Qualified1.Qualifier();
275                 }
276                 else if (Abs(distcc1+Radius(k)-R1) < Tol) {
277                   qualifier1(NbrSol) = GccEnt_enclosed;
278                 }
279                 else if (Abs(distcc1-R1-Radius(k)) < Tol) {
280                   qualifier1(NbrSol) = GccEnt_outside;
281                 }
282                 else { qualifier1(NbrSol) = GccEnt_enclosing; }
283                 if (!Qualified2.IsUnqualified()) { 
284                   qualifier2(NbrSol) = Qualified2.Qualifier();
285                 }
286                 else if (Abs(distcc2+Radius(k)-R2) < Tol) {
287                   qualifier2(NbrSol) = GccEnt_enclosed;
288                 }
289                 else if (Abs(distcc2-R2-Radius(k)) < Tol) {
290                   qualifier2(NbrSol) = GccEnt_outside;
291                 }
292                 else { qualifier2(NbrSol) = GccEnt_enclosing; }
293                 if (Center.Distance(center1) <= Tolerance &&
294                     Abs(Radius(k)-C1.Radius()) <= Tolerance) {
295                   TheSame1(NbrSol) = 1;
296                 }
297                 else {
298                   TheSame1(NbrSol) = 0;
299                   gp_Dir2d dc1(center1.XY()-Center.XY());
300                   pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc1.XY());
301                   par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
302                                                     pnttg1sol(NbrSol));
303                   pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
304                 }
305                 if (Center.Distance(center2) <= Tolerance &&
306                     Abs(Radius(k)-C2.Radius()) <= Tolerance) {
307                   TheSame2(NbrSol) = 1;
308                 }
309                 else {
310                   TheSame2(NbrSol) = 0;
311                   gp_Dir2d dc2(center2.XY()-Center.XY());
312                   pnttg2sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc2.XY());
313                   par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
314                                                     pnttg2sol(NbrSol));
315                   pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
316                 }
317                 pntcen(NbrSol) = Center;
318                 parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol));
319               }
320             }
321           }
322         }
323         WellDone = Standard_True;
324       }
325     }
326   }
327 }
328