1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-13 14:27:08 +03:00
Files
occt/src/GccAna/GccAna_Circ2d2TanRad.cxx
ski 9775fa6110 0026937: Eliminate NO_CXX_EXCEPTION macro support
Macro NO_CXX_EXCEPTION was removed from code.
Method Raise() was replaced by explicit throw statement.
Method Standard_Failure::Caught() was replaced by normal C++mechanism of exception transfer.
Method Standard_Failure::Caught() is deprecated now.
Eliminated empty constructors.
Updated samples.
Eliminate empty method ChangeValue from NCollection_Map class.
Removed not operable methods from NCollection classes.
2017-02-02 16:35:54 +03:00

748 lines
25 KiB
C++

// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <ElCLib.hxx>
#include <GccAna_Circ2d2TanRad.hxx>
#include <GccEnt_BadQualifier.hxx>
#include <GccEnt_QualifiedCirc.hxx>
#include <GccEnt_QualifiedLin.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Circ2d.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Pnt2d.hxx>
#include <IntAna2d_AnaIntersection.hxx>
#include <IntAna2d_IntPoint.hxx>
#include <Precision.hxx>
#include <Standard_NegativeValue.hxx>
#include <Standard_OutOfRange.hxx>
#include <StdFail_NotDone.hxx>
// circular tangent to two cercles and given radius
//====================================================
//==================================================================
// Initialize WellDone to false. +
// Return circle C1 and circle C2. +
// Leave with error if the construction is impossible. +
// Distinguish boundary cases to process them separately. +
// Create parallel to C1 in the proper direction. +
// Create parallel to C2 in the proper direction. +
// Intersect parallels ==> center point of the solution. +
// Create the solution to be added to already found solutions. +
// Fill the fields. +
//==================================================================
GccAna_Circ2d2TanRad::
GccAna_Circ2d2TanRad (const GccEnt_QualifiedCirc& Qualified1 ,
const GccEnt_QualifiedCirc& Qualified2 ,
const Standard_Real Radius ,
const Standard_Real Tolerance ):
qualifier1(1,8) ,
qualifier2(1,8),
TheSame1(1,8) ,
TheSame2(1,8) ,
cirsol(1,8) ,
pnttg1sol(1,8) ,
pnttg2sol(1,8) ,
par1sol(1,8) ,
par2sol(1,8) ,
pararg1(1,8) ,
pararg2(1,8)
{
Standard_Real Tol = Abs(Tolerance);
gp_Dir2d dirx(1.,0.);
WellDone = Standard_False;
NbrSol = 0;
if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
!(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
throw GccEnt_BadQualifier();
return;
}
Standard_Boolean invers = Standard_False;
gp_Circ2d C1 = Qualified1.Qualified();
gp_Circ2d C2 = Qualified2.Qualified();
Standard_Real R1 = C1.Radius();
Standard_Real R2 = C2.Radius();
Standard_Real rbid = 0.;
Standard_Integer signe=0;
Standard_Real R3;
Standard_Real dist;
TColgp_Array1OfCirc2d C(1,8);
C(1) = gp_Circ2d(C1);
C(2) = gp_Circ2d(C2);
Standard_Integer nbsol = 0;
gp_Pnt2d center1(C1.Location());
gp_Pnt2d center2(C2.Location());
gp_Pnt2d center3;
if (Radius < 0.0) { throw Standard_NegativeValue(); }
else if ( C(2).Location().IsEqual(C(1).Location(),Precision::Confusion())){
WellDone = Standard_True;
}
else {
gp_Dir2d dir1(C(2).Location().XY()-C(1).Location().XY());
dist = (center2).Distance(center1);
if ((Qualified1.IsEnclosed()) && Qualified2.IsEnclosed()) {
// =========================================================
if (Radius*2.0-Abs(R1+R2-dist) > Tol) { WellDone = Standard_True; }
else {
if ((dist-R1-R2>Tol)||(Tol<Max(R1,R2)-dist-Min(R1,R2))) {
WellDone = Standard_True;
}
else if (Abs(dist-R1-R2)<=Tol||Abs(Max(R1,R2)-dist-Min(R1,R2))<=Tol) {
if (Abs(dist-R1-R2) <= Tol) {
rbid = R2+(dist-R1-R2)/2.0;
signe = -1;
}
else if (Abs(Max(R1,R2)-dist-Min(R1,R2)) <= Tol) {
if (R1 > R2) { R3 = R2; }
else {
C2 = gp_Circ2d(C1);
R3 = R1;
}
rbid = -R3+(Min(R1,R2)+dist-Max(R1,R2))/2.;
signe = 1;
}
gp_Ax2d axe(gp_Pnt2d(center2.XY()-rbid*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1)=gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
pnttg2sol(1)=gp_Pnt2d(center1.XY()+R1*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
WellDone = Standard_True;
NbrSol = 1;
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
nbsol = 1;
}
}
}
else if (((Qualified1.IsEnclosed()) && Qualified2.IsEnclosing()) ||
// ===================================================================
((Qualified1.IsEnclosing()) && Qualified2.IsEnclosed())) {
// ========================================================
if (Qualified1.IsEnclosing()) {
R3 = R1;
C(1) = gp_Circ2d(C2);
R1 = R2;
C(2) = gp_Circ2d(C1);
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
dir1.Reverse();
// it is necessary to swap the resulting tangency points
invers = Standard_True;
}
if ((R2-Radius>Tol) || (Tol<Radius-R1) || (Tol>R1-dist-R2) ||
((Tol<Radius*2-R1-dist-R2)||(Tol<R1+R2-dist-Radius*2.0))) {
WellDone = Standard_True;
}
else if ((Abs(R2-Radius)<=Tol) || (Abs(R1-Radius)<=Tol)) {
if (Abs(R2-Radius) <= Tol) {
C(2) = gp_Circ2d(C2);
R3 = R2;
TheSame2(1) = 1;
TheSame1(1) = 0;
pnttg1sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
}
else if (Abs(Radius-R1) <= Tol) {
C(2) = gp_Circ2d(C1);
R3 = R1;
TheSame1(1) = 1;
TheSame2(1) = 0;
pnttg2sol(1) = gp_Pnt2d(C(2).Location().XY()+R3*dir1.XY());
}
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(C(2).Location(),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
}
else {
if ((Abs(R2+dist-R1) <= Tol) || (Abs(Radius*2.0-R1-dist-R2) < Tol)) {
if (Abs(R2+dist-R1) <= Tol) { signe = 1; }
else if (Abs(Radius*2.0-R1-dist-R2) < Tol) {signe = -1; }
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+
signe*(R1-Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
pnttg2sol(1)=gp_Pnt2d(center2.XY()+R2*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
nbsol = 1;
}
}
}
else if (((Qualified1.IsEnclosed()) && (Qualified2.IsOutside())) ||
// ===================================================================
((Qualified1.IsOutside()) && (Qualified2.IsEnclosed()))) {
// ========================================================
if (Qualified1.IsOutside()) {
C(2) = gp_Circ2d(C1);
C(1) = gp_Circ2d(C2);
R3 = R1;
R1 = R2;
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
dir1.Reverse();
// it is necessary to swap the resulting tangency points
invers = Standard_True;
}
if ((Radius-R1>Tol)||(dist-R2-R1>Tol)||
((R2-dist-R1+Radius*2>Tol)||(R1-R2-dist-Radius*2>Tol))){
WellDone = Standard_True;
}
else {
if (((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) ||
(Abs(R1-R2+dist-Radius*2.0) <= Tol) ||
(Abs(R1-R2-dist-Radius*2.0) <= Tol) || (Abs(dist-R1-R2) <= Tol)) {
if (Abs(R1-R2+dist-Radius*2.0) <= Tol) {
signe = -1;
}
else {
signe = 1;
if ((Radius-R1 > 0.0) && (Abs(dist-R1-R2) <= Tol)) {
R2 = R1;
}
else if (Abs(dist-R1-R2) <= Tol) {
R2 = R1;
if (Abs(R1-Radius) <= Tol) {
TheSame1(1) = 1;
}
}
}
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+
signe*(R1-Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
nbsol = 1;
}
}
}
else if (((Qualified1.IsEnclosed()) && (Qualified2.IsUnqualified())) ||
// =======================================================================
((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosed()))) {
// ============================================================
if (Qualified1.IsUnqualified()) {
C(1) = gp_Circ2d(C2);
C(2) = gp_Circ2d(C1);
R3 = R1;
R1 = R2;
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
dir1.Reverse();
// it is necessary to swap the resulting tangency points
invers = Standard_True;
}
if ((Radius-R1 > Tol) || (dist-R2-R1 > Tol)) { WellDone = Standard_True; }
else {
if ((Abs(dist-R2-R1) <= Tol) || (Abs(Radius-R1) <= Tol)) {
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(ax,Radius);
// ================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
TheSame2(1) = 0;
if (Abs(Radius-R1) > 0.0) {
TheSame1(1) = 1;
}
else {
TheSame1(1) = 0;
pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
}
}
else {
C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
nbsol = 2;
}
}
}
else if ((Qualified1.IsEnclosing()) && (Qualified2.IsEnclosing())) {
// ==================================================================
if ((Tol < Max(R1,R2)-Radius) || (Tol < Max(R1,R2)-dist-Min(R1,R2)) ||
(dist+R1+R2-Radius*2.0 > Tol)) { WellDone = Standard_True; }
else {
if ((Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) ||
(Abs(R1+R2+dist-2.0*Radius) <= Tol)) {
if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
signe = 1;
}
else {
signe = -1;
}
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+
signe*(R1-Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center2.XY()+signe*R2*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else if (Abs(Radius-Max(R1,R2)) <= Tol) {
WellDone = Standard_True;
NbrSol = 1;
if (R1 > R2) {
C(1) = gp_Circ2d(C1);
C(2) = gp_Circ2d(C2);
TheSame1(1) = 1;
TheSame2(1) = 0;
pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
}
else {
C(1) = gp_Circ2d(C2);
C(2) = gp_Circ2d(C1);
TheSame1(1) = 0;
TheSame2(1) = 1;
pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
}
gp_Ax2d axe(C(1).Location(),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
nbsol = 1;
}
}
}
else if (((Qualified1.IsEnclosing()) && (Qualified2.IsOutside())) ||
// ====================================================================
((Qualified1.IsOutside()) && (Qualified2.IsEnclosing()))) {
// =========================================================
if (Qualified1.IsOutside()) {
C(1) = gp_Circ2d(C2);
C(2) = gp_Circ2d(C1);
R3 = R1;
R1 = R2;
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
dir1.Reverse();
// it is necessary to swap the resulting tangency points
invers = Standard_True;
}
if ((R1-Radius > Tol) || (Tol < R1+R2-dist) ||
(dist-R2+R1-Radius*2.0>Tol)) {
WellDone = Standard_True;
}
else if (((Abs(R1-Radius)<=Tol) || (Abs(R1+R2-dist)<=Tol))||
(Abs(dist-R2+R1-Radius*2.0) <= Tol)) {
WellDone = Standard_True;
NbrSol = 1;
if((Abs(R1-Radius) <= Tol) || (Abs(R1+R2-dist) <= Tol)){
TheSame1(1) = 1;
}
else {
TheSame1(1) = 0;
}
TheSame2(1) = 0;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+(R1-Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()-R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist-R2)*dir1.XY());
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
nbsol = 1;
}
}
else if (((Qualified1.IsEnclosing()) && (Qualified2.IsUnqualified())) ||
// ========================================================================
((Qualified1.IsUnqualified()) && (Qualified2.IsEnclosing()))) {
// =============================================================
if (Qualified1.IsUnqualified()) {
C(1) = gp_Circ2d(C2);
C(2) = gp_Circ2d(C1);
R3 = R1;
R1 = R2;
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
invers = Standard_True;
dir1.Reverse();
}
if ((Tol < R1-dist-R2) || (R1-Radius > Tol)) { WellDone = Standard_True; }
else if ((Abs(R1-Radius) <= Tol) || (Abs(R1-dist-R2) > 0.0)) {
if (Abs(R1-Radius) <= Tol) {
TheSame1(1) = 1;
if((Abs(Radius-R2) <= Tol) &&
(center1.Distance(center2) <= Tol)) {
TheSame2(1) = 1;
}
}
else if (Abs(R1-dist-R2) > 0.0) {
TheSame1(1) = 0;
TheSame2(1) = 0;
}
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius-R1)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
}
else {
C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Abs(Radius-R2));
nbsol = 2;
}
}
else if ((Qualified1.IsOutside()) && (Qualified2.IsOutside())) {
// ==============================================================
if (Tol < Max(R1,R2)-dist-Min(R1,R2)) { WellDone = Standard_True; }
else if (dist-R1-R2-Radius*2.0 > Tol) { WellDone = Standard_True; }
else {
if (Abs(dist+Min(R1,R2)-Max(R1,R2)) <= Tol) {
WellDone = Standard_True;
NbrSol = 1;
if (R1 < R2) { signe = -1; }
else { signe = 1; }
gp_Ax2d axe(gp_Pnt2d(center1.XY()+signe*(Radius+R1)*dir1.XY()),
dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+signe*R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(pnttg1sol(1));
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else if (Abs(dist-R1-R2-Radius*2.0) <= Tol) {
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d ax(gp_Pnt2d(center1.XY()+(R1+Radius)*dir1.XY()),dirx);
cirsol(1) = gp_Circ2d(ax,Radius);
// ================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center2.XY()-R2*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else {
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
C(2) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
nbsol = 1;
}
}
}
else if (((Qualified1.IsOutside()) && (Qualified2.IsUnqualified())) ||
// ======================================================================
((Qualified1.IsUnqualified()) && (Qualified2.IsOutside()))) {
// ===========================================================
if (Qualified1.IsUnqualified()) {
C(1) = gp_Circ2d(C2);
R3 = R1;
R1 = R2;
C(2) = gp_Circ2d(C1);
R2 = R3;
center3 = center1;
center1 = center2;
center2 = center3;
dir1.Reverse();
// it is necessary to swap the resulting tangency points
invers = Standard_True;
}
if (Tol < R1-dist-R2) { WellDone = Standard_True; }
else if ((Tol < R2-dist-R1) && (Tol < Radius*2.0-R2-dist+R1)) {
WellDone = Standard_True;
}
else if ((dist-R1-R2 > Tol) && (Tol < dist-R1-R2-Radius*2.0)) {
WellDone = Standard_True;
}
else {
if ((Abs(R1-R2-dist)<=Tol) ||
((Abs(dist-R1-R2)<=Tol) && (Abs(Radius*2.0-dist+R1+R2) <= Tol)) ||
((Abs(dist+R1-R2)<=Tol) && (Abs(R2+dist-R1-Radius*2.0)<=Tol))) {
WellDone = Standard_True;
NbrSol = 1;
gp_Ax2d axe(gp_Pnt2d(center1.XY()+(Radius+R1)*dir1.XY()),
dirx);
cirsol(1) = gp_Circ2d(axe,Radius);
// =================================
qualifier1(1) = Qualified1.Qualifier();
qualifier2(1) = Qualified2.Qualifier();
pnttg1sol(1) = gp_Pnt2d(center1.XY()+R1*dir1.XY());
pnttg2sol(1) = gp_Pnt2d(center1.XY()+(dist+R2)*dir1.XY());
TheSame1(1) = 0;
TheSame2(1) = 0;
}
else {
C(3) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
C(4) = gp_Circ2d(gp_Ax2d(C(2).Location(),dirx),Radius+R2);
C(1) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Radius+R1);
C(2) = gp_Circ2d(gp_Ax2d(C(1).Location(),dirx),Abs(Radius-R2));
nbsol = 2;
}
}
}
else if ((Qualified1.IsUnqualified()) && (Qualified2.IsUnqualified())) {
// ======================================================================
if ((dist-R1-R2>Tol)&&(Tol<(dist-R1-R2-Radius*2))) {
WellDone = Standard_True;
}
else if ((Max(R1,R2)-dist-Min(R1,R2)>Tol) &&
(((Max(R1,R2)-dist-Min(R1,R2))-Radius*2.0 > Tol))) {
WellDone = Standard_True;
}
else {
Standard_Real p3 = Max(R1,R2)-Min(R1,R2)-dist-Radius*2.0;
Standard_Real p4 = dist-R1-R2;
Standard_Real p5 = Radius*2.0-dist+R1+R2;
if (p3 > 0.0) {
dist = Max(R1,R2)-Min(R1,R2)-Radius*2.0;
}
else if (p4 > 0.0 && p5 < 0.0) {
R1 = dist-R2-Radius*2.0;
}
C(1) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
C(2) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
C(3) = gp_Circ2d(gp_Ax2d(center1,dirx),Abs(Radius-R1));
C(4) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
C(5) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
C(6) = gp_Circ2d(gp_Ax2d(center2,dirx),Abs(Radius-R2));
C(7) = gp_Circ2d(gp_Ax2d(center1,dirx),Radius+R1);
C(8) = gp_Circ2d(gp_Ax2d(center2,dirx),Radius+R2);
nbsol = 4;
}
}
if (nbsol > 0) {
for (Standard_Integer j = 1 ; j <= nbsol ; j++) {
IntAna2d_AnaIntersection Intp(C(2*j-1),C(2*j));
if (Intp.IsDone()) {
if (!Intp.IsEmpty()) {
for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
NbrSol++;
gp_Pnt2d Center(Intp.Point(i).Value());
cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
// =======================================================
dir1 = gp_Dir2d(Center.XY()-center1.XY());
gp_Dir2d dir2(Center.XY()-center2.XY());
Standard_Real distcc1 = Center.Distance(center1);
Standard_Real distcc2 = Center.Distance(center2);
if (!Qualified1.IsUnqualified()) {
qualifier1(NbrSol) = Qualified1.Qualifier();
}
else if (Abs(distcc1+Radius-R1) < Tol) {
qualifier1(NbrSol) = GccEnt_enclosed;
}
else if (Abs(distcc1-R1-Radius) < Tol) {
qualifier1(NbrSol) = GccEnt_outside;
}
else { qualifier1(NbrSol) = GccEnt_enclosing; }
if (!Qualified2.IsUnqualified()) {
qualifier2(NbrSol) = Qualified2.Qualifier();
}
else if (Abs(distcc2+Radius-R2) < Tol) {
qualifier2(NbrSol) = GccEnt_enclosed;
}
else if (Abs(distcc2-R2-Radius) < Tol) {
qualifier2(NbrSol) = GccEnt_outside;
}
else { qualifier2(NbrSol) = GccEnt_enclosing; }
if ((Center.Distance(center1) > R1) &&
(Radius < Center.Distance(center1)+R1)) {
pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
}
else if ((Center.Distance(center1) < R1) &&
(Radius < R1)) {
pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir1.XY());
}
else {
pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir1.XY());
}
if ((Center.Distance(center2) > R2) &&
(Radius < Center.Distance(center2)+R2)) {
pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
}
else if ((Center.Distance(center2) < R2) &&
(Radius < R2)) {
pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dir2.XY());
}
else {
pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()-Radius*dir2.XY());
}
TheSame1(NbrSol) = 0;
TheSame2(NbrSol) = 0;
}
}
WellDone = Standard_True;
}
}
}
}
// swapping of resulting tangency points if necessary
if (invers) {
gp_Pnt2d Psav;
for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
Psav = pnttg1sol(i);
pnttg1sol(i) = pnttg2sol(i);
pnttg2sol(i) = Psav;
}
}
// calculation of parameters of tangency points
for (Standard_Integer i = 1 ; i <= NbrSol ; i++) {
par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
if (TheSame1(i) == 0) {
pararg1(i)=ElCLib::Parameter(C1,pnttg1sol(i));
}
par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
if (TheSame2(i) == 0) {
pararg2(i)=ElCLib::Parameter(C2,pnttg2sol(i));
}
}
}
Standard_Boolean GccAna_Circ2d2TanRad::
IsDone () const { return WellDone; }
Standard_Integer GccAna_Circ2d2TanRad::
NbSolutions () const { return NbrSol; }
gp_Circ2d GccAna_Circ2d2TanRad::
ThisSolution (const Standard_Integer Index) const
{
if (!WellDone) { throw StdFail_NotDone(); }
if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
return cirsol(Index);
}
void GccAna_Circ2d2TanRad::
WhichQualifier(const Standard_Integer Index ,
GccEnt_Position& Qualif1 ,
GccEnt_Position& Qualif2 ) const
{
if (!WellDone) { throw StdFail_NotDone(); }
if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
Qualif1 = qualifier1(Index);
Qualif2 = qualifier2(Index);
}
void GccAna_Circ2d2TanRad::
Tangency1 (const Standard_Integer Index,
Standard_Real& ParSol,
Standard_Real& ParArg,
gp_Pnt2d& PntSol) const{
if (!WellDone) { throw StdFail_NotDone(); }
else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
else {
if (TheSame1(Index) == 0) {
ParSol = par1sol(Index);
ParArg = pararg1(Index);
PntSol = gp_Pnt2d(pnttg1sol(Index));
}
else { throw StdFail_NotDone(); }
}
}
void GccAna_Circ2d2TanRad::
Tangency2 (const Standard_Integer Index,
Standard_Real& ParSol,
Standard_Real& ParArg,
gp_Pnt2d& PntSol) const{
if (!WellDone) { throw StdFail_NotDone(); }
else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
else {
if (TheSame2(Index) == 0) {
ParSol = par2sol(Index);
ParArg = pararg2(Index);
PntSol = gp_Pnt2d(pnttg2sol(Index));
}
else { throw StdFail_NotDone(); }
}
}
Standard_Boolean GccAna_Circ2d2TanRad::
IsTheSame1 (const Standard_Integer Index) const
{
if (!WellDone) { throw StdFail_NotDone(); }
if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
if (TheSame1(Index) == 0) { return Standard_False; }
return Standard_True;
}
Standard_Boolean GccAna_Circ2d2TanRad::
IsTheSame2 (const Standard_Integer Index) const
{
if (!WellDone) { throw StdFail_NotDone(); }
if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
if (TheSame2(Index) == 0) { return Standard_False; }
return Standard_True;
}