1 // File GccAna_Circ2d2TanOn.cxx, REG 08/07/91
3 #include <GccAna_Circ2d2TanOn.ixx>
5 #include <TColStd_Array1OfReal.hxx>
6 #include <TColStd_SequenceOfReal.hxx>
7 #include <IntAna2d_AnaIntersection.hxx>
8 #include <IntAna2d_IntPoint.hxx>
9 #include <Standard_OutOfRange.hxx>
11 #include <gp_Dir2d.hxx>
12 #include <gp_Ax2d.hxx>
13 #include <GccInt_IType.hxx>
14 #include <GccInt_BCirc.hxx>
15 #include <GccInt_BLine.hxx>
16 #include <IntAna2d_Conic.hxx>
17 #include <StdFail_NotDone.hxx>
18 #include <GccEnt_BadQualifier.hxx>
19 #include <GccAna_Circ2dBisec.hxx>
21 //=========================================================================
22 // Circles tangent to two circles C1 and C2 and centered on a straight line. +
23 // We start by distinguishing various boundary cases that will be processed separately. +
24 // In the general case: +
25 // ==================== +
26 // We calculate bissectrices to two circles that give us +
27 // all possible locations of centers of all circles tangent to C1 and C2. +
28 // We intersect these bissectrices with straight line which gives us +
29 // points among which we are going to find solutions. +
30 // The choices are made basing on Qualifiers of C1 and C2. +
31 //=========================================================================
34 GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1 ,
35 const GccEnt_QualifiedCirc& Qualified2 ,
36 const gp_Lin2d& OnLine ,
37 const Standard_Real Tolerance ):
55 WellDone = Standard_False;
57 Standard_Integer nbsol = 0;
58 Standard_Real Tol = Abs(Tolerance);
59 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
60 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
61 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
62 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
63 GccEnt_BadQualifier::Raise();
66 gp_Circ2d C1 = Qualified1.Qualified();
67 gp_Circ2d C2 = Qualified2.Qualified();
68 Standard_Real R1 = C1.Radius();
69 Standard_Real R2 = C2.Radius();
71 gp_Pnt2d center1(C1.Location());
72 gp_Pnt2d center2(C2.Location());
73 TColStd_Array1OfReal Radius(1,2);
75 Standard_Real distance = center1.Distance(center2);
77 center1.Distance(center2);
79 Standard_Real dist1 = OnLine.Distance(center1);
80 Standard_Real dist2 = OnLine.Distance(center2);
81 Standard_Real d1 = dist1+R1;
82 Standard_Real d2 = dist2+R2;
83 Standard_Real d3 = dist1-R1;
84 Standard_Real d4 = dist2-R2;
86 //=========================================================================
87 // Processing of boundary cases. +
88 //=========================================================================
91 (Qualified1.IsEnclosed() || Qualified1.IsOutside() ||
92 Qualified1.IsUnqualified()) &&
93 (Qualified2.IsEnclosed() || Qualified2.IsOutside() ||
94 Qualified2.IsUnqualified())) {
96 Radius(nbsol) = Abs(d3);
97 WellDone = Standard_True;
100 (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) &&
101 (Qualified2.IsEnclosing() || Qualified2.IsUnqualified())){
103 Radius(nbsol) = Abs(d1);
104 WellDone = Standard_True;
106 if (Abs(d1-d4)<Tol &&
107 (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) &&
108 (Qualified2.IsEnclosed() || Qualified2.IsOutside() ||
109 Qualified2.IsUnqualified())){
111 Radius(nbsol) = Abs(d1);
112 WellDone = Standard_True;
114 if (Abs(d3-d2)<Tol &&
115 (Qualified2.IsEnclosing() || Qualified2.IsUnqualified()) &&
116 (Qualified1.IsEnclosed() || Qualified1.IsOutside() ||
117 Qualified1.IsUnqualified())){
119 Radius(nbsol) = Abs(d3);
120 WellDone = Standard_True;
122 gp_Lin2d L(center1,gp_Dir2d(center2.XY()-center1.XY()));
123 IntAna2d_AnaIntersection Intp(OnLine,L);
125 if (!Intp.IsEmpty()){
126 for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
127 gp_Pnt2d Center(Intp.Point(j).Value());
128 for (Standard_Integer i = 1 ; i <= nbsol ; i++) {
130 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(i));
131 // ==========================================================
132 WellDone = Standard_True;
133 Standard_Real distcc1 = Center.Distance(center1);
134 Standard_Real distcc2 = Center.Distance(center2);
135 if (!Qualified1.IsUnqualified()) {
136 qualifier1(NbrSol) = Qualified1.Qualifier();
138 else if (Abs(distcc1+Radius(i)-R1) < Tol) {
139 qualifier1(NbrSol) = GccEnt_enclosed;
141 else if (Abs(distcc1-R1-Radius(i)) < Tol) {
142 qualifier1(NbrSol) = GccEnt_outside;
144 else { qualifier1(NbrSol) = GccEnt_enclosing; }
145 if (!Qualified2.IsUnqualified()) {
146 qualifier2(NbrSol) = Qualified2.Qualifier();
148 else if (Abs(distcc2+Radius(i)-R2) < Tol) {
149 qualifier2(NbrSol) = GccEnt_enclosed;
151 else if (Abs(distcc2-R2-Radius(i)) < Tol) {
152 qualifier2(NbrSol) = GccEnt_outside;
154 else { qualifier2(NbrSol) = GccEnt_enclosing; }
155 gp_Dir2d dc1(center1.XY()-Center.XY());
156 gp_Dir2d dc2(center2.XY()-Center.XY());
157 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc1.XY());
158 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc2.XY());
159 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
161 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol));
162 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
164 pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
165 pntcen(NbrSol) = cirsol(NbrSol).Location();
166 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
172 //=========================================================================
174 //=========================================================================
177 GccAna_Circ2dBisec Bis(C1,C2);
179 TColStd_Array1OfReal Rbid(1,2);
180 TColStd_Array1OfReal RBid(1,2);
181 Standard_Integer nbsolution = Bis.NbSolutions();
182 for (Standard_Integer i = 1 ; i <= nbsolution ; i++) {
183 Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i);
184 GccInt_IType typ = Sol->ArcType();
186 if (typ == GccInt_Cir) {
187 Intp.Perform(OnLine,Sol->Circle());
189 else if (typ == GccInt_Lin) {
190 Intp.Perform(OnLine,Sol->Line());
192 else if (typ == GccInt_Hpr) {
193 Intp.Perform(OnLine,IntAna2d_Conic(Sol->Hyperbola()));
195 else if (typ == GccInt_Ell) {
196 Intp.Perform(OnLine,IntAna2d_Conic(Sol->Ellipse()));
199 if (!Intp.IsEmpty()){
200 for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
201 gp_Pnt2d Center(Intp.Point(j).Value());
202 dist1 = Center.Distance(center1);
203 dist2 = Center.Distance(center2);
205 Standard_Integer nsol = 0;
206 Standard_Integer nnsol = 0;
209 if (Qualified1.IsEnclosed()) {
210 if (dist1-R1 < Tol) {
212 Rbid(1) = Abs(R1-dist1);
215 else if (Qualified1.IsOutside()) {
216 if (R1-dist1 < Tol) {
218 Rbid(1) = Abs(dist1-R1);
221 else if (Qualified1.IsEnclosing()) {
225 else if (Qualified1.IsUnqualified()) {
228 Rbid(1) = Abs(dist1-R1);
230 if (Qualified2.IsEnclosed() && nbsol != 0) {
231 if (dist2-R2 < Tol) {
233 RBid(1) = Abs(R2-dist2);
236 else if (Qualified2.IsOutside() && nbsol != 0) {
237 if (R2-dist2 < Tol) {
239 RBid(1) = Abs(R2-dist2);
242 else if (Qualified2.IsEnclosing() && nbsol != 0) {
246 else if (Qualified2.IsUnqualified() && nbsol != 0) {
249 RBid(2) = Abs(R2-dist2);
251 for (Standard_Integer isol = 1; isol <= nbsol ; isol++) {
252 for (Standard_Integer jsol = 1; jsol <= nsol ; jsol++) {
253 if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) {
255 Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.;
260 for (Standard_Integer k = 1 ; k <= nnsol ; k++) {
262 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k));
263 // ==========================================================
264 Standard_Real distcc1 = Center.Distance(center1);
265 Standard_Real distcc2 = Center.Distance(center2);
266 if (!Qualified1.IsUnqualified()) {
267 qualifier1(NbrSol) = Qualified1.Qualifier();
269 else if (Abs(distcc1+Radius(i)-R1) < Tol) {
270 qualifier1(NbrSol) = GccEnt_enclosed;
272 else if (Abs(distcc1-R1-Radius(i)) < Tol) {
273 qualifier1(NbrSol) = GccEnt_outside;
275 else { qualifier1(NbrSol) = GccEnt_enclosing; }
276 if (!Qualified2.IsUnqualified()) {
277 qualifier2(NbrSol) = Qualified2.Qualifier();
279 else if (Abs(distcc2+Radius(i)-R2) < Tol) {
280 qualifier2(NbrSol) = GccEnt_enclosed;
282 else if (Abs(distcc2-R2-Radius(i)) < Tol) {
283 qualifier2(NbrSol) = GccEnt_outside;
285 else { qualifier2(NbrSol) = GccEnt_enclosing; }
286 if (Center.Distance(center1) <= Tol &&
287 Abs(Radius(k)-C1.Radius()) <= Tol) {TheSame1(NbrSol)=1;}
289 TheSame1(NbrSol) = 0;
290 gp_Dir2d dc1(center1.XY()-Center.XY());
291 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+
293 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
295 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg2sol(NbrSol));
297 if (Center.Distance(center2) <= Tol &&
298 Abs(Radius(k)-C2.Radius()) <= Tol) {TheSame2(NbrSol)=1;}
300 TheSame2(NbrSol) = 0;
301 gp_Dir2d dc2(center2.XY()-Center.XY());
302 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+
304 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
306 pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol));
308 pntcen(NbrSol) = Center;
309 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
314 WellDone = Standard_True;
321 //========================================================================
323 Standard_Boolean GccAna_Circ2d2TanOn::
324 IsDone () const{ return WellDone; }
326 Standard_Integer GccAna_Circ2d2TanOn::
327 NbSolutions () const{ return NbrSol; }
329 gp_Circ2d GccAna_Circ2d2TanOn::
330 ThisSolution (const Standard_Integer Index) const{ return cirsol(Index); }
332 void GccAna_Circ2d2TanOn::
333 WhichQualifier(const Standard_Integer Index ,
334 GccEnt_Position& Qualif1 ,
335 GccEnt_Position& Qualif2 ) const
337 if (!WellDone) { StdFail_NotDone::Raise(); }
338 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
340 Qualif1 = qualifier1(Index);
341 Qualif2 = qualifier2(Index);
345 void GccAna_Circ2d2TanOn::
346 Tangency1 (const Standard_Integer Index ,
347 Standard_Real& ParSol ,
348 Standard_Real& ParArg ,
349 gp_Pnt2d& PntSol ) const{
350 if (!WellDone) { StdFail_NotDone::Raise(); }
351 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
353 if (TheSame1(Index) == 0) {
354 ParSol = par1sol(Index);
355 ParArg = pararg1(Index);
356 PntSol = gp_Pnt2d(pnttg1sol(Index));
358 else { StdFail_NotDone::Raise(); }
362 void GccAna_Circ2d2TanOn::
363 Tangency2 (const Standard_Integer Index ,
364 Standard_Real& ParSol ,
365 Standard_Real& ParArg ,
366 gp_Pnt2d& PntSol ) const{
367 if (!WellDone) { StdFail_NotDone::Raise(); }
368 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
370 if (TheSame2(Index) == 0) {
371 ParSol = par2sol(Index);
372 ParArg = pararg2(Index);
373 PntSol = gp_Pnt2d(pnttg2sol(Index));
375 else { StdFail_NotDone::Raise(); }
379 void GccAna_Circ2d2TanOn::
380 CenterOn3 (const Standard_Integer Index ,
381 Standard_Real& ParArg ,
382 gp_Pnt2d& PntSol ) const{
383 if (!WellDone) { StdFail_NotDone::Raise(); }
384 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
386 ParArg = parcen3(Index);
387 PntSol = pnttg1sol(Index);
391 Standard_Boolean GccAna_Circ2d2TanOn::
392 IsTheSame1 (const Standard_Integer Index) const
394 if (!WellDone) { StdFail_NotDone::Raise(); }
395 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
397 if (TheSame1(Index) == 0) { return Standard_False; }
398 return Standard_True;
401 Standard_Boolean GccAna_Circ2d2TanOn::
402 IsTheSame2 (const Standard_Integer Index) const
404 if (!WellDone) { StdFail_NotDone::Raise(); }
405 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
407 if (TheSame2(Index) == 0) { return Standard_False; }
408 return Standard_True;