0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / GccAna / GccAna_Circ2d2TanOn_2.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 #include <ElCLib.hxx>
19 #include <GccAna_Circ2d2TanOn.hxx>
20 #include <GccAna_Lin2dBisec.hxx>
21 #include <GccEnt_BadQualifier.hxx>
22 #include <GccEnt_QualifiedCirc.hxx>
23 #include <GccEnt_QualifiedLin.hxx>
24 #include <gp.hxx>
25 #include <gp_Ax2d.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <gp_Dir2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <IntAna2d_AnaIntersection.hxx>
31 #include <IntAna2d_IntPoint.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <StdFail_NotDone.hxx>
34
35 GccAna_Circ2d2TanOn::
36    GccAna_Circ2d2TanOn (const GccEnt_QualifiedLin&  Qualified1 , 
37                         const GccEnt_QualifiedLin&  Qualified2 , 
38                         const gp_Lin2d&             OnLine     ,
39                         const Standard_Real         Tolerance  ):
40    cirsol(1,2)     ,
41    qualifier1(1,2) ,
42    qualifier2(1,2) ,
43    TheSame1(1,2)   ,
44    TheSame2(1,2)   ,
45    pnttg1sol(1,2)  ,
46    pnttg2sol(1,2)  ,
47    pntcen(1,2)     ,
48    par1sol(1,2)    ,
49    par2sol(1,2)    ,
50    pararg1(1,2)    ,
51    pararg2(1,2)    ,
52    parcen3(1,2)
53 {
54   // initialisations
55   TheSame1.Init(0);
56   TheSame2.Init(0);
57   WellDone = Standard_False;
58   NbrSol = 0;
59
60   if (!(Qualified1.IsEnclosed() ||
61         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
62       !(Qualified2.IsEnclosed() ||
63         Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
64   throw GccEnt_BadQualifier();
65     return;
66   }
67
68   gp_Dir2d dirx(1.,0.);
69   Standard_Real Tol = Abs(Tolerance);
70
71   // calculation of bisectrices of L1 and L2
72   gp_Lin2d L1(Qualified1.Qualified());
73   gp_Lin2d L2(Qualified2.Qualified());
74   gp_Pnt2d originL1(L1.Location());
75   gp_Pnt2d originL2(L2.Location());
76   GccAna_Lin2dBisec Bis(L1,L2);
77   
78   if (Bis.IsDone()) {
79     
80     if (Bis.NbSolutions() == 1 || Bis.NbSolutions() == 2) {
81       // if 1 bisectrice, L1 and L2 are parallel
82       // if 2 bisectrices, L1 and L2 are intersected
83
84       for (Standard_Integer k = 1 ; k <= Bis.NbSolutions() ; k++) {
85         IntAna2d_AnaIntersection Intp(Bis.ThisSolution(k),OnLine);
86         if (Intp.IsDone()) {
87           WellDone = Standard_True;
88           // for degenerated cases, no acceptable solution
89           // (OnLine and bisectrice strictly parallel or not)
90           if (!Intp.IdenticalElements() 
91                && !Intp.ParallelElements() 
92                && !Intp.IsEmpty()) {
93             // at maximum 1 point of intersection !
94             for (Standard_Integer l = 1 ; l <= Intp.NbPoints() ; l++) {
95               gp_Pnt2d pt(Intp.Point(l).Value());
96               gp_Ax2d axe(pt,dirx);
97               Standard_Real Radius = L1.Distance(pt);
98               if (!L1.Contains(pt,Tol) && Radius<1.0/Tol && NbrSol<2) {
99                 // acceptable solution : the radius is correct
100                 NbrSol++;
101                 cirsol(NbrSol) = gp_Circ2d(axe,Radius);
102               }
103             }
104           }
105         }
106       }
107
108     }    
109
110   }
111   
112   // parce following the qualifiers NbrSol acceptable solutions
113   
114   for (Standard_Integer i=1 ; i <= NbrSol ; i++) {
115
116     gp_Pnt2d pbid(cirsol(i).Location());
117     Standard_Real Radius = cirsol(i).Radius();
118     Standard_Boolean ok = Standard_False;
119     
120     // solution Outside or Enclosed / L1
121     gp_Dir2d dc1(originL1.XY()-pbid.XY());
122     Standard_Real sign1 = dc1.Dot(gp_Dir2d(-L1.Direction().Y(),
123                                             L1.Direction().X()));
124     if (sign1>0.0) ok = (Qualified1.IsUnqualified() 
125                           || Qualified1.IsOutside());
126     else ok = (Qualified1.IsUnqualified() 
127                 || Qualified1.IsEnclosed());
128
129     // solution Outside or Enclosed / L2
130     gp_Dir2d dc2(originL2.XY()-pbid.XY());
131     Standard_Real sign2 = dc2.Dot(gp_Dir2d(-L2.Direction().Y(),
132                                             L2.Direction().X()));
133     if (sign2>0.0) ok = ok && (Qualified2.IsUnqualified() 
134                                 || Qualified2.IsOutside());
135     else ok = ok &&(Qualified2.IsUnqualified() 
136                      || Qualified2.IsEnclosed());
137
138     if (ok) {
139       // solution to be preserved
140       dc1 = gp_Dir2d(sign1*gp_XY(-L1.Direction().Y(),
141                                   L1.Direction().X()));
142       pnttg1sol(i) = gp_Pnt2d(pbid.XY()+Radius*dc1.XY());
143       if (sign1>0.0) qualifier1(i) = GccEnt_outside;
144       else qualifier1(i) = GccEnt_enclosed;
145       dc2 = gp_Dir2d(sign2*gp_XY(-L2.Direction().Y(),
146                                   L2.Direction().X()));
147       pnttg2sol(i) = gp_Pnt2d(pbid.XY()+Radius*dc2.XY());
148       if (sign2>0.0) qualifier2(i) = GccEnt_outside;
149       else qualifier2(i) = GccEnt_enclosed;
150       pntcen(i) = pbid;
151       par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
152       pararg1(i)=ElCLib::Parameter(L1,pnttg1sol(i));
153       par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
154       pararg2(i)=ElCLib::Parameter(L2,pnttg2sol(i));
155       parcen3(i)=ElCLib::Parameter(OnLine,pntcen(i));
156     }
157     else {
158       // solution to be rejected
159       if (i==NbrSol) NbrSol--;
160       else {
161         for (Standard_Integer k = i+1 ; k <= NbrSol ; k++) {
162           cirsol(k-1) = cirsol(k);
163         }
164         NbrSol--;
165         i--;
166       }
167     }
168
169   }
170
171 }
172