1 // Created on: 1991-09-24 2 // Created by: Joelle CHAUVET 3 // Copyright (c) 1991-1999 Matra Datavision 4 // Copyright (c) 1999-2014 OPEN CASCADE SAS 5 // 6 // This file is part of Open CASCADE Technology software library. 7 // 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. 13 // 14 // Alternatively, this file may be used under the terms of Open CASCADE 15 // commercial license or contractual agreement. 16 17 // Modified: Thu Jun 18 15:45:00 1998 18 // PRO10310 : cas ou le point est sur la droite 19 20 #include <ElCLib.hxx> 21 #include <GccAna_Circ2d2TanRad.hxx> 22 #include <GccEnt_BadQualifier.hxx> 23 #include <GccEnt_QualifiedCirc.hxx> 24 #include <GccEnt_QualifiedLin.hxx> 25 #include <gp_Ax2d.hxx> 26 #include <gp_Circ2d.hxx> 27 #include <gp_Lin2d.hxx> 28 #include <gp_Pnt2d.hxx> 29 #include <IntAna2d_AnaIntersection.hxx> 30 #include <IntAna2d_IntPoint.hxx> 31 #include <Standard_NegativeValue.hxx> 32 #include <Standard_OutOfRange.hxx> 33 #include <StdFail_NotDone.hxx> 34 #include <TColStd_Array1OfReal.hxx> 35 36 // circular tangent to a line and a point and a given radius 37 //============================================================= 38 //======================================================================== 39 // Initialize WellDone to false. + 40 // Return line L1. + 41 // Leave with error if the construction is impossible. + 42 // Create parallel to L1 in the proper direction. + 43 // Create the circle with center at Point1 of radius Radius. + 44 // Intersect the parallel and the circle. + 45 // ==> The center point of the solution. + 46 // Create the solution to be added to already found solutions. + 47 // Fill the fields. + 48 //======================================================================== 49 GccAna_Circ2d2TanRad:: GccAna_Circ2d2TanRad(const GccEnt_QualifiedLin & Qualified1,const gp_Pnt2d & Point2,const Standard_Real Radius,const Standard_Real Tolerance)50 GccAna_Circ2d2TanRad (const GccEnt_QualifiedLin& Qualified1 , 51 const gp_Pnt2d& Point2 , 52 const Standard_Real Radius , 53 const Standard_Real Tolerance ): 54 qualifier1(1,2) , 55 qualifier2(1,2), 56 TheSame1(1,2) , 57 TheSame2(1,2) , 58 cirsol(1,2) , 59 pnttg1sol(1,2) , 60 pnttg2sol(1,2) , 61 par1sol(1,2) , 62 par2sol(1,2) , 63 pararg1(1,2) , 64 pararg2(1,2) 65 { 66 67 gp_Dir2d dirx(1.0,0.0); 68 Standard_Real Tol = Abs(Tolerance); 69 NbrSol = 0; 70 WellDone = Standard_False; 71 if (!(Qualified1.IsEnclosed() || Qualified1.IsOutside() || 72 Qualified1.IsUnqualified())) { 73 throw GccEnt_BadQualifier(); 74 return; 75 } 76 Standard_Integer nbsol = 0; 77 Standard_Integer nbcote=0; 78 TColStd_Array1OfReal cote(1,2); 79 gp_Lin2d L1 = Qualified1.Qualified(); 80 Standard_Real displ1 = L1.Distance(Point2); 81 Standard_Real xdir = (L1.Direction()).X(); 82 Standard_Real ydir = (L1.Direction()).Y(); 83 Standard_Real lxloc = (L1.Location()).X(); 84 Standard_Real lyloc = (L1.Location()).Y(); 85 gp_Pnt2d origin1(lxloc,lyloc); 86 gp_Dir2d normL1(-ydir,xdir); 87 Standard_Real cxloc = Point2.X(); 88 Standard_Real cyloc = Point2.Y(); 89 90 if (Radius < 0.0) { throw Standard_NegativeValue(); } 91 92 else { 93 if ( displ1-Radius*2.0 > Tol) { WellDone = Standard_True; } 94 else if (Qualified1.IsEnclosed()) { 95 // ================================= 96 if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0)) { 97 WellDone = Standard_True; 98 } 99 else { 100 if ( displ1-Radius*2.0 > 0.0) { 101 nbsol = 2; 102 NbrSol = 1; 103 nbcote = 1; 104 cote(1) = 1.0; 105 } 106 else { 107 nbsol = 1; 108 nbcote = 1; 109 cote(1) = 1.0; 110 } 111 } 112 } 113 else if (Qualified1.IsOutside()) { 114 // ================================ 115 if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0)) { 116 WellDone = Standard_True; 117 } 118 else { 119 if ( displ1-Radius*2.0 > 0.0) { 120 nbsol = 2; 121 nbcote = 1; 122 cote(1) = -1.0; 123 } 124 else { 125 nbsol = 1; 126 nbcote = 1; 127 cote(1) = -1.0; 128 } 129 } 130 } 131 else if (Qualified1.IsUnqualified()) { 132 // ==================================== 133 if ( displ1-Radius*2.0 > 0.0) { 134 if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)>0.0)) { 135 nbsol = 2; 136 nbcote = 1; 137 cote(1) = 1.0; 138 } 139 else if ((-ydir*(cxloc-lxloc)+xdir*(cyloc-lyloc)<0.0)) { 140 nbsol = 2; 141 nbcote = 1; 142 cote(1) = -1.0; 143 } 144 } 145 else { 146 nbsol = 1; 147 nbcote = 2; 148 cote(1) = 1.0; 149 cote(2) = -1.0; 150 } 151 } 152 153 if (nbsol == 1) { 154 if (displ1<1.e-10) { 155 // particular case when Point2 is on the line 156 // construct two solutions directly 157 for (Standard_Integer jcote = 1 ; jcote <= nbcote ; jcote++) { 158 NbrSol++; 159 gp_Pnt2d Center(cxloc-cote(jcote)*ydir*Radius, 160 cyloc+cote(jcote)*xdir*Radius); 161 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius); 162 // ======================================================= 163 qualifier2(NbrSol) = GccEnt_noqualifier; 164 if (!Qualified1.IsUnqualified()) { 165 qualifier1(NbrSol) = Qualified1.Qualifier(); 166 } 167 else if (cote(jcote) > 0.0) { 168 qualifier1(NbrSol) = GccEnt_outside; 169 } 170 else { 171 qualifier1(NbrSol) = GccEnt_enclosed; 172 } 173 TheSame1(NbrSol) = 0; 174 TheSame2(NbrSol) = 0; 175 pnttg1sol(NbrSol) = Point2; 176 pnttg2sol(NbrSol) = Point2; 177 } 178 WellDone = Standard_True; 179 } 180 else { 181 gp_Circ2d cirint(gp_Ax2d(Point2,dirx),Radius); 182 for (Standard_Integer jcote = 1 ; jcote <= nbcote ; jcote++) { 183 gp_Lin2d linint(gp_Pnt2d(lxloc-cote(jcote)*ydir*Radius, 184 lyloc+cote(jcote)*xdir*Radius), 185 L1.Direction()); 186 IntAna2d_AnaIntersection Intp(linint,cirint); 187 if (Intp.IsDone()) { 188 if (!Intp.IsEmpty()) { 189 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() && NbrSol<2; i++) { 190 NbrSol++; 191 gp_Pnt2d Center(Intp.Point(i).Value()); 192 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius); 193 // ======================================================= 194 gp_Dir2d dc1(origin1.XY()-Center.XY()); 195 qualifier2(NbrSol) = GccEnt_noqualifier; 196 if (!Qualified1.IsUnqualified()) { 197 qualifier1(NbrSol) = Qualified1.Qualifier(); 198 } 199 else if (dc1.Dot(normL1) > 0.0) { 200 qualifier1(NbrSol) = GccEnt_outside; 201 } 202 else { qualifier1(NbrSol) = GccEnt_enclosed; } 203 TheSame1(NbrSol) = 0; 204 TheSame2(NbrSol) = 0; 205 pnttg1sol(NbrSol)=gp_Pnt2d(Center.XY()+ 206 cote(jcote)*Radius*gp_XY(ydir,-xdir)); 207 pnttg2sol(NbrSol) = Point2; 208 } 209 } 210 WellDone = Standard_True; 211 } 212 } 213 } 214 } 215 216 else if (nbsol == 2) { 217 gp_Pnt2d Center(Point2.XY()+cote(1)*Radius*gp_XY(-ydir,xdir)); 218 WellDone = Standard_True; 219 NbrSol = 1; 220 cirsol(1) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius); 221 // ================================================== 222 qualifier2(1) = GccEnt_noqualifier; 223 TheSame1(1) = 0; 224 TheSame2(1) = 0; 225 pnttg1sol(1)=gp_Pnt2d(Center.XY()+cote(1)*Radius*gp_XY(ydir,-xdir)); 226 pnttg2sol(1) = Point2; 227 } 228 } 229 230 for (Standard_Integer i = 1 ; i <= NbrSol ; i++) { 231 par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i)); 232 pararg1(i)=ElCLib::Parameter(L1,pnttg1sol(i)); 233 par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i)); 234 pararg2(i)=0.; 235 } 236 237 } 238 239 240 241 242