0025720: Incorrect code of math classes can lead to unpredicted behavior of algorithms
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2d2TanOnIter.cxx
1 // Created on: 1991-12-13
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 //   Creation d un cercle tangent a deux elements : Droite.               +
19 //                                                  Cercle.               +
20 //                                                  Point.                +
21 //                                                  Courbes.              +
22 //                        centre sur un troisieme : Droite.               +
23 //                                                  Cercle.               +
24 //                                                  Courbes.              +
25 //=========================================================================
26
27 #include <Geom2dGcc_Circ2d2TanOnIter.ixx>
28
29 #include <gp_Dir2d.hxx>
30 #include <gp_Ax2d.hxx>
31 #include <gp.hxx>
32 #include <StdFail_NotDone.hxx>
33 #include <GccEnt_BadQualifier.hxx>
34 #include <math_FunctionSetRoot.hxx>
35 #include <ElCLib.hxx>
36
37 #include <Geom2dGcc_CurveTool.hxx>
38 #include <Geom2dGcc_FunctionTanCuCuOnCu.hxx>
39
40 Geom2dGcc_Circ2d2TanOnIter::
41 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedLin&  Qualified1 , 
42                             const Geom2dGcc_QCurve&     Qualified2 , 
43                             const gp_Lin2d&             OnLine     ,
44                             const Standard_Real         Param1     ,
45                             const Standard_Real         Param2     ,
46                             const Standard_Real         Param3     ,
47                             const Standard_Real         Tolang     ) {
48
49                               TheSame1 = Standard_False;
50                               TheSame2 = Standard_False;
51                               par1sol = 0.;
52                               par2sol = 0.;
53                               pararg1 = 0.;
54                               pararg2 = 0.;
55                               parcen3 = 0.;
56
57                               WellDone = Standard_False;
58                               Standard_Real Tol = Abs(Tolang);
59                               WellDone = Standard_False;
60                               if (!(Qualified1.IsEnclosed() ||
61                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
62                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
63                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
64                                   GccEnt_BadQualifier::Raise();
65                                   return;
66                               }
67                               gp_Dir2d dirx(1.,0.);
68                               gp_Lin2d L1 = Qualified1.Qualified();
69                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
70                               math_Vector Umin(1,4);
71                               math_Vector Umax(1,4);
72                               math_Vector Ufirst(1,4);
73                               math_Vector tol(1,4);
74                               Umin(1) = RealFirst();
75                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
76                               Umin(3) = RealFirst();
77                               Umin(4) = 0.;
78                               Umax(1) = RealLast();
79                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
80                               Umax(3) = RealLast();
81                               Umax(4) = RealLast();
82                               Ufirst(1) = Param1;
83                               Ufirst(2) = Param2;
84                               Ufirst(3) = Param3;
85                               tol(1) = 1.e-15;
86                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Tolang);
87                               tol(3) = tol(1);   
88                               tol(4) = tol(1);   
89                               gp_Pnt2d point1 = ElCLib::Value(Param1,L1);
90                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
91                               gp_Pnt2d point3 = ElCLib::Value(Param3,OnLine);
92                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
93                               Geom2dGcc_FunctionTanCuCuOnCu Func(L1,Cu2,OnLine,Ufirst(4));
94                               math_FunctionSetRoot Root(Func, tol);
95                               Root.Perform(Func, Ufirst, Umin, Umax);
96                               Func.Value(Ufirst,Umin);
97                               if (Root.IsDone()) {
98                                 Root.Root(Ufirst);
99                                 //     gp_Vec2d Tan1,Tan2,Nor1,Nor2;
100                                 gp_Vec2d Tan1,Tan2;
101                                 ElCLib::D1(Ufirst(1),L1,point1,Tan1);
102                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
103                                 gp_Vec2d Tan3(OnLine.Direction().XY());
104                                 gp_Pnt2d point3(OnLine.Location().XY()+Ufirst(3)*Tan3.XY());
105                                 Standard_Real dist1 = point3.Distance(point1);
106                                 Standard_Real dist2 = point3.Distance(point2);
107                                 if ( Abs(dist1-dist2)/2. <= Tol) {
108                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
109                                   Standard_Real normetan2 = Tan2.Magnitude();
110                                   gp_Vec2d Vec1(point1,point3);
111                                   gp_Vec2d Vec2(point2,point3);
112                                   Standard_Real normevec2 = Vec2.Magnitude();
113                                   Standard_Real angle2;
114                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
115                                     angle2 = Vec2.Angle(Tan2);
116                                   }
117                                   else { angle2 = 0.; }
118                                   Standard_Real pscal=point3.XY().Dot(gp_XY(-L1.Direction().Y(),
119                                     L1.Direction().X()));
120                                   if (Qualified1.IsUnqualified() ||
121                                     (Qualified1.IsOutside() && pscal <= 0.) ||
122                                     (Qualified1.IsEnclosed() && pscal >= 0.)) {
123                                       if (Qualified2.IsUnqualified() || 
124                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
125                                         (Qualified2.IsOutside() && angle2 >= 0) ||
126                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
127                                           qualifier1 = Qualified1.Qualifier();
128                                           qualifier2 = Qualified2.Qualifier();
129                                           pnttg1sol = point1;
130                                           pararg1 = Ufirst(1);
131                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
132                                           pnttg2sol = point2;
133                                           pararg2 = Ufirst(2);
134                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
135                                           pntcen  = point3;
136                                           parcen3 = Ufirst(3);
137                                           WellDone = Standard_True;
138                                       }
139                                   }
140                                 }
141                               }
142 }
143
144 Geom2dGcc_Circ2d2TanOnIter::
145 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve& Qualified1 , 
146                             const Geom2dGcc_QCurve& Qualified2 , 
147                             const gp_Lin2d&          OnLine     ,
148                             const Standard_Real               Param1     ,
149                             const Standard_Real               Param2     ,
150                             const Standard_Real               Param3     ,
151                             const Standard_Real               Tolerance  ) {
152                               TheSame1 = Standard_False;
153                               TheSame2 = Standard_False;
154                               par1sol = 0.;
155                               par2sol = 0.;
156                               pararg1 = 0.;
157                               pararg2 = 0.;
158                               parcen3 = 0.;
159
160                               WellDone = Standard_False;
161                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
162                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
163                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
164                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
165                                   GccEnt_BadQualifier::Raise();
166                                   return;
167                               }
168                               Standard_Real Tol = Abs(Tolerance);
169                               gp_Dir2d dirx(1.,0.);
170                               Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
171                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
172                               math_Vector Umin(1,4);
173                               math_Vector Umax(1,4);
174                               math_Vector Ufirst(1,4);
175                               math_Vector tol(1,4);
176                               Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
177                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
178                               Umin(3) = RealFirst();
179                               Umin(4) = 0.;
180                               Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
181                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
182                               Umax(3) = RealLast();
183                               Umax(4) = RealLast();
184                               Ufirst(1) = Param1;
185                               Ufirst(2) = Param2;
186                               Ufirst(3) = Param3;
187                               tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
188                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
189                               tol(3) = 1.e-15;   
190                               tol(4) = Tol/10.;   
191                               gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
192                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
193                               gp_Pnt2d point3 = ElCLib::Value(Param3,OnLine);
194                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
195                               Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Cu2,OnLine,Ufirst(4));
196                               math_FunctionSetRoot Root(Func, tol);
197                               Root.Perform(Func, Ufirst, Umin, Umax);
198                               Func.Value(Ufirst,Umin);
199                               if (Root.IsDone()) {
200                                 Root.Root(Ufirst);
201                                 gp_Vec2d Tan1,Tan2;
202                                 Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
203                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
204                                 gp_Vec2d Tan3(OnLine.Direction().XY());
205                                 gp_Pnt2d point3(OnLine.Location().XY()+Ufirst(3)*Tan3.XY());
206                                 Standard_Real dist1 = point3.Distance(point1);
207                                 Standard_Real dist2 = point3.Distance(point2);
208                                 if ( Abs(dist1-dist2)/2. <= Tol) {
209                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
210                                   Standard_Real normetan1 = Tan1.Magnitude();
211                                   Standard_Real normetan2 = Tan2.Magnitude();
212                                   gp_Vec2d Vec1(point1,point3);
213                                   gp_Vec2d Vec2(point2,point3);
214                                   Standard_Real normevec1 = Vec1.Magnitude();
215                                   Standard_Real normevec2 = Vec2.Magnitude();
216                                   Standard_Real angle1,angle2;
217                                   if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
218                                     angle1 = Vec1.Angle(Tan1);
219                                   }
220                                   else { angle1 = 0.; }
221                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
222                                     angle2 = Vec2.Angle(Tan2);
223                                   }
224                                   else { angle2 = 0.; }
225                                   if (Qualified1.IsUnqualified()||
226                                     (Qualified1.IsEnclosing()&&angle1<=0.)||
227                                     (Qualified1.IsOutside() && angle1 >= 0.) ||
228                                     (Qualified1.IsEnclosed() && angle1 <= 0.)) {
229                                       if (Qualified2.IsUnqualified() || 
230                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
231                                         (Qualified2.IsOutside() && angle2 >= 0) ||
232                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
233                                           qualifier1 = Qualified1.Qualifier();
234                                           qualifier2 = Qualified2.Qualifier();
235                                           pnttg1sol = point1;
236                                           pararg1 = Ufirst(1);
237                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
238                                           pnttg2sol = point2;
239                                           pararg2 = Ufirst(2);
240                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
241                                           pntcen  = point3;
242                                           parcen3 = Ufirst(3);
243                                           WellDone = Standard_True;
244                                       }
245                                   }
246                                 }
247                               }
248 }
249
250 Geom2dGcc_Circ2d2TanOnIter::
251 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve& Qualified1 , 
252                             const gp_Pnt2d&          Point2     , 
253                             const gp_Lin2d&          OnLine     ,
254                             const Standard_Real      Param1     ,
255                             const Standard_Real      Param2     ,
256                             const Standard_Real      Tolerance  ) {
257                               TheSame1 = Standard_False;
258                               TheSame2 = Standard_False;
259                               par1sol = 0.;
260                               par2sol = 0.;
261                               pararg1 = 0.;
262                               pararg2 = 0.;
263                               parcen3 = 0.;
264
265                               WellDone = Standard_False;
266                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
267                                 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
268                                   GccEnt_BadQualifier::Raise();
269                                   return;
270                               }
271                               Standard_Real Tol = Abs(Tolerance);
272                               gp_Dir2d dirx(1.,0.);
273                               Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
274                               math_Vector Umin(1,3);
275                               math_Vector Umax(1,3);
276                               math_Vector Ufirst(1,3);
277                               math_Vector tol(1,3);
278                               Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
279                               Umin(2) = RealFirst();
280                               Umin(3) = 0.;
281                               Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
282                               Umax(2) = RealLast();
283                               Umax(3) = RealLast();
284                               Ufirst(1) = Param1;
285                               Ufirst(2) = Param2;
286                               tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
287                               tol(2) = 1.e-15;
288                               tol(3) = Tol/10.;
289                               gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
290                               gp_Pnt2d point3 = ElCLib::Value(Param2,OnLine);
291                               Ufirst(3) = (point3.Distance(Point2)+point3.Distance(point1))/2.;
292                               Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Point2,OnLine,Ufirst(3));
293                               math_FunctionSetRoot Root(Func, tol);
294                               Root.Perform(Func, Ufirst, Umin, Umax);
295                               Func.Value(Ufirst,Umin);
296                               if (Root.IsDone()) {
297                                 Root.Root(Ufirst);
298                                 gp_Pnt2d point1,point3;
299                                 gp_Vec2d Tan1,Tan3;
300                                 Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
301                                 ElCLib::D1(Ufirst(2),OnLine,point3,Tan3);
302                                 Standard_Real dist1 = point3.Distance(point1);
303                                 Standard_Real dist2 = point3.Distance(Point2);
304                                 if ( Abs(dist1-dist2)/2. <= Tol) {
305                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
306                                   Standard_Real normetan1 = Tan1.Magnitude();
307                                   gp_Vec2d Vec1(point1,point3);
308                                   Standard_Real normevec1 = Vec1.Magnitude();
309                                   Standard_Real angle1;
310                                   if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
311                                     angle1 = Vec1.Angle(Tan1);
312                                   }
313                                   else { angle1 = 0.; }
314                                   if (Qualified1.IsUnqualified()||
315                                     (Qualified1.IsEnclosing()&&angle1<=0.)||
316                                     (Qualified1.IsOutside() && angle1 >= 0.) ||
317                                     (Qualified1.IsEnclosed() && angle1 <= 0.)) {
318                                       qualifier1 = Qualified1.Qualifier();
319                                       qualifier2 = GccEnt_noqualifier;
320                                       pnttg1sol = point1;
321                                       pararg1 = Ufirst(1);
322                                       par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
323                                       pnttg2sol = Point2;
324                                       pararg2 = Ufirst(2);
325                                       par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
326                                       pntcen  = point3;
327                                       parcen3 = Ufirst(3);
328                                       WellDone = Standard_True;
329                                   }
330                                 }
331                               }
332 }
333
334 Geom2dGcc_Circ2d2TanOnIter::
335 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedCirc& Qualified1 , 
336                             const Geom2dGcc_QCurve&     Qualified2 , 
337                             const gp_Lin2d&             OnLine     ,
338                             const Standard_Real         Param1     ,
339                             const Standard_Real         Param2     ,
340                             const Standard_Real         Param3     ,
341                             const Standard_Real         Tolerance  ) {
342                               TheSame1 = Standard_False;
343                               TheSame2 = Standard_False;
344                               par1sol = 0.;
345                               par2sol = 0.;
346                               pararg1 = 0.;
347                               pararg2 = 0.;
348                               parcen3 = 0.;
349
350                               WellDone = Standard_False;
351                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
352                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
353                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
354                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
355                                   GccEnt_BadQualifier::Raise();
356                                   return;
357                               }
358                               Standard_Real Tol = Abs(Tolerance);
359                               gp_Dir2d dirx(1.,0.);
360                               gp_Circ2d C1 = Qualified1.Qualified();
361                               Standard_Real R1 = C1.Radius();
362                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
363                               math_Vector Umin(1,4);
364                               math_Vector Umax(1,4);
365                               math_Vector Ufirst(1,4);
366                               math_Vector tol(1,4);
367                               Umin(1) = RealFirst();
368                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
369                               Umin(3) = RealFirst();
370                               Umin(4) = 0.;
371                               Umax(1) = RealLast();
372                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
373                               Umax(3) = RealLast();
374                               Umax(4) = RealLast();
375                               Ufirst(1) = Param1;
376                               Ufirst(2) = Param2;
377                               Ufirst(3) = Param3;
378                               tol(1) = 2.e-15*M_PI;
379                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
380                               tol(3) = 1.e-15;
381                               tol(4) = Tol/10.;
382                               gp_Pnt2d point1 = ElCLib::Value(Param1,C1);
383                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
384                               gp_Pnt2d point3 = ElCLib::Value(Param3,OnLine);
385                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
386                               Geom2dGcc_FunctionTanCuCuOnCu Func(C1,Cu2,OnLine,Ufirst(4));
387                               math_FunctionSetRoot Root(Func, tol);
388                               Root.Perform(Func, Ufirst, Umin, Umax);
389                               Func.Value(Ufirst,Umin);
390                               if (Root.IsDone()) {
391                                 Root.Root(Ufirst);
392                                 //     gp_Vec2d Tan1,Tan2,Nor1,Nor2;
393                                 gp_Vec2d Tan1,Tan2,Nor2;
394                                 ElCLib::D2(Ufirst(1),C1,point1,Tan1,Nor2);
395                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
396 #ifdef OCCT_DEBUG
397                                 gp_Vec2d Tan3(OnLine.Direction().XY());
398 #else
399                                 OnLine.Direction().XY();
400 #endif
401                                 point3 = ElCLib::Value(Ufirst(1),OnLine);
402                                 Standard_Real dist1 = point3.Distance(point1);
403                                 Standard_Real dist2 = point3.Distance(point2);
404                                 if ( Abs(dist1-dist2)/2. <= Tol) {
405                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
406                                   Standard_Real normetan2 = Tan2.Magnitude();
407                                   gp_Vec2d Vec1(point1,point3);
408                                   gp_Vec2d Vec2(point2,point3);
409                                   Standard_Real normevec2 = Vec2.Magnitude();
410                                   Standard_Real angle2;
411                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
412                                     angle2 = Vec2.Angle(Tan2);
413                                   }
414                                   else { angle2 = 0.; }
415                                   Standard_Real dist = C1.Location().Distance(point3);
416                                   Standard_Real Rsol = cirsol.Radius();
417                                   if (Qualified1.IsUnqualified() || 
418                                     (Qualified1.IsEnclosing() && Rsol >= R1 && dist <= Rsol)||
419                                     (Qualified1.IsOutside() && dist >= Rsol) ||
420                                     (Qualified1.IsEnclosed() && Rsol <= R1 && dist <= Rsol)) {
421                                       if (Qualified2.IsUnqualified() || 
422                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
423                                         (Qualified2.IsOutside() && angle2 >= 0) ||
424                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
425                                           qualifier1 = Qualified1.Qualifier();
426                                           qualifier2 = Qualified2.Qualifier();
427                                           pnttg1sol = point1;
428                                           pararg1 = Ufirst(1);
429                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
430                                           pnttg2sol = point2;
431                                           pararg2 = Ufirst(2);
432                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
433                                           pntcen  = point3;
434                                           parcen3 = Ufirst(3);
435                                           WellDone = Standard_True;
436                                       }
437                                   }
438                                 }
439                               }
440 }
441
442 Geom2dGcc_Circ2d2TanOnIter::
443 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedCirc& Qualified1 , 
444                             const Geom2dGcc_QCurve&     Qualified2 , 
445                             const gp_Circ2d&            OnCirc     ,
446                             const Standard_Real         Param1     ,
447                             const Standard_Real         Param2     ,
448                             const Standard_Real         Param3     ,
449                             const Standard_Real         Tolerance  ) {
450                               TheSame1 = Standard_False;
451                               TheSame2 = Standard_False;
452                               par1sol = 0.;
453                               par2sol = 0.;
454                               pararg1 = 0.;
455                               pararg2 = 0.;
456                               parcen3 = 0.;
457
458                               WellDone = Standard_False;
459                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
460                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
461                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
462                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
463                                   GccEnt_BadQualifier::Raise();
464                                   return;
465                               }
466                               Standard_Real Tol = Abs(Tolerance);
467                               gp_Dir2d dirx(1.,0.);
468                               gp_Circ2d C1 = Qualified1.Qualified();
469                               Standard_Real R1 = C1.Radius();
470                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
471                               math_Vector Umin(1,4);
472                               math_Vector Umax(1,4);
473                               math_Vector Ufirst(1,4);
474                               math_Vector tol(1,4);
475                               Umin(1) = RealFirst();
476                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
477                               Umin(3) = RealFirst();
478                               Umin(4) = 0.;
479                               Umax(1) = RealLast();
480                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
481                               Umax(3) = RealLast();
482                               Umax(4) = RealLast();
483                               Ufirst(1) = Param1;
484                               Ufirst(2) = Param2;
485                               Ufirst(3) = Param3;
486                               tol(1) = 2.e-15*M_PI;
487                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
488                               tol(3) = 2.e-15*M_PI;
489                               tol(4) = Tol/10.;
490                               gp_Pnt2d point1 = ElCLib::Value(Param1,C1);
491                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
492                               gp_Pnt2d point3 = ElCLib::Value(Param3,OnCirc);
493                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
494                               Geom2dGcc_FunctionTanCuCuOnCu Func(C1,Cu2,OnCirc,Ufirst(4));
495                               math_FunctionSetRoot Root(Func, tol);
496                               Root.Perform(Func, Ufirst, Umin, Umax);
497                               Func.Value(Ufirst,Umin);
498                               if (Root.IsDone()) {
499                                 Root.Root(Ufirst);
500                                 //     gp_Vec2d Tan1,Tan2,Nor1;
501                                 gp_Vec2d Tan1,Tan2;
502                                 ElCLib::D1(Ufirst(1),C1,point1,Tan1);
503                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
504 #ifdef OCCT_DEBUG
505                                 gp_Vec2d Tan3(-Sin(Ufirst(3)),Cos(Ufirst(3)));
506 #endif
507                                 point3 = ElCLib::Value(Ufirst(3),OnCirc);
508                                 Standard_Real dist1 = point3.Distance(point1);
509                                 Standard_Real dist2 = point3.Distance(point2);
510                                 if ( Abs(dist1-dist2)/2. <= Tol) {
511                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
512                                   Standard_Real normetan2 = Tan2.Magnitude();
513                                   gp_Vec2d Vec1(point1,point3);
514                                   gp_Vec2d Vec2(point2,point3);
515                                   Standard_Real normevec2 = Vec2.Magnitude();
516                                   Standard_Real angle2;
517                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
518                                     angle2 = Vec2.Angle(Tan2);
519                                   }
520                                   else { angle2 = 0.; }
521                                   Standard_Real dist = C1.Location().Distance(point3);
522                                   Standard_Real Rsol = cirsol.Radius();
523                                   if (Qualified1.IsUnqualified() || 
524                                     (Qualified1.IsEnclosing() && Rsol >= R1 && dist <= Rsol)||
525                                     (Qualified1.IsOutside() && dist >= Rsol) ||
526                                     (Qualified1.IsEnclosed() && Rsol <= R1 && dist <= Rsol)) {
527                                       if (Qualified2.IsUnqualified() || 
528                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
529                                         (Qualified2.IsOutside() && angle2 >= 0) ||
530                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
531                                           qualifier1 = Qualified1.Qualifier();
532                                           qualifier2 = Qualified2.Qualifier();
533                                           pnttg1sol = point1;
534                                           pararg1 = Ufirst(1);
535                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
536                                           pnttg2sol = point2;
537                                           pararg2 = Ufirst(2);
538                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
539                                           pntcen  = point3;
540                                           parcen3 = Ufirst(3);
541                                           WellDone = Standard_True;
542                                       }
543                                   }
544                                 }
545                               }
546 }
547
548 Geom2dGcc_Circ2d2TanOnIter::
549 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedLin&  Qualified1 , 
550                             const Geom2dGcc_QCurve&     Qualified2 , 
551                             const gp_Circ2d&            OnCirc     ,
552                             const Standard_Real         Param1     ,
553                             const Standard_Real         Param2     ,
554                             const Standard_Real         Param3     ,
555                             const Standard_Real         Tolerance  ) {
556                               TheSame1 = Standard_False;
557                               TheSame2 = Standard_False;
558                               par1sol = 0.;
559                               par2sol = 0.;
560                               pararg1 = 0.;
561                               pararg2 = 0.;
562                               parcen3 = 0.;
563
564                               WellDone = Standard_False;
565                               if (!(Qualified1.IsEnclosed() ||
566                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
567                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
568                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
569                                   GccEnt_BadQualifier::Raise();
570                                   return;
571                               }
572                               Standard_Real Tol = Abs(Tolerance);
573                               gp_Dir2d dirx(1.,0.);
574                               gp_Lin2d L1 = Qualified1.Qualified();
575                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
576                               math_Vector Umin(1,4);
577                               math_Vector Umax(1,4);
578                               math_Vector Ufirst(1,4);
579                               math_Vector tol(1,4);
580                               Umin(1) = RealFirst();
581                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
582                               Umin(3) = RealFirst();
583                               Umin(4) = 0.;
584                               Umax(1) = RealLast();
585                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
586                               Umax(3) = RealLast();
587                               Umax(4) = RealLast();
588                               Ufirst(1) = Param1;
589                               Ufirst(2) = Param2;
590                               Ufirst(3) = Param3;
591                               tol(1) = 1.e-15;
592                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
593                               tol(3) = 2.e-15*M_PI;
594                               tol(4) = Tol/10.;
595                               gp_Pnt2d point1 = ElCLib::Value(Param1,L1);
596                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
597                               gp_Pnt2d point3 = ElCLib::Value(Param3,OnCirc);
598                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
599                               Geom2dGcc_FunctionTanCuCuOnCu Func(L1,Cu2,OnCirc,Ufirst(4));
600                               math_FunctionSetRoot Root(Func, tol);
601                               Root.Perform(Func, Ufirst, Umin, Umax);
602                               Func.Value(Ufirst,Umin);
603                               if (Root.IsDone()) {
604                                 Root.Root(Ufirst);
605                                 gp_Pnt2d point1,point2;
606                                 gp_Vec2d Tan1,Tan2;
607                                 ElCLib::D1(Ufirst(1),L1,point1,Tan1);
608                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
609 #ifdef OCCT_DEBUG
610                                 gp_Vec2d Tan3(-Sin(Ufirst(3)),Cos(Ufirst(3)));
611 #endif
612                                 point3 = ElCLib::Value(Ufirst(3),OnCirc);
613                                 Standard_Real dist1 = point3.Distance(point1);
614                                 Standard_Real dist2 = point3.Distance(point2);
615                                 if ( Abs(dist1-dist2)/2. <= Tol) {
616                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
617                                   Standard_Real normetan2 = Tan2.Magnitude();
618                                   gp_Vec2d Vec1(point1,point3);
619                                   gp_Vec2d Vec2(point2,point3);
620                                   Standard_Real normevec2 = Vec2.Magnitude();
621                                   Standard_Real angle2;
622                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
623                                     angle2 = Vec2.Angle(Tan2);
624                                   }
625                                   else { angle2 = 0.; }
626                                   Standard_Real pscal=point3.XY().Dot(gp_XY(-L1.Direction().Y(),
627                                     L1.Direction().X()));
628                                   if (Qualified1.IsUnqualified() ||
629                                     (Qualified1.IsOutside() && pscal <= 0.) ||
630                                     (Qualified1.IsEnclosed() && pscal >= 0.)) {
631                                       if (Qualified2.IsUnqualified() || 
632                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
633                                         (Qualified2.IsOutside() && angle2 >= 0) ||
634                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
635                                           qualifier1 = Qualified1.Qualifier();
636                                           qualifier2 = Qualified2.Qualifier();
637                                           pnttg1sol = point1;
638                                           pararg1 = Ufirst(1);
639                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
640                                           pnttg2sol = point2;
641                                           pararg2 = Ufirst(2);
642                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
643                                           pntcen  = point3;
644                                           parcen3 = Ufirst(3);
645                                           WellDone = Standard_True;
646                                       }
647                                   }
648                                 }
649                               }
650 }
651
652 Geom2dGcc_Circ2d2TanOnIter::
653 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve& Qualified1 , 
654                             const Geom2dGcc_QCurve& Qualified2 , 
655                             const gp_Circ2d&         OnCirc     ,
656                             const Standard_Real               Param1     ,
657                             const Standard_Real               Param2     ,
658                             const Standard_Real               Param3     ,
659                             const Standard_Real               Tolerance  ) {
660                               TheSame1 = Standard_False;
661                               TheSame2 = Standard_False;
662                               par1sol = 0.;
663                               par2sol = 0.;
664                               pararg1 = 0.;
665                               pararg2 = 0.;
666                               parcen3 = 0.;
667
668                               WellDone = Standard_False;
669                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
670                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
671                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
672                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
673                                   GccEnt_BadQualifier::Raise();
674                                   return;
675                               }
676                               Standard_Real Tol = Abs(Tolerance);
677                               gp_Dir2d dirx(1.,0.);
678                               Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
679                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
680                               math_Vector Umin(1,4);
681                               math_Vector Umax(1,4);
682                               math_Vector Ufirst(1,4);
683                               math_Vector tol(1,4);
684                               Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
685                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
686                               Umin(3) = RealFirst();
687                               Umin(4) = 0.;
688                               Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
689                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
690                               Umax(3) = RealLast();
691                               Umax(4) = RealLast();
692                               Ufirst(1) = Param1;
693                               Ufirst(2) = Param2;
694                               Ufirst(3) = Param3;
695                               tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
696                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
697                               tol(3) = 2.e-15*M_PI;
698                               tol(4) = Tol/10.;
699                               gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
700                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
701                               Standard_Real R1 = OnCirc.Radius();
702                               gp_Pnt2d point3(OnCirc.Location().XY()+R1*gp_XY(Cos(Param3),Sin(Param3)));
703                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
704                               Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Cu2,OnCirc,Ufirst(4));
705                               math_FunctionSetRoot Root(Func, tol);
706                               Root.Perform(Func, Ufirst, Umin, Umax);
707                               Func.Value(Ufirst,Umin);
708                               if (Root.IsDone()) {
709                                 Root.Root(Ufirst);
710                                 //     gp_Vec2d Tan1,Tan2,Nor1;
711                                 gp_Vec2d Tan1,Tan2;
712                                 Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
713                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
714 #ifdef OCCT_DEBUG
715                                 gp_Vec2d Tan3(-Sin(Ufirst(3)),Cos(Ufirst(3)));
716 #endif
717                                 point3 = gp_Pnt2d(OnCirc.Location().XY()+
718                                   R1*gp_XY(Cos(Ufirst(3)),Sin(Ufirst(3))));
719                                 Standard_Real dist1 = point3.Distance(point1);
720                                 Standard_Real dist2 = point3.Distance(point2);
721                                 if ( Abs(dist1-dist2)/2. <= Tol) {
722                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
723                                   Standard_Real normetan1 = Tan1.Magnitude();
724                                   Standard_Real normetan2 = Tan2.Magnitude();
725                                   gp_Vec2d Vec1(point1,point3);
726                                   gp_Vec2d Vec2(point2,point3);
727                                   Standard_Real normevec1 = Vec1.Magnitude();
728                                   Standard_Real normevec2 = Vec2.Magnitude();
729                                   Standard_Real angle1,angle2;
730                                   if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
731                                     angle1 = Vec1.Angle(Tan1);
732                                   }
733                                   else { angle1 = 0.; }
734                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
735                                     angle2 = Vec2.Angle(Tan2);
736                                   }
737                                   else { angle2 = 0.; }
738                                   if (Qualified1.IsUnqualified()||
739                                     (Qualified1.IsEnclosing()&&angle1<=0.)||
740                                     (Qualified1.IsOutside() && angle1 >= 0.) ||
741                                     (Qualified1.IsEnclosed() && angle1 <= 0.)) {
742                                       if (Qualified2.IsUnqualified() || 
743                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
744                                         (Qualified2.IsOutside() && angle2 >= 0) ||
745                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
746                                           qualifier1 = Qualified1.Qualifier();
747                                           qualifier2 = Qualified2.Qualifier();
748                                           pararg1 = Ufirst(1);
749                                           par1sol = 0.;
750                                           pnttg1sol = point1;
751                                           pararg2 = Ufirst(2);
752                                           pnttg2sol = point2;
753                                           par2sol = pnttg2sol.Distance(pnttg1sol);
754                                           pntcen  = point3;
755                                           parcen3 = Ufirst(3);
756                                           WellDone = Standard_True;
757                                       }
758                                   }
759                                 }
760                               }
761 }
762
763 Geom2dGcc_Circ2d2TanOnIter::
764 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve&  Qualified1 ,
765                             const gp_Pnt2d&          Point2     ,
766                             const gp_Circ2d&         OnCirc     ,
767                             const Standard_Real      Param1     ,
768                             const Standard_Real      Param2     ,
769                             const Standard_Real      Tolerance  ) {
770                               TheSame1 = Standard_False;
771                               TheSame2 = Standard_False;
772                               par1sol = 0.;
773                               par2sol = 0.;
774                               pararg1 = 0.;
775                               pararg2 = 0.;
776                               parcen3 = 0.;
777
778                               WellDone = Standard_False;
779                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
780                                 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
781                                   GccEnt_BadQualifier::Raise();
782                                   return;
783                               }
784                               Standard_Real Tol = Abs(Tolerance);
785                               gp_Dir2d dirx(1.,0.);
786                               Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
787                               math_Vector Umin(1,3);
788                               math_Vector Umax(1,3);
789                               math_Vector Ufirst(1,3);
790                               math_Vector tol(1,3);
791                               Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
792                               Umin(2) = RealFirst();
793                               Umin(3) = 0.;
794                               Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
795                               Umax(2) = RealLast();
796                               Umax(3) = RealLast();
797                               Ufirst(1) = Param1;
798                               Ufirst(2) = Param2;
799                               tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
800                               tol(2) = 2.e-15*M_PI;
801                               tol(3) = Tol/10.;
802                               gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
803                               gp_Pnt2d point3 = ElCLib::Value(Param2,OnCirc);
804                               Ufirst(3) = (point3.Distance(Point2)+point3.Distance(point1))/2.;
805                               Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Point2,OnCirc,Ufirst(3));
806                               math_FunctionSetRoot Root(Func, tol);
807                               Root.Perform(Func, Ufirst, Umin, Umax);
808                               Func.Value(Ufirst,Umin);
809                               if (Root.IsDone()) {
810                                 Root.Root(Ufirst);
811                                 gp_Pnt2d point1,point3;
812                                 gp_Vec2d Tan1,Tan3;
813                                 Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
814                                 ElCLib::D1(Ufirst(2),OnCirc,point3,Tan3);
815                                 Standard_Real dist1 = point3.Distance(point1);
816                                 Standard_Real dist2 = point3.Distance(Point2);
817                                 if ( Abs(dist1-dist2)/2. <= Tol) {
818                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
819                                   Standard_Real normetan1 = Tan1.Magnitude();
820                                   gp_Vec2d Vec1(point1,point3);
821                                   Standard_Real normevec1 = Vec1.Magnitude();
822                                   Standard_Real angle1;
823                                   if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
824                                     angle1 = Vec1.Angle(Tan1);
825                                   }
826                                   else { angle1 = 0.; }
827                                   if (Qualified1.IsUnqualified()||
828                                     (Qualified1.IsEnclosing()&&angle1<=0.)||
829                                     (Qualified1.IsOutside() && angle1 >= 0.) ||
830                                     (Qualified1.IsEnclosed() && angle1 <= 0.)) {
831                                       qualifier1 = Qualified1.Qualifier();
832                                       qualifier2 = GccEnt_noqualifier;
833                                       pnttg1sol = point1;
834                                       pararg1 = Ufirst(1);
835                                       par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
836                                       pnttg2sol = Point2;
837                                       pararg2 = 0.;
838                                       par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
839                                       pntcen  = point3;
840                                       parcen3 = Ufirst(3);
841                                       WellDone = Standard_True;
842                                   }
843                                 }
844                               }
845 }
846
847 Geom2dGcc_Circ2d2TanOnIter::
848 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve& Qualified1 , 
849                             const Geom2dGcc_QCurve& Qualified2 , 
850                             const Geom2dAdaptor_Curve&          OnCurv     ,
851                             const Standard_Real               Param1     ,
852                             const Standard_Real               Param2     ,
853                             const Standard_Real               Param3     ,
854                             const Standard_Real               Tolerance  ) {
855                               TheSame1 = Standard_False;
856                               TheSame2 = Standard_False;
857                               par1sol = 0.;
858                               par2sol = 0.;
859                               pararg1 = 0.;
860                               pararg2 = 0.;
861                               parcen3 = 0.;
862
863                               WellDone = Standard_False;
864                               Standard_Real Tol = Abs(Tolerance);
865                               WellDone = Standard_False;
866                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
867                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
868                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
869                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
870                                   GccEnt_BadQualifier::Raise();
871                                   return;
872                               }
873                               gp_Dir2d dirx(1.,0.);
874                               Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
875                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
876                               math_Vector Umin(1,4);
877                               math_Vector Umax(1,4);
878                               math_Vector Ufirst(1,4);
879                               math_Vector tol(1,4);
880                               Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
881                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
882                               Umin(3) = Geom2dGcc_CurveTool::FirstParameter(OnCurv);
883                               Umin(4) = 0.;
884                               Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
885                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
886                               Umax(3) = Geom2dGcc_CurveTool::LastParameter(OnCurv);
887                               Umax(4) = RealLast();
888                               Ufirst(1) = Param1;
889                               Ufirst(2) = Param2;
890                               Ufirst(3) = Param3;
891                               tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
892                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
893                               tol(3) = Geom2dGcc_CurveTool::EpsX(OnCurv,Abs(Tolerance));
894                               tol(4) = Tol/10.;
895                               gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
896                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
897                               gp_Pnt2d point3 = Geom2dGcc_CurveTool::Value(OnCurv,Param3);
898                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
899                               Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Cu2,OnCurv,Ufirst(4));
900                               math_FunctionSetRoot Root(Func, tol);
901                               Root.Perform(Func, Ufirst, Umin, Umax);
902                               Func.Value(Ufirst,Umin);
903                               if (Root.IsDone()) {
904                                 Root.Root(Ufirst);
905                                 gp_Vec2d Tan1,Tan2,Tan3;
906                                 Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
907                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
908                                 Geom2dGcc_CurveTool::D1(OnCurv,Ufirst(3),point3,Tan3);
909                                 Standard_Real dist1 = point3.Distance(point1);
910                                 Standard_Real dist2 = point3.Distance(point2);
911                                 if ( Abs(dist1-dist2)/2. <= Tol) {
912                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
913                                   Standard_Real normetan1 = Tan1.Magnitude();
914                                   Standard_Real normetan2 = Tan2.Magnitude();
915                                   gp_Vec2d Vec1(point1,point3);
916                                   gp_Vec2d Vec2(point2,point3);
917                                   Standard_Real normevec1 = Vec1.Magnitude();
918                                   Standard_Real normevec2 = Vec2.Magnitude();
919                                   Standard_Real angle1,angle2;
920                                   if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
921                                     angle1 = Vec1.Angle(Tan1);
922                                   }
923                                   else { angle1 = 0.; }
924                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
925                                     angle2 = Vec2.Angle(Tan2);
926                                   }
927                                   else { angle2 = 0.; }
928                                   if (Qualified1.IsUnqualified()||
929                                     (Qualified1.IsEnclosing()&&angle1<=0.)||
930                                     (Qualified1.IsOutside() && angle1 >= 0.) ||
931                                     (Qualified1.IsEnclosed() && angle1 <= 0.)) {
932                                       if (Qualified2.IsUnqualified() || 
933                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
934                                         (Qualified2.IsOutside() && angle2 >= 0) ||
935                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
936                                           qualifier1 = Qualified1.Qualifier();
937                                           qualifier2 = Qualified2.Qualifier();
938                                           pararg1 = Ufirst(1);
939                                           par1sol = 0.;
940                                           pnttg1sol = point1;
941                                           pararg2 = Ufirst(2);
942                                           pnttg2sol = point2;
943                                           par2sol = pnttg2sol.Distance(pnttg1sol);
944                                           pntcen  = point3;
945                                           parcen3 = Ufirst(3);
946                                           WellDone = Standard_True;
947                                       }
948                                   }
949                                 }
950                               }
951 }
952
953 Geom2dGcc_Circ2d2TanOnIter::
954 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedCirc& Qualified1 , 
955                             const Geom2dGcc_QCurve&       Qualified2 , 
956                             const Geom2dAdaptor_Curve&                OnCurv     ,
957                             const Standard_Real                     Param1     ,
958                             const Standard_Real                     Param2     ,
959                             const Standard_Real                     ParamOn    ,
960                             const Standard_Real                     Tolerance     ) {
961
962                               TheSame1 = Standard_False;
963                               TheSame2 = Standard_False;
964                               par1sol = 0.;
965                               par2sol = 0.;
966                               pararg1 = 0.;
967                               pararg2 = 0.;
968                               parcen3 = 0.;
969
970                               WellDone = Standard_False;
971                               if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
972                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
973                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
974                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
975                                   GccEnt_BadQualifier::Raise();
976                                   return;
977                               }
978                               Standard_Real Tol = Abs(Tolerance);
979                               gp_Circ2d C1 = Qualified1.Qualified();
980                               Standard_Real R1 = C1.Radius();
981                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
982                               math_Vector Umin(1,4);
983                               math_Vector Umax(1,4);
984                               math_Vector Ufirst(1,4);
985                               math_Vector tol(1,4);
986                               Umin(1) = RealFirst();
987                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
988                               Umin(3) = Geom2dGcc_CurveTool::FirstParameter(OnCurv);
989                               Umin(4) = 0.;
990                               Umax(1) = RealLast();
991                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
992                               Umax(3) = Geom2dGcc_CurveTool::LastParameter(OnCurv);
993                               Umax(4) = RealLast();
994                               Ufirst(1) = Param1;
995                               Ufirst(2) = Param2;
996                               Ufirst(3) = ParamOn;
997                               tol(1) = 2.e-15*M_PI;
998                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
999                               tol(3) = Geom2dGcc_CurveTool::EpsX(OnCurv,Abs(Tolerance));
1000                               tol(4) = Tol/10.;;
1001                               gp_Pnt2d point1 = ElCLib::Value(Param1,C1);
1002                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
1003                               gp_Pnt2d point3 = Geom2dGcc_CurveTool::Value(OnCurv,ParamOn);
1004                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
1005                               Geom2dGcc_FunctionTanCuCuOnCu Func(C1,Cu2,OnCurv,Ufirst(4));
1006                               math_FunctionSetRoot Root(Func, tol);
1007                               Root.Perform(Func, Ufirst, Umin, Umax);
1008                               Func.Value(Ufirst,Umin);
1009                               if (Root.IsDone()) {
1010                                 Root.Root(Ufirst);
1011                                 gp_Vec2d Tan1,Tan2,Tan3;
1012                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
1013                                 Geom2dGcc_CurveTool::D1(OnCurv,Ufirst(3),point3,Tan3);
1014                                 ElCLib::D1(Ufirst(1),C1,point1,Tan1);
1015                                 Standard_Real dist1 = point3.Distance(point1);
1016                                 Standard_Real dist2 = point3.Distance(point2);
1017                                 if ( Abs(dist1-dist2)/2. <= Tol) {
1018                                   gp_Dir2d dirx(1.,0.);
1019                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
1020                                   Standard_Real normetan2 = Tan2.Magnitude();
1021                                   gp_Vec2d Vec1(point1.XY(),point3.XY());
1022                                   gp_Vec2d Vec2(point2.XY(),point3.XY());
1023                                   Standard_Real normevec2 = Vec2.Magnitude();
1024                                   Standard_Real angle2;
1025                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
1026                                     angle2 = Vec2.Angle(Tan2);
1027                                   }
1028                                   else { angle2 = 0.; }
1029                                   Standard_Real dist = C1.Location().Distance(point3);
1030                                   Standard_Real Rsol = cirsol.Radius();
1031                                   if (Qualified1.IsUnqualified() || 
1032                                     (Qualified1.IsEnclosing() && Rsol >= R1 && dist <= Rsol)||
1033                                     (Qualified1.IsOutside() && dist >= Rsol) ||
1034                                     (Qualified1.IsEnclosed() && Rsol <= R1 && dist <= Rsol)) {
1035                                       if (Qualified2.IsUnqualified() || 
1036                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
1037                                         (Qualified2.IsOutside() && angle2 >= 0) ||
1038                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
1039                                           qualifier1 = Qualified1.Qualifier();
1040                                           qualifier2 = Qualified2.Qualifier();
1041                                           pnttg1sol = point1;
1042                                           pararg1 = Ufirst(1);
1043                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
1044                                           pnttg2sol = point2;
1045                                           pararg2 = Ufirst(2);
1046                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
1047                                           pntcen  = point3;
1048                                           parcen3 = Ufirst(3);
1049                                           WellDone = Standard_True;
1050                                       }
1051                                   }
1052                                 }
1053                               }
1054 }
1055
1056 Geom2dGcc_Circ2d2TanOnIter::
1057 Geom2dGcc_Circ2d2TanOnIter (const GccEnt_QualifiedLin&  Qualified1 , 
1058                             const Geom2dGcc_QCurve&     Qualified2 , 
1059                             const Geom2dAdaptor_Curve&                OnCurv     ,
1060                             const Standard_Real                     Param1     ,
1061                             const Standard_Real                     Param2     ,
1062                             const Standard_Real                     ParamOn    ,
1063                             const Standard_Real                     Tolerance  ) {
1064                               TheSame1 = Standard_False;
1065                               TheSame2 = Standard_False;
1066                               par1sol = 0.;
1067                               par2sol = 0.;
1068                               pararg1 = 0.;
1069                               pararg2 = 0.;
1070                               parcen3 = 0.;
1071
1072                               WellDone = Standard_False;
1073                               if (!(Qualified1.IsEnclosed() ||
1074                                 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
1075                                 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
1076                                 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
1077                                   GccEnt_BadQualifier::Raise();
1078                                   return;
1079                               }
1080                               Standard_Real Tol = Abs(Tolerance);
1081                               gp_Dir2d dirx(1.,0.);
1082                               gp_Lin2d L1 = Qualified1.Qualified();
1083                               Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
1084                               math_Vector Umin(1,4);
1085                               math_Vector Umax(1,4);
1086                               math_Vector Ufirst(1,4);
1087                               math_Vector tol(1,4);
1088                               Umin(1) = RealFirst();
1089                               Umin(2) = Geom2dGcc_CurveTool::FirstParameter(Cu2);
1090                               Umin(3) = Geom2dGcc_CurveTool::FirstParameter(OnCurv);
1091                               Umin(4) = 0.;
1092                               Umax(1) = RealLast();
1093                               Umax(2) = Geom2dGcc_CurveTool::LastParameter(Cu2);
1094                               Umax(3) = Geom2dGcc_CurveTool::LastParameter(OnCurv);
1095                               Umax(4) = RealLast();
1096                               Ufirst(1) = Param1;
1097                               Ufirst(2) = Param2;
1098                               Ufirst(3) = ParamOn;
1099                               tol(1) = 1.e-15;
1100                               tol(2) = Geom2dGcc_CurveTool::EpsX(Cu2,Abs(Tolerance));
1101                               tol(3) = Geom2dGcc_CurveTool::EpsX(OnCurv,Abs(Tolerance));
1102                               tol(4) = Tol/10.;
1103                               gp_Pnt2d point1 = ElCLib::Value(Param1,L1);
1104                               gp_Pnt2d point2 = Geom2dGcc_CurveTool::Value(Cu2,Param2);
1105                               gp_Pnt2d point3 = Geom2dGcc_CurveTool::Value(OnCurv,ParamOn);
1106                               Ufirst(4) = (point3.Distance(point2)+point3.Distance(point1))/2.;
1107                               Geom2dGcc_FunctionTanCuCuOnCu Func(L1,Cu2,OnCurv,Ufirst(4));
1108                               math_FunctionSetRoot Root(Func, tol);
1109                               Root.Perform(Func, Ufirst, Umin, Umax);
1110                               Func.Value(Ufirst,Umin);
1111                               if (Root.IsDone()) {
1112                                 Root.Root(Ufirst);
1113                                 gp_Vec2d Tan1,Tan2,Tan3;
1114                                 ElCLib::D1(Ufirst(1),L1,point1,Tan1);
1115                                 Geom2dGcc_CurveTool::D1(Cu2,Ufirst(2),point2,Tan2);
1116                                 Geom2dGcc_CurveTool::D1(OnCurv,Ufirst(3),point3,Tan3);
1117                                 Standard_Real dist1 = point3.Distance(point1);
1118                                 Standard_Real dist2 = point3.Distance(point2);
1119                                 if ( Abs(dist1-dist2)/2. <= Tol) {
1120                                   cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
1121                                   Standard_Real normetan2 = Tan2.Magnitude();
1122                                   gp_Vec2d Vec1(point1,point3);
1123                                   gp_Vec2d Vec2(point2,point3);
1124                                   Standard_Real normevec2 = Vec2.Magnitude();
1125                                   Standard_Real angle2;
1126                                   if (normevec2 >= gp::Resolution() && normetan2 >= gp::Resolution()) {
1127                                     angle2 = Vec2.Angle(Tan2);
1128                                   }
1129                                   else { angle2 = 0.; }
1130                                   Standard_Real pscal=point3.XY().Dot(gp_XY(-L1.Direction().Y(),
1131                                     L1.Direction().X()));
1132                                   if (Qualified1.IsUnqualified() ||
1133                                     (Qualified1.IsOutside() && pscal <= 0.) ||
1134                                     (Qualified1.IsEnclosed() && pscal >= 0.)) {
1135                                       if (Qualified2.IsUnqualified() || 
1136                                         (Qualified2.IsEnclosing()&&angle2<=0.)||
1137                                         (Qualified2.IsOutside() && angle2 >= 0) ||
1138                                         (Qualified2.IsEnclosed() && angle2 <= 0.)) {
1139                                           qualifier1 = Qualified1.Qualifier();
1140                                           qualifier2 = Qualified2.Qualifier();
1141                                           pnttg1sol = point1;
1142                                           pararg1 = Ufirst(1);
1143                                           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
1144                                           pnttg2sol = point2;
1145                                           pararg2 = Ufirst(2);
1146                                           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
1147                                           pntcen  = point3;
1148                                           parcen3 = Ufirst(3);
1149                                           WellDone = Standard_True;
1150                                       }
1151                                   }
1152                                 }
1153                               }
1154 }
1155
1156 Geom2dGcc_Circ2d2TanOnIter::
1157 Geom2dGcc_Circ2d2TanOnIter (const Geom2dGcc_QCurve&    Qualified1 ,
1158                             const gp_Pnt2d&             Point2     ,
1159                             const Geom2dAdaptor_Curve&             OnCurv     ,
1160                             const Standard_Real                  Param1     ,
1161                             const Standard_Real                  ParamOn    ,
1162                             const Standard_Real                  Tolerance  ) 
1163 {
1164   TheSame1 = Standard_False;
1165   TheSame2 = Standard_False;
1166   par1sol = 0.;
1167   par2sol = 0.;
1168   pararg1 = 0.;
1169   pararg2 = 0.;
1170   parcen3 = 0.;
1171
1172   WellDone = Standard_False;
1173   if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
1174     Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
1175       GccEnt_BadQualifier::Raise();
1176       return;
1177   }
1178   Standard_Real Tol = Abs(Tolerance);
1179   gp_Dir2d dirx(1.,0.);
1180   Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
1181   math_Vector Umin(1,3);
1182   math_Vector Umax(1,3);
1183   math_Vector Ufirst(1,3);
1184   math_Vector tol(1,3);
1185   Umin(1) = Geom2dGcc_CurveTool::FirstParameter(Cu1);
1186   Umin(2) = RealFirst();
1187   Umin(3) = Geom2dGcc_CurveTool::FirstParameter(OnCurv);
1188   Umax(1) = Geom2dGcc_CurveTool::LastParameter(Cu1);
1189   Umax(2) = RealLast();
1190   Umax(3) = Geom2dGcc_CurveTool::LastParameter(OnCurv);
1191   Ufirst(1) = Param1;
1192   Ufirst(2) = ParamOn;
1193   tol(1) = Geom2dGcc_CurveTool::EpsX(Cu1,Abs(Tolerance));
1194   tol(2) = Geom2dGcc_CurveTool::EpsX(OnCurv,Abs(Tolerance));
1195   tol(3) = Tol/10.;
1196   gp_Pnt2d point1 = Geom2dGcc_CurveTool::Value(Cu1,Param1);
1197   gp_Pnt2d point3 = Geom2dGcc_CurveTool::Value(OnCurv,ParamOn);
1198   Ufirst(3) = (point3.Distance(Point2)+point3.Distance(point1))/2.;
1199   Geom2dGcc_FunctionTanCuCuOnCu Func(Cu1,Point2,OnCurv,Ufirst(3));
1200   math_FunctionSetRoot Root(Func, tol);
1201   Root.Perform(Func, Ufirst, Umin, Umax);
1202   Func.Value(Ufirst,Umin);
1203   if (Root.IsDone()) {
1204     Root.Root(Ufirst);
1205     //    gp_Vec2d Tan1,Tan2,Tan3;
1206     gp_Vec2d Tan1,Tan3;
1207     Geom2dGcc_CurveTool::D1(Cu1,Ufirst(1),point1,Tan1);
1208     Geom2dGcc_CurveTool::D1(OnCurv,Ufirst(3),point3,Tan3);
1209     Standard_Real dist1 = point3.Distance(point1);
1210     Standard_Real dist2 = point3.Distance(Point2);
1211     if ( Abs(dist1-dist2)/2. <= Tol) {
1212       cirsol = gp_Circ2d(gp_Ax2d(point3,dirx),(dist1+dist2)/2.);
1213       Standard_Real normetan1 = Tan1.Magnitude();
1214       gp_Vec2d Vec1(point1,point3);
1215       Standard_Real normevec1 = Vec1.Magnitude();
1216       Standard_Real angle1;
1217       if (normevec1 >= gp::Resolution() && normetan1 >= gp::Resolution()) {
1218         angle1 = Vec1.Angle(Tan1);
1219       }
1220       else { angle1 = 0.; }
1221       if (Qualified1.IsUnqualified()||
1222         (Qualified1.IsEnclosing()&&angle1<=0.)||
1223         (Qualified1.IsOutside() && angle1 >= 0.) ||
1224         (Qualified1.IsEnclosed() && angle1 <= 0.)) {
1225           qualifier1 = Qualified1.Qualifier();
1226           qualifier2 = GccEnt_noqualifier;
1227           pnttg1sol = point1;
1228           pararg1 = Ufirst(1);
1229           par1sol = ElCLib::Parameter(cirsol,pnttg1sol);
1230           pnttg2sol = Point2;
1231           pararg2 = 0.;
1232           par2sol = ElCLib::Parameter(cirsol,pnttg2sol);
1233           pntcen  = point3;
1234           parcen3 = Ufirst(3);
1235           WellDone = Standard_True;
1236       }
1237     }
1238   }
1239 }
1240
1241 Standard_Boolean Geom2dGcc_Circ2d2TanOnIter::
1242 IsDone () const{ return WellDone; }
1243
1244 gp_Circ2d Geom2dGcc_Circ2d2TanOnIter::
1245 ThisSolution () const{ return cirsol; }
1246
1247 void Geom2dGcc_Circ2d2TanOnIter:: 
1248 WhichQualifier (GccEnt_Position& Qualif1  ,
1249                 GccEnt_Position& Qualif2  ) const
1250 {
1251   if (!WellDone) { StdFail_NotDone::Raise(); }
1252   else {
1253     Qualif1 = qualifier1;
1254     Qualif2 = qualifier2;
1255   }
1256 }
1257
1258 void Geom2dGcc_Circ2d2TanOnIter:: 
1259 Tangency1 (Standard_Real&      ParSol         ,
1260            Standard_Real&      ParArg         ,
1261            gp_Pnt2d&  PntSol         ) const
1262 {
1263   if (!WellDone) { StdFail_NotDone::Raise(); }
1264   else {
1265     if (TheSame1 == 0) {
1266       ParSol = 0;
1267       ParArg = 0;
1268       PntSol = pnttg1sol;
1269     }
1270     else { StdFail_NotDone::Raise(); }
1271   }
1272 }
1273
1274 void Geom2dGcc_Circ2d2TanOnIter:: 
1275 Tangency2 (Standard_Real&      ParSol         ,
1276            Standard_Real&      ParArg         ,
1277            gp_Pnt2d&  PntSol         ) const
1278 {
1279   if (!WellDone) { StdFail_NotDone::Raise(); }
1280   else {
1281     ParSol = 0;
1282     ParArg = 0;
1283     PntSol = pnttg2sol;
1284   }
1285 }
1286
1287 void Geom2dGcc_Circ2d2TanOnIter::
1288 CenterOn3 (Standard_Real&      ParArg         ,
1289            gp_Pnt2d&  PntSol         ) const
1290 {
1291   if (!WellDone) { StdFail_NotDone::Raise(); }
1292   else {
1293     ParArg = 0;
1294     PntSol = pntcen;
1295   }
1296 }
1297
1298 Standard_Boolean Geom2dGcc_Circ2d2TanOnIter::
1299 IsTheSame1 () const
1300 {
1301   if (!WellDone) StdFail_NotDone::Raise();
1302
1303   if (TheSame1 == 0) 
1304     return Standard_False;
1305   return Standard_True;
1306 }
1307
1308
1309 Standard_Boolean Geom2dGcc_Circ2d2TanOnIter::
1310 IsTheSame2 () const
1311 {
1312   if (!WellDone) StdFail_NotDone::Raise();
1313   return Standard_False;
1314 }