1 // Created on: 1991-09-24
2 // Created by: Joelle CHAUVET
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 // Modified:	Thu Jun 18 15:45:00 1998
18 //		PRO10310 : cas ou le point est sur la droite
19 
20 #include <ElCLib.hxx>
21 #include <GccAna_Circ2d2TanRad.hxx>
22 #include <GccEnt_BadQualifier.hxx>
23 #include <GccEnt_QualifiedCirc.hxx>
24 #include <GccEnt_QualifiedLin.hxx>
25 #include <gp_Ax2d.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <gp_Lin2d.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <IntAna2d_AnaIntersection.hxx>
30 #include <IntAna2d_IntPoint.hxx>
31 #include <Standard_NegativeValue.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <StdFail_NotDone.hxx>
34 #include <TColStd_Array1OfReal.hxx>
35 
36 // circular tangent to a line and a point and a given radius
37 //=============================================================
38 //========================================================================
39 // Initialize WellDone to false.                                         +
40 // Return line L1.                                                       +
41 // Leave with error if the construction is impossible.                   +
42 // Create parallel to L1 in the proper direction.                        +
43 // Create the circle with center at Point1 of radius Radius.             +
44 // Intersect the parallel and the circle.                                +
45 //                              ==> The center point of the  solution.   +
46 // Create the solution to be added to already found solutions.           +
47 // Fill the fields.                                                      +
48 //========================================================================
49 GccAna_Circ2d2TanRad::
GccAna_Circ2d2TanRad(const GccEnt_QualifiedLin & Qualified1,const gp_Pnt2d & Point2,const Standard_Real Radius,const Standard_Real Tolerance)50    GccAna_Circ2d2TanRad (const GccEnt_QualifiedLin&  Qualified1 ,
51                          const gp_Pnt2d&             Point2     ,
52                          const Standard_Real         Radius     ,
53                          const Standard_Real         Tolerance  ):
54    qualifier1(1,2) ,
55    qualifier2(1,2),
56    TheSame1(1,2)   ,
57    TheSame2(1,2)   ,
58    cirsol(1,2)     ,
59    pnttg1sol(1,2)  ,
60    pnttg2sol(1,2)  ,
61    par1sol(1,2)    ,
62    par2sol(1,2)    ,
63    pararg1(1,2)    ,
64    pararg2(1,2)
65 {
66 
67   gp_Dir2d dirx(1.0,0.0);
68   Standard_Real Tol = Abs(Tolerance);
69   NbrSol = 0;
70   WellDone = Standard_False;
71   if (!(Qualified1.IsEnclosed() || Qualified1.IsOutside() ||
72 	Qualified1.IsUnqualified())) {
73     throw GccEnt_BadQualifier();
74     return;
75   }
76   Standard_Integer nbsol = 0;
77   Standard_Integer nbcote=0;
78   TColStd_Array1OfReal cote(1,2);
79   gp_Lin2d L1 = Qualified1.Qualified();
80   Standard_Real displ1 = L1.Distance(Point2);
81   Standard_Real xdir = (L1.Direction()).X();
82   Standard_Real ydir = (L1.Direction()).Y();
83   Standard_Real lxloc = (L1.Location()).X();
84   Standard_Real lyloc = (L1.Location()).Y();
85   gp_Pnt2d origin1(lxloc,lyloc);
86   gp_Dir2d normL1(-ydir,xdir);
87   Standard_Real cxloc = Point2.X();
88   Standard_Real cyloc = Point2.Y();
89 
90   if (Radius < 0.0) { throw Standard_NegativeValue(); }
91 
92   else {
93     if ( displ1-Radius*2.0 > Tol) { WellDone = Standard_True; }
94     else if (Qualified1.IsEnclosed()) {
95 //  =================================
96       if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0)) {
97 	WellDone = Standard_True;
98       }
99       else {
100 	if ( displ1-Radius*2.0 > 0.0) {
101 	  nbsol = 2;
102 	  NbrSol = 1;
103 	  nbcote = 1;
104 	  cote(1) = 1.0;
105 	}
106 	else {
107 	  nbsol = 1;
108 	  nbcote = 1;
109 	  cote(1) = 1.0;
110 	}
111       }
112     }
113     else if (Qualified1.IsOutside()) {
114 //  ================================
115       if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0)) {
116 	WellDone = Standard_True;
117       }
118       else {
119 	if ( displ1-Radius*2.0 > 0.0) {
120 	  nbsol = 2;
121 	  nbcote = 1;
122 	  cote(1) = -1.0;
123 	}
124 	else {
125 	  nbsol = 1;
126 	  nbcote = 1;
127 	  cote(1) = -1.0;
128 	}
129       }
130     }
131     else if (Qualified1.IsUnqualified()) {
132 //  ====================================
133       if ( displ1-Radius*2.0 > 0.0) {
134 	if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0)) {
135 	  nbsol = 2;
136 	  nbcote = 1;
137 	  cote(1) = 1.0;
138 	}
139 	else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0)) {
140 	  nbsol = 2;
141 	  nbcote = 1;
142 	  cote(1) = -1.0;
143 	}
144       }
145       else {
146 	nbsol = 1;
147 	nbcote = 2;
148 	cote(1) = 1.0;
149 	cote(2) = -1.0;
150       }
151     }
152 
153     if (nbsol == 1) {
154       if (displ1<1.e-10) {
155 	// particular case when Point2 is on the line
156 	// construct two solutions directly
157 	for (Standard_Integer jcote = 1 ; jcote <= nbcote ; jcote++) {
158 	  NbrSol++;
159 	  gp_Pnt2d Center(cxloc-cote(jcote)*ydir*Radius,
160 			  cyloc+cote(jcote)*xdir*Radius);
161 	  cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
162 //        =======================================================
163 	  qualifier2(NbrSol) = GccEnt_noqualifier;
164 	  if (!Qualified1.IsUnqualified()) {
165 	    qualifier1(NbrSol) = Qualified1.Qualifier();
166 	  }
167 	  else if (cote(jcote) > 0.0) {
168 	    qualifier1(NbrSol) = GccEnt_outside;
169 	  }
170 	  else {
171 	    qualifier1(NbrSol) = GccEnt_enclosed;
172 	  }
173 	  TheSame1(NbrSol) = 0;
174 	  TheSame2(NbrSol) = 0;
175 	  pnttg1sol(NbrSol) = Point2;
176 	  pnttg2sol(NbrSol) = Point2;
177 	}
178 	WellDone = Standard_True;
179       }
180       else {
181 	gp_Circ2d cirint(gp_Ax2d(Point2,dirx),Radius);
182 	for (Standard_Integer jcote = 1 ; jcote <= nbcote ; jcote++) {
183 	  gp_Lin2d  linint(gp_Pnt2d(lxloc-cote(jcote)*ydir*Radius,
184 				    lyloc+cote(jcote)*xdir*Radius),
185 			   L1.Direction());
186 	  IntAna2d_AnaIntersection Intp(linint,cirint);
187 	  if (Intp.IsDone()) {
188 	    if (!Intp.IsEmpty()) {
189 	      for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol<2; i++) {
190 		NbrSol++;
191 		gp_Pnt2d Center(Intp.Point(i).Value());
192 		cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
193   //            =======================================================
194 		gp_Dir2d dc1(origin1.XY()-Center.XY());
195 		qualifier2(NbrSol) = GccEnt_noqualifier;
196 		if (!Qualified1.IsUnqualified()) {
197 		  qualifier1(NbrSol) = Qualified1.Qualifier();
198 		}
199 		else if (dc1.Dot(normL1) > 0.0) {
200 		  qualifier1(NbrSol) = GccEnt_outside;
201 		}
202 		else { qualifier1(NbrSol) = GccEnt_enclosed; }
203 		TheSame1(NbrSol) = 0;
204 		TheSame2(NbrSol) = 0;
205 		pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+
206 					   cote(jcote)*Radius*gp_XY(ydir,-xdir));
207 		pnttg2sol(NbrSol) = Point2;
208 	      }
209 	    }
210 	    WellDone = Standard_True;
211 	  }
212 	}
213       }
214     }
215 
216     else if (nbsol == 2) {
217       gp_Pnt2d Center(Point2.XY()+cote(1)*Radius*gp_XY(-ydir,xdir));
218       WellDone = Standard_True;
219       NbrSol = 1;
220       cirsol(1) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
221 //    ==================================================
222       qualifier2(1) = GccEnt_noqualifier;
223       TheSame1(1) = 0;
224       TheSame2(1) = 0;
225       pnttg1sol(1)=gp_Pnt2d(Center.XY()+cote(1)*Radius*gp_XY(ydir,-xdir));
226       pnttg2sol(1) = Point2;
227     }
228   }
229 
230   for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
231     par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
232     pararg1(i)=ElCLib::Parameter(L1,pnttg1sol(i));
233     par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
234     pararg2(i)=0.;
235   }
236 
237 }
238 
239 
240 
241 
242