0030675: Visualization - remove redundant proxy classes in hierarchy of PrsMgr_Presen...
[occt.git] / src / GccAna / GccAna_Circ2d2TanOn_8.cxx
1 // Created on: 1992-01-02
2 // Created by: Remi GILET
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //=========================================================================
18 //   Creation of a circle tangent to two elements : Straight line.        +
19 //                                                  Circle.               +
20 //                                                  Point.                +
21 //                              center on a third : Straight line.        +
22 //                                                  Circle.               +
23 //=========================================================================
24
25 #include <ElCLib.hxx>
26 #include <GccAna_Circ2d2TanOn.hxx>
27 #include <GccAna_CircPnt2dBisec.hxx>
28 #include <GccEnt_BadQualifier.hxx>
29 #include <GccEnt_QualifiedCirc.hxx>
30 #include <GccEnt_QualifiedLin.hxx>
31 #include <GccInt_BCirc.hxx>
32 #include <GccInt_Bisec.hxx>
33 #include <GccInt_BLine.hxx>
34 #include <GccInt_IType.hxx>
35 #include <gp_Ax2d.hxx>
36 #include <gp_Circ2d.hxx>
37 #include <gp_Dir2d.hxx>
38 #include <gp_Lin2d.hxx>
39 #include <gp_Pnt2d.hxx>
40 #include <IntAna2d_AnaIntersection.hxx>
41 #include <IntAna2d_Conic.hxx>
42 #include <IntAna2d_IntPoint.hxx>
43 #include <Precision.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <Standard_OutOfRange.hxx>
46 #include <StdFail_NotDone.hxx>
47 #include <TColStd_Array1OfReal.hxx>
48
49 GccAna_Circ2d2TanOn::
50    GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1 ,
51                         const gp_Pnt2d&             Point2     ,
52                         const gp_Circ2d&            OnCirc     ,
53                         const Standard_Real         Tolerance  ):
54    cirsol(1,4)     ,
55    qualifier1(1,4) ,
56    qualifier2(1,4),
57    TheSame1(1,4)   ,
58    TheSame2(1,4)   ,
59    pnttg1sol(1,4)  ,
60    pnttg2sol(1,4)  ,
61    pntcen(1,4)     ,
62    par1sol(1,4)    ,
63    par2sol(1,4)    ,
64    pararg1(1,4)    ,
65    pararg2(1,4)    ,
66    parcen3(1,4)    
67 {
68   TheSame1.Init(0);
69   TheSame2.Init(0);
70   WellDone = Standard_False;
71   NbrSol = 0;
72   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
73         Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
74     throw GccEnt_BadQualifier();
75     return;
76   }
77   Standard_Real Tol = Abs(Tolerance);
78   TColStd_Array1OfReal Radius(1,2);
79   gp_Dir2d dirx(1.,0.);
80   gp_Circ2d C1 = Qualified1.Qualified();
81   Standard_Real R1 = C1.Radius();
82   gp_Pnt2d center1(C1.Location());
83
84 //=========================================================================
85 //   Processing of boundary cases.                                          +
86 //=========================================================================
87
88   Standard_Integer nbsol1 = 1;
89 //  Standard_Integer nbsol2 = 0;
90   Standard_Real Ron = OnCirc.Radius();
91   Standard_Real distcco = OnCirc.Location().Distance(center1);
92   gp_Pnt2d pinterm;
93   gp_Dir2d dircc;
94   Standard_Boolean SameCenter(Standard_False);
95   if (!OnCirc.Location().IsEqual(center1,Precision::Confusion())) {
96     dircc = gp_Dir2d(OnCirc.Location().XY()-center1.XY());
97     pinterm = gp_Pnt2d(center1.XY()+(distcco-Ron)*dircc.XY());
98     Standard_Real distcc2 =pinterm.Distance(Point2);
99     Standard_Real distcc1 =pinterm.Distance(center1);
100     Standard_Real d1 = Abs(distcc2-Abs(distcc1-R1));
101     Standard_Real d2 = Abs(distcc2-(distcc1+R1));
102     if ( d1 > Tol || d2 > Tol) {
103       if (!SameCenter) pinterm = gp_Pnt2d(center1.XY()+(distcco+Ron)*dircc.XY());
104       distcc2 =pinterm.Distance(Point2);
105       distcc1 =pinterm.Distance(center1);
106       d1 = Abs(distcc2-Abs(distcc1-R1));
107       d2 = Abs(distcc2-(distcc1+R1));
108       if ( d1 > Tol || d2 > Tol ) { nbsol1 = 0; }
109     }
110     if (nbsol1 > 0) {
111       if (Qualified1.IsEnclosed() || Qualified1.IsOutside()) {
112         nbsol1 = 1;
113         Radius(1) = Abs(distcc1-R1);
114       }
115       else if (Qualified1.IsEnclosing()) {
116         nbsol1 = 1;
117         Radius(1) = R1+distcc1;
118       }
119       else if (Qualified1.IsUnqualified()) {
120         nbsol1 = 2;
121         Radius(1) = Abs(distcc1-R1);
122         Radius(2) = R1+distcc1;
123       }
124       for (Standard_Integer i = 1 ; i <= nbsol1 ; i++) {
125         WellDone = Standard_True;
126         if (!(i == 1 && SameCenter)) {
127           NbrSol++;
128           cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),Radius(i));
129 //    ===========================================================
130           gp_Dir2d dc1;
131           if (!SameCenter) dc1 = gp_Dir2d(center1.XY()-pinterm.XY());
132           if (!Qualified1.IsUnqualified()) { 
133             qualifier1(NbrSol) = Qualified1.Qualifier();
134           }
135           else if (Abs(distcc1+Radius(i)-R1) < Tol) {
136             qualifier1(NbrSol) = GccEnt_enclosed;
137           }
138           else if (Abs(distcc1-R1-Radius(i)) < Tol) {
139             qualifier1(NbrSol) = GccEnt_outside;
140           }
141           else { qualifier1(NbrSol) = GccEnt_enclosing; }
142           qualifier2(NbrSol) = GccEnt_noqualifier;
143           if (!SameCenter) 
144             pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+Radius(i)*dc1.XY());
145           else
146             pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY());
147           pnttg2sol(NbrSol) = Point2;
148           pntcen(NbrSol) = cirsol(NbrSol).Location();
149           par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol));
150           pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
151           par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol));
152           pararg2(NbrSol) = 0.;
153           parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol));
154         }
155       }
156       if (WellDone) { return; }
157     }
158   }
159   
160 //=========================================================================
161 //   General case.                                                         +
162 //=========================================================================
163
164   GccAna_CircPnt2dBisec Bis(C1,Point2);
165   if (Bis.IsDone()) {
166     Standard_Integer nbsolution = Bis.NbSolutions();
167     for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
168
169       Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
170       GccInt_IType type = Sol->ArcType();
171       IntAna2d_AnaIntersection Intp;
172       if (type == GccInt_Lin) {
173         Intp.Perform(Sol->Line(),OnCirc);
174       }
175       else if (type == GccInt_Cir) {
176         Intp.Perform(OnCirc,Sol->Circle());
177       }
178       else if (type == GccInt_Hpr) {
179         Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Hyperbola()));
180       }
181       else if (type == GccInt_Ell) {
182         Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Ellipse()));
183       }
184       if (Intp.IsDone()) {
185         if ((!Intp.IsEmpty())&&(!Intp.ParallelElements())&&
186             (!Intp.IdenticalElements())) {
187           for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
188             gp_Pnt2d Center(Intp.Point(j).Value());
189             Standard_Real dist1 = center1.Distance(Center);
190             Standard_Integer nbsol = 1;
191             Standard_Boolean ok = Standard_False;
192             if (Qualified1.IsEnclosed()) {
193               if (dist1-C1.Radius() <= Tol) {
194                 ok = Standard_True;
195                 Radius(1) = Abs(C1.Radius()-dist1);
196               }
197             }
198             else if (Qualified1.IsOutside()) {
199               if (C1.Radius()-dist1 <= Tol) {
200                 ok = Standard_True;
201                 Radius(1) = Abs(C1.Radius()-dist1);
202               }
203             }
204             else if (Qualified1.IsEnclosing()) {
205               ok = Standard_True;
206               Radius(1) = C1.Radius()+dist1;
207             }
208             else if (Qualified1.IsUnqualified()) {
209               ok = Standard_True;
210               nbsol = 2;
211               Radius(1) = Abs(C1.Radius()-dist1);
212               Radius(2) = C1.Radius()+dist1;
213             }
214             if (ok) {
215               for (Standard_Integer k = 1 ; k <= nbsol ; k++) {
216                 
217                 // pop : protection against case center1 == Center
218                 if (center1.IsEqual(Center,Precision::Confusion())) {
219                   continue;
220                 }                 
221                 if (OnCirc.Distance(Center)>Tol) {
222                   continue;
223                 }
224                 if (NbrSol == 4 ) break;
225                 NbrSol++;
226                 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k));
227 //              ==========================================================
228                 Standard_Real distcc1 = Center.Distance(center1);
229                 if (!Qualified1.IsUnqualified()) { 
230                   qualifier1(NbrSol) = Qualified1.Qualifier();
231                 }
232                 else if (Abs(distcc1+Radius(k)-R1) < Tol) {
233                   qualifier1(NbrSol) = GccEnt_enclosed;
234                 }
235                 else if (Abs(distcc1-R1-Radius(k)) < Tol) {
236                   qualifier1(NbrSol) = GccEnt_outside;
237                 }
238                 else { qualifier1(NbrSol) = GccEnt_enclosing; }
239                 qualifier2(NbrSol) = GccEnt_noqualifier;
240                 if (distcc1 <= Tol && Abs(Radius(k)-C1.Radius()) <= Tol) {
241                   TheSame1(NbrSol) = 1;
242                 }
243                 else {
244                   TheSame1(NbrSol) = 0;
245                   gp_Dir2d dc1(center1.XY()-Center.XY());
246                   pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+
247                                                Radius(k)*dc1.XY());
248                   par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
249                                                     pnttg1sol(NbrSol));
250                   pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
251                 }
252                 TheSame2(NbrSol) = 0;
253                 pntcen(NbrSol) = Center;
254                 pnttg2sol(NbrSol) = Point2;
255                 pararg2(NbrSol) = 0.;
256                 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
257                                                   pnttg2sol(NbrSol));
258                 parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol));
259               }
260             }
261           }
262         }
263         WellDone = Standard_True;
264       }
265     }
266   }
267 }