1 // Copyright (c) 1995-1999 Matra Datavision 2 // Copyright (c) 1999-2014 OPEN CASCADE SAS 3 // 4 // This file is part of Open CASCADE Technology software library. 5 // 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 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. 11 // 12 // Alternatively, this file may be used under the terms of Open CASCADE 13 // commercial license or contractual agreement. 14 15 16 #include <ElCLib.hxx> 17 #include <GccAna_Circ2d3Tan.hxx> 18 #include <GccAna_CircLin2dBisec.hxx> 19 #include <GccEnt_BadQualifier.hxx> 20 #include <GccEnt_QualifiedCirc.hxx> 21 #include <GccEnt_QualifiedLin.hxx> 22 #include <GccInt_BLine.hxx> 23 #include <GccInt_BParab.hxx> 24 #include <GccInt_IType.hxx> 25 #include <gp_Circ2d.hxx> 26 #include <gp_Dir2d.hxx> 27 #include <gp_Lin2d.hxx> 28 #include <gp_Pnt2d.hxx> 29 #include <IntAna2d_AnaIntersection.hxx> 30 #include <IntAna2d_Conic.hxx> 31 #include <IntAna2d_IntPoint.hxx> 32 #include <Precision.hxx> 33 #include <Standard_OutOfRange.hxx> 34 #include <StdFail_NotDone.hxx> 35 #include <TColStd_Array1OfReal.hxx> 36 37 //========================================================================= 38 // Creation of a circle tangent to two circles and a straight line. + 39 //========================================================================= 40 GccAna_Circ2d3Tan:: GccAna_Circ2d3Tan(const GccEnt_QualifiedCirc & Qualified1,const GccEnt_QualifiedCirc & Qualified2,const GccEnt_QualifiedLin & Qualified3,const Standard_Real Tolerance)41 GccAna_Circ2d3Tan (const GccEnt_QualifiedCirc& Qualified1, 42 const GccEnt_QualifiedCirc& Qualified2, 43 const GccEnt_QualifiedLin& Qualified3, 44 const Standard_Real Tolerance ): 45 46 //========================================================================= 47 // Initialization of fields. + 48 //========================================================================= 49 50 cirsol(1,16) , 51 qualifier1(1,16) , 52 qualifier2(1,16) , 53 qualifier3(1,16), 54 TheSame1(1,16) , 55 TheSame2(1,16) , 56 TheSame3(1,16) , 57 pnttg1sol(1,16) , 58 pnttg2sol(1,16) , 59 pnttg3sol(1,16) , 60 par1sol(1,16) , 61 par2sol(1,16) , 62 par3sol(1,16) , 63 pararg1(1,16) , 64 pararg2(1,16) , 65 pararg3(1,16) 66 { 67 68 gp_Dir2d dirx(1.0,0.0); 69 Standard_Real Tol = Abs(Tolerance); 70 WellDone = Standard_False; 71 NbrSol = 0; 72 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() || 73 Qualified1.IsOutside() || Qualified1.IsUnqualified()) || 74 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() || 75 Qualified2.IsOutside() || Qualified2.IsUnqualified()) || 76 !(Qualified3.IsEnclosed() || 77 Qualified3.IsOutside() || Qualified3.IsUnqualified())) { 78 throw GccEnt_BadQualifier(); 79 return; 80 } 81 82 //========================================================================= 83 // Processing. + 84 //========================================================================= 85 86 gp_Circ2d C1 = Qualified1.Qualified(); 87 gp_Circ2d C2 = Qualified2.Qualified(); 88 gp_Lin2d L3 = Qualified3.Qualified(); 89 Standard_Real R1 = C1.Radius(); 90 Standard_Real R2 = C2.Radius(); 91 gp_Pnt2d center1(C1.Location()); 92 gp_Pnt2d center2(C2.Location()); 93 (void )center2; 94 95 gp_Pnt2d origin3(L3.Location()); 96 gp_Dir2d dir3(L3.Direction()); 97 gp_Dir2d normL3(-dir3.Y(),dir3.X()); 98 99 TColStd_Array1OfReal Radius(1,2); 100 GccAna_CircLin2dBisec Bis1(C1,L3); 101 GccAna_CircLin2dBisec Bis2(C2,L3); 102 if (Bis1.IsDone() && Bis2.IsDone()) { 103 Standard_Integer nbsolution1 = Bis1.NbSolutions(); 104 Standard_Integer nbsolution2 = Bis2.NbSolutions(); 105 for (Standard_Integer i = 1 ; i <= nbsolution1; i++) { 106 Handle(GccInt_Bisec) Sol1 = Bis1.ThisSolution(i); 107 GccInt_IType typ1 = Sol1->ArcType(); 108 IntAna2d_AnaIntersection Intp; 109 for (Standard_Integer k = 1 ; k <= nbsolution2; k++) { 110 Handle(GccInt_Bisec) Sol2 = Bis2.ThisSolution(k); 111 GccInt_IType typ2 = Sol2->ArcType(); 112 if (typ1 == GccInt_Lin) { 113 if (typ2 == GccInt_Lin) { 114 Intp.Perform(Sol1->Line(),Sol2->Line()); 115 } 116 else if (typ2 == GccInt_Par) { 117 Intp.Perform(Sol1->Line(),IntAna2d_Conic(Sol2->Parabola())); 118 } 119 } 120 else if (typ1 == GccInt_Par) { 121 if (typ2 == GccInt_Lin) { 122 Intp.Perform(Sol2->Line(),IntAna2d_Conic(Sol1->Parabola())); 123 } 124 else if (typ2 == GccInt_Par) { 125 Intp.Perform(Sol1->Parabola(),IntAna2d_Conic(Sol2->Parabola())); 126 } 127 } 128 if (Intp.IsDone()) { 129 if (!Intp.IsEmpty()) { 130 for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) { 131 Standard_Real Rradius=0; 132 gp_Pnt2d Center(Intp.Point(j).Value()); 133 134 // pop : if the coordinates are too great, no creation 135 if (Center.X() > 1e10 || 136 Center.Y() > 1e10 ) break; 137 138 Standard_Real dist1 = Center.Distance(C1.Location()); 139 Standard_Real dist2 = Center.Distance(C2.Location()); 140 Standard_Real dist3 = L3.Distance(Center); 141 142 // pop : if the coordinates are too great, no creation 143 if (dist3 > 1e10 ) break; 144 145 Standard_Integer nbsol1 = 0; 146 Standard_Integer nbsol2 = 0; 147 Standard_Integer nbsol3 = 0; 148 Standard_Boolean ok = Standard_False; 149 if (Qualified1.IsEnclosed()) { 150 if (dist1-R1 < Tolerance) { 151 Radius(1) = Abs(R1-dist1); 152 nbsol1 = 1; 153 ok = Standard_True; 154 } 155 } 156 else if (Qualified1.IsOutside()) { 157 if (R1-dist1 < Tolerance) { 158 Radius(1) = Abs(R1-dist1); 159 nbsol1 = 1; 160 ok = Standard_True; 161 } 162 } 163 else if (Qualified1.IsEnclosing()) { 164 ok = Standard_True; 165 nbsol1 = 1; 166 Radius(1) = Abs(R1-dist1); 167 } 168 else if (Qualified1.IsUnqualified()) { 169 ok = Standard_True; 170 nbsol1 = 2; 171 Radius(1) = Abs(R1-dist1); 172 Radius(2) = R1+dist1; 173 } 174 if (Qualified2.IsEnclosed() && ok) { 175 if (dist2-R2 < Tolerance) { 176 for (Standard_Integer ii = 1 ; ii <= nbsol1 ; ii++) { 177 if (Abs(Radius(ii)-Abs(R2-dist2)) < Tol) { 178 Radius(1) = Abs(R2-dist2); 179 ok = Standard_True; 180 nbsol2 = 1; 181 } 182 } 183 } 184 } 185 else if (Qualified2.IsOutside() && ok) { 186 if (R2-dist2 < Tolerance) { 187 for (Standard_Integer ii = 1 ; ii <= nbsol1 ; ii++) { 188 if (Abs(Radius(ii)-Abs(R2-dist2)) < Tol) { 189 Radius(1) = Abs(R2-dist2); 190 ok = Standard_True; 191 nbsol2 = 1; 192 } 193 } 194 } 195 } 196 else if (Qualified2.IsEnclosing() && ok) { 197 for (Standard_Integer ii = 1 ; ii <= nbsol1 ; ii++) { 198 if (Abs(Radius(ii)-R2-dist2) < Tol) { 199 Radius(1) = R2+dist2; 200 ok = Standard_True; 201 nbsol2 = 1; 202 } 203 } 204 } 205 else if (Qualified2.IsUnqualified() && ok) { 206 for (Standard_Integer ii = 1 ; ii <= nbsol1 ; ii++) { 207 if (Abs(Radius(ii)-Abs(R2-dist2)) < Tol) { 208 Rradius = Abs(R2-dist2); 209 ok = Standard_True; 210 nbsol2++; 211 } 212 else if (Abs(Radius(ii)-R2-dist2) < Tol) { 213 Rradius = R2+dist2; 214 ok = Standard_True; 215 nbsol2++; 216 } 217 } 218 if (nbsol2 == 1) { 219 Radius(1) = Rradius; 220 } 221 else if (nbsol2 == 2) { 222 Radius(1) = Abs(R2-dist2); 223 Radius(2) = R2+dist2; 224 } 225 } 226 if (Qualified3.IsEnclosed() && ok) { 227 if ((((L3.Location().X()-Center.X())*(-L3.Direction().Y()))+ 228 ((L3.Location().Y()-Center.Y())*(L3.Direction().X())))<=0){ 229 ok = Standard_True; 230 nbsol3 = 1; 231 } 232 } 233 else if (Qualified2.IsOutside() && ok) { 234 if ((((L3.Location().X()-Center.X())*(-L3.Direction().Y()))+ 235 ((L3.Location().Y()-Center.Y())*(L3.Direction().X())))>=0){ 236 ok = Standard_True; 237 nbsol3 = 1; 238 } 239 } 240 else if (Qualified2.IsUnqualified() && ok) { 241 ok = Standard_True; 242 nbsol3 = 1; 243 } 244 if (ok) { 245 for (Standard_Integer ind3 = 1 ; ind3 <= nbsol3 ; ind3++) { 246 NbrSol++; 247 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius(ind3)); 248 // ========================================================== 249 Standard_Real distcc1 = Center.Distance(center1); 250 if (!Qualified1.IsUnqualified()) { 251 qualifier1(NbrSol) = Qualified1.Qualifier(); 252 } 253 else if (Abs(distcc1+Radius(ind3)-R1) < Tol) { 254 qualifier1(NbrSol) = GccEnt_enclosed; 255 } 256 else if (Abs(distcc1-R1-Radius(ind3)) < Tol) { 257 qualifier1(NbrSol) = GccEnt_outside; 258 } 259 else { qualifier1(NbrSol) = GccEnt_enclosing; } 260 Standard_Real distcc2 = Center.Distance(center1); 261 if (!Qualified2.IsUnqualified()) { 262 qualifier2(NbrSol) = Qualified2.Qualifier(); 263 } 264 else if (Abs(distcc2+Radius(ind3)-R2) < Tol) { 265 qualifier2(NbrSol) = GccEnt_enclosed; 266 } 267 else if (Abs(distcc2-R2-Radius(ind3)) < Tol) { 268 qualifier2(NbrSol) = GccEnt_outside; 269 } 270 else { qualifier2(NbrSol) = GccEnt_enclosing; } 271 gp_Dir2d dc3(origin3.XY()-Center.XY()); 272 if (!Qualified3.IsUnqualified()) { 273 qualifier3(NbrSol) = Qualified3.Qualifier(); 274 } 275 else if (dc3.Dot(normL3) > 0.0) { 276 qualifier3(NbrSol) = GccEnt_outside; 277 } 278 else { qualifier3(NbrSol) = GccEnt_enclosed; } 279 if (Center.Distance(C1.Location()) <= Tolerance && 280 Abs(Radius(ind3)-R1) <= Tolerance) { 281 TheSame1(NbrSol) = 1; 282 } 283 else { 284 TheSame1(NbrSol) = 0; 285 gp_Dir2d dc(C1.Location().XY()-Center.XY()); 286 pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(ind3)*dc.XY()); 287 // POP for protection if cirsol(NbrSol).Location == pnttg1sol(NbrSol) 288 if (cirsol(NbrSol).Location().IsEqual(pnttg1sol(NbrSol),Precision::Confusion())) 289 par1sol(NbrSol)=1; 290 else 291 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), 292 pnttg1sol(NbrSol)); 293 // POP for protection if C1.Location == pnttg1sol(NbrSol) 294 if (C1.Location().IsEqual(pnttg1sol(NbrSol),Precision::Confusion())) 295 pararg1(NbrSol)=1; 296 else 297 pararg1(NbrSol)=ElCLib::Parameter(C1,pnttg1sol(NbrSol)); 298 } 299 if (Center.Distance(C2.Location()) <= Tolerance && 300 Abs(Radius(ind3)-R2) <= Tolerance) { 301 TheSame2(NbrSol) = 1; 302 } 303 else { 304 TheSame2(NbrSol) = 0; 305 gp_Dir2d dc(C2.Location().XY()-Center.XY()); 306 pnttg2sol(NbrSol)=gp_Pnt2d(Center.XY()+Radius(ind3)*dc.XY()); 307 // POP for protection if cirsol(NbrSol).Location == pnttg1sol(NbrSol) 308 if (cirsol(NbrSol).Location().IsEqual(pnttg1sol(NbrSol),Precision::Confusion())) 309 par1sol(NbrSol)=1; 310 else 311 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), 312 pnttg2sol(NbrSol)); 313 // POP for protection if C2.Location == pnttg2sol(NbrSol) 314 if (C2.Location().IsEqual(pnttg2sol(NbrSol),Precision::Confusion())) 315 pararg2(NbrSol)=1; 316 else 317 pararg2(NbrSol)=ElCLib::Parameter(C2,pnttg2sol(NbrSol)); 318 } 319 TheSame3(NbrSol) = 0; 320 gp_Dir2d dc(L3.Location().XY()-Center.XY()); 321 Standard_Real sign = dc.Dot(gp_Dir2d(-L3.Direction().Y(), 322 L3.Direction().X())); 323 dc = gp_Dir2d(sign*gp_XY(-L3.Direction().Y(), 324 L3.Direction().X())); 325 pnttg3sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius(ind3)*dc.XY()); 326 par3sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol), 327 pnttg3sol(NbrSol)); 328 pararg3(NbrSol)=ElCLib::Parameter(L3,pnttg3sol(NbrSol)); 329 } 330 } 331 } 332 } 333 WellDone = Standard_True; 334 } 335 } 336 } 337 } 338 } 339