1 // File: GccAna_Circ2d2TanOn_4.cxx
2 // Created: Thu Jan 2 15:54:38 1992
6 #include <GccAna_Circ2d2TanOn.jxx>
9 #include <gp_Dir2d.hxx>
10 #include <gp_Ax2d.hxx>
11 #include <GccAna_LinPnt2dBisec.hxx>
12 #include <IntAna2d_AnaIntersection.hxx>
13 #include <IntAna2d_IntPoint.hxx>
14 #include <GccInt_IType.hxx>
15 #include <GccInt_Bisec.hxx>
16 #include <GccInt_BCirc.hxx>
17 #include <GccInt_BLine.hxx>
18 #include <IntAna2d_Conic.hxx>
19 #include <GccEnt_BadQualifier.hxx>
20 #include <Precision.hxx>
21 //=========================================================================
22 // Creation of a circle Tangent to : 1 straight line L1. +
23 // Passing by : 1 point Point2. +
24 // Centered on : 1 straight line OnLine. +
25 // with a Tolerance of precision : Tolerance. +
27 // We start by making difference with various boundary cases that will be +
28 // processed separately. +
29 // For the general case: +
30 // ==================== +
31 // We calculate bissectrices to L1 and Point2 that give us +
32 // all possible locations of centers of all circles +
33 // tangent to L1 and passing through Point2. +
34 // We intersect these bissectrices with straight line OnLine which gives us +
35 // the points among which we'll choose the solutions. +
36 // The choices are made basing on Qualifieurs of L1. +
37 //=========================================================================
40 GccAna_Circ2d2TanOn (const GccEnt_QualifiedLin& Qualified1 ,
41 const gp_Pnt2d& Point2 ,
42 const gp_Lin2d& OnLine ,
43 const Standard_Real Tolerance ):
60 WellDone = Standard_False;
62 if (!(Qualified1.IsEnclosed() ||
63 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
64 GccEnt_BadQualifier::Raise();
67 Standard_Real Tol = Abs(Tolerance);
69 gp_Lin2d L1 = Qualified1.Qualified();
70 gp_Pnt2d originL1(L1.Location());
71 gp_Dir2d dirL1(L1.Direction());
72 gp_Dir2d normal(-dirL1.Y(),dirL1.X());
74 //=========================================================================
75 // Processing of boundary cases. +
76 //=========================================================================
78 if (dirL1.IsEqual(OnLine.Direction(),Precision::Confusion()) &&
79 OnLine.Distance(originL1)<Precision::Confusion()) {
80 // POP : l2s 2 straight line are identic : no Sol
86 Standard_Real dp2l = OnLine.Distance(Point2);
87 gp_Dir2d donline(OnLine.Direction());
88 gp_Pnt2d pinterm(Point2.XY()+dp2l*gp_XY(-donline.Y(),donline.X()));
89 if (OnLine.Distance(pinterm) > Tol) {
90 pinterm = gp_Pnt2d(Point2.XY()-dp2l*gp_XY(-donline.Y(),donline.X()));
92 Standard_Real dist = L1.Distance(pinterm);
93 if (Abs(dist-dp2l) <= Tol) {
94 gp_Dir2d dirbid(originL1.XY()-pinterm.XY());
95 if (Qualified1.IsEnclosed() && dirbid.Dot(normal)<0.) {
96 WellDone = Standard_True;
98 else if (Qualified1.IsOutside() && dirbid.Dot(normal) > 0.) {
99 WellDone = Standard_True;
101 else if (Qualified1.IsUnqualified()) { WellDone = Standard_True; }
104 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),dp2l);
105 // ======================================================
106 qualifier2(NbrSol) = GccEnt_noqualifier;
107 gp_Dir2d dc2(originL1.XY()-pinterm.XY());
108 if (!Qualified1.IsUnqualified()) {
109 qualifier1(NbrSol) = Qualified1.Qualifier();
111 else if (dc2.Dot(normal) > 0.0) {
112 qualifier1(NbrSol) = GccEnt_outside;
114 else { qualifier1(NbrSol) = GccEnt_enclosed; }
115 Standard_Real sign = dc2.Dot(gp_Dir2d(-dirL1.Y(),
117 dc2 = gp_Dir2d(sign*gp_XY(-dirL1.Y(),dirL1.X()));
118 pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+dp2l*dc2.XY());
119 pnttg2sol(NbrSol) = Point2;
120 pntcen(NbrSol) = pinterm;
121 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol));
122 pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
123 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol));
124 pararg2(NbrSol) = 0.;
125 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
130 //=========================================================================
132 //=========================================================================
134 GccAna_LinPnt2dBisec Bis(L1,Point2);
136 Handle(GccInt_Bisec) Sol = Bis.ThisSolution();
137 GccInt_IType type = Sol->ArcType();
138 IntAna2d_AnaIntersection Intp;
139 if (type == GccInt_Lin) {
140 Intp.Perform(OnLine,Sol->Line());
142 if (type == GccInt_Par) {
143 Intp.Perform(OnLine,IntAna2d_Conic(Sol->Parabola()));
146 if (!Intp.IsEmpty()) {
147 for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
148 gp_Pnt2d Center(Intp.Point(j).Value());
149 Standard_Real Radius = L1.Distance(Center);
150 // Standard_Integer nbsol = 1;
151 Standard_Boolean ok = Standard_False;
152 if (Qualified1.IsEnclosed()) {
153 if ((((originL1.X()-Center.X())*(-dirL1.Y()))+
154 ((originL1.Y()-Center.Y())*(dirL1.X())))<=0){
158 else if (Qualified1.IsOutside()) {
159 if ((((originL1.X()-Center.X())*(-dirL1.Y()))+
160 ((originL1.Y()-Center.Y())*(dirL1.X())))>=0){
164 else if (Qualified1.IsUnqualified()) {
169 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
170 // =======================================================
171 qualifier2(NbrSol) = GccEnt_noqualifier;
172 gp_Dir2d dc2(originL1.XY()-Center.XY());
173 if (!Qualified1.IsUnqualified()) {
174 qualifier1(NbrSol) = Qualified1.Qualifier();
176 else if (dc2.Dot(normal) > 0.0) {
177 qualifier1(NbrSol) = GccEnt_outside;
179 else { qualifier1(NbrSol) = GccEnt_enclosed; }
180 TheSame1(NbrSol) = 0;
181 TheSame2(NbrSol) = 0;
182 gp_Dir2d dc1(originL1.XY()-Center.XY());
183 Standard_Real sign = dc1.Dot(gp_Dir2d(normal));
184 dc1=gp_Dir2d(sign*(normal.XY()));
185 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc1.XY());
186 pnttg2sol(NbrSol) = Point2;
187 pntcen(NbrSol) = Center;
188 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
190 pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
191 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
193 pararg2(NbrSol) = 0.;
194 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
198 WellDone = Standard_True;