summaryrefslogtreecommitdiff
path: root/src/GccAna/GccAna_Circ2dTanOnRad_4.cxx
blob: 22ba171d05f40ec0e8899a60aa8fc87c08e7eb6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// file GccAna_Circ2dTanOnRad_4.cxx, REG 08/07/91

#include <GccAna_Circ2dTanOnRad.jxx>

#include <ElCLib.hxx>
#include <IntAna2d_AnaIntersection.hxx>
#include <IntAna2d_IntPoint.hxx>
#include <Standard_NegativeValue.hxx>
#include <Standard_OutOfRange.hxx>
#include <gp_Dir2d.hxx>
#include <GccEnt_BadQualifier.hxx>

//=========================================================================
//   Cercle tangent a une droite Qualified1 (L1).                         +
//          centre sur un cercle OnCirc.                                  +
//          de rayon             Radius.                                  +
//                                                                        +
//  On initialise le tableau de solutions cirsol ainsi que tous les       +
//  champs.                                                               +
//  On elimine les cas ne presentant pas de solution.                     +
//  On cree la (les) parallele(s) a L1 dans le (les) sens voulu(s).       +
//  On intersecte cette (ces) parallele(s) avec OnCirc et on obtient les  +
//  points de centre des solutions recherchees.                           +
//  On cree ces solutions cirsol.                                         +
//=========================================================================

GccAna_Circ2dTanOnRad::
   GccAna_Circ2dTanOnRad (const GccEnt_QualifiedLin& Qualified1,
                          const gp_Circ2d&           OnCirc    ,
                          const Standard_Real        Radius    ,
                          const Standard_Real        Tolerance ):

//=========================================================================
//  Initialisation des champs.                                            +
//=========================================================================

   cirsol(1,4)   ,
   qualifier1(1,4) ,
   TheSame1(1,4) ,
   pnttg1sol(1,4),
   pntcen3(1,4)  ,
   par1sol(1,4)  ,
   pararg1(1,4)  ,
   parcen3(1,4)  
{

     TheSame1.Init(0);
   gp_Dir2d dirx(1.0,0.0);
   Standard_Real Tol = Abs(Tolerance);
   WellDone = Standard_False;
   NbrSol = 0;
   if (!(Qualified1.IsEnclosed() ||
	 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
     GccEnt_BadQualifier::Raise();
     return;
   }

//=========================================================================
//  Initialisation de diverses variables.                                 +
//=========================================================================

   Standard_Integer nbsol = 0;
   Standard_Integer sign = 0;
   gp_Lin2d L1 = Qualified1.Qualified();
   gp_Pnt2d origin1(L1.Location());
   gp_Dir2d dir1(L1.Direction());
   gp_Dir2d normL1(-dir1.Y(),dir1.X());
   Standard_Real dist1 = L1.Distance(OnCirc.Location())-OnCirc.Radius();
   Standard_Real dist2 = L1.Distance(OnCirc.Location())+OnCirc.Radius();

//=========================================================================
//  Traitement.                                                           +
//=========================================================================

   if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
   else {
     L1 = Qualified1.Qualified();
     if ((dist1-Radius>Tol) || (Tol<Radius-dist2)) { WellDone=Standard_True; }
     else {

// a modifier ulterieurement.

       if (dist1-Radius > 0.0) { dist1 = Radius; }
       else if (dist2-Radius < 0.0) { dist2 = Radius; }

       if (Qualified1.IsEnclosed()) {
//     ============================
	 nbsol = 1;
	 sign = -1;
       }
       else if (Qualified1.IsOutside()) {
//     ================================
	 nbsol = 1;
	 sign = 1;
       }
       else {
//     ====
	 nbsol = 2;
	 sign = 1;
       }
       for (Standard_Integer j = 1 ; j <= nbsol ;j++) {
	 sign = -sign;
         gp_Lin2d L(gp_Pnt2d(origin1.X()-sign*Radius*dir1.Y(),
			     origin1.Y()+sign*Radius*dir1.X()),dir1);
         IntAna2d_AnaIntersection Intp(L,OnCirc);
         if (Intp.IsDone()) {
           if (!Intp.IsEmpty()) {
             for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
               NbrSol++;
	       gp_Pnt2d Center(Intp.Point(i).Value());
	       gp_Ax2d axe(Center,dirx);
               cirsol(NbrSol) = gp_Circ2d(axe,Radius);
//             ======================================
	       gp_Dir2d dc1(origin1.XY()-Center.XY());
	       sign = (Standard_Integer) dc1.Dot(normL1);
	       if (!Qualified1.IsUnqualified()) { 
		 qualifier1(NbrSol) = Qualified1.Qualifier();
	       }
	       else if (dc1.Dot(normL1) > 0.0) {	
		 qualifier1(NbrSol) = GccEnt_outside; 
	       }
	       else { qualifier1(NbrSol) = GccEnt_enclosed; }
	       pntcen3(NbrSol) = cirsol(NbrSol).Location();
	       pnttg1sol(NbrSol) = gp_Pnt2d(pntcen3(NbrSol).XY()+
				    gp_XY(sign*Radius*dir1.Y(),
					  -sign*Radius*dir1.X()));
	       pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
	       par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
						pnttg1sol(NbrSol));
	       parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen3(NbrSol));
             }
           }
	   WellDone = Standard_True;
         }
       }
     }
   }
 }