1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
22 #include <GccAna_Circ2d2TanRad.ixx>
25 #include <gp_Ax2d.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <gp_Lin2d.hxx>
28 #include <IntAna2d_AnaIntersection.hxx>
29 #include <IntAna2d_IntPoint.hxx>
30 #include <Standard_NegativeValue.hxx>
31 #include <Standard_OutOfRange.hxx>
32 #include <StdFail_NotDone.hxx>
33 #include <GccEnt_BadQualifier.hxx>
34 #include <Precision.hxx>
36 // circular tangent to two cercles and given radius
37 //====================================================
38 //==================================================================
39 // Initialize WellDone to false. +
40 // Return circle C1 and circle C2. +
41 // Leave with error if the construction is impossible. +
42 // Distinguish boundary cases to process them separately. +
43 // Create parallel to C1 in the proper direction. +
44 // Create parallel to C2 in the proper direction. +
45 // Intersect parallels ==> center point of the solution. +
46 // Create the solution to be added to already found solutions. +
48 //==================================================================
50 GccAna_Circ2d2TanRad::
51 GccAna_Circ2d2TanRad (const GccEnt_QualifiedCirc& Qualified1 ,
52 const GccEnt_QualifiedCirc& Qualified2 ,
53 const Standard_Real Radius ,
54 const Standard_Real Tolerance ):
68 Standard_Real Tol = Abs(Tolerance);
70 WellDone = Standard_False;
72 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
73 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
74 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
75 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
76 GccEnt_BadQualifier::Raise();
79 Standard_Boolean invers = Standard_False;
80 gp_Circ2d C1 = Qualified1.Qualified();
81 gp_Circ2d C2 = Qualified2.Qualified();
82 Standard_Real R1 = C1.Radius();
83 Standard_Real R2 = C2.Radius();
84 Standard_Real rbid = 0.;
85 Standard_Integer signe=0;
88 TColgp_Array1OfCirc2d C(1,8);
91 Standard_Integer nbsol = 0;
92 gp_Pnt2d center1(C1.Location());
93 gp_Pnt2d center2(C2.Location());
95 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
96 else if ( C(2).Location().IsEqual(C(1).Location(),Precision::Confusion())){
97 WellDone = Standard_True;
100 gp_Dir2d dir1(C(2).Location().XY()-C(1).Location().XY());
101 dist = (center2).Distance(center1);
102 if ((Qualified1.IsEnclosed()) && Qualified2.IsEnclosed()) {
103 // =========================================================
104 if (Radius*2.0-Abs(R1+R2-dist) > Tol) { WellDone = Standard_True; }
106 if ((dist-R1-R2>Tol)||(Tol<Max(R1,R2)-dist-Min(R1,R2))) {
107 WellDone = Standard_True;
109 else if (Abs(dist-R1-R2)<=Tol||Abs(Max(R1,R2)-dist-Min(R1,R2))<=Tol) {
110 if (Abs(dist-R1-R2) <= Tol) {
111 rbid = R2+(dist-R1-R2)/2.0;
114 else if (Abs(Max(R1,R2)-dist-Min(R1,R2)) <= Tol) {
115 if (R1 > R2) { R3 = R2; }
120 rbid = -R3+(Min(R1,R2)+dist-Max(R1,R2))/2.;
123 gp_Ax2d axe(gp_Pnt2d(center2.XY()-rbid*dir1.XY()),dirx);
124 cirsol(1) = gp_Circ2d(axe,Radius);
125 // =================================
126 qualifier1(1) = Qualified1.Qualifier();
127 qualifier2(1) = Qualified2.Qualifier();
128 pnttg1sol(1)=gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
129 pnttg2sol(1)=gp_Pnt2d(center1.XY()+R1*dir1.XY());
132 WellDone = Standard_True;
136 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
137 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
142 else if (((Qualified1.IsEnclosed()) && Qualified2.IsEnclosing()) ||
143 // ===================================================================
144 ((Qualified1.IsEnclosing()) && Qualified2.IsEnclosed())) {
145 // ========================================================
146 if (Qualified1.IsEnclosing()) {
148 C(1) = gp_Circ2d(C2);
150 C(2) = gp_Circ2d(C1);
156 // it is necessary to swap the resulting tangency points
157 invers = Standard_True;
159 if ((R2-Radius>Tol) || (Tol<Radius-R1) || (Tol>R1-dist-R2) ||
160 ((Tol<Radius*2-R1-dist-R2)||(Tol<R1+R2-dist-Radius*2.0))) {
161 WellDone = Standard_True;
163 else if ((Abs(R2-Radius)<=Tol) || (Abs(R1-Radius)<=Tol)) {
164 if (Abs(R2-Radius) <= Tol) {
165 C(2) = gp_Circ2d(C2);
169 pnttg1sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
171 else if (Abs(Radius-R1) <= Tol) {
172 C(2) = gp_Circ2d(C1);
176 pnttg2sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
178 WellDone = Standard_True;
180 gp_Ax2d axe(C(2).Location(),dirx);
181 cirsol(1) = gp_Circ2d(axe,Radius);
182 // =================================
183 qualifier1(1) = Qualified1.Qualifier();
184 qualifier2(1) = Qualified2.Qualifier();
187 if ((Abs(R2+dist-R1) <= Tol) || (Abs(Radius*2.0-R1-dist-R2) < Tol)) {
188 if (Abs(R2+dist-R1) <= Tol) { signe = 1; }
189 else if (Abs(Radius*2.0-R1-dist-R2) < Tol) {signe = -1; }
190 WellDone = Standard_True;
192 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
193 signe*(R1-Radius)*dir1.XY()),dirx);
194 cirsol(1) = gp_Circ2d(axe,Radius);
195 // =================================
196 qualifier1(1) = Qualified1.Qualifier();
197 qualifier2(1) = Qualified2.Qualifier();
198 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
199 pnttg2sol(1)=gp_Pnt2d(center2.XY()+R2*dir1.XY());
204 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
205 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
210 else if (((Qualified1.IsEnclosed()) && (Qualified2.IsOutside())) ||
211 // ===================================================================
212 ((Qualified1.IsOutside()) && (Qualified2.IsEnclosed()))) {
213 // ========================================================
214 if (Qualified1.IsOutside()) {
215 C(2) = gp_Circ2d(C1);
216 C(1) = gp_Circ2d(C2);
224 // it is necessary to swap the resulting tangency points
225 invers = Standard_True;
227 if ((Radius-R1>Tol)||(dist-R2-R1>Tol)||
228 ((R2-dist-R1+Radius*2>Tol)||(R1-R2-dist-Radius*2>Tol))){
229 WellDone = Standard_True;
232 if (((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) ||
233 (Abs(R1-R2+dist-Radius*2.0) <= Tol) ||
234 (Abs(R1-R2-dist-Radius*2.0) <= Tol) || (Abs(dist-R1-R2) <= Tol)) {
235 if (Abs(R1-R2+dist-Radius*2.0) <= Tol) {
240 if ((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) {
243 else if (Abs(dist-R1-R2) <= Tol) {
245 if (Abs(R1-Radius) <= Tol) {
250 WellDone = Standard_True;
252 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
253 signe*(R1-Radius)*dir1.XY()),dirx);
254 cirsol(1) = gp_Circ2d(axe,Radius);
255 // =================================
256 qualifier1(1) = Qualified1.Qualifier();
257 qualifier2(1) = Qualified2.Qualifier();
258 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
259 pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
264 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
265 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
270 else if (((Qualified1.IsEnclosed()) && (Qualified2.IsUnqualified())) ||
271 // =======================================================================
272 ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosed()))) {
273 // ============================================================
274 if (Qualified1.IsUnqualified()) {
275 C(1) = gp_Circ2d(C2);
276 C(2) = gp_Circ2d(C1);
284 // it is necessary to swap the resulting tangency points
285 invers = Standard_True;
287 if ((Radius-R1 > Tol) || (dist-R2-R1 > Tol)) { WellDone = Standard_True; }
289 if ((Abs(dist-R2-R1) <= Tol) || (Abs(Radius-R1) <= Tol)) {
290 WellDone = Standard_True;
292 gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
293 cirsol(1) = gp_Circ2d(ax,Radius);
294 // ================================
295 qualifier1(1) = Qualified1.Qualifier();
296 qualifier2(1) = Qualified2.Qualifier();
297 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
299 if (Abs(Radius-R1) > 0.0) {
304 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
308 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
309 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
310 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
311 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
316 else if ((Qualified1.IsEnclosing()) && (Qualified2.IsEnclosing())) {
317 // ==================================================================
318 if ((Tol < Max(R1,R2)-Radius) || (Tol < Max(R1,R2)-dist-Min(R1,R2)) ||
319 (dist+R1+R2-Radius*2.0 > Tol)) { WellDone = Standard_True; }
321 if ((Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) ||
322 (Abs(R1+R2+dist-2.0*Radius) <= Tol)) {
323 if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
329 WellDone = Standard_True;
331 gp_Ax2d axe(gp_Pnt2d(center1.XY()+
332 signe*(R1-Radius)*dir1.XY()),dirx);
333 cirsol(1) = gp_Circ2d(axe,Radius);
334 // =================================
335 qualifier1(1) = Qualified1.Qualifier();
336 qualifier2(1) = Qualified2.Qualifier();
337 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
338 pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
342 else if (Abs(Radius-Max(R1,R2)) <= Tol) {
343 WellDone = Standard_True;
346 C(1) = gp_Circ2d(C1);
347 C(2) = gp_Circ2d(C2);
350 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
353 C(1) = gp_Circ2d(C2);
354 C(2) = gp_Circ2d(C1);
357 pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
359 gp_Ax2d axe(C(1).Location(),dirx);
360 cirsol(1) = gp_Circ2d(axe,Radius);
361 // =================================
362 qualifier1(1) = Qualified1.Qualifier();
363 qualifier2(1) = Qualified2.Qualifier();
366 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
367 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
372 else if (((Qualified1.IsEnclosing()) && (Qualified2.IsOutside())) ||
373 // ====================================================================
374 ((Qualified1.IsOutside()) && (Qualified2.IsEnclosing()))) {
375 // =========================================================
376 if (Qualified1.IsOutside()) {
377 C(1) = gp_Circ2d(C2);
378 C(2) = gp_Circ2d(C1);
386 // it is necessary to swap the resulting tangency points
387 invers = Standard_True;
389 if ((R1-Radius > Tol) || (Tol < R1+R2-dist) ||
390 (dist-R2+R1-Radius*2.0>Tol)) {
391 WellDone = Standard_True;
393 else if (((Abs(R1-Radius)<=Tol) || (Abs(R1+R2-dist)<=Tol))||
394 (Abs(dist-R2+R1-Radius*2.0) <= Tol)) {
395 WellDone = Standard_True;
397 if((Abs(R1-Radius) <= Tol) || (Abs(R1+R2-dist) <= Tol)){
404 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
405 cirsol(1) = gp_Circ2d(axe,Radius);
406 // =================================
407 qualifier1(1) = Qualified1.Qualifier();
408 qualifier2(1) = Qualified2.Qualifier();
409 pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
410 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
413 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
414 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
418 else if (((Qualified1.IsEnclosing()) && (Qualified2.IsUnqualified())) ||
419 // ========================================================================
420 ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosing()))) {
421 // =============================================================
422 if (Qualified1.IsUnqualified()) {
423 C(1) = gp_Circ2d(C2);
424 C(2) = gp_Circ2d(C1);
431 invers = Standard_True;
434 if ((Tol < R1-dist-R2) || (R1-Radius > Tol)) { WellDone = Standard_True; }
435 else if ((Abs(R1-Radius) <= Tol) || (Abs(R1-dist-R2) > 0.0)) {
436 if (Abs(R1-Radius) <= Tol) {
438 if((Abs(Radius-R2) <= Tol) &&
439 (center1.Distance(center2) <= Tol)) {
443 else if (Abs(R1-dist-R2) > 0.0) {
447 WellDone = Standard_True;
449 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius-R1)*dir1.XY()),dirx);
450 cirsol(1) = gp_Circ2d(axe,Radius);
451 // =================================
452 qualifier1(1) = Qualified1.Qualifier();
453 qualifier2(1) = Qualified2.Qualifier();
454 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
455 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
458 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
459 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
460 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
461 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
465 else if ((Qualified1.IsOutside()) && (Qualified2.IsOutside())) {
466 // ==============================================================
467 if (Tol < Max(R1,R2)-dist-Min(R1,R2)) { WellDone = Standard_True; }
468 else if (dist-R1-R2-Radius*2.0 > Tol) { WellDone = Standard_True; }
470 if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
471 WellDone = Standard_True;
473 if (R1 < R2) { signe = -1; }
475 gp_Ax2d axe(gp_Pnt2d(center1.XY()+signe*(Radius+R1)*dir1.XY()),
477 cirsol(1) = gp_Circ2d(axe,Radius);
478 // =================================
479 qualifier1(1) = Qualified1.Qualifier();
480 qualifier2(1) = Qualified2.Qualifier();
481 pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
482 pnttg2sol(1) = gp_Pnt2d(pnttg1sol(1));
486 else if (Abs(dist-R1-R2-Radius*2.0) <= Tol) {
487 WellDone = Standard_True;
489 gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1+Radius)*dir1.XY()),dirx);
490 cirsol(1) = gp_Circ2d(ax,Radius);
491 // ================================
492 qualifier1(1) = Qualified1.Qualifier();
493 qualifier2(1) = Qualified2.Qualifier();
494 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
495 pnttg2sol(1) = gp_Pnt2d(center2.XY()-R2*dir1.XY());
500 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
501 C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
506 else if (((Qualified1.IsOutside()) && (Qualified2.IsUnqualified())) ||
507 // ======================================================================
508 ((Qualified1.IsUnqualified()) && (Qualified2.IsOutside()))) {
509 // ===========================================================
510 if (Qualified1.IsUnqualified()) {
511 C(1) = gp_Circ2d(C2);
514 C(2) = gp_Circ2d(C1);
520 // it is necessary to swap the resulting tangency points
521 invers = Standard_True;
523 if (Tol < R1-dist-R2) { WellDone = Standard_True; }
524 else if ((Tol < R2-dist-R1) && (Tol < Radius*2.0-R2-dist+R1)) {
525 WellDone = Standard_True;
527 else if ((dist-R1-R2 > Tol) && (Tol < dist-R1-R2-Radius*2.0)) {
528 WellDone = Standard_True;
531 if ((Abs(R1-R2-dist)<=Tol) ||
532 ((Abs(dist-R1-R2)<=Tol) && (Abs(Radius*2.0-dist+R1+R2) <= Tol)) ||
533 ((Abs(dist+R1-R2)<=Tol) && (Abs(R2+dist-R1-Radius*2.0)<=Tol))) {
534 WellDone = Standard_True;
536 gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius+R1)*dir1.XY()),
538 cirsol(1) = gp_Circ2d(axe,Radius);
539 // =================================
540 qualifier1(1) = Qualified1.Qualifier();
541 qualifier2(1) = Qualified2.Qualifier();
542 pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
543 pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
548 C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
549 C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
550 C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
551 C(2) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R2));
556 else if ((Qualified1.IsUnqualified()) && (Qualified2.IsUnqualified())) {
557 // ======================================================================
558 if ((dist-R1-R2>Tol)&&(Tol<(dist-R1-R2-Radius*2))) {
559 WellDone = Standard_True;
561 else if ((Max(R1,R2)-dist-Min(R1,R2)>Tol) &&
562 (((Max(R1,R2)-dist-Min(R1,R2))-Radius*2.0 > Tol))) {
563 WellDone = Standard_True;
566 Standard_Real p3 = Max(R1,R2)-Min(R1,R2)-dist-Radius*2.0;
567 Standard_Real p4 = dist-R1-R2;
568 Standard_Real p5 = Radius*2.0-dist+R1+R2;
570 dist = Max(R1,R2)-Min(R1,R2)-Radius*2.0;
572 else if (p4 > 0.0 && p5 < 0.0) {
573 R1 = dist-R2-Radius*2.0;
575 C(1) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
576 C(2) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
577 C(3) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
578 C(4) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
579 C(5) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
580 C(6) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
581 C(7) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
582 C(8) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
587 for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
588 IntAna2d_AnaIntersection Intp(C(2*j-1),C(2*j));
590 if (!Intp.IsEmpty()) {
591 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
593 gp_Pnt2d Center(Intp.Point(i).Value());
594 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
595 // =======================================================
596 dir1 = gp_Dir2d(Center.XY()-center1.XY());
597 gp_Dir2d dir2(Center.XY()-center2.XY());
598 Standard_Real distcc1 = Center.Distance(center1);
599 Standard_Real distcc2 = Center.Distance(center2);
600 if (!Qualified1.IsUnqualified()) {
601 qualifier1(NbrSol) = Qualified1.Qualifier();
603 else if (Abs(distcc1+Radius-R1) < Tol) {
604 qualifier1(NbrSol) = GccEnt_enclosed;
606 else if (Abs(distcc1-R1-Radius) < Tol) {
607 qualifier1(NbrSol) = GccEnt_outside;
609 else { qualifier1(NbrSol) = GccEnt_enclosing; }
610 if (!Qualified2.IsUnqualified()) {
611 qualifier2(NbrSol) = Qualified2.Qualifier();
613 else if (Abs(distcc2+Radius-R2) < Tol) {
614 qualifier2(NbrSol) = GccEnt_enclosed;
616 else if (Abs(distcc2-R2-Radius) < Tol) {
617 qualifier2(NbrSol) = GccEnt_outside;
619 else { qualifier2(NbrSol) = GccEnt_enclosing; }
620 if ((Center.Distance(center1) > R1) &&
621 (Radius < Center.Distance(center1)+R1)) {
622 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
624 else if ((Center.Distance(center1) < R1) &&
626 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1.XY());
629 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
631 if ((Center.Distance(center2) > R2) &&
632 (Radius < Center.Distance(center2)+R2)) {
633 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
635 else if ((Center.Distance(center2) < R2) &&
637 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir2.XY());
640 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
642 TheSame1(NbrSol) = 0;
643 TheSame2(NbrSol) = 0;
646 WellDone = Standard_True;
651 // swapping of resulting tangency points if necessary
654 for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
656 pnttg1sol(i) = pnttg2sol(i);
660 // calculation of parameters of tangency points
661 for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
662 par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
663 if (TheSame1(i) == 0) {
664 pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i));
666 par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
667 if (TheSame2(i) == 0) {
668 pararg2(i)=ElCLib::Parameter(C2,pnttg2sol(i));
673 Standard_Boolean GccAna_Circ2d2TanRad::
674 IsDone () const { return WellDone; }
676 Standard_Integer GccAna_Circ2d2TanRad::
677 NbSolutions () const { return NbrSol; }
679 gp_Circ2d GccAna_Circ2d2TanRad::
680 ThisSolution (const Standard_Integer Index) const
682 if (!WellDone) { StdFail_NotDone::Raise(); }
683 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
684 return cirsol(Index);
687 void GccAna_Circ2d2TanRad::
688 WhichQualifier(const Standard_Integer Index ,
689 GccEnt_Position& Qualif1 ,
690 GccEnt_Position& Qualif2 ) const
692 if (!WellDone) { StdFail_NotDone::Raise(); }
693 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
695 Qualif1 = qualifier1(Index);
696 Qualif2 = qualifier2(Index);
699 void GccAna_Circ2d2TanRad::
700 Tangency1 (const Standard_Integer Index,
701 Standard_Real& ParSol,
702 Standard_Real& ParArg,
703 gp_Pnt2d& PntSol) const{
704 if (!WellDone) { StdFail_NotDone::Raise(); }
705 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
707 if (TheSame1(Index) == 0) {
708 ParSol = par1sol(Index);
709 ParArg = pararg1(Index);
710 PntSol = gp_Pnt2d(pnttg1sol(Index));
712 else { StdFail_NotDone::Raise(); }
716 void GccAna_Circ2d2TanRad::
717 Tangency2 (const Standard_Integer Index,
718 Standard_Real& ParSol,
719 Standard_Real& ParArg,
720 gp_Pnt2d& PntSol) const{
721 if (!WellDone) { StdFail_NotDone::Raise(); }
722 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
724 if (TheSame2(Index) == 0) {
725 ParSol = par2sol(Index);
726 ParArg = pararg2(Index);
727 PntSol = gp_Pnt2d(pnttg2sol(Index));
729 else { StdFail_NotDone::Raise(); }
733 Standard_Boolean GccAna_Circ2d2TanRad::
734 IsTheSame1 (const Standard_Integer Index) const
736 if (!WellDone) { StdFail_NotDone::Raise(); }
737 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
739 if (TheSame1(Index) == 0) { return Standard_False; }
741 return Standard_True;
744 Standard_Boolean GccAna_Circ2d2TanRad::
745 IsTheSame2 (const Standard_Integer Index) const
747 if (!WellDone) { StdFail_NotDone::Raise(); }
748 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
750 if (TheSame2(Index) == 0) { return Standard_False; }
751 return Standard_True;