0031007: Coding - eliminate warnings issued while compiling with -pedantic flag
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2d2TanRadGeo.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Adaptor2d_OffsetCurve.hxx>
17 #include <ElCLib.hxx>
18 #include <GccEnt_BadQualifier.hxx>
19 #include <GccEnt_QualifiedCirc.hxx>
20 #include <GccEnt_QualifiedLin.hxx>
21 #include <Geom2dAdaptor_HCurve.hxx>
22 #include <Geom2dGcc_Circ2d2TanRadGeo.hxx>
23 #include <Geom2dGcc_CurveTool.hxx>
24 #include <Geom2dGcc_QCurve.hxx>
25 #include <Geom2dInt_GInter.hxx>
26 #include <gp_Ax2d.hxx>
27 #include <gp_Circ2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <IntRes2d_Domain.hxx>
31 #include <IntRes2d_IntersectionPoint.hxx>
32 #include <Standard_NegativeValue.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
35 #include <TColStd_Array1OfReal.hxx>
36
37 static const Standard_Integer aNbSolMAX = 16;
38
39 // circulaire tant a une courbe et une droite ,de rayon donne
40 //==============================================================
41
42 //========================================================================
43 // On initialise WellDone a false.                                       +
44 // On recupere la courbe Cu2 et la droite L1.                            +
45 // On sort en erreur dans les cas ou la construction est impossible.     +
46 // On fait la parallele a Cu2 dans le bon sens.                          +
47 // On fait la parallele a L1 dans le bon sens.                           +
48 // On intersecte les paralleles ==> point de centre de la solution.      +
49 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
50 // On remplit les champs.                                                +
51 //========================================================================
52
53 Geom2dGcc_Circ2d2TanRadGeo::
54 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin&  Qualified1,
55                             const Geom2dGcc_QCurve&     Qualified2,
56                             const Standard_Real         Radius    ,
57                             const Standard_Real         Tolerance ):
58
59 //========================================================================
60 // initialisation des champs.                                            +
61 //========================================================================
62
63 cirsol(1,aNbSolMAX)   ,
64 qualifier1(1,aNbSolMAX),
65 qualifier2(1,aNbSolMAX),
66 TheSame1(1,aNbSolMAX) ,
67 TheSame2(1,aNbSolMAX) ,
68 pnttg1sol(1,aNbSolMAX),
69 pnttg2sol(1,aNbSolMAX),
70 par1sol(1,aNbSolMAX)  ,
71 par2sol(1,aNbSolMAX)  ,
72 pararg1(1,aNbSolMAX)  ,
73 pararg2(1,aNbSolMAX)  
74 {
75
76   //========================================================================
77   // Traitement.                                                           +
78   //========================================================================
79
80   Standard_Real Tol = Abs(Tolerance);
81   Standard_Real thefirst = -100000.;
82   Standard_Real thelast  =  100000.;
83   Standard_Real firstparam;
84   Standard_Real lastparam;
85   gp_Dir2d dirx(1.,0.);
86   TColStd_Array1OfReal cote1(1,2);
87   TColStd_Array1OfReal cote2(1,2);
88   Standard_Integer nbrcote1=0;
89   Standard_Integer nbrcote2=0;
90   WellDone = Standard_False;
91   NbrSol = 0;
92   if (!(Qualified1.IsEnclosed() ||
93     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
94     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
95     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
96
97       throw GccEnt_BadQualifier();
98       return;
99   }
100   gp_Lin2d L1 = Qualified1.Qualified();
101   Standard_Real x1dir = (L1.Direction()).X();
102   Standard_Real y1dir = (L1.Direction()).Y();
103   Standard_Real lxloc = (L1.Location()).X();
104   Standard_Real lyloc = (L1.Location()).Y();
105   gp_Pnt2d origin1(lxloc,lyloc);
106   gp_Dir2d normL1(-y1dir,x1dir);
107   Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
108   if (Radius < 0.0) { throw Standard_NegativeValue(); }
109   else {
110     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
111       //   =======================================================
112       nbrcote1 = 1;
113       nbrcote2 = 1;
114       cote1(1) = Radius;
115       cote2(1) = Radius;
116     }
117     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
118       //   ==========================================================
119       nbrcote1 = 1;
120       nbrcote2 = 1;
121       cote1(1) = Radius;
122       cote2(1) = -Radius;
123     }
124     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
125       //   ===========================================================
126       nbrcote1 = 1;
127       nbrcote2 = 1;
128       cote1(1) = -Radius;
129       cote2(1) = Radius;
130     }
131     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
132       //   =========================================================
133       nbrcote1 = 1;
134       nbrcote2 = 1;
135       cote1(1) = -Radius;
136       cote2(1) = -Radius;
137     }
138     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
139       //   =========================================================
140       nbrcote1 = 1;
141       nbrcote2 = 2;
142       cote1(1) = Radius;
143       cote2(1) = Radius;
144       cote2(2) = -Radius;
145     }
146     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
147       //   =========================================================
148       nbrcote1 = 2;
149       nbrcote2 = 1;
150       cote1(1) = Radius;
151       cote1(2) = -Radius;
152       cote2(1) = Radius;
153     }
154     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
155       //   =============================================================
156       nbrcote1 = 1;
157       nbrcote2 = 2;
158       cote1(1) = -Radius;
159       cote2(1) = Radius;
160       cote2(2) = -Radius;
161     }
162     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
163       //   ========================================================
164       nbrcote1 = 2;
165       nbrcote2 = 1;
166       cote1(1) = Radius;
167       cote1(2) = -Radius;
168       cote2(1) = -Radius;
169     }
170     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
171       //   =================================================================
172       nbrcote1 = 2;
173       nbrcote2 = 2;
174       cote1(1) = Radius;
175       cote1(2) = -Radius;
176       cote2(1) = Radius;
177       cote2(2) = -Radius;
178     }
179     gp_Dir2d Dir(-y1dir,x1dir);
180     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
181       gp_Pnt2d Point(L1.Location().XY()+cote1(jcote1)*Dir.XY());
182       gp_Lin2d Line(Point,L1.Direction()); // ligne avec deport.
183       IntRes2d_Domain D1;
184       for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
185         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
186         Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
187         firstparam = Max(C2.FirstParameter(),thefirst);
188         lastparam  = Min(C2.LastParameter(),thelast);
189         IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
190                            C2.Value(lastparam), lastparam, Tol);
191         Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
192         if (Intp.IsDone()) {
193           if (!Intp.IsEmpty()) {
194             for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
195               NbrSol++;
196               gp_Pnt2d Center(Intp.Point(i).Value());
197               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
198               //             =======================================================
199               gp_Dir2d dc1(origin1.XY()-Center.XY());
200               qualifier2(NbrSol) = Qualified2.Qualifier();
201               if (!Qualified1.IsUnqualified()) { 
202                 qualifier1(NbrSol) = Qualified1.Qualifier();
203               }
204               else if (dc1.Dot(normL1) > 0.0) {
205                 qualifier1(NbrSol) = GccEnt_outside;
206               }
207               else { qualifier1(NbrSol) = GccEnt_enclosed; }
208               TheSame1(NbrSol) = 0;
209               TheSame2(NbrSol) = 0;
210               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
211               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
212               pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
213               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
214               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
215                 pnttg1sol(NbrSol));
216               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
217                 pnttg2sol(NbrSol));
218             }
219           }
220           WellDone = Standard_True;
221         }
222       }
223     }
224   }
225 }
226
227 // circulaire tant a une courbe et un cercle ,de rayon donne
228 //=============================================================
229
230 //========================================================================
231 // On initialise WellDone a false.                                       +
232 // On recupere la courbe Cu2 et le cercle C1.                            +
233 // On sort en erreur dans les cas ou la construction est impossible.     +
234 // On fait la parallele a Cu2 dans le bon sens.                          +
235 // On fait la parallele a C1 dans le bon sens.                           +
236 // On intersecte les paralleles ==> point de centre de la solution.      +
237 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
238 // On remplit les champs.                                                +
239 //========================================================================
240
241 Geom2dGcc_Circ2d2TanRadGeo::
242 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
243                             const Geom2dGcc_QCurve&     Qualified2,
244                             const Standard_Real         Radius    ,
245                             const Standard_Real         Tolerance ):
246
247 //========================================================================
248 // initialisation des champs.                                            +
249 //========================================================================
250
251 cirsol(1,aNbSolMAX)   ,
252 qualifier1(1,aNbSolMAX),
253 qualifier2(1,aNbSolMAX),
254 TheSame1(1,aNbSolMAX) ,
255 TheSame2(1,aNbSolMAX) ,
256 pnttg1sol(1,aNbSolMAX),
257 pnttg2sol(1,aNbSolMAX),
258 par1sol(1,aNbSolMAX)  ,
259 par2sol(1,aNbSolMAX)  ,
260 pararg1(1,aNbSolMAX)  ,
261 pararg2(1,aNbSolMAX)  
262 {
263
264   //========================================================================
265   // Traitement.                                                           +
266   //========================================================================
267
268   Standard_Real Tol = Abs(Tolerance);
269   Standard_Real thefirst = -100000.;
270   Standard_Real thelast  =  100000.;
271   Standard_Real firstparam;
272   Standard_Real lastparam;
273   gp_Dir2d dirx(1.,0.);
274   TColStd_Array1OfReal cote1(1,2);
275   TColStd_Array1OfReal cote2(1,2);
276   Standard_Integer nbrcote1=0;
277   Standard_Integer nbrcote2=0;
278   WellDone = Standard_False;
279   NbrSol = 0;
280   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
281     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
282     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
283     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
284       throw GccEnt_BadQualifier();
285       return;
286   }
287   gp_Circ2d C1 = Qualified1.Qualified();
288   gp_Pnt2d center1(C1.Location());
289   Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
290   if (Radius < 0.0) { throw Standard_NegativeValue(); }
291   else {
292     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
293       //   =======================================================
294       nbrcote1 = 1;
295       nbrcote2 = 1;
296       cote1(1) = Radius;
297       cote2(1) = Radius;
298     }
299     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
300       //   ==========================================================
301       nbrcote1 = 1;
302       nbrcote2 = 1;
303       cote1(1) = Radius;
304       cote2(1) = -Radius;
305     }
306     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
307       //   ===========================================================
308       nbrcote1 = 1;
309       nbrcote2 = 1;
310       cote1(1) = -Radius;
311       cote2(1) = Radius;
312     }
313     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
314       //   =========================================================
315       nbrcote1 = 1;
316       nbrcote2 = 1;
317       cote1(1) = -Radius;
318       cote2(1) = -Radius;
319     }
320     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
321       //   =========================================================
322       nbrcote1 = 1;
323       nbrcote2 = 2;
324       cote1(1) = Radius;
325       cote2(1) = Radius;
326       cote2(2) = -Radius;
327     }
328     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
329       //   =========================================================
330       nbrcote1 = 2;
331       nbrcote2 = 1;
332       cote1(1) = Radius;
333       cote1(2) = -Radius;
334       cote2(1) = Radius;
335     }
336     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
337       //   =============================================================
338       nbrcote1 = 1;
339       nbrcote2 = 2;
340       cote1(1) = -Radius;
341       cote2(1) = Radius;
342       cote2(2) = -Radius;
343     }
344     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
345       //   ========================================================
346       nbrcote1 = 2;
347       nbrcote2 = 1;
348       cote1(1) = Radius;
349       cote1(2) = -Radius;
350       cote2(1) = -Radius;
351     }
352     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
353       //   =================================================================
354       nbrcote1 = 2;
355       nbrcote2 = 2;
356       cote1(1) = Radius;
357       cote1(2) = -Radius;
358       cote2(1) = Radius;
359       cote2(2) = -Radius;
360     }
361     Standard_Real R1 = C1.Radius();
362     Geom2dInt_TheIntConicCurveOfGInter Intp;
363     for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
364       gp_Circ2d Circ(C1.XAxis(),R1+cote1(jcote1));
365       IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
366         ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
367       D1.SetEquivalentParameters(0.,2.*M_PI);
368       for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
369         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
370         Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
371         firstparam = Max(C2.FirstParameter(),thefirst);
372         lastparam  = Min(C2.LastParameter(),thelast);
373         IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
374                            C2.Value(lastparam), lastparam, Tol);
375         Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
376         if (Intp.IsDone()) {
377           if (!Intp.IsEmpty()) {
378             for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
379               NbrSol++;
380               gp_Pnt2d Center(Intp.Point(i).Value());
381               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
382               //             =======================================================
383 #ifdef OCCT_DEBUG
384               gp_Dir2d dir1(Center.XY()-center1.XY());
385 #else
386               Center.XY() ;
387               center1.XY() ;
388 #endif
389               Standard_Real distcc1 = Center.Distance(center1);
390               if (!Qualified1.IsUnqualified()) { 
391                 qualifier1(NbrSol) = Qualified1.Qualifier();
392               }
393               else if (Abs(distcc1+Radius-R1) < Tol) {
394                 qualifier1(NbrSol) = GccEnt_enclosed;
395               }
396               else if (Abs(distcc1-R1-Radius) < Tol) {
397                 qualifier1(NbrSol) = GccEnt_outside;
398               }
399               else { qualifier1(NbrSol) = GccEnt_enclosing; }
400               qualifier2(NbrSol) = Qualified2.Qualifier();
401               TheSame1(NbrSol) = 0;
402               TheSame2(NbrSol) = 0;
403               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
404               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
405               pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
406               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
407               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
408                 pnttg1sol(NbrSol));
409               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
410                 pnttg2sol(NbrSol));
411             }
412           }
413           WellDone = Standard_True;
414         }
415       }
416     }
417   }
418 }
419
420 // circulaire tant a une courbe et un point ,de rayon donne
421 //============================================================
422
423 //========================================================================
424 // On initialise WellDone a false.                                       +
425 // On recupere la courbe Cu1 et le point P2.                             +
426 // On sort en erreur dans les cas ou la construction est impossible.     +
427 // On fait la parallele a Cu1 dans le bon sens.                          +
428 // On fait la parallele a P2 dans le bon sens.                           +
429 // On intersecte les paralleles ==> point de centre de la solution.      +
430 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
431 // On remplit les champs.                                                +
432 //========================================================================
433
434 Geom2dGcc_Circ2d2TanRadGeo::
435 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
436                             const gp_Pnt2d&     Point2    ,
437                             const Standard_Real Radius    ,
438                             const Standard_Real Tolerance ):
439
440 //========================================================================
441 // initialisation des champs.                                            +
442 //========================================================================
443
444 cirsol(1,aNbSolMAX)   ,
445 qualifier1(1,aNbSolMAX),
446 qualifier2(1,aNbSolMAX),
447 TheSame1(1,aNbSolMAX) ,
448 TheSame2(1,aNbSolMAX) ,
449 pnttg1sol(1,aNbSolMAX),
450 pnttg2sol(1,aNbSolMAX),
451 par1sol(1,aNbSolMAX)  ,
452 par2sol(1,aNbSolMAX)  ,
453 pararg1(1,aNbSolMAX)  ,
454 pararg2(1,aNbSolMAX)  
455 {
456
457   //========================================================================
458   // Traitement.                                                           +
459   //========================================================================
460
461   Standard_Real Tol = Abs(Tolerance);
462   Standard_Real thefirst = -100000.;
463   Standard_Real thelast  =  100000.;
464   Standard_Real firstparam;
465   Standard_Real lastparam;
466   gp_Dir2d dirx(1.,0.);
467   TColStd_Array1OfReal cote1(1,2);
468   Standard_Integer nbrcote1=0;
469   WellDone = Standard_False;
470   NbrSol = 0;
471   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
472     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
473       throw GccEnt_BadQualifier();
474       return;
475   }
476   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
477   if (Radius < 0.0) { throw Standard_NegativeValue(); }
478   else {
479     if (Qualified1.IsEnclosed()) {
480       //    ===========================
481       nbrcote1 = 1;
482       cote1(1) = Radius;
483     }
484     else if(Qualified1.IsOutside()) {
485       //   ===============================
486       nbrcote1 = 1;
487       cote1(1) = -Radius;
488     }
489     else if(Qualified1.IsUnqualified()) {
490       //   ===================================
491       nbrcote1 = 2;
492       cote1(1) = Radius;
493       cote1(2) = -Radius;
494     }
495     gp_Circ2d Circ(gp_Ax2d(Point2,gp_Dir2d(1.,0.)),Radius);
496     IntRes2d_Domain D1(ElCLib::Value(0.,Circ),   0.,Tol,
497       ElCLib::Value(M_PI+M_PI,Circ),M_PI+M_PI,Tol);
498     D1.SetEquivalentParameters(0.,M_PI+M_PI);
499     Geom2dInt_TheIntConicCurveOfGInter Intp;
500     for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
501       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
502       Adaptor2d_OffsetCurve Cu2(HCu1,cote1(jcote1));
503       firstparam = Max(Cu2.FirstParameter(),thefirst);
504       lastparam  = Min(Cu2.LastParameter(),thelast);
505       IntRes2d_Domain D2(Cu2.Value(firstparam), firstparam, Tol,
506                          Cu2.Value(lastparam), lastparam, Tol);
507       Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
508       if (Intp.IsDone()) {
509         if (!Intp.IsEmpty()) {
510           for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
511             NbrSol++;
512             gp_Pnt2d Center(Intp.Point(i).Value());
513             cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
514             //           =======================================================
515             qualifier1(NbrSol) = Qualified1.Qualifier();
516             qualifier2(NbrSol) = GccEnt_noqualifier;
517             TheSame1(NbrSol) = 0;
518             TheSame2(NbrSol) = 0;
519             pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
520             pararg2(NbrSol) = 0.;
521             pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
522             pnttg2sol(NbrSol) = Point2;
523             par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
524               pnttg1sol(NbrSol));
525             par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
526               pnttg2sol(NbrSol));
527           }
528         }
529         WellDone = Standard_True;
530       }
531     }
532   }
533 }
534
535 //=======================================================================
536 //function : PrecRoot
537 //purpose  : In case, when curves has tangent zones, intersection point
538 //            found may be precised. This function uses precision algorithm
539 //            of Extrema Curve-Curve method (dot product between every
540 //            tangent vector and vector between points in two curves must
541 //            be equal to zero).
542 //=======================================================================
543 static void PrecRoot(const Adaptor2d_OffsetCurve& theC1,
544                      const Adaptor2d_OffsetCurve& theC2,
545                      const Standard_Real theU0,
546                      const Standard_Real theV0,
547                      Standard_Real& theUfinal,
548                      Standard_Real& theVfinal)
549 {
550 /*
551 It is necessary for precision to solve the system
552
553     \left\{\begin{matrix}
554     (x_{1}(u)-x_{2}(v))*{x_{1}(u)}'+(y_{1}(u)-y_{2}(v))*{y_{1}(u)}'=0\\ 
555     (x_{1}(u)-x_{2}(v))*{x_{2}(v)}'+(y_{1}(u)-y_{2}(v))*{y_{2}(v)}'=0
556     \end{matrix}\right.
557
558 Precision of any 2*2-system (two equation and two variables)
559
560     \left\{\begin{matrix}
561     S_{1}(u,v)=0\\ 
562     S_{2}(u,v)=0
563     \end{matrix}\right.
564
565 by Newton method can be made as follows:
566
567     u=u_{0}-\left (\frac{\frac{\partial S_{2}}{\partial v}*S_{1}-
568       \frac{\partial S_{1}}{\partial v}*S_{2}}
569       {\frac{\partial S_{1}}{\partial u}*
570       \frac{\partial S_{2}}{\partial v}-
571       \frac{\partial S_{1}}{\partial v}*
572       \frac{\partial S_{2}}{\partial u}}  \right )_{u_{0},v_{0}}\\ 
573     v=v_{0}-\left (\frac{\frac{\partial S_{1}}{\partial u}*S_{2}-
574       \frac{\partial S_{2}}{\partial u}*S_{1}}
575       {\frac{\partial S_{1}}{\partial u}*
576       \frac{\partial S_{2}}{\partial v}-
577       \frac{\partial S_{1}}{\partial v}*
578       \frac{\partial S_{2}}{\partial u}}  \right )_{u_{0},v_{0}}
579     \end{matrix}\right.
580
581 where u_{0} and v_{0} are initial values or values computed on previous iteration.
582 */
583
584   theUfinal = theU0;
585   theVfinal = theV0;
586
587   const Standard_Integer aNbIterMax = 100;
588
589   Standard_Real aU = theU0, aV = theV0;
590   gp_Pnt2d aPu, aPv;
591   gp_Vec2d aD1u, aD1v, aD2u, aD2v;
592
593   Standard_Integer aNbIter = 0;
594
595   Standard_Real aStepU = 0.0, aStepV = 0.0;
596
597   Standard_Real aSQDistPrev = RealFirst();
598
599   theC1.D2(aU, aPu, aD1u, aD2u);
600   theC2.D2(aV, aPv, aD1v, aD2v);
601
602   const Standard_Real aCrProd = Abs(aD1u.Crossed(aD1v));
603   if(aCrProd*aCrProd > 1.0e-6*
604       aD1u.SquareMagnitude()*aD1v.SquareMagnitude())
605   {
606     //Curves are not tangent. Therefore, we consider that 
607     //2D-intersection algorithm have found good point which
608     //did not need in more precision.
609     return;
610   }
611
612   do
613   {
614     aNbIter++;
615
616     gp_Vec2d aVuv(aPv, aPu);
617
618     Standard_Real aSQDist = aVuv.SquareMagnitude();
619     if(IsEqual(aSQDist, 0.0))
620       break;
621
622     if((aNbIter == 1) || (aSQDist < aSQDistPrev))
623     {
624       aSQDistPrev = aSQDist;
625       theUfinal = aU;
626       theVfinal = aV;
627     }
628
629
630     Standard_Real aG1 = aD1u.Magnitude();
631     Standard_Real aG2 = aD1v.Magnitude();
632
633     if(IsEqual(aG1, 0.0) || IsEqual(aG2, 0.0))
634     {//Here we do not processing singular cases.
635       break;
636     }
637
638     Standard_Real aF1 = aVuv.Dot(aD1u);
639     Standard_Real aF2 = aVuv.Dot(aD1v);
640
641     Standard_Real aFIu = aVuv.Dot(aD2u);
642     Standard_Real aFIv = aVuv.Dot(aD2v);
643     Standard_Real aPSIu = aD1u.Dot(aD2u);
644     Standard_Real aPSIv = aD1v.Dot(aD2v);
645
646     Standard_Real aTheta = aD1u*aD1v;
647
648     Standard_Real aS1 = aF1/aG1;
649     Standard_Real aS2 = aF2/aG2;
650
651     Standard_Real aDS1u = (aG1*aG1+aFIu)/aG1 - (aS1*aPSIu/(aG1*aG1));
652     Standard_Real aDS1v = -aTheta/aG1;
653     Standard_Real aDS2u = aTheta/aG2;
654     Standard_Real aDS2v = (aFIv-aG2*aG2)/aG2 - (aS2*aPSIv/(aG2*aG2));
655
656     Standard_Real aDet = aDS1u*aDS2v-aDS1v*aDS2u;
657
658     if(IsEqual(aDet, 0.0))
659     {
660       if(!IsEqual(aStepV, 0.0) && !IsEqual(aDS1u, 0.0))
661       {
662         aV += aStepV;
663         aU = aU - (aDS1v*aStepV - aS1)/aDS1u;
664       }
665       else if(!IsEqual(aStepU, 0.0) && !IsEqual(aDS1v, 0.0))
666       {
667         aU += aStepU;
668         aV = aV - (aDS1u*aStepU - aS1)/aDS1v;
669       }
670       else
671       {
672         break;
673       }
674     }
675     else
676     {
677       aStepU = -(aS1*aDS2v-aS2*aDS1v)/aDet;
678       aStepV = -(aS2*aDS1u-aS1*aDS2u)/aDet;
679
680       if(Abs(aStepU) < Epsilon(Abs(aU)))
681       {
682         if(Abs(aStepV) < Epsilon(Abs(aV)))
683         {
684           break;
685         }
686       }
687
688       aU += aStepU;
689       aV += aStepV;
690     }
691
692     theC1.D2(aU, aPu, aD1u, aD2u);
693     theC2.D2(aV, aPv, aD1v, aD2v);
694   }
695   while(aNbIter <= aNbIterMax);
696 }
697
698
699
700 // circulaire tant a deux courbes ,de rayon donne
701 //==================================================
702
703 //========================================================================
704 // On initialise WellDone a false.                                       +
705 // On recupere les courbes Cu1 et Cu2.                                   +
706 // On sort en erreur dans les cas ou la construction est impossible.     +
707 // On fait la parallele a Cu1 dans le bon sens.                          +
708 // On fait la parallele a Cu2 dans le bon sens.                          +
709 // On intersecte les paralleles ==> point de centre de la solution.      +
710 // On cree la solution qu on ajoute aux solutions deja trouvees.         +
711 // On remplit les champs.                                                +
712 //========================================================================
713 Geom2dGcc_Circ2d2TanRadGeo::
714 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
715                             const Geom2dGcc_QCurve& Qualified2,
716                             const Standard_Real Radius    ,
717                             const Standard_Real Tolerance ):
718
719 //========================================================================
720 // initialisation des champs.                                            +
721 //========================================================================
722
723 cirsol(1,aNbSolMAX)   ,
724 qualifier1(1,aNbSolMAX),
725 qualifier2(1,aNbSolMAX),
726 TheSame1(1,aNbSolMAX) ,
727 TheSame2(1,aNbSolMAX) ,
728 pnttg1sol(1,aNbSolMAX),
729 pnttg2sol(1,aNbSolMAX),
730 par1sol(1,aNbSolMAX)  ,
731 par2sol(1,aNbSolMAX)  ,
732 pararg1(1,aNbSolMAX)  ,
733 pararg2(1,aNbSolMAX)  
734 {
735
736   //========================================================================
737   // Traitement.                                                           +
738   //========================================================================
739
740   Standard_Real Tol = Abs(Tolerance);
741 #ifdef OCCT_DEBUG
742   const Standard_Real thefirst = -100000.;
743   const Standard_Real thelast  =  100000.;
744 #endif
745   gp_Dir2d dirx(1.,0.);
746   TColStd_Array1OfReal cote1(1,2);
747   TColStd_Array1OfReal cote2(1,2);
748   Standard_Integer nbrcote1=0;
749   Standard_Integer nbrcote2=0;
750   WellDone = Standard_False;
751   NbrSol = 0;
752   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
753     Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
754     !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
755     Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
756       throw GccEnt_BadQualifier();
757       return;
758   }
759   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
760   Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
761   if (Radius < 0.0) { throw Standard_NegativeValue(); }
762   else {
763     if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
764       //   =======================================================
765       nbrcote1 = 1;
766       nbrcote2 = 1;
767       cote1(1) = Radius;
768       cote2(1) = Radius;
769     }
770     else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
771       //   ==========================================================
772       nbrcote1 = 1;
773       nbrcote2 = 1;
774       cote1(1) = Radius;
775       cote2(1) = -Radius;
776     }
777     else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
778       //   ===========================================================
779       nbrcote1 = 1;
780       nbrcote2 = 1;
781       cote1(1) = -Radius;
782       cote2(1) = Radius;
783     }
784     else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
785       //   =========================================================
786       nbrcote1 = 1;
787       nbrcote2 = 1;
788       cote1(1) = -Radius;
789       cote2(1) = -Radius;
790     }
791     if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
792       //   =========================================================
793       nbrcote1 = 1;
794       nbrcote2 = 2;
795       cote1(1) = Radius;
796       cote2(1) = Radius;
797       cote2(2) = -Radius;
798     }
799     if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
800       //   =========================================================
801       nbrcote1 = 2;
802       nbrcote2 = 1;
803       cote1(1) = Radius;
804       cote1(2) = -Radius;
805       cote2(1) = Radius;
806     }
807     else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
808       //   =============================================================
809       nbrcote1 = 1;
810       nbrcote2 = 2;
811       cote1(1) = -Radius;
812       cote2(1) = Radius;
813       cote2(2) = -Radius;
814     }
815     if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
816       //   ========================================================
817       nbrcote1 = 2;
818       nbrcote2 = 1;
819       cote1(1) = Radius;
820       cote1(2) = -Radius;
821       cote2(1) = -Radius;
822     }
823     else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
824       //   =================================================================
825       nbrcote1 = 2;
826       nbrcote2 = 2;
827       cote1(1) = Radius;
828       cote1(2) = -Radius;
829       cote2(1) = Radius;
830       cote2(2) = -Radius;
831     }
832     Geom2dInt_GInter Intp;
833     for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
834       Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1); 
835       Adaptor2d_OffsetCurve C1(HCu1,cote1(jcote1));
836 #ifdef OCCT_DEBUG
837       Standard_Real firstparam = Max(C1.FirstParameter(), thefirst);
838       Standard_Real lastparam = Min(C1.LastParameter(), thelast);
839       IntRes2d_Domain D2C1(C1.Value(firstparam),firstparam,Tol,
840         C1.Value(lastparam),lastparam,Tol);
841 #endif
842       for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
843         Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
844         Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
845 #ifdef OCCT_DEBUG
846         firstparam = Max(C2.FirstParameter(), thefirst);
847         lastparam  = Min(C2.LastParameter(),thelast);
848         IntRes2d_Domain D2C2(C2.Value(firstparam),firstparam,Tol,
849           C2.Value(lastparam),lastparam,Tol);
850 #endif
851         Intp.Perform(C1,C2,Tol,Tol);
852         if (Intp.IsDone()) {
853           if (!Intp.IsEmpty()) {
854             const Standard_Real aSQApproxTol = Precision::Approximation() *
855                                                 Precision::Approximation();
856             for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++)
857             {
858               Standard_Real aU0 = Intp.Point(i).ParamOnFirst();
859               Standard_Real aV0 = Intp.Point(i).ParamOnSecond();
860
861               Standard_Real aU1 = aU0-Precision::PApproximation();
862               Standard_Real aV1 = aV0-Precision::PApproximation();
863
864               Standard_Real aU2 = aU0+Precision::PApproximation();
865               Standard_Real aV2 = aV0+Precision::PApproximation();
866
867               gp_Pnt2d P11 = C1.Value(aU1);
868               gp_Pnt2d P12 = C2.Value(aV1);
869               gp_Pnt2d P21 = C1.Value(aU2);
870               gp_Pnt2d P22 = C2.Value(aV2);
871
872               Standard_Real aDist1112 = P11.SquareDistance(P12);
873               Standard_Real aDist1122 = P11.SquareDistance(P22);
874
875               Standard_Real aDist1221 = P12.SquareDistance(P21);
876               Standard_Real aDist2122 = P21.SquareDistance(P22);
877
878               if( (Min(aDist1112, aDist1122) <= aSQApproxTol) &&
879                   (Min(aDist1221, aDist2122) <= aSQApproxTol))
880               {
881                 PrecRoot(C1, C2, aU0, aV0, aU0, aV0);
882               }
883
884               NbrSol++;
885               gp_Pnt2d Center(C1.Value(aU0));
886               cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
887               //             =======================================================
888               qualifier1(NbrSol) = Qualified1.Qualifier();
889               qualifier1(NbrSol) = Qualified1.Qualifier();
890               TheSame1(NbrSol) = 0;
891               TheSame2(NbrSol) = 0;
892               pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
893               pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
894               pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
895               pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
896               par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
897                 pnttg1sol(NbrSol));
898               par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
899                 pnttg2sol(NbrSol));
900             }
901           }
902
903           WellDone = Standard_True;
904         }
905       }
906     }
907   }
908 }
909
910 //=========================================================================
911
912 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
913 IsDone () const { return WellDone; }
914
915 Standard_Integer Geom2dGcc_Circ2d2TanRadGeo::
916 NbSolutions () const { return NbrSol; }
917
918 gp_Circ2d Geom2dGcc_Circ2d2TanRadGeo::
919 ThisSolution (const Standard_Integer Index) const 
920 {
921   if (!WellDone) { throw StdFail_NotDone(); }
922   if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
923   return cirsol(Index);
924 }
925
926 void Geom2dGcc_Circ2d2TanRadGeo::
927 WhichQualifier(const Standard_Integer Index   ,
928                GccEnt_Position& Qualif1 ,
929                GccEnt_Position& Qualif2 ) const
930 {
931   if (!WellDone) { throw StdFail_NotDone(); }
932   else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
933   else {
934     Qualif1 = qualifier1(Index);
935     Qualif2 = qualifier2(Index);
936   }
937 }
938
939 void Geom2dGcc_Circ2d2TanRadGeo::
940 Tangency1 (const Standard_Integer Index,
941            Standard_Real&   ParSol,
942            Standard_Real&   ParArg,
943            gp_Pnt2d&        PntSol) const{
944              if (!WellDone) { throw StdFail_NotDone(); }
945              else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
946              else {
947                if (TheSame1(Index) == 0) {
948                  ParSol = par1sol(Index);
949                  ParArg = pararg1(Index);
950                  PntSol = gp_Pnt2d(pnttg1sol(Index));
951                }
952                else { throw StdFail_NotDone(); }
953              }
954 }
955
956 void Geom2dGcc_Circ2d2TanRadGeo::
957 Tangency2 (const Standard_Integer Index,
958            Standard_Real&   ParSol,
959            Standard_Real&   ParArg,
960            gp_Pnt2d&        PntSol) const{
961              if (!WellDone) { throw StdFail_NotDone(); }
962              else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
963              else {
964                if (TheSame2(Index) == 0) {
965                  ParSol = par2sol(Index);
966                  ParArg = pararg2(Index);
967                  PntSol = gp_Pnt2d(pnttg2sol(Index));
968                }
969                else { throw StdFail_NotDone(); }
970              }
971 }
972
973 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
974 IsTheSame1 (const Standard_Integer Index) const
975 {
976   if (!WellDone) { throw StdFail_NotDone(); }
977   if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
978
979   if (TheSame1(Index) == 0) { return Standard_False; }
980   return Standard_True;
981 }
982
983 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
984 IsTheSame2 (const Standard_Integer Index) const
985 {
986   if (!WellDone) { throw StdFail_NotDone(); }
987   if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
988
989   if (TheSame2(Index) == 0) { return Standard_False; }
990   return Standard_True;
991 }
992