0023024: Update headers of OCCT files
[occt.git] / src / GccAna / GccAna_Circ2dTanOnRad.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2012 OPEN CASCADE SAS
3//
4// The content of this file is subject to the Open CASCADE Technology Public
5// License Version 6.5 (the "License"). You may not use the content of this file
6// except in compliance with the License. Please obtain a copy of the License
7// at http://www.opencascade.org and read it completely before using this file.
8//
9// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11//
12// The Original Code and all software distributed under the License is
13// distributed on an "AS IS" basis, without warranty of any kind, and the
14// Initial Developer hereby disclaims all such warranties, including without
15// limitation, any warranties of merchantability, fitness for a particular
16// purpose or non-infringement. Please see the License for the specific terms
17// and conditions governing the rights and limitations under the License.
18
7fd59977 19// PRO12736 : bug quand OnLine // Ox, JCT 20/03/98
20
21//========================================================================
0d969553
Y
22// circular tangent to element of type : - Circle. +
23// - Line. +
7fd59977 24// - Point. +
0d969553
Y
25// center on second element of type : - Circle. +
26// - Line. +
27// of given radius : Radius. +
7fd59977 28//========================================================================
29
30#include <GccAna_Circ2dTanOnRad.ixx>
31
32#include <ElCLib.hxx>
33#include <math_DirectPolynomialRoots.hxx>
34#include <TColStd_Array1OfReal.hxx>
35#include <Standard_NegativeValue.hxx>
36#include <gp_Dir2d.hxx>
37#include <Standard_OutOfRange.hxx>
38#include <StdFail_NotDone.hxx>
39#include <GccEnt_BadQualifier.hxx>
40
41typedef math_DirectPolynomialRoots Roots;
42
43//=========================================================================
0d969553
Y
44// Circle tangent : to circle Qualified1 (C1). +
45// center : on straight line OnLine. +
46// of radius : Radius. +
7fd59977 47// +
0d969553
Y
48// Initialise the table of solutions cirsol and all fields. +
49// Eliminate depending on the qualifier the cases not being solutions. +
50// Solve the equation of the second degree indicating that the found center +
51// point (xc,yc) is at a distance Radius from circle C1 and +
52// on straight line OnLine. +
53// The solutions aret represented by circles : +
54// - with center Pntcen(xc,yc) +
55// - with radius Radius. +
7fd59977 56//=========================================================================
57
58GccAna_Circ2dTanOnRad::
59 GccAna_Circ2dTanOnRad (const GccEnt_QualifiedCirc& Qualified1,
60 const gp_Lin2d& OnLine ,
61 const Standard_Real Radius ,
62 const Standard_Real Tolerance ) :
63 cirsol(1,4) ,
64 qualifier1(1,4) ,
65 TheSame1(1,4) ,
66 pnttg1sol(1,4) ,
67 pntcen3(1,4) ,
68 par1sol(1,4) ,
69 pararg1(1,4) ,
70 parcen3(1,4)
71{
72
73 TheSame1.Init(0);
74 gp_Dir2d dirx(1.0,0.0);
75 Standard_Real Tol = Abs(Tolerance);
76 WellDone = Standard_False;
77 NbrSol = 0;
78 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
79 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
80 GccEnt_BadQualifier::Raise();
81 return;
82 }
83 TColStd_Array1OfReal Coef(1,2);
84 gp_Circ2d C1 = Qualified1.Qualified();
85
86 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
87 else {
88 Standard_Integer nbsol = 0;
89 Standard_Integer signe = 0;
90 gp_Pnt2d Center;
91 Standard_Real xc;
92 Standard_Real yc;
93 Standard_Real R1 = C1.Radius();
94 Standard_Real dist = OnLine.Distance(C1.Location());
95 Standard_Real xdir = (OnLine.Direction()).X();
96 Standard_Real ydir = (OnLine.Direction()).Y();
97 Standard_Real lxloc = (OnLine.Location()).X();
98 Standard_Real lyloc = (OnLine.Location()).Y();
99 gp_Pnt2d center1(C1.Location());
100 Standard_Real x1 = center1.X();
101 Standard_Real y1 = center1.Y();
102 Standard_Real xbid = 0.;
103 if (Qualified1.IsEnclosed()) {
104// ============================
105 if (Tol < Radius-R1+dist) { WellDone = Standard_True; }
106 else {
107 if (Abs(Radius-R1+dist) < Tol) {
108 WellDone = Standard_True;
109 NbrSol = 1;
110 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
111 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
112 }
113 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
114 signe = 1;
115 }
116 else {
117 Coef(1) = (R1-Radius)*(R1-Radius);
118 nbsol = 1;
119 }
120 }
121 }
122 else if (Qualified1.IsEnclosing()) {
123// ==================================
124 if (R1+dist-Radius > Tol) { WellDone = Standard_True; }
125 else {
126 if (R1+dist-Radius > 0.0) {
127 WellDone = Standard_True;
128 NbrSol = 1;
129 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
130 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
131 }
132 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
133 signe = -1;
134 }
135 else {
136 Coef(1) = (Radius-R1)*(Radius-R1);
137 nbsol = 1;
138 }
139 }
140 }
141 else {
142// ====
143 if (dist-R1-Radius > Tol) { WellDone = Standard_False; }
144 else {
145 if (Abs(dist-R1-Radius) < Tol) {
146 WellDone = Standard_True;
147 NbrSol = 1;
148 if (-ydir*(x1-lxloc)+xdir*(y1-lyloc)<0.0) {
149 Center = gp_Pnt2d(x1-ydir*dist,y1+xdir*dist);
150 }
151 else { Center = gp_Pnt2d(x1+ydir*dist,y1-xdir*dist); }
152 signe = -1;
153 }
154 else {
155 if (Qualified1.IsOutside()) {
156// ===========================
157 Coef(1) = (Radius+R1)*(Radius+R1);
158 nbsol = 1;
159 }
160 else {
161// ====
162 Coef(1) = (Radius-R1)*(Radius-R1);
163 Coef(2) = (Radius+R1)*(Radius+R1);
164 nbsol = 2;
165 }
166 }
167 }
168 }
169 if (signe != 0) {
170 cirsol(1) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
171// ==================================================
172 Standard_Real distcc1 = Center.Distance(center1);
173 if (!Qualified1.IsUnqualified()) {
174 qualifier1(1) = Qualified1.Qualifier();
175 }
176 else if (Abs(distcc1+Radius-R1) < Tol) {
177 qualifier1(1) = GccEnt_enclosed;
178 }
179 else if (Abs(distcc1-R1-Radius) < Tol) {
180 qualifier1(1) = GccEnt_outside;
181 }
182 else { qualifier1(1) = GccEnt_enclosing; }
183 if (Abs(Radius-R1) <= Tol) { TheSame1(1) = 1; }
184 else {
185 gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
186 pnttg1sol(1) = gp_Pnt2d(Center.XY()+signe*Radius*dir1cen.XY());
187 par1sol(1)=ElCLib::Parameter(cirsol(1),pnttg1sol(1));
188 pararg1(1)=ElCLib::Parameter(C1,pnttg1sol(1));
189 }
190 pntcen3(1) = cirsol(NbrSol).Location();
191 parcen3(1)=ElCLib::Parameter(OnLine,pntcen3(1));
192 }
193 else if (nbsol > 0) {
194 for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
195 Standard_Real A,B,C;
196 OnLine.Coefficients(A,B,C);
197 Standard_Real D = A;
198 Standard_Real x0,y0;
199 if ( Abs(D) <= Tol ) {
200 A = B;
201 B = D;
202 xbid = x1;
203 x0 = y1;
204 y0 = x1;
205 }
206 else{
207 x0 = x1;
208 y0 = y1;
209 }
210 Roots Sol((B*B+A*A)/(A*A),
211 2.0*(B*C/(A*A)+(B/A)*x0-y0),
212 x0*x0+y0*y0+C*C/(A*A)-Coef(j)+2.0*C*x0/A);
213 if (Sol.IsDone()) {
214 for (Standard_Integer i = 1 ; i <= Sol.NbSolutions() ; i++) {
215
216 if ( Abs(D) > Tol ) {
217 yc = Sol.Value(i);
218 xc = -(B/A)*yc-C/A;
219 }
220 else {
221 xc = Sol.Value(i);
222 yc = -(B/A)*xc-C/A;
223 }
224 Center = gp_Pnt2d(xc,yc);
225 if (OnLine.Distance(Center)>Tol)
226 continue;
227 NbrSol++;
228 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
229// =======================================================
230 Standard_Real distcc1 = Center.Distance(center1);
231 if (!Qualified1.IsUnqualified()) {
232 qualifier1(NbrSol) = Qualified1.Qualifier();
233 }
234 else if (Abs(distcc1+Radius-R1) < Tol) {
235 qualifier1(NbrSol) = GccEnt_enclosed;
236 }
237 else if (Abs(distcc1-R1-Radius) < Tol) {
238 qualifier1(NbrSol) = GccEnt_outside;
239 }
240 else { qualifier1(NbrSol) = GccEnt_enclosing; }
241 gp_Dir2d dir1cen(Center.X()-x1,Center.Y()-y1);
242 if ((Radius > R1) || (Center.Distance(center1) > R1)) {
243 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1cen.XY());
244 }
245 else {
246 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1cen.XY());
247 }
248 pntcen3(NbrSol) = cirsol(NbrSol).Location();
249 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
250 pnttg1sol(NbrSol));
251 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
252 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen3(NbrSol));
253 }
254 WellDone = Standard_True;
255 }
256 }
257 }
258 }
259 }
260
261Standard_Boolean GccAna_Circ2dTanOnRad::
262 IsDone () const { return WellDone; }
263
264Standard_Integer GccAna_Circ2dTanOnRad::
265 NbSolutions () const { return NbrSol; }
266
267gp_Circ2d GccAna_Circ2dTanOnRad::ThisSolution (const Standard_Integer Index) const
268{
269 if (Index > NbrSol || Index <= 0) {
270 Standard_OutOfRange::Raise();
271 }
272 return cirsol(Index);
273}
274
275void GccAna_Circ2dTanOnRad::
276 WhichQualifier(const Standard_Integer Index ,
277 GccEnt_Position& Qualif1 ) const
278{
279 if (!WellDone) { StdFail_NotDone::Raise(); }
280 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
281 else {
282 Qualif1 = qualifier1(Index);
283 }
284}
285
286void GccAna_Circ2dTanOnRad::
287 Tangency1 (const Standard_Integer Index,
288 Standard_Real& ParSol,
289 Standard_Real& ParArg,
290 gp_Pnt2d& PntSol) const{
291 if (!WellDone) {
292 StdFail_NotDone::Raise();
293 }
294 else if (Index <= 0 ||Index > NbrSol) {
295 Standard_OutOfRange::Raise();
296 }
297 else {
298 ParSol = par1sol(Index);
299 ParArg = pararg1(Index);
300 PntSol = gp_Pnt2d(pnttg1sol(Index));
301 }
302 }
303
304
305void GccAna_Circ2dTanOnRad::
306 CenterOn3 (const Standard_Integer Index,
307 Standard_Real& ParArg,
308 gp_Pnt2d& PntSol) const{
309 if (!WellDone) {
310 StdFail_NotDone::Raise();
311 }
312 else if (Index <= 0 ||Index > NbrSol) {
313 Standard_OutOfRange::Raise();
314 }
315 else {
316 ParArg = parcen3(Index);
317 PntSol = pnttg1sol(Index);
318 }
319 }
320
321Standard_Boolean GccAna_Circ2dTanOnRad::IsTheSame1 (const Standard_Integer Index) const
322{
323 if (!WellDone)
324 StdFail_NotDone::Raise();
325
326 if (Index <= 0 ||Index > NbrSol)
327 Standard_OutOfRange::Raise();
328
329 if (TheSame1(Index) == 0)
330 return Standard_False;
331
332 return Standard_True;
333}