0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / GccAna / GccAna_Circ2d2TanOn_1.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_CircLin2dBisec.hxx>
21 #include <GccEnt_BadQualifier.hxx>
22 #include <GccEnt_QualifiedCirc.hxx>
23 #include <GccEnt_QualifiedLin.hxx>
24 #include <GccInt_BCirc.hxx>
25 #include <GccInt_IType.hxx>
26 #include <gp_Ax2d.hxx>
27 #include <gp_Circ2d.hxx>
28 #include <gp_Dir2d.hxx>
29 #include <gp_Lin2d.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <IntAna2d_AnaIntersection.hxx>
32 #include <IntAna2d_Conic.hxx>
33 #include <IntAna2d_IntPoint.hxx>
34 #include <Standard_OutOfRange.hxx>
35 #include <StdFail_NotDone.hxx>
36
37 //=========================================================================
38 //   Creation of a circle tangent to Circle C1 and a straight line L2.    +
39 //                        centered on a straight line.                    +
40 //  We start by making difference between cases that we are going to      +
41 //  proceess separately.                                            +
42 //  In general case:                                                  +
43 //  ====================                                                  +
44 //  We calculate bissectrices to C1 and L2 that give us            +
45 //  all possibles locations of centers of all circles tangent to C1 and L2+                                                  +
46 //  We intersect these bissectrices with straight line OnLine which gives   +
47 //  us points among which we'll choose the solutions.   +
48 //  The choices are made basing on Qualifiers of C1 and L2.  +
49 //=========================================================================
50 GccAna_Circ2d2TanOn::
51    GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1  , 
52                         const GccEnt_QualifiedLin&  Qualified2  , 
53                         const gp_Lin2d&             OnLine      ,
54                         const Standard_Real         Tolerance   ):
55    cirsol(1,4)     ,
56    qualifier1(1,4) ,
57    qualifier2(1,4),
58    TheSame1(1,4)   ,
59    TheSame2(1,4)   ,
60    pnttg1sol(1,4)  ,
61    pnttg2sol(1,4)  ,
62    pntcen(1,4)     ,
63    par1sol(1,4)    ,
64    par2sol(1,4)    ,
65    pararg1(1,4)    ,
66    pararg2(1,4)    ,
67    parcen3(1,4)
68 {
69
70    TheSame1.Init(0);
71    TheSame2.Init(0);
72    WellDone = Standard_False;
73    NbrSol = 0;
74    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
75          Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
76        !(Qualified2.IsEnclosed() ||
77          Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
78      throw GccEnt_BadQualifier();
79      return;
80    }
81    Standard_Real Tol = Abs(Tolerance);
82    Standard_Real Radius=0;
83    Standard_Boolean ok = Standard_False;
84    gp_Dir2d dirx(1.,0.);
85    gp_Circ2d C1 = Qualified1.Qualified();
86    gp_Lin2d  L2 = Qualified2.Qualified();
87    Standard_Real R1 = C1.Radius();
88    gp_Pnt2d center1(C1.Location());
89    gp_Pnt2d origin2(L2.Location());
90    gp_Dir2d dirL2(L2.Direction());
91    gp_Dir2d normL2(-dirL2.Y(),dirL2.X());
92
93 //=========================================================================
94 //   Processing of limit cases.                                          +
95 //=========================================================================
96
97    Standard_Real distcl = OnLine.Distance(center1);
98    gp_Pnt2d pinterm(center1.XY()+distcl*
99                     gp_XY(-OnLine.Direction().Y(),OnLine.Direction().X()));
100    if (OnLine.Distance(pinterm) > Tolerance) {
101      pinterm = gp_Pnt2d(center1.XY()+distcl*
102                         gp_XY(-OnLine.Direction().Y(),OnLine.Direction().X()));
103    }
104    Standard_Real dist2 = L2.Distance(pinterm);
105    if (Qualified1.IsEnclosed() || Qualified1.IsOutside()) {
106      if (Abs(distcl-R1-dist2) <= Tol) { ok = Standard_True; }
107    }
108    else if (Qualified1.IsEnclosing()) {
109      if (Abs(dist2-distcl-R1) <= Tol) { ok = Standard_True; }
110    }
111    else if (Qualified1.IsUnqualified()) { ok = Standard_True; }
112    else { 
113      throw GccEnt_BadQualifier();
114      return;
115    }
116    if (ok) {
117      if (Qualified2.IsOutside()) {
118        gp_Pnt2d pbid(pinterm.XY()+dist2*gp_XY(-dirL2.Y(),dirL2.X()));
119        if (L2.Distance(pbid) <= Tol) { WellDone = Standard_True; }
120      }
121      else if (Qualified2.IsEnclosed()) {
122        gp_Pnt2d pbid(pinterm.XY()-dist2*gp_XY(-dirL2.Y(),dirL2.X()));
123        if (L2.Distance(pbid) <= Tol) { WellDone = Standard_True; }
124      }
125      else if (Qualified2.IsUnqualified()) { WellDone = Standard_False; }
126      else { 
127        throw GccEnt_BadQualifier();
128        return;
129      }
130    }
131    if (WellDone) {
132      NbrSol++;
133      cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),dist2);
134 //   =======================================================
135      gp_Dir2d dc1(center1.XY()-pinterm.XY());
136      gp_Dir2d dc2(origin2.XY()-pinterm.XY());
137      Standard_Real distcc1 = pinterm.Distance(center1);
138      if (!Qualified1.IsUnqualified()) { 
139        qualifier1(NbrSol) = Qualified1.Qualifier();
140      }
141      else if (Abs(distcc1+dist2-R1) < Tol) {
142        qualifier1(NbrSol) = GccEnt_enclosed;
143      }
144      else if (Abs(distcc1-R1-dist2) < Tol) {
145        qualifier1(NbrSol) = GccEnt_outside;
146      }
147      else { qualifier1(NbrSol) = GccEnt_enclosing; }
148      if (!Qualified2.IsUnqualified()) { 
149        qualifier2(NbrSol) = Qualified2.Qualifier();
150      }
151      else if (dc2.Dot(normL2) > 0.0) {
152        qualifier2(NbrSol) = GccEnt_outside;
153      }
154      else { qualifier2(NbrSol) = GccEnt_enclosed; }
155
156      Standard_Real sign = dc2.Dot(gp_Dir2d(-dirL2.Y(),dirL2.X()));
157      dc2 = gp_Dir2d(sign*gp_XY(-dirL2.Y(),dirL2.X()));
158      pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+dist2*dc1.XY());
159      pnttg2sol(NbrSol) = gp_Pnt2d(pinterm.XY()+dist2*dc2.XY());
160      par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol));
161      pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
162      par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol));
163      pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
164      pntcen(NbrSol) = cirsol(NbrSol).Location();
165      parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
166      return;
167    }
168
169 //=========================================================================
170 //   General case.                                                        +
171 //=========================================================================
172
173    GccAna_CircLin2dBisec Bis(C1,L2);
174    if (Bis.IsDone()) {
175      Standard_Integer nbsolution = Bis.NbSolutions();
176      for (Standard_Integer i = 1 ; i <=  nbsolution; i++) {
177        Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
178        GccInt_IType type = Sol->ArcType();
179        IntAna2d_AnaIntersection Intp;
180        if (type == GccInt_Lin) {
181          Intp.Perform(OnLine,Sol->Line());
182        }
183        else if (type == GccInt_Par) {
184          Intp.Perform(OnLine,IntAna2d_Conic(Sol->Parabola()));
185        }
186        if (Intp.IsDone()) {
187          if (!Intp.IsEmpty()) {
188            for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
189              gp_Pnt2d Center(Intp.Point(j).Value());
190              Standard_Real dist1 = Center.Distance(center1);
191              dist2 = L2.Distance(Center);
192 //           Standard_Integer nbsol = 1;
193              ok = Standard_False;
194              if (Qualified1.IsEnclosed()) {
195                if (dist1-R1 < Tolerance) {
196                  if (Abs(Abs(R1-dist1)-dist2)<Tolerance) { ok=Standard_True; }
197                }
198              }
199              else if (Qualified1.IsOutside()) {
200                if (R1-dist1 < Tolerance) {
201                  if (Abs(Abs(R1-dist1)-dist2)<Tolerance) { ok=Standard_True; }
202                }
203              }
204              else if (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) {
205                ok = Standard_True;
206              }
207              if (Qualified2.IsEnclosed() && ok) {
208                if ((((origin2.X()-Center.X())*(-dirL2.Y()))+
209                     ((origin2.Y()-Center.Y())*(dirL2.X())))<=0){
210                  ok = Standard_True;
211                  Radius = dist2;
212                }
213              }
214              else if (Qualified2.IsOutside() && ok) {
215                if ((((origin2.X()-Center.X())*(-dirL2.Y()))+
216                     ((origin2.Y()-Center.Y())*(dirL2.X())))>=0){
217                  ok = Standard_True;
218                  Radius = dist2;
219                }
220              }
221              else if (Qualified2.IsUnqualified() && ok) {
222                ok = Standard_True;
223                Radius = dist2;
224              }
225              if (ok) {
226                NbrSol++;
227                cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
228 //             =======================================================
229                gp_Dir2d dc1(center1.XY()-Center.XY());
230                gp_Dir2d dc2(origin2.XY()-Center.XY());
231                Standard_Real distcc1 = Center.Distance(center1);
232                if (!Qualified1.IsUnqualified()) { 
233                  qualifier1(NbrSol) = Qualified1.Qualifier();
234                }
235                else if (Abs(distcc1+Radius-R1) < Tol) {
236                  qualifier1(NbrSol) = GccEnt_enclosed;
237                }
238                else if (Abs(distcc1-R1-Radius) < Tol) {
239                  qualifier1(NbrSol) = GccEnt_outside;
240                }
241                else { qualifier1(NbrSol) = GccEnt_enclosing; }
242                if (!Qualified2.IsUnqualified()) { 
243                  qualifier2(NbrSol) = Qualified2.Qualifier();
244                }
245                else if (dc2.Dot(normL2) > 0.0) {
246                  qualifier2(NbrSol) = GccEnt_outside;
247                }
248                else { qualifier2(NbrSol) = GccEnt_enclosed; }
249                if (Center.Distance(center1) <= Tolerance &&
250                    Abs(Radius-C1.Radius()) <= Tolerance) {
251                  TheSame1(NbrSol) = 1;
252                  }
253                else {
254                  TheSame1(NbrSol) = 0;
255                  pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc1.XY());
256                  par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
257                                                         pnttg1sol(NbrSol));
258                  pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
259                }
260                TheSame2(NbrSol) = 0;
261                Standard_Real sign = dc2.Dot(gp_Dir2d(-dirL2.Y(),dirL2.X()));
262                dc2 = gp_Dir2d(sign*gp_XY(-dirL2.Y(),dirL2.X()));
263                pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc2.XY());
264                par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
265                                                       pnttg2sol(NbrSol));
266                pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
267                pntcen(NbrSol) = Center;
268                parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
269              }
270            }
271          }
272          WellDone = Standard_True;
273        }
274      }
275    }
276  }
277
278
279
280
281
282