| 1 | // File: GccAna_Circ2d2TanOn_6.cxx |
| 2 | // Created: Thu Jan 2 15:56:04 1992 |
| 3 | // Author: Remi GILET |
| 4 | // <reg@topsn3> |
| 5 | |
| 6 | #include <GccAna_Circ2d2TanOn.jxx> |
| 7 | |
| 8 | #include <ElCLib.hxx> |
| 9 | #include <gp_Dir2d.hxx> |
| 10 | #include <gp_Ax2d.hxx> |
| 11 | #include <IntAna2d_AnaIntersection.hxx> |
| 12 | #include <IntAna2d_IntPoint.hxx> |
| 13 | #include <GccAna_Circ2dBisec.hxx> |
| 14 | #include <GccInt_IType.hxx> |
| 15 | #include <GccInt_BCirc.hxx> |
| 16 | #include <GccInt_BLine.hxx> |
| 17 | #include <IntAna2d_Conic.hxx> |
| 18 | #include <TColStd_Array1OfReal.hxx> |
| 19 | #include <GccEnt_BadQualifier.hxx> |
| 20 | |
| 21 | //========================================================================= |
| 22 | // Creation of a circle tangent to two circles C1 and C2. + |
| 23 | // centered on a circle. + |
| 24 | // We start with distinguishing various boundary cases that will be + |
| 25 | // processed separately. + |
| 26 | // In the general case: + |
| 27 | // ==================== + |
| 28 | // We calculate bissectrices to C1 and C2 that give us all + |
| 29 | // possible locations of centers of all circles tangent to C1 and C2. + |
| 30 | // We intersect these bissectrices with circle OnCirc which gives us + |
| 31 | // points among which we choose the solutions. + |
| 32 | // The choice is made basing in Qualifiers of C1 and C2. + |
| 33 | //========================================================================= |
| 34 | |
| 35 | GccAna_Circ2d2TanOn:: |
| 36 | GccAna_Circ2d2TanOn (const GccEnt_QualifiedCirc& Qualified1 , |
| 37 | const GccEnt_QualifiedCirc& Qualified2 , |
| 38 | const gp_Circ2d& OnCirc , |
| 39 | const Standard_Real Tolerance ): |
| 40 | cirsol(1,8) , |
| 41 | qualifier1(1,8) , |
| 42 | qualifier2(1,8) , |
| 43 | TheSame1(1,8) , |
| 44 | TheSame2(1,8) , |
| 45 | pnttg1sol(1,8) , |
| 46 | pnttg2sol(1,8) , |
| 47 | pntcen(1,8) , |
| 48 | par1sol(1,8) , |
| 49 | par2sol(1,8) , |
| 50 | pararg1(1,8) , |
| 51 | pararg2(1,8) , |
| 52 | parcen3(1,8) |
| 53 | { |
| 54 | TheSame1.Init(0); |
| 55 | TheSame2.Init(0); |
| 56 | WellDone = Standard_False; |
| 57 | NbrSol = 0; |
| 58 | if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || |
| 59 | Qualified1.IsOutside() || Qualified1.IsUnqualified()) || |
| 60 | !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || |
| 61 | Qualified2.IsOutside() || Qualified2.IsUnqualified())) { |
| 62 | GccEnt_BadQualifier::Raise(); |
| 63 | return; |
| 64 | } |
| 65 | Standard_Real Tol= Abs(Tolerance); |
| 66 | gp_Circ2d C1 = Qualified1.Qualified(); |
| 67 | gp_Circ2d C2 = Qualified2.Qualified(); |
| 68 | gp_Dir2d dirx(1.,0.); |
| 69 | TColStd_Array1OfReal Radius(1,2); |
| 70 | TColStd_Array1OfReal Rradius(1,2); |
| 71 | gp_Pnt2d center1(C1.Location()); |
| 72 | gp_Pnt2d center2(C2.Location()); |
| 73 | |
| 74 | Standard_Real R1 = C1.Radius(); |
| 75 | Standard_Real R2 = C2.Radius(); |
| 76 | |
| 77 | //========================================================================= |
| 78 | // Processing of boundary cases. + |
| 79 | //========================================================================= |
| 80 | |
| 81 | Standard_Integer nbsol1 = 1; |
| 82 | Standard_Integer nbsol2 = 0; |
| 83 | Standard_Real Ron = OnCirc.Radius(); |
| 84 | Standard_Real distcco = OnCirc.Location().Distance(center1); |
| 85 | gp_Dir2d dircc(OnCirc.Location().XY()-center1.XY()); |
| 86 | gp_Pnt2d pinterm(center1.XY()+(distcco-Ron)*dircc.XY()); |
| 87 | Standard_Real distcc2 =pinterm.Distance(center2); |
| 88 | Standard_Real distcc1 =pinterm.Distance(center1); |
| 89 | Standard_Real d1 = Abs(distcc2-R2-Abs(distcc1-R1)); |
| 90 | Standard_Real d2 = Abs(distcc2+R2-Abs(distcc1-R1)); |
| 91 | Standard_Real d3 = Abs(distcc2-R2-(distcc1+R1)); |
| 92 | Standard_Real d4 = Abs(distcc2+R2-(distcc1+R1)); |
| 93 | if ( d1 > Tol || d2 > Tol || d3 > Tol || d4 > Tol) { |
| 94 | pinterm = gp_Pnt2d(center1.XY()+(distcco+Ron)*dircc.XY()); |
| 95 | distcc2 =pinterm.Distance(center2); |
| 96 | distcc1 =pinterm.Distance(center1); |
| 97 | d1 = Abs(distcc2-R2-Abs(distcc1-R1)); |
| 98 | d2 = Abs(distcc2+R2-Abs(distcc1-R1)); |
| 99 | d3 = Abs(distcc2-R2-(distcc1+R1)); |
| 100 | d4 = Abs(distcc2+R2-(distcc1+R1)); |
| 101 | if ( d1 > Tol || d2 > Tol || d3 > Tol || d4 > Tol) { nbsol1 = 0; } |
| 102 | } |
| 103 | if (nbsol1 > 0) { |
| 104 | if (Qualified1.IsEnclosed() || Qualified1.IsOutside()) { |
| 105 | nbsol1 = 1; |
| 106 | Radius(1) = Abs(distcc1-R1); |
| 107 | } |
| 108 | else if (Qualified1.IsEnclosing()) { |
| 109 | nbsol1 = 1; |
| 110 | Radius(1) = R1+distcc1; |
| 111 | } |
| 112 | else if (Qualified1.IsUnqualified()) { |
| 113 | nbsol1 = 2; |
| 114 | Radius(1) = Abs(distcc1-R1); |
| 115 | Radius(2) = R1+distcc1; |
| 116 | } |
| 117 | if (Qualified2.IsEnclosed() || Qualified2.IsOutside()) { |
| 118 | nbsol2 = 1; |
| 119 | Rradius(1) = Abs(distcc2-R2); |
| 120 | } |
| 121 | else if (Qualified2.IsEnclosing()) { |
| 122 | nbsol2 = 1; |
| 123 | Rradius(1) = R2+distcc2; |
| 124 | } |
| 125 | else if (Qualified2.IsUnqualified()) { |
| 126 | nbsol2 = 2; |
| 127 | Rradius(1) = Abs(distcc2-R2); |
| 128 | Rradius(2) = R2+distcc2; |
| 129 | } |
| 130 | for (Standard_Integer i = 1 ; i <= nbsol1 ; i++) { |
| 131 | for (Standard_Integer j = 1 ; j <= nbsol2 ; j++) { |
| 132 | if (Abs(Radius(i)-Rradius(j)) <= Tol) { |
| 133 | WellDone = Standard_True; |
| 134 | NbrSol++; |
| 135 | cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),Radius(i)); |
| 136 | // =========================================================== |
| 137 | gp_Dir2d dc1(center1.XY()-pinterm.XY()); |
| 138 | gp_Dir2d dc2(center2.XY()-pinterm.XY()); |
| 139 | distcc1 = pinterm.Distance(center1); |
| 140 | distcc2 = pinterm.Distance(center2); |
| 141 | if (!Qualified1.IsUnqualified()) { |
| 142 | qualifier1(NbrSol) = Qualified1.Qualifier(); |
| 143 | } |
| 144 | else if (Abs(distcc1+Radius(i)-R1) < Tol) { |
| 145 | qualifier1(NbrSol) = GccEnt_enclosed; |
| 146 | } |
| 147 | else if (Abs(distcc1-R1-Radius(i)) < Tol) { |
| 148 | qualifier1(NbrSol) = GccEnt_outside; |
| 149 | } |
| 150 | else { qualifier1(NbrSol) = GccEnt_enclosing; } |
| 151 | if (!Qualified2.IsUnqualified()) { |
| 152 | qualifier2(NbrSol) = Qualified2.Qualifier(); |
| 153 | } |
| 154 | else if (Abs(distcc2+Radius(i)-R2) < Tol) { |
| 155 | qualifier2(NbrSol) = GccEnt_enclosed; |
| 156 | } |
| 157 | else if (Abs(distcc2-R2-Radius(i)) < Tol) { |
| 158 | qualifier2(NbrSol) = GccEnt_outside; |
| 159 | } |
| 160 | else { qualifier2(NbrSol) = GccEnt_enclosing; } |
| 161 | pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+Radius(i)*dc1.XY()); |
| 162 | pnttg2sol(NbrSol) = gp_Pnt2d(pinterm.XY()+Radius(i)*dc2.XY()); |
| 163 | pntcen(NbrSol) = cirsol(NbrSol).Location(); |
| 164 | par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol)); |
| 165 | pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol)); |
| 166 | par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol)); |
| 167 | pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol)); |
| 168 | parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol)); |
| 169 | } |
| 170 | } |
| 171 | } |
| 172 | if (WellDone) { return; } |
| 173 | } |
| 174 | |
| 175 | //========================================================================= |
| 176 | // General case. + |
| 177 | //========================================================================= |
| 178 | |
| 179 | GccAna_Circ2dBisec Bis(C1,C2); |
| 180 | if (Bis.IsDone()) { |
| 181 | TColStd_Array1OfReal Rbid(1,2); |
| 182 | TColStd_Array1OfReal RBid(1,2); |
| 183 | Standard_Integer nbsolution = Bis.NbSolutions(); |
| 184 | for (Standard_Integer i = 1 ; i <= nbsolution ; i++) { |
| 185 | Handle(GccInt_Bisec) Sol = Bis.ThisSolution(i); |
| 186 | GccInt_IType typ = Sol->ArcType(); |
| 187 | IntAna2d_AnaIntersection Intp; |
| 188 | if (typ == GccInt_Cir) { |
| 189 | Intp.Perform(OnCirc,Sol->Circle()); |
| 190 | } |
| 191 | else if (typ == GccInt_Lin) { |
| 192 | Intp.Perform(Sol->Line(),OnCirc); |
| 193 | } |
| 194 | else if (typ == GccInt_Hpr) { |
| 195 | Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Hyperbola())); |
| 196 | } |
| 197 | else if (typ == GccInt_Ell) { |
| 198 | Intp.Perform(OnCirc,IntAna2d_Conic(Sol->Ellipse())); |
| 199 | } |
| 200 | if (Intp.IsDone()) { |
| 201 | if ((!Intp.IsEmpty())&&(!Intp.ParallelElements())&& |
| 202 | (!Intp.IdenticalElements())) { |
| 203 | for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) { |
| 204 | gp_Pnt2d Center(Intp.Point(j).Value()); |
| 205 | Standard_Real dist1 = Center.Distance(center1); |
| 206 | Standard_Real dist2 = Center.Distance(center2); |
| 207 | Standard_Integer nbsol = 0; |
| 208 | Standard_Integer nsol = 0; |
| 209 | Standard_Integer nnsol = 0; |
| 210 | R1 = C1.Radius(); |
| 211 | R2 = C2.Radius(); |
| 212 | if (Qualified1.IsEnclosed()) { |
| 213 | if (dist1-R1 < Tol) { |
| 214 | nbsol = 1; |
| 215 | Rbid(1) = Abs(R1-dist1); |
| 216 | } |
| 217 | } |
| 218 | else if (Qualified1.IsOutside()) { |
| 219 | if (R1-dist1 < Tol) { |
| 220 | nbsol = 1; |
| 221 | Rbid(1) = Abs(dist1-R1); |
| 222 | } |
| 223 | } |
| 224 | else if (Qualified1.IsEnclosing()) { |
| 225 | nbsol = 1; |
| 226 | Rbid(1) = dist1+R1; |
| 227 | } |
| 228 | else if (Qualified1.IsUnqualified()) { |
| 229 | nbsol = 2; |
| 230 | Rbid(1) = dist1+R1; |
| 231 | Rbid(1) = Abs(dist1-R1); |
| 232 | } |
| 233 | if (Qualified2.IsEnclosed() && nbsol != 0) { |
| 234 | if (dist2-R2 < Tol) { |
| 235 | nsol = 1; |
| 236 | RBid(1) = Abs(R2-dist2); |
| 237 | } |
| 238 | } |
| 239 | else if (Qualified2.IsOutside() && nbsol != 0) { |
| 240 | if (R2-dist2 < Tol) { |
| 241 | nsol = 1; |
| 242 | RBid(1) = Abs(R2-dist2); |
| 243 | } |
| 244 | } |
| 245 | else if (Qualified2.IsEnclosing() && nbsol != 0) { |
| 246 | nsol = 1; |
| 247 | RBid(1) = dist2+R2; |
| 248 | } |
| 249 | else if (Qualified2.IsUnqualified() && nbsol != 0) { |
| 250 | nsol = 2; |
| 251 | RBid(1) = dist2+R2; |
| 252 | RBid(2) = Abs(R2-dist2); |
| 253 | } |
| 254 | for (Standard_Integer isol = 1; isol <= nbsol ; isol++) { |
| 255 | for (Standard_Integer jsol = 1; jsol <= nsol ; jsol++) { |
| 256 | if (Abs(Rbid(isol)-RBid(jsol)) <= Tol) { |
| 257 | nnsol++; |
| 258 | Radius(nnsol) = (RBid(jsol)+Rbid(isol))/2.; |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | if (nnsol > 0) { |
| 263 | for (Standard_Integer k = 1 ; k <= nnsol ; k++) { |
| 264 | NbrSol++; |
| 265 | cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(k)); |
| 266 | // ========================================================== |
| 267 | distcc1 = Center.Distance(center1); |
| 268 | distcc2 = Center.Distance(center2); |
| 269 | if (!Qualified1.IsUnqualified()) { |
| 270 | qualifier1(NbrSol) = Qualified1.Qualifier(); |
| 271 | } |
| 272 | else if (Abs(distcc1+Radius(k)-R1) < Tol) { |
| 273 | qualifier1(NbrSol) = GccEnt_enclosed; |
| 274 | } |
| 275 | else if (Abs(distcc1-R1-Radius(k)) < Tol) { |
| 276 | qualifier1(NbrSol) = GccEnt_outside; |
| 277 | } |
| 278 | else { qualifier1(NbrSol) = GccEnt_enclosing; } |
| 279 | if (!Qualified2.IsUnqualified()) { |
| 280 | qualifier2(NbrSol) = Qualified2.Qualifier(); |
| 281 | } |
| 282 | else if (Abs(distcc2+Radius(k)-R2) < Tol) { |
| 283 | qualifier2(NbrSol) = GccEnt_enclosed; |
| 284 | } |
| 285 | else if (Abs(distcc2-R2-Radius(k)) < Tol) { |
| 286 | qualifier2(NbrSol) = GccEnt_outside; |
| 287 | } |
| 288 | else { qualifier2(NbrSol) = GccEnt_enclosing; } |
| 289 | if (Center.Distance(center1) <= Tolerance && |
| 290 | Abs(Radius(k)-C1.Radius()) <= Tolerance) { |
| 291 | TheSame1(NbrSol) = 1; |
| 292 | } |
| 293 | else { |
| 294 | TheSame1(NbrSol) = 0; |
| 295 | gp_Dir2d dc1(center1.XY()-Center.XY()); |
| 296 | pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc1.XY()); |
| 297 | par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), |
| 298 | pnttg1sol(NbrSol)); |
| 299 | pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol)); |
| 300 | } |
| 301 | if (Center.Distance(center2) <= Tolerance && |
| 302 | Abs(Radius(k)-C2.Radius()) <= Tolerance) { |
| 303 | TheSame2(NbrSol) = 1; |
| 304 | } |
| 305 | else { |
| 306 | TheSame2(NbrSol) = 0; |
| 307 | gp_Dir2d dc2(center2.XY()-Center.XY()); |
| 308 | pnttg2sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(k)*dc2.XY()); |
| 309 | par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), |
| 310 | pnttg2sol(NbrSol)); |
| 311 | pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol)); |
| 312 | } |
| 313 | pntcen(NbrSol) = Center; |
| 314 | parcen3(NbrSol)=ElCLib::Parameter(OnCirc,pntcen(NbrSol)); |
| 315 | } |
| 316 | } |
| 317 | } |
| 318 | } |
| 319 | WellDone = Standard_True; |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | } |
| 324 | |