Commit | Line | Data |
---|---|---|
7fd59977 | 1 | // File GccAna_Circ2d2TanRad.cxx, REG 08/07/91 |
0d969553 Y |
2 | |
3 | ||
7fd59977 | 4 | |
5 | #include <GccAna_Circ2d2TanRad.ixx> | |
6 | ||
7 | #include <ElCLib.hxx> | |
8 | #include <gp_Ax2d.hxx> | |
9 | #include <gp_Circ2d.hxx> | |
10 | #include <gp_Lin2d.hxx> | |
11 | #include <IntAna2d_AnaIntersection.hxx> | |
12 | #include <IntAna2d_IntPoint.hxx> | |
13 | #include <Standard_NegativeValue.hxx> | |
14 | #include <Standard_OutOfRange.hxx> | |
15 | #include <StdFail_NotDone.hxx> | |
16 | #include <GccEnt_BadQualifier.hxx> | |
17 | #include <Precision.hxx> | |
18 | ||
0d969553 | 19 | // circular tangent to two cercles and given radius |
7fd59977 | 20 | //==================================================== |
0d969553 Y |
21 | //================================================================== |
22 | // Initialize WellDone to false. + | |
23 | // Return circle C1 and circle C2. + | |
24 | // Leave with error if the construction is impossible. + | |
25 | // Distinguish boundary cases to process them separately. + | |
26 | // Create parallel to C1 in the proper direction. + | |
27 | // Create parallel to C2 in the proper direction. + | |
28 | // Intersect parallels ==> center point of the solution. + | |
29 | // Create the solution to be added to already found solutions. + | |
30 | // Fill the fields. + | |
31 | //================================================================== | |
7fd59977 | 32 | |
33 | GccAna_Circ2d2TanRad:: | |
34 | GccAna_Circ2d2TanRad (const GccEnt_QualifiedCirc& Qualified1 , | |
35 | const GccEnt_QualifiedCirc& Qualified2 , | |
36 | const Standard_Real Radius , | |
37 | const Standard_Real Tolerance ): | |
38 | qualifier1(1,8) , | |
39 | qualifier2(1,8), | |
40 | TheSame1(1,8) , | |
41 | TheSame2(1,8) , | |
42 | cirsol(1,8) , | |
43 | pnttg1sol(1,8) , | |
44 | pnttg2sol(1,8) , | |
45 | par1sol(1,8) , | |
46 | par2sol(1,8) , | |
47 | pararg1(1,8) , | |
48 | pararg2(1,8) | |
49 | { | |
50 | ||
51 | Standard_Real Tol = Abs(Tolerance); | |
52 | gp_Dir2d dirx(1.,0.); | |
53 | WellDone = Standard_False; | |
54 | NbrSol = 0; | |
55 | if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || | |
56 | Qualified1.IsOutside() || Qualified1.IsUnqualified()) || | |
57 | !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || | |
58 | Qualified2.IsOutside() || Qualified2.IsUnqualified())) { | |
59 | GccEnt_BadQualifier::Raise(); | |
60 | return; | |
61 | } | |
62 | Standard_Boolean invers = Standard_False; | |
63 | gp_Circ2d C1 = Qualified1.Qualified(); | |
64 | gp_Circ2d C2 = Qualified2.Qualified(); | |
65 | Standard_Real R1 = C1.Radius(); | |
66 | Standard_Real R2 = C2.Radius(); | |
67 | Standard_Real rbid = 0.; | |
68 | Standard_Integer signe=0; | |
69 | Standard_Real R3; | |
70 | Standard_Real dist; | |
71 | TColgp_Array1OfCirc2d C(1,8); | |
72 | C(1) = gp_Circ2d(C1); | |
73 | C(2) = gp_Circ2d(C2); | |
74 | Standard_Integer nbsol = 0; | |
75 | gp_Pnt2d center1(C1.Location()); | |
76 | gp_Pnt2d center2(C2.Location()); | |
77 | gp_Pnt2d center3; | |
78 | if (Radius < 0.0) { Standard_NegativeValue::Raise(); } | |
79 | else if ( C(2).Location().IsEqual(C(1).Location(),Precision::Confusion())){ | |
80 | WellDone = Standard_True; | |
81 | } | |
82 | else { | |
83 | gp_Dir2d dir1(C(2).Location().XY()-C(1).Location().XY()); | |
84 | dist = (center2).Distance(center1); | |
85 | if ((Qualified1.IsEnclosed()) && Qualified2.IsEnclosed()) { | |
86 | // ========================================================= | |
87 | if (Radius*2.0-Abs(R1+R2-dist) > Tol) { WellDone = Standard_True; } | |
88 | else { | |
89 | if ((dist-R1-R2>Tol)||(Tol<Max(R1,R2)-dist-Min(R1,R2))) { | |
90 | WellDone = Standard_True; | |
91 | } | |
92 | else if (Abs(dist-R1-R2)<=Tol||Abs(Max(R1,R2)-dist-Min(R1,R2))<=Tol) { | |
93 | if (Abs(dist-R1-R2) <= Tol) { | |
94 | rbid = R2+(dist-R1-R2)/2.0; | |
95 | signe = -1; | |
96 | } | |
97 | else if (Abs(Max(R1,R2)-dist-Min(R1,R2)) <= Tol) { | |
98 | if (R1 > R2) { R3 = R2; } | |
99 | else { | |
100 | C2 = gp_Circ2d(C1); | |
101 | R3 = R1; | |
102 | } | |
103 | rbid = -R3+(Min(R1,R2)+dist-Max(R1,R2))/2.; | |
104 | signe = 1; | |
105 | } | |
106 | gp_Ax2d axe(gp_Pnt2d(center2.XY()-rbid*dir1.XY()),dirx); | |
107 | cirsol(1) = gp_Circ2d(axe,Radius); | |
108 | // ================================= | |
109 | qualifier1(1) = Qualified1.Qualifier(); | |
110 | qualifier2(1) = Qualified2.Qualifier(); | |
111 | pnttg1sol(1)=gp_Pnt2d(center2.XY()+signe*R2*dir1.XY()); | |
112 | pnttg2sol(1)=gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
113 | TheSame1(1) = 0; | |
114 | TheSame2(1) = 0; | |
115 | WellDone = Standard_True; | |
116 | NbrSol = 1; | |
117 | } | |
118 | else { | |
119 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
120 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2)); | |
121 | nbsol = 1; | |
122 | } | |
123 | } | |
124 | } | |
125 | else if (((Qualified1.IsEnclosed()) && Qualified2.IsEnclosing()) || | |
126 | // =================================================================== | |
127 | ((Qualified1.IsEnclosing()) && Qualified2.IsEnclosed())) { | |
128 | // ======================================================== | |
129 | if (Qualified1.IsEnclosing()) { | |
130 | R3 = R1; | |
131 | C(1) = gp_Circ2d(C2); | |
132 | R1 = R2; | |
133 | C(2) = gp_Circ2d(C1); | |
134 | R2 = R3; | |
135 | center3 = center1; | |
136 | center1 = center2; | |
137 | center2 = center3; | |
138 | dir1.Reverse(); | |
0d969553 | 139 | // it is necessary to swap the resulting tangency points |
7fd59977 | 140 | invers = Standard_True; |
141 | } | |
142 | if ((R2-Radius>Tol) || (Tol<Radius-R1) || (Tol>R1-dist-R2) || | |
143 | ((Tol<Radius*2-R1-dist-R2)||(Tol<R1+R2-dist-Radius*2.0))) { | |
144 | WellDone = Standard_True; | |
145 | } | |
146 | else if ((Abs(R2-Radius)<=Tol) || (Abs(R1-Radius)<=Tol)) { | |
147 | if (Abs(R2-Radius) <= Tol) { | |
148 | C(2) = gp_Circ2d(C2); | |
149 | R3 = R2; | |
150 | TheSame2(1) = 1; | |
151 | TheSame1(1) = 0; | |
152 | pnttg1sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY()); | |
153 | } | |
154 | else if (Abs(Radius-R1) <= Tol) { | |
155 | C(2) = gp_Circ2d(C1); | |
156 | R3 = R1; | |
157 | TheSame1(1) = 1; | |
158 | TheSame2(1) = 0; | |
159 | pnttg2sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY()); | |
160 | } | |
161 | WellDone = Standard_True; | |
162 | NbrSol = 1; | |
163 | gp_Ax2d axe(C(2).Location(),dirx); | |
164 | cirsol(1) = gp_Circ2d(axe,Radius); | |
165 | // ================================= | |
166 | qualifier1(1) = Qualified1.Qualifier(); | |
167 | qualifier2(1) = Qualified2.Qualifier(); | |
168 | } | |
169 | else { | |
170 | if ((Abs(R2+dist-R1) <= Tol) || (Abs(Radius*2.0-R1-dist-R2) < Tol)) { | |
171 | if (Abs(R2+dist-R1) <= Tol) { signe = 1; } | |
172 | else if (Abs(Radius*2.0-R1-dist-R2) < Tol) {signe = -1; } | |
173 | WellDone = Standard_True; | |
174 | NbrSol = 1; | |
175 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+ | |
176 | signe*(R1-Radius)*dir1.XY()),dirx); | |
177 | cirsol(1) = gp_Circ2d(axe,Radius); | |
178 | // ================================= | |
179 | qualifier1(1) = Qualified1.Qualifier(); | |
180 | qualifier2(1) = Qualified2.Qualifier(); | |
181 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY()); | |
182 | pnttg2sol(1)=gp_Pnt2d(center2.XY()+R2*dir1.XY()); | |
183 | TheSame1(1) = 0; | |
184 | TheSame2(1) = 0; | |
185 | } | |
186 | else { | |
187 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
188 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2)); | |
189 | nbsol = 1; | |
190 | } | |
191 | } | |
192 | } | |
193 | else if (((Qualified1.IsEnclosed()) && (Qualified2.IsOutside())) || | |
194 | // =================================================================== | |
195 | ((Qualified1.IsOutside()) && (Qualified2.IsEnclosed()))) { | |
196 | // ======================================================== | |
197 | if (Qualified1.IsOutside()) { | |
198 | C(2) = gp_Circ2d(C1); | |
199 | C(1) = gp_Circ2d(C2); | |
200 | R3 = R1; | |
201 | R1 = R2; | |
202 | R2 = R3; | |
203 | center3 = center1; | |
204 | center1 = center2; | |
205 | center2 = center3; | |
206 | dir1.Reverse(); | |
0d969553 | 207 | // it is necessary to swap the resulting tangency points |
7fd59977 | 208 | invers = Standard_True; |
209 | } | |
210 | if ((Radius-R1>Tol)||(dist-R2-R1>Tol)|| | |
211 | ((R2-dist-R1+Radius*2>Tol)||(R1-R2-dist-Radius*2>Tol))){ | |
212 | WellDone = Standard_True; | |
213 | } | |
214 | else { | |
215 | if (((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) || | |
216 | (Abs(R1-R2+dist-Radius*2.0) <= Tol) || | |
217 | (Abs(R1-R2-dist-Radius*2.0) <= Tol) || (Abs(dist-R1-R2) <= Tol)) { | |
218 | if (Abs(R1-R2+dist-Radius*2.0) <= Tol) { | |
219 | signe = -1; | |
220 | } | |
221 | else { | |
222 | signe = 1; | |
223 | if ((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) { | |
224 | R2 = R1; | |
225 | } | |
226 | else if (Abs(dist-R1-R2) <= Tol) { | |
227 | R2 = R1; | |
228 | if (Abs(R1-Radius) <= Tol) { | |
229 | TheSame1(1) = 1; | |
230 | } | |
231 | } | |
232 | } | |
233 | WellDone = Standard_True; | |
234 | NbrSol = 1; | |
235 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+ | |
236 | signe*(R1-Radius)*dir1.XY()),dirx); | |
237 | cirsol(1) = gp_Circ2d(axe,Radius); | |
238 | // ================================= | |
239 | qualifier1(1) = Qualified1.Qualifier(); | |
240 | qualifier2(1) = Qualified2.Qualifier(); | |
241 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY()); | |
242 | pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY()); | |
243 | TheSame1(1) = 0; | |
244 | TheSame2(1) = 0; | |
245 | } | |
246 | else { | |
247 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
248 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
249 | nbsol = 1; | |
250 | } | |
251 | } | |
252 | } | |
253 | else if (((Qualified1.IsEnclosed()) && (Qualified2.IsUnqualified())) || | |
254 | // ======================================================================= | |
255 | ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosed()))) { | |
256 | // ============================================================ | |
257 | if (Qualified1.IsUnqualified()) { | |
258 | C(1) = gp_Circ2d(C2); | |
259 | C(2) = gp_Circ2d(C1); | |
260 | R3 = R1; | |
261 | R1 = R2; | |
262 | R2 = R3; | |
263 | center3 = center1; | |
264 | center1 = center2; | |
265 | center2 = center3; | |
266 | dir1.Reverse(); | |
0d969553 | 267 | // it is necessary to swap the resulting tangency points |
7fd59977 | 268 | invers = Standard_True; |
269 | } | |
270 | if ((Radius-R1 > Tol) || (dist-R2-R1 > Tol)) { WellDone = Standard_True; } | |
271 | else { | |
272 | if ((Abs(dist-R2-R1) <= Tol) || (Abs(Radius-R1) <= Tol)) { | |
273 | WellDone = Standard_True; | |
274 | NbrSol = 1; | |
275 | gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx); | |
276 | cirsol(1) = gp_Circ2d(ax,Radius); | |
277 | // ================================ | |
278 | qualifier1(1) = Qualified1.Qualifier(); | |
279 | qualifier2(1) = Qualified2.Qualifier(); | |
280 | pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY()); | |
281 | TheSame2(1) = 0; | |
282 | if (Abs(Radius-R1) > 0.0) { | |
283 | TheSame1(1) = 1; | |
284 | } | |
285 | else { | |
286 | TheSame1(1) = 0; | |
287 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
288 | } | |
289 | } | |
290 | else { | |
291 | C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
292 | C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
293 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
294 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2)); | |
295 | nbsol = 2; | |
296 | } | |
297 | } | |
298 | } | |
299 | else if ((Qualified1.IsEnclosing()) && (Qualified2.IsEnclosing())) { | |
300 | // ================================================================== | |
301 | if ((Tol < Max(R1,R2)-Radius) || (Tol < Max(R1,R2)-dist-Min(R1,R2)) || | |
302 | (dist+R1+R2-Radius*2.0 > Tol)) { WellDone = Standard_True; } | |
303 | else { | |
304 | if ((Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) || | |
305 | (Abs(R1+R2+dist-2.0*Radius) <= Tol)) { | |
306 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) { | |
307 | signe = 1; | |
308 | } | |
309 | else { | |
310 | signe = -1; | |
311 | } | |
312 | WellDone = Standard_True; | |
313 | NbrSol = 1; | |
314 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+ | |
315 | signe*(R1-Radius)*dir1.XY()),dirx); | |
316 | cirsol(1) = gp_Circ2d(axe,Radius); | |
317 | // ================================= | |
318 | qualifier1(1) = Qualified1.Qualifier(); | |
319 | qualifier2(1) = Qualified2.Qualifier(); | |
320 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
321 | pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY()); | |
322 | TheSame1(1) = 0; | |
323 | TheSame2(1) = 0; | |
324 | } | |
325 | else if (Abs(Radius-Max(R1,R2)) <= Tol) { | |
326 | WellDone = Standard_True; | |
327 | NbrSol = 1; | |
328 | if (R1 > R2) { | |
329 | C(1) = gp_Circ2d(C1); | |
330 | C(2) = gp_Circ2d(C2); | |
331 | TheSame1(1) = 1; | |
332 | TheSame2(1) = 0; | |
333 | pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY()); | |
334 | } | |
335 | else { | |
336 | C(1) = gp_Circ2d(C2); | |
337 | C(2) = gp_Circ2d(C1); | |
338 | TheSame1(1) = 0; | |
339 | TheSame2(1) = 1; | |
340 | pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY()); | |
341 | } | |
342 | gp_Ax2d axe(C(1).Location(),dirx); | |
343 | cirsol(1) = gp_Circ2d(axe,Radius); | |
344 | // ================================= | |
345 | qualifier1(1) = Qualified1.Qualifier(); | |
346 | qualifier2(1) = Qualified2.Qualifier(); | |
347 | } | |
348 | else { | |
349 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
350 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2)); | |
351 | nbsol = 1; | |
352 | } | |
353 | } | |
354 | } | |
355 | else if (((Qualified1.IsEnclosing()) && (Qualified2.IsOutside())) || | |
356 | // ==================================================================== | |
357 | ((Qualified1.IsOutside()) && (Qualified2.IsEnclosing()))) { | |
358 | // ========================================================= | |
359 | if (Qualified1.IsOutside()) { | |
360 | C(1) = gp_Circ2d(C2); | |
361 | C(2) = gp_Circ2d(C1); | |
362 | R3 = R1; | |
363 | R1 = R2; | |
364 | R2 = R3; | |
365 | center3 = center1; | |
366 | center1 = center2; | |
367 | center2 = center3; | |
368 | dir1.Reverse(); | |
0d969553 | 369 | // it is necessary to swap the resulting tangency points |
7fd59977 | 370 | invers = Standard_True; |
371 | } | |
372 | if ((R1-Radius > Tol) || (Tol < R1+R2-dist) || | |
373 | (dist-R2+R1-Radius*2.0>Tol)) { | |
374 | WellDone = Standard_True; | |
375 | } | |
376 | else if (((Abs(R1-Radius)<=Tol) || (Abs(R1+R2-dist)<=Tol))|| | |
377 | (Abs(dist-R2+R1-Radius*2.0) <= Tol)) { | |
378 | WellDone = Standard_True; | |
379 | NbrSol = 1; | |
380 | if((Abs(R1-Radius) <= Tol) || (Abs(R1+R2-dist) <= Tol)){ | |
381 | TheSame1(1) = 1; | |
382 | } | |
383 | else { | |
384 | TheSame1(1) = 0; | |
385 | } | |
386 | TheSame2(1) = 0; | |
387 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx); | |
388 | cirsol(1) = gp_Circ2d(axe,Radius); | |
389 | // ================================= | |
390 | qualifier1(1) = Qualified1.Qualifier(); | |
391 | qualifier2(1) = Qualified2.Qualifier(); | |
392 | pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY()); | |
393 | pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY()); | |
394 | } | |
395 | else { | |
396 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
397 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
398 | nbsol = 1; | |
399 | } | |
400 | } | |
401 | else if (((Qualified1.IsEnclosing()) && (Qualified2.IsUnqualified())) || | |
402 | // ======================================================================== | |
403 | ((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosing()))) { | |
404 | // ============================================================= | |
405 | if (Qualified1.IsUnqualified()) { | |
406 | C(1) = gp_Circ2d(C2); | |
407 | C(2) = gp_Circ2d(C1); | |
408 | R3 = R1; | |
409 | R1 = R2; | |
410 | R2 = R3; | |
411 | center3 = center1; | |
412 | center1 = center2; | |
413 | center2 = center3; | |
414 | invers = Standard_True; | |
415 | dir1.Reverse(); | |
416 | } | |
417 | if ((Tol < R1-dist-R2) || (R1-Radius > Tol)) { WellDone = Standard_True; } | |
418 | else if ((Abs(R1-Radius) <= Tol) || (Abs(R1-dist-R2) > 0.0)) { | |
419 | if (Abs(R1-Radius) <= Tol) { | |
420 | TheSame1(1) = 1; | |
421 | if((Abs(Radius-R2) <= Tol) && | |
422 | (center1.Distance(center2) <= Tol)) { | |
423 | TheSame2(1) = 1; | |
424 | } | |
425 | } | |
426 | else if (Abs(R1-dist-R2) > 0.0) { | |
427 | TheSame1(1) = 0; | |
428 | TheSame2(1) = 0; | |
429 | } | |
430 | WellDone = Standard_True; | |
431 | NbrSol = 1; | |
432 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius-R1)*dir1.XY()),dirx); | |
433 | cirsol(1) = gp_Circ2d(axe,Radius); | |
434 | // ================================= | |
435 | qualifier1(1) = Qualified1.Qualifier(); | |
436 | qualifier2(1) = Qualified2.Qualifier(); | |
437 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
438 | pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY()); | |
439 | } | |
440 | else { | |
441 | C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
442 | C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
443 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1)); | |
444 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2)); | |
445 | nbsol = 2; | |
446 | } | |
447 | } | |
448 | else if ((Qualified1.IsOutside()) && (Qualified2.IsOutside())) { | |
449 | // ============================================================== | |
450 | if (Tol < Max(R1,R2)-dist-Min(R1,R2)) { WellDone = Standard_True; } | |
451 | else if (dist-R1-R2-Radius*2.0 > Tol) { WellDone = Standard_True; } | |
452 | else { | |
453 | if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) { | |
454 | WellDone = Standard_True; | |
455 | NbrSol = 1; | |
456 | if (R1 < R2) { signe = -1; } | |
457 | else { signe = -1; } | |
458 | gp_Ax2d axe(gp_Pnt2d(center1.XY()-(Radius+R1)*dir1.XY()), | |
459 | dirx); | |
460 | cirsol(1) = gp_Circ2d(axe,Radius); | |
461 | // ================================= | |
462 | qualifier1(1) = Qualified1.Qualifier(); | |
463 | qualifier2(1) = Qualified2.Qualifier(); | |
464 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY()); | |
465 | pnttg2sol(1) = gp_Pnt2d(pnttg1sol(1)); | |
466 | TheSame1(1) = 0; | |
467 | TheSame2(1) = 0; | |
468 | } | |
469 | else if (Abs(dist-R1-R2-Radius*2.0) <= Tol) { | |
470 | WellDone = Standard_True; | |
471 | NbrSol = 1; | |
472 | gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1+Radius)*dir1.XY()),dirx); | |
473 | cirsol(1) = gp_Circ2d(ax,Radius); | |
474 | // ================================ | |
475 | qualifier1(1) = Qualified1.Qualifier(); | |
476 | qualifier2(1) = Qualified2.Qualifier(); | |
477 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
478 | pnttg2sol(1) = gp_Pnt2d(center2.XY()-R2*dir1.XY()); | |
479 | TheSame1(1) = 0; | |
480 | TheSame2(1) = 0; | |
481 | } | |
482 | else { | |
483 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1); | |
484 | C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
485 | nbsol = 1; | |
486 | } | |
487 | } | |
488 | } | |
489 | else if (((Qualified1.IsOutside()) && (Qualified2.IsUnqualified())) || | |
490 | // ====================================================================== | |
491 | ((Qualified1.IsUnqualified()) && (Qualified2.IsOutside()))) { | |
492 | // =========================================================== | |
493 | if (Qualified1.IsUnqualified()) { | |
494 | C(1) = gp_Circ2d(C2); | |
495 | R3 = R1; | |
496 | R1 = R2; | |
497 | C(2) = gp_Circ2d(C1); | |
498 | R2 = R3; | |
499 | center3 = center1; | |
500 | center1 = center2; | |
501 | center2 = center3; | |
502 | dir1.Reverse(); | |
0d969553 | 503 | // it is necessary to swap the resulting tangency points |
7fd59977 | 504 | invers = Standard_True; |
505 | } | |
506 | if (Tol < R1-dist-R2) { WellDone = Standard_True; } | |
507 | else if ((Tol < R2-dist-R1) && (Tol < Radius*2.0-R2-dist+R1)) { | |
508 | WellDone = Standard_True; | |
509 | } | |
510 | else if ((dist-R1-R2 > Tol) && (Tol < dist-R1-R2-Radius*2.0)) { | |
511 | WellDone = Standard_True; | |
512 | } | |
513 | else { | |
514 | if ((Abs(R1-R2-dist)<=Tol) || | |
515 | ((Abs(dist-R1-R2)<=Tol) && (Abs(Radius*2.0-dist+R1+R2) <= Tol)) || | |
516 | ((Abs(dist+R1-R2)<=Tol) && (Abs(R2+dist-R1-Radius*2.0)<=Tol))) { | |
517 | WellDone = Standard_True; | |
518 | NbrSol = 1; | |
519 | gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius+R1)*dir1.XY()), | |
520 | dirx); | |
521 | cirsol(1) = gp_Circ2d(axe,Radius); | |
522 | // ================================= | |
523 | qualifier1(1) = Qualified1.Qualifier(); | |
524 | qualifier2(1) = Qualified2.Qualifier(); | |
525 | pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY()); | |
526 | pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY()); | |
527 | TheSame1(1) = 0; | |
528 | TheSame2(1) = 0; | |
529 | } | |
530 | else { | |
531 | C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1); | |
532 | C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2); | |
533 | C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1); | |
534 | C(2) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R2)); | |
535 | nbsol = 2; | |
536 | } | |
537 | } | |
538 | } | |
539 | else if ((Qualified1.IsUnqualified()) && (Qualified2.IsUnqualified())) { | |
540 | // ====================================================================== | |
541 | if ((dist-R1-R2>Tol)&&(Tol<(dist-R1-R2-Radius*2))) { | |
542 | WellDone = Standard_True; | |
543 | } | |
544 | else if ((Max(R1,R2)-dist-Min(R1,R2)>Tol) && | |
545 | (((Max(R1,R2)-dist-Min(R1,R2))-Radius*2.0 > Tol))) { | |
546 | WellDone = Standard_True; | |
547 | } | |
548 | else { | |
549 | Standard_Real p3 = Max(R1,R2)-Min(R1,R2)-dist-Radius*2.0; | |
550 | Standard_Real p4 = dist-R1-R2; | |
551 | Standard_Real p5 = Radius*2.0-dist+R1+R2; | |
552 | if (p3 > 0.0) { | |
553 | dist = Max(R1,R2)-Min(R1,R2)-Radius*2.0; | |
554 | } | |
555 | else if (p4 > 0.0 && p5 < 0.0) { | |
556 | R1 = dist-R2-Radius*2.0; | |
557 | } | |
558 | C(1) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1)); | |
559 | C(2) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2)); | |
560 | C(3) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1)); | |
561 | C(4) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2); | |
562 | C(5) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1); | |
563 | C(6) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2)); | |
564 | C(7) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1); | |
565 | C(8) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2); | |
566 | nbsol = 4; | |
567 | } | |
568 | } | |
569 | if (nbsol > 0) { | |
570 | for (Standard_Integer j = 1 ; j <= nbsol ; j++) { | |
571 | IntAna2d_AnaIntersection Intp(C(2*j-1),C(2*j)); | |
572 | if (Intp.IsDone()) { | |
573 | if (!Intp.IsEmpty()) { | |
574 | for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) { | |
575 | NbrSol++; | |
576 | gp_Pnt2d Center(Intp.Point(i).Value()); | |
577 | cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius); | |
578 | // ======================================================= | |
579 | dir1 = gp_Dir2d(Center.XY()-center1.XY()); | |
580 | gp_Dir2d dir2(Center.XY()-center2.XY()); | |
581 | Standard_Real distcc1 = Center.Distance(center1); | |
582 | Standard_Real distcc2 = Center.Distance(center2); | |
583 | if (!Qualified1.IsUnqualified()) { | |
584 | qualifier1(NbrSol) = Qualified1.Qualifier(); | |
585 | } | |
586 | else if (Abs(distcc1+Radius-R1) < Tol) { | |
587 | qualifier1(NbrSol) = GccEnt_enclosed; | |
588 | } | |
589 | else if (Abs(distcc1-R1-Radius) < Tol) { | |
590 | qualifier1(NbrSol) = GccEnt_outside; | |
591 | } | |
592 | else { qualifier1(NbrSol) = GccEnt_enclosing; } | |
593 | if (!Qualified2.IsUnqualified()) { | |
594 | qualifier2(NbrSol) = Qualified2.Qualifier(); | |
595 | } | |
596 | else if (Abs(distcc2+Radius-R2) < Tol) { | |
597 | qualifier2(NbrSol) = GccEnt_enclosed; | |
598 | } | |
599 | else if (Abs(distcc2-R2-Radius) < Tol) { | |
600 | qualifier2(NbrSol) = GccEnt_outside; | |
601 | } | |
602 | else { qualifier2(NbrSol) = GccEnt_enclosing; } | |
603 | if ((Center.Distance(center1) > R1) && | |
604 | (Radius < Center.Distance(center1)+R1)) { | |
605 | pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY()); | |
606 | } | |
607 | else if ((Center.Distance(center1) < R1) && | |
608 | (Radius < R1)) { | |
609 | pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1.XY()); | |
610 | } | |
611 | else { | |
612 | pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY()); | |
613 | } | |
614 | if ((Center.Distance(center2) > R2) && | |
615 | (Radius < Center.Distance(center2)+R2)) { | |
616 | pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY()); | |
617 | } | |
618 | else if ((Center.Distance(center2) < R2) && | |
619 | (Radius < R2)) { | |
620 | pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir2.XY()); | |
621 | } | |
622 | else { | |
623 | pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY()); | |
624 | } | |
625 | TheSame1(NbrSol) = 0; | |
626 | TheSame2(NbrSol) = 0; | |
627 | } | |
628 | } | |
629 | WellDone = Standard_True; | |
630 | } | |
631 | } | |
632 | } | |
633 | } | |
0d969553 | 634 | // swapping of resulting tangency points if necessary |
7fd59977 | 635 | if (invers) { |
636 | gp_Pnt2d Psav; | |
637 | for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { | |
638 | Psav = pnttg1sol(i); | |
639 | pnttg1sol(i) = pnttg2sol(i); | |
640 | pnttg2sol(i) = Psav; | |
641 | } | |
642 | } | |
0d969553 | 643 | // calculation of parameters of tangency points |
7fd59977 | 644 | for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { |
645 | par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i)); | |
646 | if (TheSame1(i) == 0) { | |
647 | pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i)); | |
648 | } | |
649 | par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i)); | |
650 | if (TheSame2(i) == 0) { | |
651 | pararg2(i)=ElCLib::Parameter(C2,pnttg2sol(i)); | |
652 | } | |
653 | } | |
654 | } | |
655 | ||
656 | Standard_Boolean GccAna_Circ2d2TanRad:: | |
657 | IsDone () const { return WellDone; } | |
658 | ||
659 | Standard_Integer GccAna_Circ2d2TanRad:: | |
660 | NbSolutions () const { return NbrSol; } | |
661 | ||
662 | gp_Circ2d GccAna_Circ2d2TanRad:: | |
663 | ThisSolution (const Standard_Integer Index) const | |
664 | { | |
665 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
666 | if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
667 | return cirsol(Index); | |
668 | } | |
669 | ||
670 | void GccAna_Circ2d2TanRad:: | |
671 | WhichQualifier(const Standard_Integer Index , | |
672 | GccEnt_Position& Qualif1 , | |
673 | GccEnt_Position& Qualif2 ) const | |
674 | { | |
675 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
676 | if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
677 | ||
678 | Qualif1 = qualifier1(Index); | |
679 | Qualif2 = qualifier2(Index); | |
680 | } | |
681 | ||
682 | void GccAna_Circ2d2TanRad:: | |
683 | Tangency1 (const Standard_Integer Index, | |
684 | Standard_Real& ParSol, | |
685 | Standard_Real& ParArg, | |
686 | gp_Pnt2d& PntSol) const{ | |
687 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
688 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
689 | else { | |
690 | if (TheSame1(Index) == 0) { | |
691 | ParSol = par1sol(Index); | |
692 | ParArg = pararg1(Index); | |
693 | PntSol = gp_Pnt2d(pnttg1sol(Index)); | |
694 | } | |
695 | else { StdFail_NotDone::Raise(); } | |
696 | } | |
697 | } | |
698 | ||
699 | void GccAna_Circ2d2TanRad:: | |
700 | Tangency2 (const Standard_Integer Index, | |
701 | Standard_Real& ParSol, | |
702 | Standard_Real& ParArg, | |
703 | gp_Pnt2d& PntSol) const{ | |
704 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
705 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
706 | else { | |
707 | if (TheSame2(Index) == 0) { | |
708 | ParSol = par2sol(Index); | |
709 | ParArg = pararg2(Index); | |
710 | PntSol = gp_Pnt2d(pnttg2sol(Index)); | |
711 | } | |
712 | else { StdFail_NotDone::Raise(); } | |
713 | } | |
714 | } | |
715 | ||
716 | Standard_Boolean GccAna_Circ2d2TanRad:: | |
717 | IsTheSame1 (const Standard_Integer Index) const | |
718 | { | |
719 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
720 | if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
721 | ||
722 | if (TheSame1(Index) == 0) { return Standard_False; } | |
723 | ||
724 | return Standard_True; | |
725 | } | |
726 | ||
727 | Standard_Boolean GccAna_Circ2d2TanRad:: | |
728 | IsTheSame2 (const Standard_Integer Index) const | |
729 | { | |
730 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
731 | if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
732 | ||
733 | if (TheSame2(Index) == 0) { return Standard_False; } | |
734 | return Standard_True; | |
735 | } |