1 // Created on: 1992-10-21
2 // Created by: Remi GILET
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <GccAna_Circ2d2TanRad.hxx>
19 #include <GccEnt_BadQualifier.hxx>
20 #include <GccEnt_QualifiedCirc.hxx>
21 #include <GccEnt_QualifiedLin.hxx>
22 #include <Geom2d_Circle.hxx>
23 #include <Geom2d_Line.hxx>
24 #include <Geom2d_Point.hxx>
25 #include <Geom2dGcc_Circ2d2TanRad.hxx>
26 #include <Geom2dGcc_Circ2d2TanRadGeo.hxx>
27 #include <Geom2dGcc_QCurve.hxx>
28 #include <Geom2dGcc_QualifiedCurve.hxx>
29 #include <gp_Circ2d.hxx>
30 #include <gp_Lin2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <Standard_NegativeValue.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
36 static const Standard_Integer aNbSolMAX = 16;
38 // circulaire tangent a deux cercles et de rayon donne
39 //====================================================
40 //========================================================================
41 // On initialise WellDone a false. +
42 // On recupere le cercle C1 et le cercle C2. +
43 // On sort en erreur dans les cas ou la construction est impossible. +
44 // On distingue les cas limites pour les triater separement. +
45 // On fait la parallele a C1 dans le bon sens. +
46 // On fait la parallele a C2 dans le bon sens. +
47 // On intersecte les paralleles ==> point de centre de la solution. +
48 // On cree la solution qu on ajoute aux solutions deja trouvees. +
49 // On remplit les champs. +
50 //========================================================================
52 Geom2dGcc_Circ2d2TanRad::
53 Geom2dGcc_Circ2d2TanRad (const Geom2dGcc_QualifiedCurve& Qualified1 ,
54 const Geom2dGcc_QualifiedCurve& Qualified2 ,
55 const Standard_Real Radius ,
56 const Standard_Real Tolerance ):
58 qualifier1(1,aNbSolMAX),
59 qualifier2(1,aNbSolMAX),
60 TheSame1(1,aNbSolMAX) ,
61 TheSame2(1,aNbSolMAX) ,
62 pnttg1sol(1,aNbSolMAX),
63 pnttg2sol(1,aNbSolMAX),
64 par1sol(1,aNbSolMAX) ,
65 par2sol(1,aNbSolMAX) ,
66 pararg1(1,aNbSolMAX) ,
69 if (Radius < 0.) { throw Standard_NegativeValue(); }
71 Geom2dAdaptor_Curve C1 = Qualified1.Qualified();
72 Geom2dAdaptor_Curve C2 = Qualified2.Qualified();
73 Handle(Geom2d_Curve) CC1 = C1.Curve();
74 Handle(Geom2d_Curve) CC2 = C2.Curve();
75 GeomAbs_CurveType Type1 = C1.GetType();
76 GeomAbs_CurveType Type2 = C2.GetType();
78 //=============================================================================
80 //=============================================================================
82 Invert = Standard_False;
84 if ((Type1 == GeomAbs_Line || Type1 == GeomAbs_Circle) &&
85 (Type2 == GeomAbs_Line || Type2 == GeomAbs_Circle)) {
86 if (Type1 == GeomAbs_Circle) {
87 Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
88 gp_Circ2d c1(CCC1->Circ2d());
89 GccEnt_QualifiedCirc Qc1 = GccEnt_QualifiedCirc(c1,
90 Qualified1.Qualifier());
91 if (Type2 == GeomAbs_Circle) {
92 Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
93 gp_Circ2d c2(CCC2->Circ2d());
94 GccAna_Circ2d2TanRad CircAna(Qc1,
95 GccEnt_QualifiedCirc(c2,Qualified2.Qualifier()),
97 WellDone = CircAna.IsDone();
98 NbrSol = CircAna.NbSolutions();
99 for(Standard_Integer i=1; i<=NbrSol; i++) {
100 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
105 Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
106 gp_Lin2d l2(LL2->Lin2d());
107 if (!Qualified2.IsEnclosing()) {
108 GccAna_Circ2d2TanRad CircAna(Qc1,
109 GccEnt_QualifiedLin(l2,Qualified2.Qualifier()),
111 WellDone = CircAna.IsDone();
112 NbrSol = CircAna.NbSolutions();
113 for(Standard_Integer i=1; i<=NbrSol; i++) {
114 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
119 WellDone = Standard_False;
120 throw GccEnt_BadQualifier();
125 Handle(Geom2d_Line) LL1 = Handle(Geom2d_Line)::DownCast(CC1);
126 gp_Lin2d l1(LL1->Lin2d());
127 if (Qualified1.IsEnclosing()) {
128 WellDone = Standard_False;
129 throw GccEnt_BadQualifier();
132 GccEnt_QualifiedLin Ql1 = GccEnt_QualifiedLin(l1,
133 Qualified1.Qualifier());
134 if (Type2 == GeomAbs_Circle) {
135 Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
136 gp_Circ2d c2(CCC2->Circ2d());
137 Invert = Standard_True;
138 GccAna_Circ2d2TanRad CircAna(GccEnt_QualifiedCirc(c2,
139 Qualified2.Qualifier()),
140 Ql1,Radius,Tolerance);
141 WellDone = CircAna.IsDone();
142 NbrSol = CircAna.NbSolutions();
143 for(Standard_Integer i=1; i<=NbrSol; i++) {
144 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
149 Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
150 gp_Lin2d l2(LL2->Lin2d());
151 if (!Qualified2.IsEnclosing()) {
152 GccAna_Circ2d2TanRad CircAna(Ql1,
153 GccEnt_QualifiedLin(l2,Qualified2.Qualifier()),
155 WellDone = CircAna.IsDone();
156 NbrSol = CircAna.NbSolutions();
157 for(Standard_Integer i=1; i<=NbrSol; i++) {
158 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
163 WellDone = Standard_False;
164 throw GccEnt_BadQualifier();
170 //=============================================================================
172 //=============================================================================
174 if (Type1 == GeomAbs_Line) {
175 Handle(Geom2d_Line) LL1 = Handle(Geom2d_Line)::DownCast(CC1);
176 gp_Lin2d l1(LL1->Lin2d());
177 if (Qualified1.IsEnclosing()) {
178 WellDone = Standard_False;
179 throw GccEnt_BadQualifier();
182 GccEnt_QualifiedLin Ql1 = GccEnt_QualifiedLin(l1,
183 Qualified1.Qualifier());
184 Geom2dGcc_QCurve Qc2(C2,Qualified2.Qualifier());
185 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Ql1,Qc2,Radius,Tolerance);
186 WellDone = CircGeo.IsDone();
187 NbrSol = CircGeo.NbSolutions();
188 for(Standard_Integer i=1; i<=NbrSol; i++) {
189 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
194 else if (Type1 == GeomAbs_Circle) {
195 Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
196 gp_Circ2d c1(CCC1->Circ2d());
197 GccEnt_QualifiedCirc Qc1 = GccEnt_QualifiedCirc(c1,
198 Qualified1.Qualifier());
199 Geom2dGcc_QCurve Qc2(C2,Qualified2.Qualifier());
200 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Qc1,Qc2,Radius,Tolerance);
201 WellDone = CircGeo.IsDone();
202 NbrSol = CircGeo.NbSolutions();
203 for(Standard_Integer i=1; i<=NbrSol; i++) {
204 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
208 else if (Type2 == GeomAbs_Line) {
209 Invert = Standard_True;
210 Handle(Geom2d_Line) LL2 = Handle(Geom2d_Line)::DownCast(CC2);
211 gp_Lin2d l2(LL2->Lin2d());
212 if (Qualified2.IsEnclosing()) {
213 WellDone = Standard_False;
214 throw GccEnt_BadQualifier();
217 GccEnt_QualifiedLin Ql2 = GccEnt_QualifiedLin(l2,
218 Qualified2.Qualifier());
219 Geom2dGcc_QCurve Qc1(C1,Qualified1.Qualifier());
220 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Ql2,Qc1,Radius,Tolerance);
221 WellDone = CircGeo.IsDone();
222 NbrSol = CircGeo.NbSolutions();
223 for(Standard_Integer i=1; i<=NbrSol; i++) {
224 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
229 else if (Type2 == GeomAbs_Circle) {
230 Invert = Standard_True;
231 Handle(Geom2d_Circle) CCC2 = Handle(Geom2d_Circle)::DownCast(CC2);
232 gp_Circ2d c2(CCC2->Circ2d());
233 GccEnt_QualifiedCirc Qc2 = GccEnt_QualifiedCirc(c2,
234 Qualified2.Qualifier());
235 Geom2dGcc_QCurve Qc1(C1,Qualified1.Qualifier());
236 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Qc2,Qc1,Radius,Tolerance);
237 WellDone = CircGeo.IsDone();
238 NbrSol = CircGeo.NbSolutions();
239 for(Standard_Integer i=1; i<=NbrSol; i++) {
240 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
245 Geom2dGcc_QCurve Qc1(C1,Qualified1.Qualifier());
246 Geom2dGcc_QCurve Qc2(C2,Qualified2.Qualifier());
247 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Qc1,Qc2,Radius,Tolerance);
248 WellDone = CircGeo.IsDone();
249 NbrSol = CircGeo.NbSolutions();
250 for(Standard_Integer i=1; i<=NbrSol; i++) {
251 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
259 Geom2dGcc_Circ2d2TanRad::
260 Geom2dGcc_Circ2d2TanRad (const Geom2dGcc_QualifiedCurve& Qualified1 ,
261 const Handle(Geom2d_Point)& Point ,
262 const Standard_Real Radius ,
263 const Standard_Real Tolerance ):
264 cirsol(1,aNbSolMAX) ,
265 qualifier1(1,aNbSolMAX),
266 qualifier2(1,aNbSolMAX),
267 TheSame1(1,aNbSolMAX) ,
268 TheSame2(1,aNbSolMAX) ,
269 pnttg1sol(1,aNbSolMAX),
270 pnttg2sol(1,aNbSolMAX),
271 par1sol(1,aNbSolMAX) ,
272 par2sol(1,aNbSolMAX) ,
273 pararg1(1,aNbSolMAX) ,
276 if (Radius < 0.) { throw Standard_NegativeValue(); }
278 Geom2dAdaptor_Curve C1 = Qualified1.Qualified();
279 Handle(Geom2d_Curve) CC1 = C1.Curve();
280 GeomAbs_CurveType Type1 = C1.GetType();
282 //=============================================================================
284 //=============================================================================
286 Invert = Standard_False;
288 if (Type1 == GeomAbs_Line || Type1 == GeomAbs_Circle) {
289 if (Type1 == GeomAbs_Circle) {
290 Handle(Geom2d_Circle) CCC1 = Handle(Geom2d_Circle)::DownCast(CC1);
291 gp_Circ2d c1(CCC1->Circ2d());
292 GccEnt_QualifiedCirc Qc1(c1,Qualified1.Qualifier());
293 GccAna_Circ2d2TanRad CircAna(Qc1,Point->Pnt2d(),Radius,Tolerance);
294 WellDone = CircAna.IsDone();
295 NbrSol = CircAna.NbSolutions();
296 for(Standard_Integer i=1; i<=NbrSol; i++) {
297 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
302 Handle(Geom2d_Line) LLL1 = Handle(Geom2d_Line)::DownCast(CC1);
303 gp_Lin2d l1(LLL1->Lin2d());
304 GccEnt_QualifiedLin Ql1(l1,Qualified1.Qualifier());
305 GccAna_Circ2d2TanRad CircAna(Ql1,Point->Pnt2d(),Radius,Tolerance);
306 WellDone = CircAna.IsDone();
307 NbrSol = CircAna.NbSolutions();
308 for(Standard_Integer i=1; i<=NbrSol; i++) {
309 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
314 //=============================================================================
316 //=============================================================================
318 Geom2dGcc_QCurve Qc1(C1,Qualified1.Qualifier());
319 Geom2dGcc_Circ2d2TanRadGeo CircGeo(Qc1,Point->Pnt2d(),Radius,Tolerance);
320 WellDone = CircGeo.IsDone();
321 NbrSol = CircGeo.NbSolutions();
322 for(Standard_Integer i=1; i<=NbrSol; i++) {
323 CircGeo.WhichQualifier(i,qualifier1(i),qualifier2(i));
330 Geom2dGcc_Circ2d2TanRad::
331 Geom2dGcc_Circ2d2TanRad (const Handle(Geom2d_Point)& Point1 ,
332 const Handle(Geom2d_Point)& Point2 ,
333 const Standard_Real Radius ,
334 const Standard_Real Tolerance ):
347 if (Radius < 0.) { throw Standard_NegativeValue(); }
350 //=============================================================================
352 //=============================================================================
354 Invert = Standard_False;
356 GccAna_Circ2d2TanRad CircAna(Point1->Pnt2d(),Point2->Pnt2d(),
358 WellDone = CircAna.IsDone();
359 NbrSol = CircAna.NbSolutions();
360 for(Standard_Integer i=1; i<=NbrSol; i++) {
361 CircAna.WhichQualifier(i,qualifier1(i),qualifier2(i));
367 void Geom2dGcc_Circ2d2TanRad::Results(const GccAna_Circ2d2TanRad& Circ)
369 for (Standard_Integer j = 1; j <= NbrSol; j++) {
370 cirsol(j) = Circ.ThisSolution(j);
371 if (Circ.IsTheSame1(j)) { TheSame1(j) = 1; }
372 else {TheSame1(j) = 0; }
373 if (Circ.IsTheSame2(j)) { TheSame2(j) = 1; }
374 else {TheSame2(j) = 0; }
375 Circ.Tangency1(j,par1sol(j),pararg1(j),pnttg1sol(j));
376 Circ.Tangency2(j,par2sol(j),pararg2(j),pnttg2sol(j));
380 void Geom2dGcc_Circ2d2TanRad::Results(const Geom2dGcc_Circ2d2TanRadGeo& Circ)
382 for (Standard_Integer j = 1; j <= NbrSol; j++) {
383 cirsol(j) = Circ.ThisSolution(j);
384 if (Circ.IsTheSame1(j)) { TheSame1(j) = 1; }
385 else {TheSame1(j) = 0; }
386 if (Circ.IsTheSame2(j)) { TheSame2(j) = 1; }
387 else {TheSame2(j) = 0; }
388 Circ.Tangency1(j,par1sol(j),pararg1(j),pnttg1sol(j));
389 Circ.Tangency2(j,par2sol(j),pararg2(j),pnttg2sol(j));
393 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
394 IsDone () const { return WellDone; }
396 Standard_Integer Geom2dGcc_Circ2d2TanRad::
402 gp_Circ2d Geom2dGcc_Circ2d2TanRad::
403 ThisSolution (const Standard_Integer Index) const
405 if (!WellDone) { throw StdFail_NotDone(); }
406 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
407 return cirsol(Index);
410 void Geom2dGcc_Circ2d2TanRad::
411 WhichQualifier (const Standard_Integer Index ,
412 GccEnt_Position& Qualif1 ,
413 GccEnt_Position& Qualif2) const
415 if (!WellDone) { throw StdFail_NotDone(); }
416 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
419 Qualif1 = qualifier2(Index);
420 Qualif2 = qualifier1(Index);
423 Qualif1 = qualifier1(Index);
424 Qualif2 = qualifier2(Index);
429 void Geom2dGcc_Circ2d2TanRad::
430 Tangency1 (const Standard_Integer Index,
431 Standard_Real& ParSol,
432 Standard_Real& ParArg,
433 gp_Pnt2d& PntSol) const
435 if (!WellDone) { throw StdFail_NotDone(); }
436 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
439 if (TheSame2(Index) == 0) {
440 ParSol = par2sol(Index);
441 ParArg = pararg2(Index);
442 PntSol = pnttg2sol(Index);
444 else { throw StdFail_NotDone(); }
447 if (TheSame1(Index) == 0) {
448 ParSol = par1sol(Index);
449 ParArg = pararg1(Index);
450 PntSol = pnttg1sol(Index);
452 else { throw StdFail_NotDone(); }
457 void Geom2dGcc_Circ2d2TanRad::
458 Tangency2 (const Standard_Integer Index,
459 Standard_Real& ParSol,
460 Standard_Real& ParArg,
461 gp_Pnt2d& PntSol) const
463 if (!WellDone) { throw StdFail_NotDone(); }
464 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
467 if (TheSame2(Index) == 0) {
468 ParSol = par2sol(Index);
469 ParArg = pararg2(Index);
470 PntSol = pnttg2sol(Index);
472 else { throw StdFail_NotDone(); }
475 if (TheSame1(Index) == 0) {
476 ParSol = par1sol(Index);
477 ParArg = pararg1(Index);
478 PntSol = pnttg1sol(Index);
480 else { throw StdFail_NotDone(); }
485 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
486 IsTheSame1 (const Standard_Integer Index) const
488 if (!WellDone) { throw StdFail_NotDone(); }
489 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
491 if (TheSame2(Index) == 0) { return Standard_False; }
492 else { return Standard_True; }
495 if (TheSame1(Index) == 0) { return Standard_False; }
496 else { return Standard_True; }
500 Standard_Boolean Geom2dGcc_Circ2d2TanRad::
501 IsTheSame2 (const Standard_Integer Index) const
503 if (!WellDone) { throw StdFail_NotDone(); }
504 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
506 if (TheSame2(Index) == 0) { return Standard_False; }
507 else { return Standard_True; }
510 if (TheSame1(Index) == 0) { return Standard_False; }
511 else { return Standard_True; }
513 // return Standard_True;