Commit | Line | Data |
---|---|---|
b311480e | 1 | // Copyright (c) 1995-1999 Matra Datavision |
2 | // Copyright (c) 1999-2012 OPEN CASCADE SAS | |
3 | // | |
4 | // The content of this file is subject to the Open CASCADE Technology Public | |
5 | // License Version 6.5 (the "License"). You may not use the content of this file | |
6 | // except in compliance with the License. Please obtain a copy of the License | |
7 | // at http://www.opencascade.org and read it completely before using this file. | |
8 | // | |
9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its | |
10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. | |
11 | // | |
12 | // The Original Code and all software distributed under the License is | |
13 | // distributed on an "AS IS" basis, without warranty of any kind, and the | |
14 | // Initial Developer hereby disclaims all such warranties, including without | |
15 | // limitation, any warranties of merchantability, fitness for a particular | |
16 | // purpose or non-infringement. Please see the License for the specific terms | |
17 | // and conditions governing the rights and limitations under the License. | |
18 | ||
7fd59977 | 19 | |
20 | //========================================================================= | |
0d969553 Y |
21 | // Straight line tangent to two circles or tangent to a circle and passing + |
22 | // through point. + | |
7fd59977 | 23 | //========================================================================= |
24 | ||
25 | #include <GccAna_Lin2d2Tan.ixx> | |
26 | ||
27 | #include <ElCLib.hxx> | |
28 | #include <gp_XY.hxx> | |
29 | #include <gp_Dir2d.hxx> | |
30 | #include <gp_Vec2d.hxx> | |
31 | #include <gp_Circ2d.hxx> | |
32 | #include <Standard_OutOfRange.hxx> | |
33 | #include <StdFail_NotDone.hxx> | |
34 | #include <GccEnt_BadQualifier.hxx> | |
35 | ||
36 | //========================================================================= | |
0d969553 | 37 | // Straight line passing through two points. + |
7fd59977 | 38 | // =============================== + |
39 | //========================================================================= | |
40 | ||
41 | GccAna_Lin2d2Tan:: | |
42 | GccAna_Lin2d2Tan (const gp_Pnt2d& ThePoint1, | |
43 | const gp_Pnt2d& ThePoint2 , | |
44 | const Standard_Real Tolerance ): | |
45 | linsol(1,1), | |
46 | qualifier1(1,1), | |
47 | qualifier2(1,1) , | |
48 | pnttg1sol(1,1), | |
49 | pnttg2sol(1,1), | |
50 | par1sol(1,1), | |
51 | par2sol(1,1), | |
52 | pararg1(1,1), | |
53 | pararg2(1,1) | |
54 | { | |
55 | ||
56 | Standard_Real Tol = Abs(Tolerance); | |
57 | WellDone = Standard_False; | |
58 | NbrSol = 0; | |
59 | Standard_Real dist = ThePoint1.Distance(ThePoint2); | |
60 | qualifier1(1) = GccEnt_noqualifier; | |
61 | qualifier2(1) = GccEnt_noqualifier; | |
62 | if (dist >= Tol) { | |
63 | gp_Dir2d dir(ThePoint2.X()-ThePoint1.X(),ThePoint2.Y()-ThePoint1.Y()); | |
64 | linsol(1) = gp_Lin2d(ThePoint1,dir); | |
65 | // =================================== | |
66 | WellDone = Standard_True; | |
67 | NbrSol = 1; | |
68 | pnttg1sol(1) = ThePoint1; | |
69 | pnttg2sol(1) = ThePoint2; | |
70 | par1sol(NbrSol)=ElCLib::Parameter(linsol(NbrSol),pnttg1sol(NbrSol)); | |
71 | par2sol(NbrSol)=ElCLib::Parameter(linsol(NbrSol),pnttg2sol(NbrSol)); | |
72 | pararg1(1) = 0.0; | |
73 | pararg2(1) = 0.0; | |
74 | } | |
75 | } | |
76 | ||
77 | //========================================================================= | |
0d969553 | 78 | // Straight line tangent to a circle passing by a point. + |
7fd59977 | 79 | // ================================================= + |
0d969553 Y |
80 | // Basing on the qualifier attached to circle Qualified1 (C1) define + |
81 | // the direction of the tangent to be calculated. + | |
82 | // This tangent will have connection point P1 (point of tangency with the circle. + | |
83 | // It has angle A (sinus R1/dist or -R1/dist) with straight line + | |
84 | // passing by the center of the circle and ThePoint. + | |
7fd59977 | 85 | //========================================================================= |
86 | ||
87 | GccAna_Lin2d2Tan:: | |
88 | GccAna_Lin2d2Tan (const GccEnt_QualifiedCirc& Qualified1, | |
89 | const gp_Pnt2d& ThePoint , | |
90 | const Standard_Real Tolerance ): | |
91 | linsol(1,2), | |
92 | qualifier1(1,2), | |
93 | qualifier2(1,2), | |
94 | pnttg1sol(1,2), | |
95 | pnttg2sol(1,2), | |
96 | par1sol(1,2), | |
97 | par2sol(1,2), | |
98 | pararg1(1,2), | |
99 | pararg2(1,2) | |
100 | { | |
101 | ||
102 | Standard_Real Tol = Abs(Tolerance); | |
103 | WellDone = Standard_False; | |
104 | NbrSol = 0; | |
105 | if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || | |
106 | Qualified1.IsOutside() || Qualified1.IsUnqualified())) { | |
107 | GccEnt_BadQualifier::Raise(); | |
108 | return; | |
109 | } | |
110 | gp_Circ2d C1 = Qualified1.Qualified(); | |
111 | Standard_Real R1 = C1.Radius(); | |
112 | ||
113 | if (Qualified1.IsEnclosed()) { GccEnt_BadQualifier::Raise(); } | |
114 | // ============================ | |
115 | else if (Tol < R1-ThePoint.Distance(C1.Location())) { | |
116 | WellDone = Standard_True; | |
117 | } | |
118 | else if (Abs(ThePoint.Distance(C1.Location())-R1) <= Tol) { | |
119 | gp_Dir2d dir(gp_Vec2d(C1.Location(),ThePoint)); | |
120 | linsol(1) = gp_Lin2d(ThePoint,gp_Dir2d(Standard_Real(-dir.Y()), | |
121 | Standard_Real(dir.X()))); | |
122 | // ===================================================================== | |
123 | qualifier1(1) = Qualified1.Qualifier(); | |
124 | qualifier2(1) = GccEnt_noqualifier; | |
125 | WellDone = Standard_True; | |
126 | NbrSol = 1; | |
127 | pnttg1sol(1) = ThePoint; | |
128 | pnttg2sol(1) = ThePoint; | |
129 | } | |
130 | else { | |
131 | Standard_Real signe = 1; | |
132 | Standard_Real dist = ThePoint.Distance(C1.Location()); | |
133 | Standard_Real d = dist - Sqrt(dist*dist - R1*R1); | |
134 | if (Qualified1.IsEnclosing()) { | |
135 | // ============================= | |
136 | signe = 1; | |
137 | NbrSol = 1; | |
138 | } | |
139 | else if (Qualified1.IsOutside()) { | |
140 | signe = -1; | |
141 | NbrSol = 1; | |
142 | } | |
143 | else if (Qualified1.IsUnqualified()) { | |
144 | // ==================================== | |
145 | signe = 1; | |
146 | NbrSol = 2; | |
147 | } | |
148 | for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { | |
149 | gp_Pnt2d P1(C1.Location().Rotated(ThePoint,ASin(signe*R1/dist))); | |
150 | gp_Dir2d D1(gp_Vec2d(P1,ThePoint)); | |
151 | P1=gp_Pnt2d(P1.XY() + d*D1.XY()); | |
152 | linsol(i) = gp_Lin2d(P1,gp_Dir2d(gp_Vec2d(P1,ThePoint))); | |
153 | // ======================================================== | |
154 | qualifier1(i) = Qualified1.Qualifier(); | |
155 | qualifier2(i) = GccEnt_noqualifier; | |
156 | pnttg1sol(i) = P1; | |
157 | pnttg2sol(i) = ThePoint; | |
158 | signe = -signe; | |
159 | } | |
160 | WellDone = Standard_True; | |
161 | } | |
162 | for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { | |
163 | par1sol(i)=ElCLib::Parameter(linsol(i),pnttg1sol(i)); | |
164 | par2sol(i)=ElCLib::Parameter(linsol(i),pnttg2sol(i)); | |
165 | pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i)); | |
166 | pararg2(i) = 0.; | |
167 | } | |
168 | } | |
169 | ||
170 | //========================================================================= | |
0d969553 Y |
171 | // Straight line tangent to two circles. + |
172 | // ==================================== + | |
173 | // In the boundary cas (two interior circles are tangent to each other) + | |
174 | // take the straight line orthogonal to the straight line connecting + | |
175 | // two circles. + | |
176 | // In other cases subject the center of C1 (Qualified1) or of + | |
177 | // C2 (Qualified2), provided that R1 is greater than R2, to a + | |
178 | // rotation of angle A with sinus(A) = (R1+R2)/dist or + | |
179 | // sinus(A) = (R1-R2)/dist or + | |
180 | // sinus(A) = (R2-R1)/dist or + | |
181 | // sinus(A) = (-R1-R2)/dist + | |
182 | // The point found this way is P1 or P2. + | |
183 | // The direction of the straight line to be calculated should pass by + | |
184 | // the center of rotation (center of C1 or of C2) and P1 or P2. + | |
185 | // Then translate the straight line to make it tangent to C1. + | |
7fd59977 | 186 | //========================================================================= |
187 | ||
188 | GccAna_Lin2d2Tan:: | |
189 | GccAna_Lin2d2Tan (const GccEnt_QualifiedCirc& Qualified1, | |
190 | const GccEnt_QualifiedCirc& Qualified2, | |
191 | const Standard_Real Tolerance ): | |
192 | linsol(1,4), | |
193 | qualifier1(1,4), | |
194 | qualifier2(1,4) , | |
195 | pnttg1sol(1,4), | |
196 | pnttg2sol(1,4), | |
197 | par1sol(1,4), | |
198 | par2sol(1,4), | |
199 | pararg1(1,4), | |
200 | pararg2(1,4) | |
201 | { | |
202 | ||
203 | Standard_Real Tol = Abs(Tolerance); | |
204 | WellDone = Standard_False; | |
205 | NbrSol = 0; | |
206 | if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || | |
207 | Qualified1.IsOutside() || Qualified1.IsUnqualified()) || | |
208 | !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || | |
209 | Qualified2.IsOutside() || Qualified2.IsUnqualified())) { | |
210 | GccEnt_BadQualifier::Raise(); | |
211 | return; | |
212 | } | |
213 | gp_Circ2d C1 = Qualified1.Qualified(); | |
214 | gp_Circ2d C2 = Qualified2.Qualified(); | |
215 | ||
216 | if (Qualified1.IsEnclosed() || Qualified2.IsEnclosed()) { | |
217 | // ======================================================= | |
218 | GccEnt_BadQualifier::Raise(); | |
219 | } | |
220 | else { | |
221 | Standard_Real R1 = C1.Radius(); | |
222 | Standard_Real R2 = C2.Radius(); | |
223 | gp_Dir2d D1; | |
224 | Standard_Integer signe = 1; | |
225 | Standard_Real dist = C1.Location().Distance(C2.Location()); | |
226 | if (Tol < Max(R1,R2)-dist-Min(R1,R2) ) { WellDone = Standard_True; } | |
227 | else if (!Qualified1.IsUnqualified() || !Qualified2.IsUnqualified()) { | |
228 | // ==================================================================== | |
229 | if (Qualified1.IsEnclosing() && Qualified2.IsEnclosing()) { | |
230 | // ========================================================= | |
231 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol && dist >= Tol) { | |
232 | if (R1<R2) { D1 = gp_Dir2d(gp_Vec2d(C2.Location(),C1.Location()));} | |
233 | else { D1 = gp_Dir2d(gp_Vec2d(C1.Location(),C2.Location())); } | |
234 | gp_Pnt2d P1(C1.Location().XY()+R1*D1.XY()); | |
235 | linsol(1) = gp_Lin2d(P1,gp_Dir2d(-D1.Y(),D1.X())); | |
236 | // ================================================= | |
237 | qualifier1(1) = Qualified1.Qualifier(); | |
238 | qualifier2(1) = Qualified2.Qualifier(); | |
239 | pnttg1sol(1) = P1; | |
240 | pnttg2sol(1) = P1; | |
241 | WellDone = Standard_True; | |
242 | NbrSol = 1; | |
243 | } | |
244 | else { | |
245 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
246 | ASin((R1-R2)/dist))); | |
247 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
248 | P1=gp_Pnt2d((C1.Location().XY()+gp_XY(R1*D1.Y(),-R1*D1.X()))); | |
249 | linsol(1) = gp_Lin2d(P1,D1); | |
250 | // =========================== | |
251 | qualifier1(1) = Qualified1.Qualifier(); | |
252 | qualifier2(1) = Qualified1.Qualifier(); | |
253 | pnttg1sol(1) = P1; | |
254 | pnttg2sol(1) = gp_Pnt2d(C2.Location().XY()+ | |
255 | gp_XY(R2*D1.Y(),-R2*D1.X())); | |
256 | WellDone = Standard_True; | |
257 | NbrSol = 1; | |
258 | } | |
259 | } | |
260 | else if ((Qualified1.IsEnclosing() && Qualified2.IsOutside()) || | |
261 | // ================================================================ | |
262 | (Qualified2.IsEnclosing() && Qualified1.IsOutside())) { | |
263 | // ===================================================== | |
264 | if (Qualified1.IsEnclosing() && Qualified2.IsOutside()) { | |
265 | signe = 1; | |
266 | } | |
267 | else { | |
268 | signe = -1; | |
269 | } | |
270 | if (R1+R2-dist > Tol) { WellDone = Standard_True; } | |
271 | else if (Abs(dist-R1-R2)<Tol && dist>Tol) { | |
272 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),C2.Location())); | |
273 | gp_Pnt2d P1(C1.Location().XY()+R1*D1.XY()); | |
274 | linsol(1) = gp_Lin2d(P1,gp_Dir2d(-D1.Y(),D1.X())); | |
275 | // ================================================= | |
276 | qualifier1(1) = Qualified1.Qualifier(); | |
277 | qualifier2(1) = Qualified1.Qualifier(); | |
278 | pnttg1sol(1) = P1; | |
279 | pnttg2sol(1) = P1; | |
280 | WellDone = Standard_True; | |
281 | NbrSol = 1; | |
282 | } | |
283 | else { | |
284 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
285 | ASin(signe*(R1+R2)/dist))); | |
286 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
287 | P1=gp_Pnt2d(C1.Location().XY()+signe*(gp_XY(R1*D1.Y(), | |
288 | -R1*D1.X()))); | |
289 | linsol(1) = gp_Lin2d(P1,D1); | |
290 | // =========================== | |
291 | qualifier1(1) = Qualified1.Qualifier(); | |
292 | qualifier2(1) = Qualified1.Qualifier(); | |
293 | pnttg1sol(1) = P1; | |
294 | pnttg2sol(1) = gp_Pnt2d(C2.Location().XY()+ | |
295 | signe*(gp_XY(-R2*D1.Y(),R2*D1.X()))); | |
296 | WellDone = Standard_True; | |
297 | NbrSol = 1; | |
298 | } | |
299 | } | |
300 | else if (Qualified1.IsOutside() && Qualified2.IsOutside()) { | |
301 | // ========================================================= | |
302 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) < Tol && dist > Tol) { | |
303 | if (R1<R2) { D1 = gp_Dir2d(gp_Vec2d(C2.Location(),C1.Location()));} | |
304 | else { D1 = gp_Dir2d(gp_Vec2d(C1.Location(),C2.Location())); } | |
305 | linsol(1) = gp_Lin2d(gp_Pnt2d(C1.Location().XY()+R1*D1.XY()), | |
306 | // ============================================================= | |
307 | gp_Dir2d(D1.Y(),-D1.X())); | |
308 | // ========================= | |
309 | qualifier1(1) = Qualified1.Qualifier(); | |
310 | qualifier2(1) = Qualified1.Qualifier(); | |
311 | pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*D1.XY()); | |
312 | pnttg2sol(1) = pnttg1sol(1); | |
313 | WellDone = Standard_True; | |
314 | NbrSol = 1; | |
315 | } | |
316 | else { | |
317 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
318 | ASin((R2-R1)/dist))); | |
319 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
320 | P1 = gp_Pnt2d(C1.Location().XY()+gp_XY(-R1*D1.Y(),R1*D1.X())); | |
321 | linsol(1) = gp_Lin2d(P1,D1); | |
322 | // =========================== | |
323 | qualifier1(1) = Qualified1.Qualifier(); | |
324 | qualifier2(1) = Qualified1.Qualifier(); | |
325 | pnttg1sol(1) = P1; | |
326 | pnttg2sol(1) = gp_Pnt2d(C2.Location().XY()+ | |
327 | (gp_XY(-R2*D1.Y(),R2*D1.X()))); | |
328 | WellDone = Standard_True; | |
329 | NbrSol = 1; | |
330 | } | |
331 | } | |
332 | else { | |
333 | if ((Qualified1.IsUnqualified() && Qualified2.IsEnclosing()) || | |
334 | // =============================================================== | |
335 | (Qualified2.IsUnqualified() && Qualified1.IsEnclosing())) { | |
336 | // ========================================================= | |
337 | if (Qualified2.IsUnqualified()) { signe = 1; } | |
338 | else { signe = -1; } | |
339 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) < Tol && dist > Tol) { | |
340 | if (R1<R2) { D1=gp_Dir2d(gp_Vec2d(C2.Location(),C1.Location()));} | |
341 | else { D1 = gp_Dir2d(gp_Vec2d(C1.Location(),C2.Location())); } | |
342 | linsol(1) = gp_Lin2d(gp_Pnt2d(C1.Location().XY()+R1*D1.XY()), | |
343 | // ============================================================= | |
344 | gp_Dir2d(-D1.Y(),D1.X())); | |
345 | // ========================= | |
346 | qualifier1(1) = Qualified1.Qualifier(); | |
347 | qualifier2(1) = Qualified1.Qualifier(); | |
348 | pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*D1.XY()); | |
349 | pnttg2sol(1) = pnttg1sol(1); | |
350 | WellDone = Standard_True; | |
351 | NbrSol = 1; | |
352 | } | |
353 | else { | |
354 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
355 | ASin((R1-R2)/dist))); | |
356 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
357 | P1 = gp_Pnt2d(C1.Location().XY()+gp_XY(R1*D1.Y(),-R1*D1.X())); | |
358 | linsol(1) = gp_Lin2d(P1,D1); | |
359 | // =========================== | |
360 | qualifier1(1) = Qualified1.Qualifier(); | |
361 | qualifier2(1) = Qualified1.Qualifier(); | |
362 | pnttg1sol(1) = P1; | |
363 | pnttg2sol(1) = gp_Pnt2d(C2.Location().XY()+ | |
364 | signe*(gp_XY(R2*D1.Y(),-R2*D1.X()))); | |
365 | WellDone = Standard_True; | |
366 | NbrSol = 1; | |
367 | if (Min(R1,R2)+Max(R1,R2)<dist) { | |
368 | gp_Pnt2d P2(C2.Location().Rotated(C1.Location(), | |
369 | ASin(signe*(R1+R2)/dist))); | |
370 | gp_Dir2d D2(gp_Vec2d(C1.Location(),P2)); | |
371 | P2=gp_Pnt2d(C1.Location().XY()+ | |
372 | signe*(gp_XY(R1*D2.Y(),-R1*D2.X()))); | |
373 | linsol(2) = gp_Lin2d(P2,D2); | |
374 | // =========================== | |
375 | qualifier1(1) = Qualified1.Qualifier(); | |
376 | qualifier2(1) = Qualified1.Qualifier(); | |
377 | pnttg1sol(2) = P1; | |
378 | pnttg2sol(2) = gp_Pnt2d(C2.Location().XY()+ | |
379 | (gp_XY(-R2*D2.Y(),R2*D2.X()))); | |
380 | NbrSol = 2; | |
381 | } | |
382 | } | |
383 | } | |
384 | else if ((Qualified1.IsUnqualified() && Qualified2.IsOutside()) || | |
385 | // ================================================================== | |
386 | (Qualified2.IsUnqualified() && Qualified1.IsOutside())) { | |
387 | // ======================================================= | |
388 | if (Qualified2.IsUnqualified()) { signe = 1; } | |
389 | else { signe = -1; } | |
390 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol && dist >= Tol) { | |
391 | if (R1<R2) { D1=gp_Dir2d(gp_Vec2d(C2.Location(),C1.Location()));} | |
392 | else { D1 = gp_Dir2d(gp_Vec2d(C1.Location(),C2.Location())); } | |
393 | linsol(1) = gp_Lin2d(gp_Pnt2d(C1.Location().XY()+R1*D1.XY()), | |
394 | // ============================================================= | |
395 | gp_Dir2d(D1.Y(),-D1.X())); | |
396 | // ========================= | |
397 | qualifier1(1) = Qualified1.Qualifier(); | |
398 | qualifier2(1) = Qualified1.Qualifier(); | |
399 | pnttg1sol(1) = gp_Pnt2d(C1.Location().XY()+R1*D1.XY()); | |
400 | pnttg2sol(1) = pnttg1sol(1); | |
401 | WellDone = Standard_True; | |
402 | NbrSol = 1; | |
403 | } | |
404 | else { | |
405 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
406 | ASin(signe*(R2-R1)/dist))); | |
407 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
408 | P1 = gp_Pnt2d(C1.Location().XY()+gp_XY(-R1*D1.Y(),R1*D1.X())); | |
409 | linsol(1) = gp_Lin2d(P1,D1); | |
410 | // =========================== | |
411 | qualifier1(1) = Qualified1.Qualifier(); | |
412 | qualifier2(1) = Qualified1.Qualifier(); | |
413 | pnttg1sol(1) = P1; | |
414 | pnttg2sol(1) = gp_Pnt2d(C2.Location().XY()+ | |
415 | signe*(gp_XY(-R2*D1.Y(),R2*D1.X()))); | |
416 | WellDone = Standard_True; | |
417 | NbrSol = 1; | |
418 | if (Min(R1,R2)+Max(R1,R2)<dist) { | |
419 | gp_Pnt2d P2(C2.Location().Rotated(C1.Location(), | |
420 | ASin(signe*(-R2-R1)/dist))); | |
421 | gp_Dir2d D2(gp_Vec2d(C1.Location(),P2)); | |
422 | P2=gp_Pnt2d(C1.Location().XY()+ | |
423 | signe*(gp_XY(-R1*D2.Y(),R1*D2.X()))); | |
424 | linsol(2) = gp_Lin2d(P2,D2); | |
425 | // =========================== | |
426 | qualifier1(1) = Qualified1.Qualifier(); | |
427 | qualifier2(1) = Qualified1.Qualifier(); | |
428 | pnttg1sol(2) = P2; | |
429 | pnttg2sol(2) = gp_Pnt2d(C2.Location().XY()+ | |
430 | signe*(gp_XY(R2*D2.Y(),-R2*D2.X()))); | |
431 | NbrSol = 2; | |
432 | } | |
433 | } | |
434 | } | |
435 | } | |
436 | } | |
437 | else { | |
438 | for (Standard_Integer i = 1 ; i <= 2 ; i++) { | |
439 | signe = -signe; | |
440 | NbrSol++; | |
441 | gp_Pnt2d P1(C2.Location().Rotated(C1.Location(), | |
442 | ASin(signe*(R2-R1)/dist))); | |
443 | D1 = gp_Dir2d(gp_Vec2d(C1.Location(),P1)); | |
444 | P1 = gp_Pnt2d(C1.Location().XY()+signe*gp_XY(-R1*D1.Y(),R1*D1.X())); | |
445 | linsol(NbrSol) = gp_Lin2d(P1,D1); | |
446 | // =========================== | |
447 | qualifier1(NbrSol) = Qualified1.Qualifier(); | |
448 | qualifier2(NbrSol) = Qualified1.Qualifier(); | |
449 | pnttg1sol(NbrSol) = P1; | |
450 | pnttg2sol(NbrSol) = gp_Pnt2d(C2.Location().XY()+ | |
451 | signe*(gp_XY(-R2*D1.Y(),R2*D1.X()))); | |
452 | WellDone = Standard_True; | |
453 | if (Min(R1,R2)+Max(R1,R2)<dist) { | |
454 | gp_Pnt2d P2(C2.Location().Rotated(C1.Location(), | |
455 | ASin(signe*(R2+R1)/dist))); | |
456 | gp_Dir2d D2(gp_Vec2d(C1.Location(),P2)); | |
457 | P2=gp_Pnt2d(C1.Location().XY()+ | |
458 | signe*(gp_XY(R1*D2.Y(),-R1*D2.X()))); | |
459 | NbrSol++; | |
460 | linsol(NbrSol) = gp_Lin2d(P2,D2); | |
461 | // ================================ | |
462 | qualifier1(NbrSol) = Qualified1.Qualifier(); | |
463 | qualifier2(NbrSol) = Qualified1.Qualifier(); | |
464 | pnttg1sol(NbrSol) = P2; | |
465 | pnttg2sol(NbrSol) = gp_Pnt2d(C2.Location().XY()+ | |
466 | signe*(gp_XY(-R2*D2.Y(),R2*D2.X()))); | |
467 | } | |
468 | } | |
469 | } | |
470 | } | |
471 | for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { | |
472 | par1sol(i)=ElCLib::Parameter(linsol(i),pnttg1sol(i)); | |
473 | par2sol(i)=ElCLib::Parameter(linsol(i),pnttg2sol(i)); | |
474 | pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i)); | |
475 | pararg2(i)=ElCLib::Parameter(C2,pnttg2sol(i)); | |
476 | } | |
477 | } | |
478 | ||
479 | Standard_Boolean GccAna_Lin2d2Tan:: | |
480 | IsDone () const { return WellDone; } | |
481 | ||
482 | Standard_Integer GccAna_Lin2d2Tan:: | |
483 | NbSolutions () const { return NbrSol; } | |
484 | ||
485 | gp_Lin2d GccAna_Lin2d2Tan:: | |
486 | ThisSolution (const Standard_Integer Index) const { | |
487 | ||
488 | if (Index > NbrSol || Index <= 0) { Standard_OutOfRange::Raise(); } | |
489 | return linsol(Index); | |
490 | } | |
491 | ||
492 | void GccAna_Lin2d2Tan:: | |
493 | WhichQualifier(const Standard_Integer Index , | |
494 | GccEnt_Position& Qualif1 , | |
495 | GccEnt_Position& Qualif2 ) const | |
496 | { | |
497 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
498 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
499 | else { | |
500 | Qualif1 = qualifier1(Index); | |
501 | Qualif2 = qualifier2(Index); | |
502 | } | |
503 | } | |
504 | ||
505 | void GccAna_Lin2d2Tan:: | |
506 | Tangency1 (const Standard_Integer Index, | |
507 | Standard_Real& ParSol, | |
508 | Standard_Real& ParArg, | |
509 | gp_Pnt2d& PntSol) const { | |
510 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
511 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
512 | else { | |
513 | ParSol = par1sol(Index); | |
514 | ParArg = pararg1(Index); | |
515 | PntSol = gp_Pnt2d(pnttg1sol(Index)); | |
516 | } | |
517 | } | |
518 | ||
519 | void GccAna_Lin2d2Tan:: | |
520 | Tangency2 (const Standard_Integer Index , | |
521 | Standard_Real& ParSol , | |
522 | Standard_Real& ParArg , | |
523 | gp_Pnt2d& PntSol ) const { | |
524 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
525 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
526 | else { | |
527 | ParSol = par2sol(Index); | |
528 | ParArg = pararg2(Index); | |
529 | PntSol = gp_Pnt2d(pnttg2sol(Index)); | |
530 | } | |
531 | } |