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.
17 #include <GccAna_Circ2d2TanRad.hxx>
18 #include <GccEnt_BadQualifier.hxx>
19 #include <GccEnt_QualifiedCirc.hxx>
20 #include <GccEnt_QualifiedLin.hxx>
21 #include <gp_Ax2d.hxx>
22 #include <gp_Circ2d.hxx>
23 #include <gp_Lin2d.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <IntAna2d_AnaIntersection.hxx>
26 #include <IntAna2d_IntPoint.hxx>
27 #include <Precision.hxx>
28 #include <Standard_NegativeValue.hxx>
29 #include <Standard_OutOfRange.hxx>
30 #include <StdFail_NotDone.hxx>
32 // circular tangent to two cercles and given radius
33 //====================================================
34 //==================================================================
35 // Initialize WellDone to false. +
36 // Return circle C1 and circle C2. +
37 // Leave with error if the construction is impossible. +
38 // Distinguish boundary cases to process them separately. +
39 // Create parallel to C1 in the proper direction. +
40 // Create parallel to C2 in the proper direction. +
41 // Intersect parallels ==> center point of the solution. +
42 // Create the solution to be added to already found solutions. +
44 //==================================================================
45 GccAna_Circ2d2TanRad::
46 GccAna_Circ2d2TanRad (const GccEnt_QualifiedCirc& Qualified1 ,
47 const GccEnt_QualifiedCirc& Qualified2 ,
48 const Standard_Real Radius ,
49 const Standard_Real Tolerance ):
63 Standard_Real Tol = Abs(Tolerance);
65 WellDone = Standard_False;
67 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
68 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
69 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
70 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
71 throw GccEnt_BadQualifier();
74 Standard_Boolean invers = Standard_False;
75 gp_Circ2d C1 = Qualified1.Qualified();
76 gp_Circ2d C2 = Qualified2.Qualified();
77 Standard_Real R1 = C1.Radius();
78 Standard_Real R2 = C2.Radius();
79 Standard_Real rbid = 0.;
80 Standard_Integer signe=0;
83 TColgp_Array1OfCirc2d C(1,8);
86 Standard_Integer nbsol = 0;
87 gp_Pnt2d center1(C1.Location());
88 gp_Pnt2d center2(C2.Location());
90 if (Radius < 0.0) { throw Standard_NegativeValue(); }
91 else if ( C(2).Location().IsEqual(C(1).Location(),Precision::Confusion())){
92 WellDone = Standard_True;
95 gp_Dir2d dir1(C(2).Location().XY()-C(1).Location().XY());
96 dist = (center2).Distance(center1);
97 if ((Qualified1.IsEnclosed()) && Qualified2.IsEnclosed()) {
98 // =========================================================
99 if (Radius*2.0-Abs(R1+R2-dist) > Tol) { WellDone = Standard_True; }
101 if ((dist-R1-R2>Tol)||(Tol<Max(R1,R2)-dist-Min(R1,R2))) {
102 WellDone = Standard_True;
104 else if (Abs(dist-R1-R2)<=Tol||Abs(Max(R1,R2)-dist-Min(R1,R2))<=Tol) {
105 if (Abs(dist-R1-R2) <= Tol) {
106 rbid = R2+(dist-R1-R2)/2.0;
109 else if (Abs(Max(R1,R2)-dist-Min(R1,R2)) <= Tol) {
110 if (R1 > R2) { R3 = R2; }
115 rbid = -R3+(Min(R1,R2)+dist-Max(R1,R2))/2.;
118 gp_Ax2d axe(gp_Pnt2d(center2.XY()-rbid*dir1.XY()),dirx);
119 cirsol(1) = gp_Circ2d(axe,Radius);
120 // =================================
121 qualifier1(1) = Qualified1.Qualifier();
122 qualifier2(1) = Qualified2.Qualifier();
123 pnttg1sol(1)=gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
124 pnttg2sol(1)=gp_Pnt2d(center1.XY()+R1*dir1.XY());
127 WellDone = Standard_True;
131 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
132 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
137 else if (((Qualified1.IsEnclosed()) && Qualified2.IsEnclosing()) ||
138 // ===================================================================
139 ((Qualified1.IsEnclosing()) && Qualified2.IsEnclosed())) {
140 // ========================================================
141 if (Qualified1.IsEnclosing()) {
143 C(1) = gp_Circ2d(C2);
145 C(2) = gp_Circ2d(C1);
151 // it is necessary to swap the resulting tangency points
152 invers = Standard_True;
154 if ((R2-Radius>Tol) || (Tol<Radius-R1) || (Tol>R1-dist-R2) ||
155 ((Tol<Radius*2-R1-dist-R2)||(Tol<R1+R2-dist-Radius*2.0))) {
156 WellDone = Standard_True;
158 else if ((Abs(R2-Radius)<=Tol) || (Abs(R1-Radius)<=Tol)) {
159 if (Abs(R2-Radius) <= Tol) {
160 C(2) = gp_Circ2d(C2);
164 pnttg1sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
166 else if (Abs(Radius-R1) <= Tol) {
167 C(2) = gp_Circ2d(C1);
171 pnttg2sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
173 WellDone = Standard_True;
175 gp_Ax2d axe(C(2).Location(),dirx);
176 cirsol(1) = gp_Circ2d(axe,Radius);
177 // =================================
178 qualifier1(1) = Qualified1.Qualifier();
179 qualifier2(1) = Qualified2.Qualifier();
182 if ((Abs(R2+dist-R1) <= Tol) || (Abs(Radius*2.0-R1-dist-R2) < Tol)) {
183 if (Abs(R2+dist-R1) <= Tol) { signe = 1; }
184 else if (Abs(Radius*2.0-R1-dist-R2) < Tol) {signe = -1; }
185 WellDone = Standard_True;
187 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
188 signe*(R1-Radius)*dir1.XY()),dirx);
189 cirsol(1) = gp_Circ2d(axe,Radius);
190 // =================================
191 qualifier1(1) = Qualified1.Qualifier();
192 qualifier2(1) = Qualified2.Qualifier();
193 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
194 pnttg2sol(1)=gp_Pnt2d(center2.XY()+R2*dir1.XY());
199 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
200 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
205 else if (((Qualified1.IsEnclosed()) && (Qualified2.IsOutside())) ||
206 // ===================================================================
207 ((Qualified1.IsOutside()) && (Qualified2.IsEnclosed()))) {
208 // ========================================================
209 if (Qualified1.IsOutside()) {
210 C(2) = gp_Circ2d(C1);
211 C(1) = gp_Circ2d(C2);
219 // it is necessary to swap the resulting tangency points
220 invers = Standard_True;
222 if ((Radius-R1>Tol)||(dist-R2-R1>Tol)||
223 ((R2-dist-R1+Radius*2>Tol)||(R1-R2-dist-Radius*2>Tol))){
224 WellDone = Standard_True;
227 if (((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) ||
228 (Abs(R1-R2+dist-Radius*2.0) <= Tol) ||
229 (Abs(R1-R2-dist-Radius*2.0) <= Tol) || (Abs(dist-R1-R2) <= Tol)) {
230 if (Abs(R1-R2+dist-Radius*2.0) <= Tol) {
235 if ((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) {
238 else if (Abs(dist-R1-R2) <= Tol) {
240 if (Abs(R1-Radius) <= Tol) {
245 WellDone = Standard_True;
247 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
248 signe*(R1-Radius)*dir1.XY()),dirx);
249 cirsol(1) = gp_Circ2d(axe,Radius);
250 // =================================
251 qualifier1(1) = Qualified1.Qualifier();
252 qualifier2(1) = Qualified2.Qualifier();
253 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
254 pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
259 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
260 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
265 else if (((Qualified1.IsEnclosed()) && (Qualified2.IsUnqualified())) ||
266 // =======================================================================
267 ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosed()))) {
268 // ============================================================
269 if (Qualified1.IsUnqualified()) {
270 C(1) = gp_Circ2d(C2);
271 C(2) = gp_Circ2d(C1);
279 // it is necessary to swap the resulting tangency points
280 invers = Standard_True;
282 if ((Radius-R1 > Tol) || (dist-R2-R1 > Tol)) { WellDone = Standard_True; }
284 if ((Abs(dist-R2-R1) <= Tol) || (Abs(Radius-R1) <= Tol)) {
285 WellDone = Standard_True;
287 gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
288 cirsol(1) = gp_Circ2d(ax,Radius);
289 // ================================
290 qualifier1(1) = Qualified1.Qualifier();
291 qualifier2(1) = Qualified2.Qualifier();
292 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
294 if (Abs(Radius-R1) > 0.0) {
299 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
303 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
304 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
305 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
306 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
311 else if ((Qualified1.IsEnclosing()) && (Qualified2.IsEnclosing())) {
312 // ==================================================================
313 if ((Tol < Max(R1,R2)-Radius) || (Tol < Max(R1,R2)-dist-Min(R1,R2)) ||
314 (dist+R1+R2-Radius*2.0 > Tol)) { WellDone = Standard_True; }
316 if ((Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) ||
317 (Abs(R1+R2+dist-2.0*Radius) <= Tol)) {
318 if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
324 WellDone = Standard_True;
326 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
327 signe*(R1-Radius)*dir1.XY()),dirx);
328 cirsol(1) = gp_Circ2d(axe,Radius);
329 // =================================
330 qualifier1(1) = Qualified1.Qualifier();
331 qualifier2(1) = Qualified2.Qualifier();
332 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
333 pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
337 else if (Abs(Radius-Max(R1,R2)) <= Tol) {
338 WellDone = Standard_True;
341 C(1) = gp_Circ2d(C1);
342 C(2) = gp_Circ2d(C2);
345 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
348 C(1) = gp_Circ2d(C2);
349 C(2) = gp_Circ2d(C1);
352 pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
354 gp_Ax2d axe(C(1).Location(),dirx);
355 cirsol(1) = gp_Circ2d(axe,Radius);
356 // =================================
357 qualifier1(1) = Qualified1.Qualifier();
358 qualifier2(1) = Qualified2.Qualifier();
361 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
362 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
367 else if (((Qualified1.IsEnclosing()) && (Qualified2.IsOutside())) ||
368 // ====================================================================
369 ((Qualified1.IsOutside()) && (Qualified2.IsEnclosing()))) {
370 // =========================================================
371 if (Qualified1.IsOutside()) {
372 C(1) = gp_Circ2d(C2);
373 C(2) = gp_Circ2d(C1);
381 // it is necessary to swap the resulting tangency points
382 invers = Standard_True;
384 if ((R1-Radius > Tol) || (Tol < R1+R2-dist) ||
385 (dist-R2+R1-Radius*2.0>Tol)) {
386 WellDone = Standard_True;
388 else if (((Abs(R1-Radius)<=Tol) || (Abs(R1+R2-dist)<=Tol))||
389 (Abs(dist-R2+R1-Radius*2.0) <= Tol)) {
390 WellDone = Standard_True;
392 if((Abs(R1-Radius) <= Tol) || (Abs(R1+R2-dist) <= Tol)){
399 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
400 cirsol(1) = gp_Circ2d(axe,Radius);
401 // =================================
402 qualifier1(1) = Qualified1.Qualifier();
403 qualifier2(1) = Qualified2.Qualifier();
404 pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
405 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
408 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
409 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
413 else if (((Qualified1.IsEnclosing()) && (Qualified2.IsUnqualified())) ||
414 // ========================================================================
415 ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosing()))) {
416 // =============================================================
417 if (Qualified1.IsUnqualified()) {
418 C(1) = gp_Circ2d(C2);
419 C(2) = gp_Circ2d(C1);
426 invers = Standard_True;
429 if ((Tol < R1-dist-R2) || (R1-Radius > Tol)) { WellDone = Standard_True; }
430 else if ((Abs(R1-Radius) <= Tol) || (Abs(R1-dist-R2) > 0.0)) {
431 if (Abs(R1-Radius) <= Tol) {
433 if((Abs(Radius-R2) <= Tol) &&
434 (center1.Distance(center2) <= Tol)) {
438 else if (Abs(R1-dist-R2) > 0.0) {
442 WellDone = Standard_True;
444 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius-R1)*dir1.XY()),dirx);
445 cirsol(1) = gp_Circ2d(axe,Radius);
446 // =================================
447 qualifier1(1) = Qualified1.Qualifier();
448 qualifier2(1) = Qualified2.Qualifier();
449 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
450 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
453 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
454 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
455 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
456 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
460 else if ((Qualified1.IsOutside()) && (Qualified2.IsOutside())) {
461 // ==============================================================
462 if (Tol < Max(R1,R2)-dist-Min(R1,R2)) { WellDone = Standard_True; }
463 else if (dist-R1-R2-Radius*2.0 > Tol) { WellDone = Standard_True; }
465 if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
466 WellDone = Standard_True;
468 if (R1 < R2) { signe = -1; }
470 gp_Ax2d axe(gp_Pnt2d(center1.XY()+signe*(Radius+R1)*dir1.XY()),
472 cirsol(1) = gp_Circ2d(axe,Radius);
473 // =================================
474 qualifier1(1) = Qualified1.Qualifier();
475 qualifier2(1) = Qualified2.Qualifier();
476 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
477 pnttg2sol(1) = gp_Pnt2d(pnttg1sol(1));
481 else if (Abs(dist-R1-R2-Radius*2.0) <= Tol) {
482 WellDone = Standard_True;
484 gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1+Radius)*dir1.XY()),dirx);
485 cirsol(1) = gp_Circ2d(ax,Radius);
486 // ================================
487 qualifier1(1) = Qualified1.Qualifier();
488 qualifier2(1) = Qualified2.Qualifier();
489 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
490 pnttg2sol(1) = gp_Pnt2d(center2.XY()-R2*dir1.XY());
495 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
496 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
501 else if (((Qualified1.IsOutside()) && (Qualified2.IsUnqualified())) ||
502 // ======================================================================
503 ((Qualified1.IsUnqualified()) && (Qualified2.IsOutside()))) {
504 // ===========================================================
505 if (Qualified1.IsUnqualified()) {
506 C(1) = gp_Circ2d(C2);
509 C(2) = gp_Circ2d(C1);
515 // it is necessary to swap the resulting tangency points
516 invers = Standard_True;
518 if (Tol < R1-dist-R2) { WellDone = Standard_True; }
519 else if ((Tol < R2-dist-R1) && (Tol < Radius*2.0-R2-dist+R1)) {
520 WellDone = Standard_True;
522 else if ((dist-R1-R2 > Tol) && (Tol < dist-R1-R2-Radius*2.0)) {
523 WellDone = Standard_True;
526 if ((Abs(R1-R2-dist)<=Tol) ||
527 ((Abs(dist-R1-R2)<=Tol) && (Abs(Radius*2.0-dist+R1+R2) <= Tol)) ||
528 ((Abs(dist+R1-R2)<=Tol) && (Abs(R2+dist-R1-Radius*2.0)<=Tol))) {
529 WellDone = Standard_True;
531 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius+R1)*dir1.XY()),
533 cirsol(1) = gp_Circ2d(axe,Radius);
534 // =================================
535 qualifier1(1) = Qualified1.Qualifier();
536 qualifier2(1) = Qualified2.Qualifier();
537 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
538 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
543 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
544 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
545 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
546 C(2) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R2));
551 else if ((Qualified1.IsUnqualified()) && (Qualified2.IsUnqualified())) {
552 // ======================================================================
553 if ((dist-R1-R2>Tol)&&(Tol<(dist-R1-R2-Radius*2))) {
554 WellDone = Standard_True;
556 else if ((Max(R1,R2)-dist-Min(R1,R2)>Tol) &&
557 (((Max(R1,R2)-dist-Min(R1,R2))-Radius*2.0 > Tol))) {
558 WellDone = Standard_True;
561 Standard_Real p3 = Max(R1,R2)-Min(R1,R2)-dist-Radius*2.0;
562 Standard_Real p4 = dist-R1-R2;
563 Standard_Real p5 = Radius*2.0-dist+R1+R2;
565 dist = Max(R1,R2)-Min(R1,R2)-Radius*2.0;
567 else if (p4 > 0.0 && p5 < 0.0) {
568 R1 = dist-R2-Radius*2.0;
570 C(1) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
571 C(2) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
572 C(3) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
573 C(4) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
574 C(5) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
575 C(6) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
576 C(7) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
577 C(8) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
582 for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
583 IntAna2d_AnaIntersection Intp(C(2*j-1),C(2*j));
585 if (!Intp.IsEmpty()) {
586 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
588 gp_Pnt2d Center(Intp.Point(i).Value());
589 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
590 // =======================================================
591 dir1 = gp_Dir2d(Center.XY()-center1.XY());
592 gp_Dir2d dir2(Center.XY()-center2.XY());
593 Standard_Real distcc1 = Center.Distance(center1);
594 Standard_Real distcc2 = Center.Distance(center2);
595 if (!Qualified1.IsUnqualified()) {
596 qualifier1(NbrSol) = Qualified1.Qualifier();
598 else if (Abs(distcc1+Radius-R1) < Tol) {
599 qualifier1(NbrSol) = GccEnt_enclosed;
601 else if (Abs(distcc1-R1-Radius) < Tol) {
602 qualifier1(NbrSol) = GccEnt_outside;
604 else { qualifier1(NbrSol) = GccEnt_enclosing; }
605 if (!Qualified2.IsUnqualified()) {
606 qualifier2(NbrSol) = Qualified2.Qualifier();
608 else if (Abs(distcc2+Radius-R2) < Tol) {
609 qualifier2(NbrSol) = GccEnt_enclosed;
611 else if (Abs(distcc2-R2-Radius) < Tol) {
612 qualifier2(NbrSol) = GccEnt_outside;
614 else { qualifier2(NbrSol) = GccEnt_enclosing; }
615 if ((Center.Distance(center1) > R1) &&
616 (Radius < Center.Distance(center1)+R1)) {
617 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
619 else if ((Center.Distance(center1) < R1) &&
621 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1.XY());
624 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
626 if ((Center.Distance(center2) > R2) &&
627 (Radius < Center.Distance(center2)+R2)) {
628 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
630 else if ((Center.Distance(center2) < R2) &&
632 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir2.XY());
635 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
637 TheSame1(NbrSol) = 0;
638 TheSame2(NbrSol) = 0;
641 WellDone = Standard_True;
646 // swapping of resulting tangency points if necessary
649 for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
651 pnttg1sol(i) = pnttg2sol(i);
655 // calculation of parameters of tangency points
656 for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
657 par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
658 if (TheSame1(i) == 0) {
659 pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i));
661 par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
662 if (TheSame2(i) == 0) {
663 pararg2(i)=ElCLib::Parameter(C2,pnttg2sol(i));
668 Standard_Boolean GccAna_Circ2d2TanRad::
669 IsDone () const { return WellDone; }
671 Standard_Integer GccAna_Circ2d2TanRad::
672 NbSolutions () const { return NbrSol; }
674 gp_Circ2d GccAna_Circ2d2TanRad::
675 ThisSolution (const Standard_Integer Index) const
677 if (!WellDone) { throw StdFail_NotDone(); }
678 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
679 return cirsol(Index);
682 void GccAna_Circ2d2TanRad::
683 WhichQualifier(const Standard_Integer Index ,
684 GccEnt_Position& Qualif1 ,
685 GccEnt_Position& Qualif2 ) const
687 if (!WellDone) { throw StdFail_NotDone(); }
688 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
690 Qualif1 = qualifier1(Index);
691 Qualif2 = qualifier2(Index);
694 void GccAna_Circ2d2TanRad::
695 Tangency1 (const Standard_Integer Index,
696 Standard_Real& ParSol,
697 Standard_Real& ParArg,
698 gp_Pnt2d& PntSol) const{
699 if (!WellDone) { throw StdFail_NotDone(); }
700 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
702 if (TheSame1(Index) == 0) {
703 ParSol = par1sol(Index);
704 ParArg = pararg1(Index);
705 PntSol = gp_Pnt2d(pnttg1sol(Index));
707 else { throw StdFail_NotDone(); }
711 void GccAna_Circ2d2TanRad::
712 Tangency2 (const Standard_Integer Index,
713 Standard_Real& ParSol,
714 Standard_Real& ParArg,
715 gp_Pnt2d& PntSol) const{
716 if (!WellDone) { throw StdFail_NotDone(); }
717 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
719 if (TheSame2(Index) == 0) {
720 ParSol = par2sol(Index);
721 ParArg = pararg2(Index);
722 PntSol = gp_Pnt2d(pnttg2sol(Index));
724 else { throw StdFail_NotDone(); }
728 Standard_Boolean GccAna_Circ2d2TanRad::
729 IsTheSame1 (const Standard_Integer Index) const
731 if (!WellDone) { throw StdFail_NotDone(); }
732 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
734 if (TheSame1(Index) == 0) { return Standard_False; }
736 return Standard_True;
739 Standard_Boolean GccAna_Circ2d2TanRad::
740 IsTheSame2 (const Standard_Integer Index) const
742 if (!WellDone) { throw StdFail_NotDone(); }
743 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
745 if (TheSame2(Index) == 0) { return Standard_False; }
746 return Standard_True;