Integration of OCCT 6.5.0 from SVN
[occt.git] / src / GccIter / GccIter_Lin2d2Tan.gxx
1 // File:        GccIter_Lin2d2Tan.gxx
2 // Created:     Fri Dec 20 15:00:23 1991
3 // Author:      Remi GILET
4 //              <reg@topsn3>
5
6 //========================================================================
7 //  CREATION D UNE LIGNE TANGENTE A DEUX COURBES.                        +
8 //========================================================================
9
10 #include <StdFail_NotDone.hxx>
11 #include <GccEnt_BadQualifier.hxx>
12 #include <gp_XY.hxx>
13 #include <gp_Dir2d.hxx>
14 #include <gp_Vec2d.hxx>
15 #include <gp_Circ2d.hxx>
16 #include <math_Vector.hxx>
17 #include <math_Matrix.hxx>
18 #include <math_FunctionSetRoot.hxx>
19 #include <math_FunctionRoot.hxx>
20
21 GccIter_Lin2d2Tan::
22    GccIter_Lin2d2Tan (const GccEnt_QualifiedCirc& Qualified1 ,
23                       const TheQualifiedCurve&    Qualified2 ,
24                       const Standard_Real         Param2     ,
25                       const Standard_Real         Tolang     ) {
26      
27    par1sol = 0.;
28    pararg1 = 0.;
29 #ifdef DEB
30    Standard_Real Tol = Abs(Tolang);
31 #endif
32    WellDone = Standard_False;
33    if (Qualified1.IsEnclosed()) { GccEnt_BadQualifier::Raise(); }
34    gp_Circ2d C1 = Qualified1.Qualified();
35    TheCurve Cu2 = Qualified2.Qualified();
36    Standard_Real U1 = TheCurveTool::FirstParameter(Cu2);
37    Standard_Real U2 = TheCurveTool::LastParameter(Cu2);
38    GccIter_FuncTCirCu func(C1,Cu2);
39    math_FunctionRoot sol(func,Param2,TheCurveTool::EpsX(Cu2,Abs(Tolang)),U1,U2,100);
40    if (sol.IsDone()) {
41      Standard_Real Usol = sol.Root();
42 //     gp_Pnt2d Origine,Pt;
43 //  Modified by Sergey KHROMOV - Thu Apr  5 17:39:47 2001 Begin
44      Standard_Real Norm;
45      func.Value(Usol, Norm);
46      if (Abs(Norm) < Tolang) {
47 //  Modified by Sergey KHROMOV - Thu Apr  5 17:39:48 2001 End
48      gp_Pnt2d Origine;
49      gp_Vec2d Vect1;
50      gp_Vec2d Vect2;
51      TheCurveTool::D2(Cu2,Usol,Origine,Vect1,Vect2);
52      gp_Vec2d Vdir(C1.Location().XY() - Origine.XY());
53      Standard_Real sign1 = Vect1.Dot(Vdir);
54      if (sign1 <= 0. ) { Vect1.Reverse(); }
55      Standard_Real sign2 = Vect2.Crossed(Vect1);
56      if (Qualified2.IsUnqualified() || 
57          (Qualified2.IsEnclosing() && sign2<=0.) ||
58          (Qualified2.IsOutside() && sign1 <= 0. && sign2 >= 0.) ||
59          (Qualified2.IsEnclosed() && sign1 >= 0. && sign2 >= 0.)) {
60        if (Qualified1.IsUnqualified() ||
61            (Qualified1.IsOutside() && Vect1.Angle(Vdir) <= 0.) ||
62            (Qualified1.IsEnclosing() && Vect1.Angle(Vdir) >= 0.)) {
63          gp_Dir2d direc(Vect1);
64          Standard_Real R1 = C1.Radius();
65          gp_XY normal(-R1*direc.Y(),R1*direc.X());
66          sign1 = Vect1.Crossed(Vdir);
67          if (Qualified1.IsEnclosing()) {
68            pnttg1sol = gp_Pnt2d(C1.Location().XY()-normal);
69          }
70          else if (Qualified1.IsOutside()) {
71            pnttg1sol = gp_Pnt2d(C1.Location().XY()+normal);
72          }
73          else {
74            if (sign1 >= 0.) {
75              pnttg1sol = gp_Pnt2d(C1.Location().XY()-normal);
76            }
77            else {
78              pnttg1sol = gp_Pnt2d(C1.Location().XY()+normal);
79            }
80          }
81 //       if (gp_Vec2d(direc.XY()).Angle(gp_Vec2d(pnttg1sol,Origine)) <= Tol) {
82            pnttg2sol = Origine;
83            linsol = gp_Lin2d(pnttg1sol,direc);
84            WellDone = Standard_True;
85            qualifier1 = Qualified1.Qualifier();
86            qualifier2 = Qualified2.Qualifier();
87            pararg2 = Usol;
88            par1sol = 0.;
89            par2sol = pnttg2sol.Distance(pnttg1sol);
90            pararg1 = 0.;
91          }
92        }
93      }
94    }
95  }
96
97 GccIter_Lin2d2Tan::
98    GccIter_Lin2d2Tan (const TheQualifiedCurve& Qualified1 ,
99                       const TheQualifiedCurve& Qualified2 ,
100                       const Standard_Real      Param1     ,
101                       const Standard_Real      Param2     ,
102                       const Standard_Real      Tolang     ) {
103    par1sol = 0.;
104    pararg1 = 0.;
105    WellDone = Standard_False;
106    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
107          Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
108        !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 
109          Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
110      GccEnt_BadQualifier::Raise();
111      return;
112    }
113    TheCurve Cu1 = Qualified1.Qualified();
114    TheCurve Cu2 = Qualified2.Qualified();
115    GccIter_FuncTCuCu Func(Cu1,Cu2);
116    math_Vector Umin(1,2);
117    math_Vector Umax(1,2);
118    math_Vector Ufirst(1,2);
119    math_Vector tol(1,2);
120    Umin(1) = TheCurveTool::FirstParameter(Cu1);
121    Umin(2) = TheCurveTool::FirstParameter(Cu2);
122    Umax(1) = TheCurveTool::LastParameter(Cu1);
123    Umax(2) = TheCurveTool::LastParameter(Cu2);
124    Ufirst(1) = Param1;
125    Ufirst(2) = Param2;
126    tol(1) = TheCurveTool::EpsX(Cu1,Abs(Tolang));
127    tol(2) = TheCurveTool::EpsX(Cu2,Abs(Tolang));
128    math_FunctionSetRoot Root(Func,Ufirst,tol,Umin,Umax);
129    if (Root.IsDone()) {
130      Root.Root(Ufirst);
131 //  Modified by Sergey KHROMOV - Thu Apr  5 17:45:00 2001 Begin
132      math_Vector Norm(1,2);
133      Func.Value(Ufirst, Norm);
134      if (Abs(Norm(1)) < Tolang && Abs(Norm(2)) < Tolang) {
135 //  Modified by Sergey KHROMOV - Thu Apr  5 17:45:01 2001 End
136        gp_Pnt2d point1,point2;
137        gp_Vec2d Vect11,Vect12,Vect21,Vect22;
138        TheCurveTool::D2(Cu1,Ufirst(1),point1,Vect11,Vect12);
139        TheCurveTool::D2(Cu2,Ufirst(2),point2,Vect21,Vect22);
140        gp_Vec2d Vec(point1.XY(),point2.XY());
141        Standard_Real Angle1 = Vec.Angle(Vect12);
142        Standard_Real sign1 = Vect11.Dot(Vec);
143        if (Qualified1.IsUnqualified() || 
144            (Qualified1.IsEnclosing() && Angle1 >= 0.) ||
145            (Qualified1.IsOutside() && Angle1 <= 0. && sign1 <= 0.) ||
146            (Qualified1.IsEnclosed() && Angle1 <= 0. && sign1 >= 0.)) {
147          Angle1 = Vec.Angle(Vect22);
148          sign1 = Vect21.Dot(Vec);
149          if (Qualified2.IsUnqualified() || 
150              (Qualified2.IsEnclosing() && Angle1 >= 0.) ||
151              (Qualified2.IsOutside() && Angle1 <= 0. && sign1 <= 0.) ||
152              (Qualified2.IsEnclosed() && Angle1 <= 0. && sign1 >= 0.)) {
153            qualifier1 = Qualified1.Qualifier();
154            qualifier2 = Qualified2.Qualifier();
155            pararg1 = Ufirst(1);
156            par1sol = 0.;
157            pnttg1sol = point1;
158            pararg2 = Ufirst(2);
159            pnttg2sol = point2;
160            par2sol = pnttg2sol.Distance(pnttg1sol);
161            gp_Dir2d dir(pnttg2sol.X()-pnttg1sol.X(),pnttg2sol.Y()-pnttg1sol.Y());
162            linsol = gp_Lin2d(pnttg1sol,dir);
163            WellDone = Standard_True;
164          }
165        }
166      }
167    }
168  }
169
170 GccIter_Lin2d2Tan::
171    GccIter_Lin2d2Tan (const TheQualifiedCurve& Qualified1 ,
172                       const gp_Pnt2d&          ThePoint   ,
173                       const Standard_Real      Param1     ,
174                       const Standard_Real      Tolang     ) {
175      
176    par1sol = 0.;
177    pararg1 = 0.;
178    WellDone = Standard_False;
179    if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 
180          Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
181      GccEnt_BadQualifier::Raise();
182      return;
183    }
184    TheCurve Cu1 = Qualified1.Qualified();
185    Standard_Real U1 = TheCurveTool::FirstParameter(Cu1);
186    Standard_Real U2 = TheCurveTool::LastParameter(Cu1);
187    GccIter_FuncTCuPt func(Cu1,ThePoint);
188    math_FunctionRoot sol(func,Param1,TheCurveTool::EpsX(Cu1,Abs(Tolang)),U1,U2,100);
189    if (sol.IsDone()) {
190      Standard_Real Usol = sol.Root();
191 //  Modified by Sergey KHROMOV - Thu Apr  5 17:45:17 2001 Begin
192      Standard_Real Norm;
193      func.Value(Usol, Norm);
194      if (Abs(Norm) < Tolang) {
195 //  Modified by Sergey KHROMOV - Thu Apr  5 17:45:19 2001 End
196        gp_Pnt2d Origine;
197        gp_Vec2d Vect1;
198        gp_Vec2d Vect2;
199        TheCurveTool::D2(Cu1,Usol,Origine,Vect1,Vect2);
200        gp_Vec2d Vdir(ThePoint.XY()-Origine.XY());
201        Standard_Real sign1 = Vect1.Dot(Vdir);
202        Standard_Real sign2 = Vect2.Crossed(Vdir);
203        if (Qualified1.IsUnqualified() || 
204            (Qualified1.IsEnclosing() && 
205             ((sign1 >= 0. && sign2 <= 0.) || (sign1 <= 0. && sign2 <= 0.))) ||
206            (Qualified1.IsOutside() && sign1 <= 0. && sign2 >= 0.) ||
207            (Qualified1.IsEnclosed() && sign1 >= 0. && sign2 >= 0.)) {
208          WellDone = Standard_True;
209          linsol = gp_Lin2d(Origine,gp_Dir2d(Vdir));
210          qualifier1 = Qualified1.Qualifier();
211          qualifier2 = GccEnt_noqualifier;
212          pnttg1sol = Origine;
213          pnttg2sol = ThePoint;
214          pararg1 = Usol;
215          par1sol = 0.;
216          pararg2 = ThePoint.Distance(Origine);
217          par2sol = 0.;
218        }
219      }
220    }
221  }
222
223 Standard_Boolean GccIter_Lin2d2Tan::
224    IsDone () const { return WellDone; }
225
226 gp_Lin2d GccIter_Lin2d2Tan::
227    ThisSolution () const 
228 {
229   if (!WellDone) StdFail_NotDone::Raise();
230   return linsol;
231 }
232
233 void GccIter_Lin2d2Tan:: 
234   WhichQualifier (GccEnt_Position& Qualif1  ,
235                   GccEnt_Position& Qualif2  ) const
236 {
237   if (!WellDone) { StdFail_NotDone::Raise(); }
238   else {
239     Qualif1 = qualifier1;
240     Qualif2 = qualifier2;
241   }
242 }
243
244 void GccIter_Lin2d2Tan::
245    Tangency1 (Standard_Real& ParSol ,
246               Standard_Real& ParArg ,
247               gp_Pnt2d& Pnt) const {
248    if (!WellDone) { StdFail_NotDone::Raise(); }
249    else {
250      ParSol = par1sol;
251      ParArg = pararg1;
252      Pnt    = pnttg1sol;
253    }
254  }
255
256 void GccIter_Lin2d2Tan::
257    Tangency2 (Standard_Real& ParSol ,
258               Standard_Real& ParArg ,
259               gp_Pnt2d& Pnt) const {
260    if (!WellDone) { StdFail_NotDone::Raise(); }
261    else {
262      ParSol = par2sol;
263      ParArg = pararg2;
264      Pnt    = pnttg2sol;
265    }
266  }
267