6dc567ef7b5e03aca771dd85790dca700bc6aac9
[occt.git] / src / GccAna / GccAna_Circ2d2TanRad_1.cxx
1 // Created on: 1991-09-24
2 // Created by: Remi GILET
3 // Copyright (c) 1991-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_Circ2d2TanRad.hxx>
20 #include <GccEnt_BadQualifier.hxx>
21 #include <GccEnt_QualifiedCirc.hxx>
22 #include <GccEnt_QualifiedLin.hxx>
23 #include <gp_Ax2d.hxx>
24 #include <gp_Circ2d.hxx>
25 #include <gp_Lin2d.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <IntAna2d_AnaIntersection.hxx>
28 #include <IntAna2d_IntPoint.hxx>
29 #include <Standard_NegativeValue.hxx>
30 #include <Standard_OutOfRange.hxx>
31 #include <StdFail_NotDone.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33
34 // circular tangent to a circle, a line and a given radius
35 //==============================================================
36 //========================================================================
37 // Initialize WellDone to false.                                         +
38 // Return circle C1 and straight line L2.                                +
39 // Leave with error if the construction is impossible.                   +
40 // Create parallel to C1 in the proper direction.                        +
41 // Create parallel to L2 in the proper direction.                        +
42 // Intersect parallels ==> center point of the solution.                 +
43 // Create the solution and add it to already found ones.                 +
44 // Fill the fields.                                                      +
45 //========================================================================
46 GccAna_Circ2d2TanRad::
47    GccAna_Circ2d2TanRad (const GccEnt_QualifiedCirc& Qualified1 ,
48                          const GccEnt_QualifiedLin&  Qualified2 ,
49                          const Standard_Real         Radius     ,
50                          const Standard_Real         Tolerance  ):
51    qualifier1(1,8) ,
52    qualifier2(1,8),
53    TheSame1(1,8)   ,
54    TheSame2(1,8)   ,
55    cirsol(1,8)     ,
56    pnttg1sol(1,8)  ,
57    pnttg2sol(1,8)  ,
58    par1sol(1,8)    ,
59    par2sol(1,8)    ,
60    pararg1(1,8)    ,
61    pararg2(1,8)    
62 {
63
64   Standard_Real Tol = Abs(Tolerance);
65   gp_Dir2d dirx(1.,0.);
66   NbrSol = 0;
67   WellDone = Standard_False;
68   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
69         Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
70       !(Qualified2.IsEnclosed() || Qualified2.IsOutside() || 
71         Qualified2.IsUnqualified())) {
72     throw GccEnt_BadQualifier();
73     return;
74   }
75   Standard_Integer i ;
76   for ( i = 1 ; i <= 8 ; i++) { TheSame2(i) = 0; }
77   Standard_Integer ncote1=0;
78   Standard_Integer ncote2=0;
79   Standard_Integer nbsol = 0;
80   Standard_Real cote = 0.0;
81   Standard_Real ccote = 0.0;
82   TColStd_Array1OfReal cote1(1,3);
83   TColStd_Array1OfReal cote2(1,2);
84   gp_Circ2d C1 = Qualified1.Qualified();
85   gp_Lin2d  L2 = Qualified2.Qualified();
86   Standard_Real xdir = (L2.Direction()).X();
87   Standard_Real ydir = (L2.Direction()).Y();
88   gp_Dir2d normL2(-ydir,xdir);
89   Standard_Real lxloc = (L2.Location()).X();
90   Standard_Real lyloc = (L2.Location()).Y();
91   Standard_Real cxloc = (C1.Location()).X();
92   Standard_Real cyloc = (C1.Location()).Y();
93   Standard_Real R1 = C1.Radius();
94   gp_Pnt2d center1(cxloc,cyloc);
95   gp_Pnt2d origin2(lxloc,lyloc);
96   Standard_Real dist = Radius*2.0 + R1;
97   Standard_Real distance = L2.Distance(center1);
98   
99   if (Radius < 0.0) { throw Standard_NegativeValue(); }
100   else {
101     if ( distance-dist >Tol) { WellDone = Standard_True; }
102     else if (Qualified1.IsEnclosed()) {
103 //  =================================
104       if (Qualified2.IsEnclosed()) {
105 //    ============================
106         if (distance-R1 > Tol) { WellDone = Standard_True; }
107         else if (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) && 
108                   (Radius*2.0-R1+distance > Tol)) ||
109                  ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) &&
110                   (Radius*2.0-R1-distance > Tol))||
111                  (Radius-R1 > Tol)) { WellDone = Standard_True; }
112         else {
113           if (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) && 
114                (Radius*2.0>R1-distance)) || (Abs(distance-R1)<Tol) ||
115               ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) &&
116                (Radius*2.0 > (R1+distance+Tol)))) {
117             cote = 1.0;
118             nbsol = 3;
119             ccote = 1.0;
120           }
121           else {
122             ncote1 = 1;
123             ncote2 = 1;
124             cote1(1) = R1-Radius;
125             cote2(1) = 1.0;
126             nbsol = 1;
127           }
128         }
129       }
130       else if (Qualified2.IsOutside()) {
131 //    ================================
132         if (distance > R1+Tol) { WellDone = Standard_True; }
133         else if ((((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)) > 0.0) &&
134                   (Radius*2.0-R1+distance > Tol)) ||
135                  (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)) < 0.0) &&
136                   (Radius*2.0-R1-distance > Tol)) ||
137                  (Radius-R1 >Tol)) { WellDone = Standard_True; }
138         else {
139           if (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc) > 0.0) && 
140                (Radius*2.0 > R1-distance)) || (Abs(R1-Radius) < Tol) ||
141               ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc) < 0.0) &&
142                (Radius*2.0>(R1+distance))) || (Abs(distance-R1)<Tol)) {
143             cote = -1.0;
144             nbsol = 3;
145             ccote = 1.0;
146           }
147           else {
148             ncote1 = 1;
149             ncote2 = 1;
150             cote1(1) = R1-Radius;
151             cote2(1) = -1.0;
152             nbsol = 1;
153           }
154         }
155       }
156       else if (Qualified2.IsUnqualified()) {
157 //    ====================================
158         if ((distance-R1>Tol) || (Radius*2.0-R1-distance>Tol) ||
159             (Radius-R1 > Tol)) { WellDone = Standard_True; }
160         else if (distance > R1) {
161           if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc) > 0.0)) {
162             cote = 1.0;
163           }
164           else {
165             cote = -1.0;
166             nbsol = 3;
167           }
168           nbsol = 3;
169           ccote = 1;
170         }
171         else {
172           ncote1 = 1;
173           ncote2 = 2;
174           cote1(1) = R1-Radius;
175           cote2(1) = 1.0;
176           cote2(2) = -1.0;
177           nbsol = 1;
178         }
179       }
180       if (nbsol == 3) {
181       }
182     }
183     else if (Qualified1.IsEnclosing()) {
184 //  ==================================
185       if (Qualified2.IsEnclosed()) {
186 //    =================================
187         if ((distance<R1-Tol)||(Radius<R1-Tol)||(Radius*2<distance+R1-Tol) ||
188             (Tol<R1-Radius)||(-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0)){
189           WellDone = Standard_True;
190         }
191         else if ((distance<R1) || (Radius<R1) || (Radius*2.0<distance+R1)) {
192           cote = 1.0;
193           ccote =1.0;
194           nbsol = 3;
195         }
196         else {
197           ncote1 = 1;
198           ncote2 = 1;
199           cote1(1) = Radius-R1;
200           cote2(1) = 1.0;
201           nbsol = 1;
202         }
203       }
204       else if (Qualified2.IsOutside()) {
205 //    ================================
206         if ((Tol<R1-distance) || (Tol<distance+R1-Radius*2.0) ||
207             (Tol<R1-Radius)||(-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0)){
208           WellDone = Standard_True;
209         }
210         else if ((distance<R1) || (Radius*2.0<distance+R1) || (Radius<R1)) {
211           cote = -1.0;
212           ccote = -1.0;
213           nbsol = 3;
214         }
215         else {
216           ncote1 = 1;
217           ncote2 = 1;
218           cote1(1) = Radius-R1;
219           cote2(1) = -1.0;
220           nbsol = 1;
221         }
222       }
223       else if (Qualified2.IsUnqualified()) {
224 //    ====================================
225         if ((distance<R1-Tol) || (Radius*2.0<distance+R1-Tol) ||
226             (Radius < R1-Tol)) { WellDone = Standard_True; }
227         else if ((distance < R1) || (Radius*2.0 < distance+R1)) {
228           if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc) > 0.0)) {
229             cote = 1.0;
230             ccote = 1.0;
231             nbsol = 3;
232           }
233           else {
234             ccote = -1.0;
235             cote = -1.0;
236             nbsol = 3;
237           }
238         }
239         else {
240           ncote1 = 1;
241           ncote2 = 2;
242           cote1(1) = Radius-R1;
243           cote2(1) = 1.0;
244           cote2(2) = -1.0;
245           nbsol = 1;
246         }
247       }
248     }
249     else if ((Qualified1.IsOutside()) && (Qualified2.IsEnclosed())) {
250 //  ===============================================================
251       if (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) &&
252            (distance>R1+Tol)) || (distance > R1+Radius*2.0+Tol)) {
253         WellDone = Standard_True;
254       }
255       else {
256         if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) &&
257             (distance>R1)) {
258           cote = 1.0;
259           nbsol = 2;
260         }
261         else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) &&
262                  (distance>R1+2.0*Radius)) {
263           cote = -1.0;
264           nbsol = 2;
265         }
266         else {
267           ncote1 = 1;
268           ncote2 = 1;
269           cote1(1) = Radius+R1;
270           cote2(1) = 1.0;
271           nbsol = 1;
272         }
273       }
274     }
275     else if ((Qualified1.IsOutside()) && (Qualified2.IsOutside())) {
276 //  ==============================================================
277       if (((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) &&
278            (distance>R1+Tol)) || (distance > R1+Radius*2.0+Tol)) {
279         WellDone = Standard_True;
280       }
281       else {
282         if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) && (distance>R1)) {
283           cote = -1.0;
284           nbsol = 2;
285         }
286         else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) &&
287                  (distance>R1+2.0*Radius)) {
288           cote = 1.0;
289           nbsol = 2;
290         }
291         else {
292           ncote1 = 1;
293           ncote2 = 1;
294           cote1(1) = Radius+R1;
295           cote2(1) = -1.0;
296           nbsol = 1;
297         }
298       }
299     }
300     else if ((Qualified1.IsOutside()) && (Qualified2.IsUnqualified())) {
301 //  ==================================================================
302       if (distance > Radius*2.0+R1+Tol) { WellDone = Standard_True; }
303       else if (distance > Radius*2.0+R1) {
304         if (-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) { cote = 1.0; }
305         else { cote = -1.0; }
306         nbsol = 4;
307       }
308       else {
309         ncote1 = 1;
310         ncote2 = 2;
311         cote1(1) = Radius+R1;
312         cote2(1) = 1.0;
313         cote2(2) = -1.0;
314         nbsol = 1;
315       }
316     }
317     else if ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosed())) {
318 //  ===================================================================
319       if ((distance>R1+Radius*2.0+Tol) ||
320           ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) && 
321            (distance > R1+Tol))){ WellDone = Standard_True; }
322       else {
323         if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) && (distance > R1)){
324           cote = 1.0;
325           nbsol = 2;
326         }
327         else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) &&
328                  (distance>R1+2.0*Radius)) {
329           cote = -1.0;
330           nbsol = 2;
331         }
332         else {
333           ncote1 = 2;
334           ncote2 = 1;
335           cote1(1) = Abs(Radius-R1);
336           cote1(2) = Radius+R1;
337           cote2(1) = 1.0;
338           nbsol = 1;
339         }
340       }
341     }
342     else if ((Qualified1.IsUnqualified()) && (Qualified2.IsOutside())) {
343 //  ==================================================================
344       if ((distance>R1+Radius*2.0+Tol) ||
345           ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) && 
346            (distance > R1+Tol))){ WellDone = Standard_True; }
347       else {
348         if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0) && (distance > R1)){
349           cote = -1.0;
350           nbsol = 2;
351         }
352         else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) &&
353                  (distance>R1+2.0*Radius)) {
354           cote = 1.0;
355           nbsol = 2;
356         }
357         else {
358           ncote1 = 2;
359           ncote2 = 1;
360           cote1(1) = Abs(Radius-R1);
361           cote1(2) = Radius+R1;
362           cote2(1) = -1.0;
363           nbsol = 1;
364         }
365       }
366     }
367     else if ((Qualified1.IsUnqualified()) && (Qualified2.IsUnqualified())) {
368 //  ======================================================================
369       if (distance>R1+Radius*2.0+Tol) { WellDone = Standard_True; }
370       else if (distance>R1+Radius*2.0) {
371         if (-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0) { cote = -1.0; }
372         else { cote = 1.0; }
373         nbsol = 4;
374       }
375       else {
376         ncote1 = 2;
377         ncote2 = 2;
378         cote1(1) = Abs(Radius-R1);
379         cote1(2) = Radius+R1;
380         cote2(1) = 1.0;
381         cote2(2) = -1.0;
382         nbsol = 1;
383       }
384     }
385     if (nbsol == 1) {
386       for (Standard_Integer jcote1 = 1 ; jcote1 <= ncote1 ; jcote1++) {
387         for (Standard_Integer jcote2 = 1 ; jcote2 <= ncote2 ; jcote2++) {
388           if (cote1(jcote1)<Tol) continue;
389           gp_Circ2d cirint(gp_Ax2d(center1,dirx),cote1(jcote1));
390           gp_Lin2d  linint(gp_Pnt2d(lxloc-cote2(jcote2)*ydir*Radius,
391                              lyloc+cote2(jcote2)*xdir*Radius),L2.Direction());
392           IntAna2d_AnaIntersection Intp(linint,cirint);
393           if (Intp.IsDone()) {
394             if (!Intp.IsEmpty()) {
395               for (i = 1 ; i <= Intp.NbPoints() ; i++) {
396                 NbrSol++;
397                 gp_Pnt2d Center(Intp.Point(i).Value());
398                 gp_Ax2d axe(Center,dirx);
399                 cirsol(NbrSol) = gp_Circ2d(axe,Radius);
400 //              ======================================
401 #ifdef OCCT_DEBUG
402                 gp_Dir2d dc1(center1.XY()-Center.XY());
403 #endif
404                 gp_Dir2d dc2(origin2.XY()-Center.XY());
405                 Standard_Real distcc1 = Center.Distance(center1);
406                 if (!Qualified1.IsUnqualified()) { 
407                   qualifier1(NbrSol) = Qualified1.Qualifier();
408                 }
409                 else if (Abs(distcc1+Radius-R1) < Tol) {
410                   qualifier1(NbrSol) = GccEnt_enclosed;
411                 }
412                 else if (Abs(distcc1-R1-Radius) < Tol) {
413                   qualifier1(NbrSol) = GccEnt_outside;
414                 }
415                 else { qualifier1(NbrSol) = GccEnt_enclosing; }
416                 if (!Qualified2.IsUnqualified()) { 
417                   qualifier2(NbrSol) = Qualified2.Qualifier();
418                 }
419                 else if (dc2.Dot(normL2) > 0.0) {
420                   qualifier2(NbrSol) = GccEnt_outside;
421                 }
422                 else { qualifier2(NbrSol) = GccEnt_enclosed; }
423                 TheSame1(NbrSol) = 0;
424                 if ((Radius < R1) && Center.Distance(center1) <= R1) {
425                   pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*(gp_Dir2d(
426                                         Center.XY()-center1.XY()).XY()));
427                 }
428                 else {
429                   pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*(gp_Dir2d(
430                                         Center.XY()-center1.XY()).XY()));
431                 }
432                 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+
433                                        cote2(jcote2)*Radius*gp_XY(ydir,-xdir));
434               }
435             }
436             WellDone = Standard_True;
437           }
438         }
439       }
440     }
441     else if (nbsol == 2) {
442       gp_Pnt2d Cen(center1.XY()+cote*(R1+Radius)*gp_XY(-ydir,xdir));
443       gp_Ax2d axe(Cen,dirx);
444       cirsol(1) = gp_Circ2d(axe,Radius);
445 //    =================================
446       WellDone = Standard_True;
447       NbrSol = 1;
448       TheSame1(1) = 0;
449       qualifier1(1) = Qualified1.Qualifier();;
450       qualifier2(1) = Qualified2.Qualifier();
451       pnttg1sol(1)=gp_Pnt2d(Cen.XY()+cote*Radius*gp_XY(ydir,-xdir));
452       pnttg2sol(1)=gp_Pnt2d(Cen.XY()+Radius*gp_XY(ydir,-xdir));
453     }
454     else if (nbsol == 3) {
455       WellDone = Standard_True;
456       NbrSol = 1;
457       gp_Pnt2d Cen(center1.XY()+cote*(R1-Radius)*gp_XY(ydir,-xdir));
458       gp_Ax2d axe(Cen,dirx);
459       cirsol(1) = gp_Circ2d(axe,Radius);
460 //    =================================
461       qualifier1(1) = Qualified1.Qualifier();
462       qualifier2(1) = Qualified2.Qualifier();
463       pnttg2sol(1) = gp_Pnt2d(Cen.XY()+cote*Radius*gp_XY(ydir,-xdir));
464       if (Abs(R1-Radius) > 0.0) {
465         pnttg1sol(1) = gp_Pnt2d(Cen.XY()+ccote*Radius*gp_XY(ydir,-xdir));
466       }
467       else { TheSame1(1) = 1; }
468     }
469     else if (nbsol == 4) {
470       gp_Pnt2d Cent(center1.XY()+cote*(R1+Radius)*gp_XY(-ydir,xdir));
471       gp_Ax2d axe(Cent,dirx);
472       cirsol(1) = gp_Circ2d(axe,Radius);
473 //    =================================
474       qualifier1(1) = Qualified1.Qualifier();
475       qualifier2(1) = Qualified2.Qualifier();
476       WellDone = Standard_True;
477       NbrSol = 1;
478       TheSame1(1) = 0;
479       pnttg1sol(1)=gp_Pnt2d(Cent.XY()+cote*Radius*gp_XY(ydir,-xdir));
480       pnttg2sol(1)=gp_Pnt2d(Cent.XY()+cote*Radius*gp_XY(-ydir,xdir));
481     }
482   }
483   for (i = 1 ; i <= NbrSol ; i++) {
484     par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
485     if (TheSame1(i) == 0) {
486       pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i));
487     }
488     par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
489     pararg2(i)=ElCLib::Parameter(L2,pnttg2sol(i));
490   }
491 }
492
493