Commit | Line | Data |
---|---|---|
b311480e | 1 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 | 2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 3 | // |
973c2be1 | 4 | // This file is part of Open CASCADE Technology software library. |
b311480e | 5 | // |
d5f74e42 | 6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
10 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 11 | // |
973c2be1 | 12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. | |
7fd59977 | 14 | |
7fd59977 | 15 | |
7fd59977 | 16 | #include <ElCLib.hxx> |
42cf5bc1 | 17 | #include <GccAna_Circ2d2TanOn.hxx> |
18 | #include <GccAna_Circ2dBisec.hxx> | |
19 | #include <GccEnt_BadQualifier.hxx> | |
20 | #include <GccEnt_QualifiedCirc.hxx> | |
21 | #include <GccEnt_QualifiedLin.hxx> | |
7fd59977 | 22 | #include <GccInt_BCirc.hxx> |
23 | #include <GccInt_BLine.hxx> | |
42cf5bc1 | 24 | #include <GccInt_IType.hxx> |
25 | #include <gp_Ax2d.hxx> | |
26 | #include <gp_Circ2d.hxx> | |
27 | #include <gp_Dir2d.hxx> | |
28 | #include <gp_Lin2d.hxx> | |
29 | #include <gp_Pnt2d.hxx> | |
30 | #include <IntAna2d_AnaIntersection.hxx> | |
7fd59977 | 31 | #include <IntAna2d_Conic.hxx> |
42cf5bc1 | 32 | #include <IntAna2d_IntPoint.hxx> |
33 | #include <Standard_OutOfRange.hxx> | |
7fd59977 | 34 | #include <StdFail_NotDone.hxx> |
42cf5bc1 | 35 | #include <TColStd_Array1OfReal.hxx> |
36 | #include <TColStd_SequenceOfReal.hxx> | |
7fd59977 | 37 | |
38 | //========================================================================= | |
0d969553 Y |
39 | // Circles tangent to two circles C1 and C2 and centered on a straight line. + |
40 | // We start by distinguishing various boundary cases that will be processed separately. + | |
41 | // In the general case: + | |
7fd59977 | 42 | // ==================== + |
0d969553 Y |
43 | // We calculate bissectrices to two circles that give us + |
44 | // all possible locations of centers of all circles tangent to C1 and C2. + | |
45 | // We intersect these bissectrices with straight line which gives us + | |
46 | // points among which we are going to find solutions. + | |
47 | // The choices are made basing on Qualifiers of C1 and C2. + | |
7fd59977 | 48 | //========================================================================= |
7fd59977 | 49 | GccAna_Circ2d2TanOn:: |
50 | GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1 , | |
51 | const GccEnt_QualifiedCirc& Qualified2 , | |
52 | const gp_Lin2d& OnLine , | |
53 | const Standard_Real Tolerance ): | |
54 | cirsol(1,4) , | |
55 | qualifier1(1,4), | |
56 | qualifier2(1,4) , | |
57 | TheSame1(1,4) , | |
58 | TheSame2(1,4) , | |
59 | pnttg1sol(1,4), | |
60 | pnttg2sol(1,4), | |
61 | pntcen(1,4) , | |
62 | par1sol(1,4) , | |
63 | par2sol(1,4) , | |
64 | pararg1(1,4) , | |
65 | pararg2(1,4) , | |
66 | parcen3(1,4) | |
67 | { | |
68 | ||
69 | TheSame1.Init(0); | |
70 | TheSame2.Init(0); | |
71 | WellDone = Standard_False; | |
72 | NbrSol = 0; | |
73 | Standard_Integer nbsol = 0; | |
74 | Standard_Real Tol = Abs(Tolerance); | |
75 | if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || | |
76 | Qualified1.IsOutside() || Qualified1.IsUnqualified()) || | |
77 | !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || | |
78 | Qualified2.IsOutside() || Qualified2.IsUnqualified())) { | |
79 | GccEnt_BadQualifier::Raise(); | |
80 | return; | |
81 | } | |
82 | gp_Circ2d C1 = Qualified1.Qualified(); | |
83 | gp_Circ2d C2 = Qualified2.Qualified(); | |
84 | Standard_Real R1 = C1.Radius(); | |
85 | Standard_Real R2 = C2.Radius(); | |
86 | gp_Dir2d dirx(1.,0.); | |
87 | gp_Pnt2d center1(C1.Location()); | |
88 | gp_Pnt2d center2(C2.Location()); | |
89 | TColStd_Array1OfReal Radius(1,2); | |
6e6cd5d9 | 90 | |
7fd59977 | 91 | Standard_Real dist1 = OnLine.Distance(center1); |
92 | Standard_Real dist2 = OnLine.Distance(center2); | |
93 | Standard_Real d1 = dist1+R1; | |
94 | Standard_Real d2 = dist2+R2; | |
95 | Standard_Real d3 = dist1-R1; | |
96 | Standard_Real d4 = dist2-R2; | |
97 | ||
98 | //========================================================================= | |
0d969553 | 99 | // Processing of boundary cases. + |
7fd59977 | 100 | //========================================================================= |
101 | ||
102 | if (Abs(d3-d4)<Tol && | |
103 | (Qualified1.IsEnclosed() || Qualified1.IsOutside() || | |
104 | Qualified1.IsUnqualified()) && | |
105 | (Qualified2.IsEnclosed() || Qualified2.IsOutside() || | |
106 | Qualified2.IsUnqualified())) { | |
107 | nbsol++; | |
108 | Radius(nbsol) = Abs(d3); | |
109 | WellDone = Standard_True; | |
110 | } | |
111 | if (Abs(d1-d2)<Tol && | |
112 | (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) && | |
113 | (Qualified2.IsEnclosing() || Qualified2.IsUnqualified())){ | |
114 | nbsol++; | |
115 | Radius(nbsol) = Abs(d1); | |
116 | WellDone = Standard_True; | |
117 | } | |
118 | if (Abs(d1-d4)<Tol && | |
119 | (Qualified1.IsEnclosing() || Qualified1.IsUnqualified()) && | |
120 | (Qualified2.IsEnclosed() || Qualified2.IsOutside() || | |
121 | Qualified2.IsUnqualified())){ | |
122 | nbsol++; | |
123 | Radius(nbsol) = Abs(d1); | |
124 | WellDone = Standard_True; | |
125 | } | |
126 | if (Abs(d3-d2)<Tol && | |
127 | (Qualified2.IsEnclosing() || Qualified2.IsUnqualified()) && | |
128 | (Qualified1.IsEnclosed() || Qualified1.IsOutside() || | |
129 | Qualified1.IsUnqualified())){ | |
130 | nbsol++; | |
131 | Radius(nbsol) = Abs(d3); | |
132 | WellDone = Standard_True; | |
133 | } | |
134 | gp_Lin2d L(center1,gp_Dir2d(center2.XY()-center1.XY())); | |
135 | IntAna2d_AnaIntersection Intp(OnLine,L); | |
136 | if (Intp.IsDone()) { | |
137 | if (!Intp.IsEmpty()){ | |
138 | for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) { | |
139 | gp_Pnt2d Center(Intp.Point(j).Value()); | |
140 | for (Standard_Integer i = 1 ; i <= nbsol ; i++) { | |
141 | NbrSol++; | |
142 | cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(i)); | |
143 | // ========================================================== | |
144 | WellDone = Standard_True; | |
145 | Standard_Real distcc1 = Center.Distance(center1); | |
146 | Standard_Real distcc2 = Center.Distance(center2); | |
147 | if (!Qualified1.IsUnqualified()) { | |
148 | qualifier1(NbrSol) = Qualified1.Qualifier(); | |
149 | } | |
150 | else if (Abs(distcc1+Radius(i)-R1) < Tol) { | |
151 | qualifier1(NbrSol) = GccEnt_enclosed; | |
152 | } | |
153 | else if (Abs(distcc1-R1-Radius(i)) < Tol) { | |
154 | qualifier1(NbrSol) = GccEnt_outside; | |
155 | } | |
156 | else { qualifier1(NbrSol) = GccEnt_enclosing; } | |
157 | if (!Qualified2.IsUnqualified()) { | |
158 | qualifier2(NbrSol) = Qualified2.Qualifier(); | |
159 | } | |
160 | else if (Abs(distcc2+Radius(i)-R2) < Tol) { | |
161 | qualifier2(NbrSol) = GccEnt_enclosed; | |
162 | } | |
163 | else if (Abs(distcc2-R2-Radius(i)) < Tol) { | |
164 | qualifier2(NbrSol) = GccEnt_outside; | |
165 | } | |
166 | else { qualifier2(NbrSol) = GccEnt_enclosing; } | |
167 | gp_Dir2d dc1(center1.XY()-Center.XY()); | |
168 | gp_Dir2d dc2(center2.XY()-Center.XY()); | |
169 | pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc1.XY()); | |
170 | pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(i)*dc2.XY()); | |
171 | par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), | |
172 | pnttg1sol(NbrSol)); | |
173 | pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol)); | |
174 | par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), | |
175 | pnttg2sol(NbrSol)); | |
176 | pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol)); | |
177 | pntcen(NbrSol) = cirsol(NbrSol).Location(); | |
178 | parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol)); | |
179 | } | |
180 | } | |
181 | } | |
182 | } | |
183 | ||
184 | //========================================================================= | |
0d969553 | 185 | // General case. + |
7fd59977 | 186 | //========================================================================= |
187 | ||
188 | if (!WellDone) { | |
189 | GccAna_Circ2dBisec Bis(C1,C2); | |
190 | if (Bis.IsDone()) { | |
191 | TColStd_Array1OfReal Rbid(1,2); | |
192 | TColStd_Array1OfReal RBid(1,2); | |
193 | Standard_Integer nbsolution = Bis.NbSolutions(); | |
194 | for (Standard_Integer i = 1 ; i <= nbsolution ; i++) { | |
195 | Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i); | |
196 | GccInt_IType typ = Sol->ArcType(); | |
197 | ||
198 | if (typ == GccInt_Cir) { | |
199 | Intp.Perform(OnLine,Sol->Circle()); | |
200 | } | |
201 | else if (typ == GccInt_Lin) { | |
202 | Intp.Perform(OnLine,Sol->Line()); | |
203 | } | |
204 | else if (typ == GccInt_Hpr) { | |
205 | Intp.Perform(OnLine,IntAna2d_Conic(Sol->Hyperbola())); | |
206 | } | |
207 | else if (typ == GccInt_Ell) { | |
208 | Intp.Perform(OnLine,IntAna2d_Conic(Sol->Ellipse())); | |
209 | } | |
210 | if (Intp.IsDone()) { | |
211 | if (!Intp.IsEmpty()){ | |
212 | for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) { | |
213 | gp_Pnt2d Center(Intp.Point(j).Value()); | |
214 | dist1 = Center.Distance(center1); | |
215 | dist2 = Center.Distance(center2); | |
216 | nbsol = 0; | |
217 | Standard_Integer nsol = 0; | |
218 | Standard_Integer nnsol = 0; | |
219 | R1 = C1.Radius(); | |
220 | R2 = C2.Radius(); | |
221 | if (Qualified1.IsEnclosed()) { | |
222 | if (dist1-R1 < Tol) { | |
223 | nbsol = 1; | |
224 | Rbid(1) = Abs(R1-dist1); | |
225 | } | |
226 | } | |
227 | else if (Qualified1.IsOutside()) { | |
228 | if (R1-dist1 < Tol) { | |
229 | nbsol = 1; | |
230 | Rbid(1) = Abs(dist1-R1); | |
231 | } | |
232 | } | |
233 | else if (Qualified1.IsEnclosing()) { | |
234 | nbsol = 1; | |
235 | Rbid(1) = dist1+R1; | |
236 | } | |
237 | else if (Qualified1.IsUnqualified()) { | |
238 | nbsol = 2; | |
239 | Rbid(1) = dist1+R1; | |
240 | Rbid(1) = Abs(dist1-R1); | |
241 | } | |
242 | if (Qualified2.IsEnclosed() && nbsol != 0) { | |
243 | if (dist2-R2 < Tol) { | |
244 | nsol = 1; | |
245 | RBid(1) = Abs(R2-dist2); | |
246 | } | |
247 | } | |
248 | else if (Qualified2.IsOutside() && nbsol != 0) { | |
249 | if (R2-dist2 < Tol) { | |
250 | nsol = 1; | |
251 | RBid(1) = Abs(R2-dist2); | |
252 | } | |
253 | } | |
254 | else if (Qualified2.IsEnclosing() && nbsol != 0) { | |
255 | nsol = 1; | |
256 | RBid(1) = dist2+R2; | |
257 | } | |
258 | else if (Qualified2.IsUnqualified() && nbsol != 0) { | |
259 | nsol = 2; | |
260 | RBid(1) = dist2+R2; | |
261 | RBid(2) = Abs(R2-dist2); | |
262 | } | |
263 | for (Standard_Integer isol = 1; isol <= nbsol ; isol++) { | |
264 | for (Standard_Integer jsol = 1; jsol <= nsol ; jsol++) { | |
265 | if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) { | |
266 | nnsol++; | |
267 | Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.; | |
268 | } | |
269 | } | |
270 | } | |
271 | if (nnsol > 0) { | |
272 | for (Standard_Integer k = 1 ; k <= nnsol ; k++) { | |
273 | NbrSol++; | |
274 | cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k)); | |
275 | // ========================================================== | |
276 | Standard_Real distcc1 = Center.Distance(center1); | |
277 | Standard_Real distcc2 = Center.Distance(center2); | |
278 | if (!Qualified1.IsUnqualified()) { | |
279 | qualifier1(NbrSol) = Qualified1.Qualifier(); | |
280 | } | |
281 | else if (Abs(distcc1+Radius(i)-R1) < Tol) { | |
282 | qualifier1(NbrSol) = GccEnt_enclosed; | |
283 | } | |
284 | else if (Abs(distcc1-R1-Radius(i)) < Tol) { | |
285 | qualifier1(NbrSol) = GccEnt_outside; | |
286 | } | |
287 | else { qualifier1(NbrSol) = GccEnt_enclosing; } | |
288 | if (!Qualified2.IsUnqualified()) { | |
289 | qualifier2(NbrSol) = Qualified2.Qualifier(); | |
290 | } | |
291 | else if (Abs(distcc2+Radius(i)-R2) < Tol) { | |
292 | qualifier2(NbrSol) = GccEnt_enclosed; | |
293 | } | |
294 | else if (Abs(distcc2-R2-Radius(i)) < Tol) { | |
295 | qualifier2(NbrSol) = GccEnt_outside; | |
296 | } | |
297 | else { qualifier2(NbrSol) = GccEnt_enclosing; } | |
298 | if (Center.Distance(center1) <= Tol && | |
299 | Abs(Radius(k)-C1.Radius()) <= Tol) {TheSame1(NbrSol)=1;} | |
300 | else { | |
301 | TheSame1(NbrSol) = 0; | |
302 | gp_Dir2d dc1(center1.XY()-Center.XY()); | |
303 | pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+ | |
304 | Radius(k)*dc1.XY()); | |
305 | par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), | |
306 | pnttg1sol(NbrSol)); | |
307 | pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg2sol(NbrSol)); | |
308 | } | |
309 | if (Center.Distance(center2) <= Tol && | |
310 | Abs(Radius(k)-C2.Radius()) <= Tol) {TheSame2(NbrSol)=1;} | |
311 | else { | |
312 | TheSame2(NbrSol) = 0; | |
313 | gp_Dir2d dc2(center2.XY()-Center.XY()); | |
314 | pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+ | |
315 | Radius(k)*dc2.XY()); | |
316 | par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), | |
317 | pnttg2sol(NbrSol)); | |
318 | pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol)); | |
319 | } | |
320 | pntcen(NbrSol) = Center; | |
321 | parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol)); | |
322 | } | |
323 | } | |
324 | } | |
325 | } | |
326 | WellDone = Standard_True; | |
327 | } | |
328 | } | |
329 | } | |
330 | } | |
331 | } | |
332 | ||
333 | //======================================================================== | |
334 | ||
335 | Standard_Boolean GccAna_Circ2d2TanOn:: | |
336 | IsDone () const{ return WellDone; } | |
337 | ||
338 | Standard_Integer GccAna_Circ2d2TanOn:: | |
339 | NbSolutions () const{ return NbrSol; } | |
340 | ||
341 | gp_Circ2d GccAna_Circ2d2TanOn:: | |
342 | ThisSolution (const Standard_Integer Index) const{ return cirsol(Index); } | |
343 | ||
344 | void GccAna_Circ2d2TanOn:: | |
345 | WhichQualifier(const Standard_Integer Index , | |
346 | GccEnt_Position& Qualif1 , | |
347 | GccEnt_Position& Qualif2 ) const | |
348 | { | |
349 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
350 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
351 | else { | |
352 | Qualif1 = qualifier1(Index); | |
353 | Qualif2 = qualifier2(Index); | |
354 | } | |
355 | } | |
356 | ||
357 | void GccAna_Circ2d2TanOn:: | |
358 | Tangency1 (const Standard_Integer Index , | |
359 | Standard_Real& ParSol , | |
360 | Standard_Real& ParArg , | |
361 | gp_Pnt2d& PntSol ) const{ | |
362 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
363 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
364 | else { | |
365 | if (TheSame1(Index) == 0) { | |
366 | ParSol = par1sol(Index); | |
367 | ParArg = pararg1(Index); | |
368 | PntSol = gp_Pnt2d(pnttg1sol(Index)); | |
369 | } | |
370 | else { StdFail_NotDone::Raise(); } | |
371 | } | |
372 | } | |
373 | ||
374 | void GccAna_Circ2d2TanOn:: | |
375 | Tangency2 (const Standard_Integer Index , | |
376 | Standard_Real& ParSol , | |
377 | Standard_Real& ParArg , | |
378 | gp_Pnt2d& PntSol ) const{ | |
379 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
380 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
381 | else { | |
382 | if (TheSame2(Index) == 0) { | |
383 | ParSol = par2sol(Index); | |
384 | ParArg = pararg2(Index); | |
385 | PntSol = gp_Pnt2d(pnttg2sol(Index)); | |
386 | } | |
387 | else { StdFail_NotDone::Raise(); } | |
388 | } | |
389 | } | |
390 | ||
391 | void GccAna_Circ2d2TanOn:: | |
392 | CenterOn3 (const Standard_Integer Index , | |
393 | Standard_Real& ParArg , | |
394 | gp_Pnt2d& PntSol ) const{ | |
395 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
396 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
397 | else { | |
398 | ParArg = parcen3(Index); | |
399 | PntSol = pnttg1sol(Index); | |
400 | } | |
401 | } | |
402 | ||
403 | Standard_Boolean GccAna_Circ2d2TanOn:: | |
404 | IsTheSame1 (const Standard_Integer Index) const | |
405 | { | |
406 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
407 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
408 | ||
409 | if (TheSame1(Index) == 0) { return Standard_False; } | |
410 | return Standard_True; | |
411 | } | |
412 | ||
413 | Standard_Boolean GccAna_Circ2d2TanOn:: | |
414 | IsTheSame2 (const Standard_Integer Index) const | |
415 | { | |
416 | if (!WellDone) { StdFail_NotDone::Raise(); } | |
417 | else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); } | |
418 | ||
419 | if (TheSame2(Index) == 0) { return Standard_False; } | |
420 | return Standard_True; | |
421 | } |