6cb7b88101c37ceee26cce71265d8b9f503d037e
[occt.git] / src / GccAna / GccAna_Lin2dTanPer.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 ORTHOGONAL to a STRAIGHT LINE.                      +
18 //=========================================================================
19
20 #include <ElCLib.hxx>
21 #include <GccAna_Lin2dTanPer.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_ConstructionError.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
35
36 //=========================================================================
37 //   Straight line passing by point  : ThePoint and                       +
38 //       orthogonal to straight line : TheLin.                            +
39 //   Create the straight line of origin     : ThePoint                           +
40 //                  and direction  : TheLin.Direction() turned by 90   +
41 //=========================================================================
42 GccAna_Lin2dTanPer::
43    GccAna_Lin2dTanPer (const gp_Pnt2d& ThePnt    ,
44                        const gp_Lin2d& TheLin    ):
45    linsol(1,1),
46    qualifier1(1,1) ,
47    pnttg1sol(1,1),
48    pntint2sol(1,1),
49    par1sol(1,1),
50    par2sol(1,1),
51    pararg1(1,1),
52    pararg2(1,1)
53 {
54
55    linsol(1) = gp_Lin2d(ThePnt,gp_Dir2d(-(TheLin.Direction().Y()),
56 // ===============================================================
57                                         TheLin.Direction().X()));
58 //                                      ========================
59    pnttg1sol(1) = ThePnt;
60    IntAna2d_AnaIntersection Intp(linsol(1),TheLin);
61    if (Intp.IsDone()) {
62      if (!Intp.IsEmpty()) {
63        for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
64          pntint2sol(1) = Intp.Point(i).Value();
65        }
66      }
67    }
68    par1sol(1) = ElCLib::Parameter(linsol(1),pnttg1sol(1));
69    par2sol(1) = ElCLib::Parameter(linsol(1),pntint2sol(1));
70    pararg1(1) = 0.;
71    pararg2(1) = ElCLib::Parameter(TheLin,pntint2sol(1));
72    NbrSol = 1;
73    WellDone = Standard_True;
74  }
75
76 //=========================================================================
77 //   Straight line passing by point      : ThePnt                             +
78 //       and orthogonal to circle        : TheCircle.                         +
79 //   Create the straight line of origin  : ThePoint                           +
80 //                  and direction        : (TheCircle.Location(),ThePnt).     +
81 //=========================================================================
82
83 GccAna_Lin2dTanPer::
84    GccAna_Lin2dTanPer (const gp_Pnt2d&  ThePnt    ,
85                        const gp_Circ2d& TheCircle ):
86    linsol(1,1),
87    qualifier1(1,1) ,
88    pnttg1sol(1,1),
89    pntint2sol(1,1),
90    par1sol(1,1),
91    par2sol(1,1),
92    pararg1(1,1),
93    pararg2(1,1)
94 {
95
96    linsol(1) = gp_Lin2d(ThePnt,
97 // ============================
98                         gp_Dir2d(TheCircle.Location().XY()-ThePnt.XY()));
99 //                      ================================================
100    pnttg1sol(1) = ThePnt;
101    IntAna2d_AnaIntersection Intp(linsol(1),TheCircle);
102    if (Intp.IsDone()) {
103      if (!Intp.IsEmpty()) {
104        Standard_Real maxdist = RealLast();
105        for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
106          if (Intp.Point(i).Value().Distance(ThePnt) < maxdist) {
107            pntint2sol(1) = Intp.Point(i).Value();
108          }
109        }
110      }
111    }
112    par1sol(1) = ElCLib::Parameter(linsol(1),pnttg1sol(1));
113    par2sol(1) = ElCLib::Parameter(linsol(1),pntint2sol(1));
114    pararg1(1) = 0.;
115    pararg2(1) = ElCLib::Parameter(TheCircle,pntint2sol(1));
116    NbrSol = 1;
117    WellDone = Standard_True;
118  }
119
120 //=========================================================================
121 //   Straight line tangent to circle     : Qualified1 (C1)                    +
122 //   and orthogonal to straight line     : TheLin.                            +
123 //   Create straight line of origin      : P1 (on C1)                         +
124 //                  and direction        : TheLin.Direction() turned by 90`   +
125 //=========================================================================
126
127 GccAna_Lin2dTanPer::
128    GccAna_Lin2dTanPer (const GccEnt_QualifiedCirc& Qualified1,
129                        const gp_Lin2d&             TheLin    ):
130    linsol(1,2),
131    qualifier1(1,2) ,
132    pnttg1sol(1,2),
133    pntint2sol(1,2),
134    par1sol(1,2),
135    par2sol(1,2),
136    pararg1(1,2),
137    pararg2(1,2)
138 {
139
140    WellDone = Standard_False;
141    Standard_Integer nbsol = 0;
142    Standard_Integer signe = 0;
143    NbrSol = 0;
144    gp_Circ2d C1 = Qualified1.Qualified();
145
146    if (Qualified1.IsEnclosed()) {
147 // ============================
148      GccEnt_BadQualifier::Raise();
149    }
150    else if (Qualified1.IsEnclosing()) {
151 // ==================================
152      nbsol = 1;
153      signe = -1;
154    }
155    else if (Qualified1.IsOutside()) {
156 // ================================
157      nbsol = 1;
158      signe = 1;
159    }
160    else {
161      nbsol = 2;
162      signe = -1;
163    }
164    gp_XY xy(C1.Radius()*TheLin.Direction().XY());
165    for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
166      signe = -signe;
167      NbrSol++;
168      linsol(NbrSol)=gp_Lin2d(gp_Pnt2d((C1.Location().XY()).Added(signe*xy)),
169 //   =======================================================================
170                              gp_Dir2d(-TheLin.Direction().Y(),
171 //                           =================================
172                                       TheLin.Direction().X()));
173 //                                    ========================
174      pnttg1sol(NbrSol) = gp_Pnt2d((C1.Location().XY()).Added(signe*xy));
175      IntAna2d_AnaIntersection Intp(linsol(NbrSol),TheLin);
176      if (Intp.IsDone()) {
177        if (!Intp.IsEmpty()) {
178          for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
179            pntint2sol(NbrSol) = Intp.Point(i).Value();
180          }
181        }
182      }
183      par1sol(NbrSol) = ElCLib::Parameter(linsol(NbrSol),pnttg1sol(NbrSol));
184      par2sol(NbrSol) = ElCLib::Parameter(linsol(NbrSol),pntint2sol(NbrSol));
185      pararg1(NbrSol) = ElCLib::Parameter(C1,pnttg1sol(NbrSol));
186      pararg2(NbrSol) = ElCLib::Parameter(TheLin,pntint2sol(NbrSol));
187      WellDone = Standard_True;
188    }
189  }
190
191 //=========================================================================
192 //   Straight line tangent to circle     : Qualified1 (C1)                    +
193 //       and orthogonal to circle        : TheCircle.                         +
194 //   Create straight line of origin      : P1 (on C1)                         +
195 //                  and direction        : TheLin.Direction() turned by 90`   +
196 //=========================================================================
197
198 GccAna_Lin2dTanPer::
199    GccAna_Lin2dTanPer (const GccEnt_QualifiedCirc& Qualified1,
200                        const gp_Circ2d&            TheCircle ):
201    linsol(1,2),
202    qualifier1(1,2) ,
203    pnttg1sol(1,2),
204    pntint2sol(1,2),
205    par1sol(1,2),
206    par2sol(1,2),
207    pararg1(1,2),
208    pararg2(1,2)
209 {
210
211    WellDone = Standard_False;
212    NbrSol = 0;
213    Standard_Integer signe = 0;
214    gp_Circ2d C1 = Qualified1.Qualified();
215
216    if (Qualified1.IsEnclosed()) {
217 // ============================
218      GccEnt_BadQualifier::Raise();
219    }
220    else if (Qualified1.IsEnclosing()) {
221 // ==================================
222      signe = -1;
223      qualifier1(1) = GccEnt_enclosing;
224    }
225    else if (Qualified1.IsOutside()) {
226 // ================================
227      signe = 1;
228      qualifier1(1) = GccEnt_outside;
229    }
230    else if (Qualified1.IsUnqualified()) {
231 // ====================================
232      signe = -1;
233      qualifier1(1) = GccEnt_enclosing;
234      qualifier1(2) = GccEnt_outside;
235    }
236    for (Standard_Integer j = 1 ; j <= 2 ; j++) {
237      NbrSol++;
238      signe = -signe;
239      gp_Dir2d D1(TheCircle.Location().XY()-C1.Location().XY());
240      linsol(NbrSol) = gp_Lin2d(gp_Pnt2d((C1.Location().XY())+
241 //   ===================================================
242                        signe*(D1.XY()*C1.Radius())),gp_Dir2d(-D1.Y(),D1.X()));
243 //                     ======================================================
244      pnttg1sol(NbrSol) = gp_Pnt2d((C1.Location().XY())+
245                                   signe*(D1.XY()*C1.Radius()));
246      IntAna2d_AnaIntersection Intp(linsol(NbrSol),TheCircle);
247      if (Intp.IsDone()) {
248        if (!Intp.IsEmpty()) {
249          Standard_Real maxdist = RealLast();
250          for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
251            if (Intp.Point(i).Value().Distance(pnttg1sol(NbrSol)) < maxdist) {
252              pntint2sol(NbrSol) = Intp.Point(i).Value();
253            }
254          }
255        }
256      }
257      par1sol(NbrSol) = ElCLib::Parameter(linsol(NbrSol),pnttg1sol(NbrSol));
258      par2sol(NbrSol) = ElCLib::Parameter(linsol(NbrSol),pntint2sol(NbrSol));
259      pararg1(NbrSol) = ElCLib::Parameter(C1,pnttg1sol(NbrSol));
260      pararg2(NbrSol) = ElCLib::Parameter(TheCircle,pntint2sol(NbrSol));
261      WellDone = Standard_True;
262    }
263  }
264
265 Standard_Boolean GccAna_Lin2dTanPer::
266    IsDone () const { return WellDone; }
267
268 Standard_Integer GccAna_Lin2dTanPer::
269    NbSolutions () const 
270 {
271   if (!WellDone) { StdFail_NotDone::Raise(); } 
272   return NbrSol;
273 }
274
275 gp_Lin2d GccAna_Lin2dTanPer::
276    ThisSolution (const Standard_Integer Index) const 
277 {
278   if (!WellDone) { StdFail_NotDone::Raise(); } 
279   if (Index <= 0 || Index > NbrSol) { Standard_RangeError::Raise(); }
280   return linsol(Index);
281 }
282
283 void GccAna_Lin2dTanPer::
284   WhichQualifier(const Standard_Integer Index   ,
285                        GccEnt_Position& Qualif1 ) const
286 {
287   if (!WellDone) { StdFail_NotDone::Raise(); }
288   if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
289   else {
290     Qualif1 = qualifier1(Index);
291   }
292 }
293
294 void GccAna_Lin2dTanPer::
295    Tangency1 (const Standard_Integer Index,
296               Standard_Real& ParSol,
297               Standard_Real& ParArg,
298               gp_Pnt2d& Pnt) const{
299    if (!WellDone) { StdFail_NotDone::Raise(); }
300    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
301    else {
302      ParSol = par1sol(Index);
303      ParArg = pararg1(Index);
304      Pnt    = gp_Pnt2d(pnttg1sol(Index));
305    }
306  }
307
308 void GccAna_Lin2dTanPer::
309    Intersection2 (const Standard_Integer Index,
310                   Standard_Real& ParSol,
311                   Standard_Real& ParArg,
312                   gp_Pnt2d& PntSol) const {
313    if (!WellDone) { StdFail_NotDone::Raise(); }
314    else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
315    else {
316      ParSol = par2sol(Index);
317      ParArg = pararg2(Index);
318      PntSol = gp_Pnt2d(pntint2sol(Index));
319    }
320  }
321