0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / GccAna / GccAna_Lin2dTanObl.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 //   CREATION of a STRAIGHT LINE TANGENT to a CIRCLE or PASSING by a POINT +
17 //                and MAKING ANGLE A with a STRAIGHT LINE.                   +
18 //=========================================================================
19
20 #include <ElCLib.hxx>
21 #include <GccAna_Lin2dTanObl.hxx>
22 #include <GccEnt_BadQualifier.hxx>
23 #include <GccEnt_QualifiedCirc.hxx>
24 #include <gp_Circ2d.hxx>
25 #include <gp_Dir2d.hxx>
26 #include <gp_Lin2d.hxx>
27 #include <gp_Pnt2d.hxx>
28 #include <gp_Vec2d.hxx>
29 #include <gp_XY.hxx>
30 #include <IntAna2d_AnaIntersection.hxx>
31 #include <IntAna2d_IntPoint.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <StdFail_NotDone.hxx>
34
35 //=========================================================================
36 //   Creation of a straight line passing by a point : ThePoint                +
37 //                         making an angle     : TheAngle                +
38 //                         with straight line  : TheLine.                +
39 //   Subject the straight line (ThePoint,TheLine.Location()) to a rotation +
40 //   by angle TheAngle ==> D1.                                            +
41 //   create straight line passing through ThePoint of direction D1.              +
42 //=========================================================================
43 GccAna_Lin2dTanObl::
44    GccAna_Lin2dTanObl (const gp_Pnt2d&          ThePoint  ,
45                        const gp_Lin2d&          TheLine   ,
46                        const Standard_Real      TheAngle  ):
47    linsol(1,1)    ,
48    qualifier1(1,1),
49    pnttg1sol(1,1) ,
50    pntint2sol(1,1),
51    par1sol(1,1)   ,
52    par2sol(1,1)   ,
53    pararg1(1,1)   ,
54    pararg2(1,1)   
55 {
56
57    Standard_Real Cosa = TheLine.Direction().X();
58    Standard_Real Sina = TheLine.Direction().Y();
59    linsol(1) = gp_Lin2d(ThePoint,
60 // ==============================
61                         gp_Dir2d(Cosa*Cos(TheAngle)-Sina*Sin(TheAngle),
62 //                      ===============================================
63                                  Sina*Cos(TheAngle)+Sin(TheAngle)*Cosa));
64 //                               =======================================
65    qualifier1(1) = GccEnt_noqualifier;
66    pnttg1sol(1) = ThePoint;
67    IntAna2d_AnaIntersection Intp(linsol(1),TheLine);
68    if (Intp.IsDone()) {
69      if (!Intp.IsEmpty()) {
70        for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
71          pntint2sol(1) = Intp.Point(i).Value();
72        }
73      }
74      par1sol(1)=ElCLib::Parameter(linsol(1),pnttg1sol(1));
75      par2sol(1)=ElCLib::Parameter(linsol(1),pntint2sol(1));
76      pararg1(1)=0.;
77      pararg2(1)=ElCLib::Parameter(TheLine,pntint2sol(1));
78      NbrSol = 1;
79      WellDone = Standard_True;
80    }
81    else { 
82      WellDone = Standard_False; 
83      NbrSol=0;
84    }
85  }
86
87 //=========================================================================
88 //   Creation of a straight line tangent to a circle  : Qualified1 (C1)         +
89 //                         making angle           : TheAngle                +
90 //                         with a straight line   : TheLine.                +
91 //   Subject the straight line  (C1.Location,TheLine.Location()) to a       +
92 //   rotation by angle TheAngle or -TheAngle ==> D1.                       +
93 //   create the straight line passing by C1 of direction D1.                    +
94 //=========================================================================
95
96 GccAna_Lin2dTanObl::
97    GccAna_Lin2dTanObl (const GccEnt_QualifiedCirc& Qualified1 ,
98                        const gp_Lin2d&             TheLine    ,
99                        const Standard_Real         TheAngle   ):
100    linsol(1,2)   ,
101    qualifier1(1,2) ,
102    pnttg1sol(1,2),
103    pntint2sol(1,2),
104    par1sol(1,2),
105    par2sol(1,2),
106    pararg1(1,2),
107    pararg2(1,2)
108 {
109
110    WellDone = Standard_False;
111    NbrSol = 0;
112    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
113          Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
114      throw GccEnt_BadQualifier();
115      return;
116    }
117    Standard_Real Cosa = TheLine.Direction().X();
118    Standard_Real Sina = TheLine.Direction().Y();
119    if (Qualified1.IsEnclosed()) {
120 // ============================
121      throw GccEnt_BadQualifier();
122    }
123    else {
124      gp_Circ2d C1 = Qualified1.Qualified();
125      Standard_Real R1 = C1.Radius();
126      if (Qualified1.IsEnclosing()) {
127 //   =============================
128        gp_XY xy(Cos(TheAngle)*Cosa-Sin(TheAngle)*Sina,
129                 Cos(TheAngle)*Sina+Sin(TheAngle)*Cosa);
130        pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*gp_XY(xy.Y(),-xy.X()));
131        linsol(1) = gp_Lin2d(pnttg1sol(1),gp_Dir2d(xy));
132 //     ===============================================
133        qualifier1(1) = Qualified1.Qualifier();
134        IntAna2d_AnaIntersection Intp(linsol(1),TheLine);
135        NbrSol = 1;
136        WellDone = Standard_True;
137        if (Intp.IsDone()) {
138          if (!Intp.IsEmpty()) {
139            for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
140              pntint2sol(1) = Intp.Point(i).Value();
141            }
142          }
143        }
144      }
145      else if (Qualified1.IsOutside()) {
146 //   ================================
147        gp_XY xy(Cos(TheAngle)*Cosa-Sin(TheAngle)*Sina,
148                 Cos(TheAngle)*Sina+Sin(TheAngle)*Cosa);
149        pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*gp_XY(-xy.Y(),xy.X()));
150        linsol(1) = gp_Lin2d(pnttg1sol(1),gp_Dir2d(xy));
151 //     ===============================================
152        qualifier1(1) = Qualified1.Qualifier();
153        IntAna2d_AnaIntersection Intp(linsol(1),TheLine);
154        WellDone = Standard_True;
155        NbrSol = 1;
156        if (Intp.IsDone()) {
157          if (!Intp.IsEmpty()) {
158            for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
159              pntint2sol(1) = Intp.Point(i).Value();
160            }
161          }
162        }
163      }
164      else if (Qualified1.IsUnqualified()) {
165 //   ====================================
166        gp_XY xy(Cos(TheAngle)*Cosa-Sin(TheAngle)*Sina,
167                 Cos(TheAngle)*Sina+Sin(TheAngle)*Cosa);
168        pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*gp_XY(xy.Y(),-xy.X()));
169        linsol(1) = gp_Lin2d(pnttg1sol(1),gp_Dir2d(xy));
170 //     ===============================================
171        qualifier1(1) = GccEnt_enclosing;
172        IntAna2d_AnaIntersection Intp(linsol(1),TheLine);
173        WellDone = Standard_True;
174        NbrSol=1;
175        if (Intp.IsDone()) {
176          if (!Intp.IsEmpty()) {
177            for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
178              pntint2sol(1) = Intp.Point(i).Value();
179            }
180          }
181        }
182        pnttg1sol(2) = gp_Pnt2d(C1.Location().XY()+R1*gp_XY(-xy.Y(),xy.X()));
183        linsol(2) = gp_Lin2d(pnttg1sol(2),gp_Dir2d(xy));
184 //     ===============================================
185        qualifier1(2) = GccEnt_outside;
186        Intp = IntAna2d_AnaIntersection(linsol(1),TheLine);
187        NbrSol++;
188        WellDone = Standard_True;
189        if (Intp.IsDone()) {
190          if (!Intp.IsEmpty()) {
191            for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
192              pntint2sol(2) = Intp.Point(i).Value();
193            }
194          }
195        }
196      }
197      for (Standard_Integer index = 1; index <= NbrSol; index++) {
198        par1sol(index)=ElCLib::Parameter(linsol(index),pnttg1sol(index));
199        pararg1(index)=ElCLib::Parameter(C1,pnttg1sol(index));
200        par2sol(index)=ElCLib::Parameter(linsol(index),pntint2sol(index));
201        pararg2(index)=ElCLib::Parameter(TheLine,pntint2sol(index));
202      }
203    }
204  }
205
206 Standard_Boolean GccAna_Lin2dTanObl::
207    IsDone () const { return WellDone; }
208
209 Standard_Integer GccAna_Lin2dTanObl::
210    NbSolutions () const 
211
212   if (!WellDone) throw StdFail_NotDone();
213   return NbrSol;
214 }
215
216 gp_Lin2d GccAna_Lin2dTanObl::
217    ThisSolution (const Standard_Integer Index) const 
218 {
219   if (!WellDone) 
220     throw StdFail_NotDone();
221   if (Index <= 0 || Index > NbrSol) 
222     throw Standard_OutOfRange();
223
224   return linsol(Index);
225 }
226
227 void GccAna_Lin2dTanObl::
228   WhichQualifier(const Standard_Integer Index   ,
229                        GccEnt_Position& Qualif1 ) const
230 {
231   if (!WellDone) { throw StdFail_NotDone(); }
232    else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
233    else {
234      Qualif1 = qualifier1(Index);
235    }
236 }
237
238 void GccAna_Lin2dTanObl::
239    Tangency1 (const Standard_Integer   Index,
240                     Standard_Real&     ParSol,
241                     Standard_Real&     ParArg,
242                     gp_Pnt2d& PntSol) const{
243    if (!WellDone) { throw StdFail_NotDone(); }
244    else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
245    else {
246      ParSol = par1sol(Index);
247      ParArg = pararg1(Index);
248      PntSol = gp_Pnt2d(pnttg1sol(Index));
249    }
250  }
251
252 void GccAna_Lin2dTanObl::
253    Intersection2 (const Standard_Integer Index,
254                   Standard_Real& ParSol,
255                   Standard_Real& ParArg,
256                   gp_Pnt2d& PntSol) const{
257    if (!WellDone) { throw StdFail_NotDone(); }
258    else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
259    else {
260      ParSol = par2sol(Index);
261      ParArg = pararg2(Index);
262      PntSol = gp_Pnt2d(pntint2sol(Index));
263    }
264  }
265
266