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