1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 // PRO12736 : bug quand OnLine // Ox, JCT 20/03/98
16 //========================================================================
17 // circular tangent to element of type : - Circle. +
20 // center on second element of type : - Circle. +
22 // of given radius : Radius. +
23 //========================================================================
26 #include <GccAna_Circ2dTanOnRad.hxx>
27 #include <GccEnt_BadQualifier.hxx>
28 #include <GccEnt_QualifiedCirc.hxx>
29 #include <gp_Circ2d.hxx>
30 #include <gp_Dir2d.hxx>
31 #include <gp_Lin2d.hxx>
32 #include <gp_Pnt2d.hxx>
33 #include <math_DirectPolynomialRoots.hxx>
34 #include <Standard_NegativeValue.hxx>
35 #include <Standard_OutOfRange.hxx>
36 #include <StdFail_NotDone.hxx>
37 #include <TColStd_Array1OfReal.hxx>
39 typedef math_DirectPolynomialRoots Roots;
41 //=========================================================================
42 // Circle tangent : to circle Qualified1 (C1). +
43 // center : on straight line OnLine. +
44 // of radius : Radius. +
46 // Initialise the table of solutions cirsol and all fields. +
47 // Eliminate depending on the qualifier the cases not being solutions. +
48 // Solve the equation of the second degree indicating that the found center +
49 // point (xc,yc) is at a distance Radius from circle C1 and +
50 // on straight line OnLine. +
51 // The solutions aret represented by circles : +
52 // - with center Pntcen(xc,yc) +
53 // - with radius Radius. +
54 //=========================================================================
56 GccAna_Circ2dTanOnRad::
57 GccAna_Circ2dTanOnRad (const GccEnt_QualifiedCirc& Qualified1,
58 const gp_Lin2d& OnLine ,
59 const Standard_Real Radius ,
60 const Standard_Real Tolerance ) :
72 gp_Dir2d dirx(1.0,0.0);
73 Standard_Real Tol = Abs(Tolerance);
74 WellDone = Standard_False;
76 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
77 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
78 throw GccEnt_BadQualifier();
81 TColStd_Array1OfReal Coef(1,2);
82 gp_Circ2d C1 = Qualified1.Qualified();
84 if (Radius < 0.0) { throw Standard_NegativeValue(); }
86 Standard_Integer nbsol = 0;
87 Standard_Integer signe = 0;
91 Standard_Real R1 = C1.Radius();
92 Standard_Real dist = OnLine.Distance(C1.Location());
93 Standard_Real xdir = (OnLine.Direction()).X();
94 Standard_Real ydir = (OnLine.Direction()).Y();
95 Standard_Real lxloc = (OnLine.Location()).X();
96 Standard_Real lyloc = (OnLine.Location()).Y();
97 gp_Pnt2d center1(C1.Location());
98 Standard_Real x1 = center1.X();
99 Standard_Real y1 = center1.Y();
100 if (Qualified1.IsEnclosed()) {
101 // ============================
102 if (Tol < Radius-R1+dist) { WellDone = Standard_True; }
104 if (Abs(Radius-R1+dist) < Tol) {
105 WellDone = Standard_True;
107 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
108 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
110 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
114 Coef(1) = (R1-Radius)*(R1-Radius);
119 else if (Qualified1.IsEnclosing()) {
120 // ==================================
121 if (R1+dist-Radius > Tol) { WellDone = Standard_True; }
123 if (R1+dist-Radius > 0.0) {
124 WellDone = Standard_True;
126 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
127 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
129 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
133 Coef(1) = (Radius-R1)*(Radius-R1);
140 if (dist-R1-Radius > Tol) { WellDone = Standard_False; }
142 if (Abs(dist-R1-Radius) < Tol) {
143 WellDone = Standard_True;
145 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
146 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
148 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
152 if (Qualified1.IsOutside()) {
153 // ===========================
154 Coef(1) = (Radius+R1)*(Radius+R1);
159 Coef(1) = (Radius-R1)*(Radius-R1);
160 Coef(2) = (Radius+R1)*(Radius+R1);
167 cirsol(1) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
168 // ==================================================
169 Standard_Real distcc1 = Center.Distance(center1);
170 if (!Qualified1.IsUnqualified()) {
171 qualifier1(1) = Qualified1.Qualifier();
173 else if (Abs(distcc1+Radius-R1) < Tol) {
174 qualifier1(1) = GccEnt_enclosed;
176 else if (Abs(distcc1-R1-Radius) < Tol) {
177 qualifier1(1) = GccEnt_outside;
179 else { qualifier1(1) = GccEnt_enclosing; }
180 if (Abs(Radius-R1) <= Tol) { TheSame1(1) = 1; }
182 gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
183 pnttg1sol(1) = gp_Pnt2d(Center.XY()+signe*Radius*dir1cen.XY());
184 par1sol(1)=ElCLib::Parameter(cirsol(1),pnttg1sol(1));
185 pararg1(1)=ElCLib::Parameter(C1,pnttg1sol(1));
187 pntcen3(1) = cirsol(NbrSol).Location();
188 parcen3(1)=ElCLib::Parameter(OnLine,pntcen3(1));
190 else if (nbsol > 0) {
191 for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
193 OnLine.Coefficients(A,B,C);
196 if ( Abs(D) <= Tol ) {
206 Roots Sol((B*B+A*A)/(A*A),
207 2.0*(B*C/(A*A)+(B/A)*x0-y0),
208 x0*x0+y0*y0+C*C/(A*A)-Coef(j)+2.0*C*x0/A);
210 for (Standard_Integer i = 1 ; i <= Sol.NbSolutions() ; i++) {
212 if ( Abs(D) > Tol ) {
220 Center = gp_Pnt2d(xc,yc);
221 if (OnLine.Distance(Center)>Tol)
224 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
225 // =======================================================
226 Standard_Real distcc1 = Center.Distance(center1);
227 if (!Qualified1.IsUnqualified()) {
228 qualifier1(NbrSol) = Qualified1.Qualifier();
230 else if (Abs(distcc1+Radius-R1) < Tol) {
231 qualifier1(NbrSol) = GccEnt_enclosed;
233 else if (Abs(distcc1-R1-Radius) < Tol) {
234 qualifier1(NbrSol) = GccEnt_outside;
236 else { qualifier1(NbrSol) = GccEnt_enclosing; }
237 gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
238 if ((Radius > R1) || (Center.Distance(center1) > R1)) {
239 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1cen.XY());
242 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1cen.XY());
244 pntcen3(NbrSol) = cirsol(NbrSol).Location();
245 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
247 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
248 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen3(NbrSol));
250 WellDone = Standard_True;
257 Standard_Boolean GccAna_Circ2dTanOnRad::
258 IsDone () const { return WellDone; }
260 Standard_Integer GccAna_Circ2dTanOnRad::
261 NbSolutions () const { return NbrSol; }
263 gp_Circ2d GccAna_Circ2dTanOnRad::ThisSolution (const Standard_Integer Index) const
265 if (Index > NbrSol || Index <= 0) {
266 throw Standard_OutOfRange();
268 return cirsol(Index);
271 void GccAna_Circ2dTanOnRad::
272 WhichQualifier(const Standard_Integer Index ,
273 GccEnt_Position& Qualif1 ) const
275 if (!WellDone) { throw StdFail_NotDone(); }
276 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
278 Qualif1 = qualifier1(Index);
282 void GccAna_Circ2dTanOnRad::
283 Tangency1 (const Standard_Integer Index,
284 Standard_Real& ParSol,
285 Standard_Real& ParArg,
286 gp_Pnt2d& PntSol) const{
288 throw StdFail_NotDone();
290 else if (Index <= 0 ||Index > NbrSol) {
291 throw Standard_OutOfRange();
294 ParSol = par1sol(Index);
295 ParArg = pararg1(Index);
296 PntSol = gp_Pnt2d(pnttg1sol(Index));
301 void GccAna_Circ2dTanOnRad::
302 CenterOn3 (const Standard_Integer Index,
303 Standard_Real& ParArg,
304 gp_Pnt2d& PntSol) const{
306 throw StdFail_NotDone();
308 else if (Index <= 0 ||Index > NbrSol) {
309 throw Standard_OutOfRange();
312 ParArg = parcen3(Index);
313 PntSol = pnttg1sol(Index);
317 Standard_Boolean GccAna_Circ2dTanOnRad::IsTheSame1 (const Standard_Integer Index) const
320 throw StdFail_NotDone();
322 if (Index <= 0 ||Index > NbrSol)
323 throw Standard_OutOfRange();
325 if (TheSame1(Index) == 0)
326 return Standard_False;
328 return Standard_True;