1 // Created on: 1992-01-02
2 // Created by: Remi GILET
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <GccAna_Circ2d2TanOn.hxx>
20 #include <GccAna_LinPnt2dBisec.hxx>
21 #include <GccEnt_BadQualifier.hxx>
22 #include <GccEnt_QualifiedCirc.hxx>
23 #include <GccEnt_QualifiedLin.hxx>
24 #include <GccInt_BCirc.hxx>
25 #include <GccInt_Bisec.hxx>
26 #include <GccInt_BLine.hxx>
27 #include <GccInt_IType.hxx>
28 #include <gp_Ax2d.hxx>
29 #include <gp_Circ2d.hxx>
30 #include <gp_Dir2d.hxx>
31 #include <gp_Lin2d.hxx>
32 #include <gp_Pnt2d.hxx>
33 #include <IntAna2d_AnaIntersection.hxx>
34 #include <IntAna2d_Conic.hxx>
35 #include <IntAna2d_IntPoint.hxx>
36 #include <Precision.hxx>
37 #include <Standard_OutOfRange.hxx>
38 #include <StdFail_NotDone.hxx>
40 //=========================================================================
41 // Creation of a circle Tangent to : 1 straight line L1. +
42 // Passing by : 1 point Point2. +
43 // Centered on : 1 straight line OnLine. +
44 // with a Tolerance of precision : Tolerance. +
46 // We start by making difference with various boundary cases that will be +
47 // processed separately. +
48 // For the general case: +
49 // ==================== +
50 // We calculate bissectrices to L1 and Point2 that give us +
51 // all possible locations of centers of all circles +
52 // tangent to L1 and passing through Point2. +
53 // We intersect these bissectrices with straight line OnLine which gives us +
54 // the points among which we'll choose the solutions. +
55 // The choices are made basing on Qualifieurs of L1. +
56 //=========================================================================
58 GccAna_Circ2d2TanOn (const GccEnt_QualifiedLin& Qualified1 ,
59 const gp_Pnt2d& Point2 ,
60 const gp_Lin2d& OnLine ,
61 const Standard_Real Tolerance ):
78 WellDone = Standard_False;
80 if (!(Qualified1.IsEnclosed() ||
81 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
82 throw GccEnt_BadQualifier();
85 Standard_Real Tol = Abs(Tolerance);
87 gp_Lin2d L1 = Qualified1.Qualified();
88 gp_Pnt2d originL1(L1.Location());
89 gp_Dir2d dirL1(L1.Direction());
90 gp_Dir2d normal(-dirL1.Y(),dirL1.X());
92 //=========================================================================
93 // Processing of boundary cases. +
94 //=========================================================================
96 if (dirL1.IsEqual(OnLine.Direction(),Precision::Confusion()) &&
97 OnLine.Distance(originL1)<Precision::Confusion()) {
98 // POP : l2s 2 straight line are identic : no Sol
104 Standard_Real dp2l = OnLine.Distance(Point2);
105 gp_Dir2d donline(OnLine.Direction());
106 gp_Pnt2d pinterm(Point2.XY()+dp2l*gp_XY(-donline.Y(),donline.X()));
107 if (OnLine.Distance(pinterm) > Tol) {
108 pinterm = gp_Pnt2d(Point2.XY()-dp2l*gp_XY(-donline.Y(),donline.X()));
110 Standard_Real dist = L1.Distance(pinterm);
111 if (Abs(dist-dp2l) <= Tol) {
112 gp_Dir2d dirbid(originL1.XY()-pinterm.XY());
113 if (Qualified1.IsEnclosed() && dirbid.Dot(normal)<0.) {
114 WellDone = Standard_True;
116 else if (Qualified1.IsOutside() && dirbid.Dot(normal) > 0.) {
117 WellDone = Standard_True;
119 else if (Qualified1.IsUnqualified()) { WellDone = Standard_True; }
122 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(pinterm,dirx),dp2l);
123 // ======================================================
124 qualifier2(NbrSol) = GccEnt_noqualifier;
125 gp_Dir2d dc2(originL1.XY()-pinterm.XY());
126 if (!Qualified1.IsUnqualified()) {
127 qualifier1(NbrSol) = Qualified1.Qualifier();
129 else if (dc2.Dot(normal) > 0.0) {
130 qualifier1(NbrSol) = GccEnt_outside;
132 else { qualifier1(NbrSol) = GccEnt_enclosed; }
133 Standard_Real sign = dc2.Dot(gp_Dir2d(-dirL1.Y(),
135 dc2 = gp_Dir2d(sign*gp_XY(-dirL1.Y(),dirL1.X()));
136 pnttg1sol(NbrSol) = gp_Pnt2d(pinterm.XY()+dp2l*dc2.XY());
137 pnttg2sol(NbrSol) = Point2;
138 pntcen(NbrSol) = pinterm;
139 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg1sol(NbrSol));
140 pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
141 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),pnttg2sol(NbrSol));
142 pararg2(NbrSol) = 0.;
143 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
148 //=========================================================================
150 //=========================================================================
152 GccAna_LinPnt2dBisec Bis(L1,Point2);
154 Handle(GccInt_Bisec) Sol = Bis.ThisSolution();
155 GccInt_IType type = Sol->ArcType();
156 IntAna2d_AnaIntersection Intp;
157 if (type == GccInt_Lin) {
158 Intp.Perform(OnLine,Sol->Line());
160 if (type == GccInt_Par) {
161 Intp.Perform(OnLine,IntAna2d_Conic(Sol->Parabola()));
164 if (!Intp.IsEmpty()) {
165 for (Standard_Integer j = 1 ; j <= Intp.NbPoints() ; j++) {
166 gp_Pnt2d Center(Intp.Point(j).Value());
167 Standard_Real Radius = L1.Distance(Center);
168 // Standard_Integer nbsol = 1;
169 Standard_Boolean ok = Standard_False;
170 if (Qualified1.IsEnclosed()) {
171 if ((((originL1.X()-Center.X())*(-dirL1.Y()))+
172 ((originL1.Y()-Center.Y())*(dirL1.X())))<=0){
176 else if (Qualified1.IsOutside()) {
177 if ((((originL1.X()-Center.X())*(-dirL1.Y()))+
178 ((originL1.Y()-Center.Y())*(dirL1.X())))>=0){
182 else if (Qualified1.IsUnqualified()) {
187 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
188 // =======================================================
189 qualifier2(NbrSol) = GccEnt_noqualifier;
190 gp_Dir2d dc2(originL1.XY()-Center.XY());
191 if (!Qualified1.IsUnqualified()) {
192 qualifier1(NbrSol) = Qualified1.Qualifier();
194 else if (dc2.Dot(normal) > 0.0) {
195 qualifier1(NbrSol) = GccEnt_outside;
197 else { qualifier1(NbrSol) = GccEnt_enclosed; }
198 TheSame1(NbrSol) = 0;
199 TheSame2(NbrSol) = 0;
200 gp_Dir2d dc1(originL1.XY()-Center.XY());
201 Standard_Real sign = dc1.Dot(gp_Dir2d(normal));
202 dc1=gp_Dir2d(sign*(normal.XY()));
203 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc1.XY());
204 pnttg2sol(NbrSol) = Point2;
205 pntcen(NbrSol) = Center;
206 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
208 pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
209 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
211 pararg2(NbrSol) = 0.;
212 parcen3(NbrSol)=ElCLib::Parameter(OnLine,pntcen(NbrSol));
216 WellDone = Standard_True;