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_Lin2dBisec.hxx>
21 #include <GccEnt_BadQualifier.hxx>
22 #include <GccEnt_QualifiedCirc.hxx>
23 #include <GccEnt_QualifiedLin.hxx>
25 #include <gp_Ax2d.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <gp_Dir2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <IntAna2d_AnaIntersection.hxx>
31 #include <IntAna2d_IntPoint.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <StdFail_NotDone.hxx>
36 GccAna_Circ2d2TanOn (const GccEnt_QualifiedLin& Qualified1 ,
37 const GccEnt_QualifiedLin& Qualified2 ,
38 const gp_Lin2d& OnLine ,
39 const Standard_Real Tolerance ):
57 WellDone = Standard_False;
60 if (!(Qualified1.IsEnclosed() ||
61 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
62 !(Qualified2.IsEnclosed() ||
63 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
64 throw GccEnt_BadQualifier();
69 Standard_Real Tol = Abs(Tolerance);
71 // calculation of bisectrices of L1 and L2
72 gp_Lin2d L1(Qualified1.Qualified());
73 gp_Lin2d L2(Qualified2.Qualified());
74 gp_Pnt2d originL1(L1.Location());
75 gp_Pnt2d originL2(L2.Location());
76 GccAna_Lin2dBisec Bis(L1,L2);
80 if (Bis.NbSolutions() == 1 || Bis.NbSolutions() == 2) {
81 // if 1 bisectrice, L1 and L2 are parallel
82 // if 2 bisectrices, L1 and L2 are intersected
84 for (Standard_Integer k = 1 ; k <= Bis.NbSolutions() ; k++) {
85 IntAna2d_AnaIntersection Intp(Bis.ThisSolution(k),OnLine);
87 WellDone = Standard_True;
88 // for degenerated cases, no acceptable solution
89 // (OnLine and bisectrice strictly parallel or not)
90 if (!Intp.IdenticalElements()
91 && !Intp.ParallelElements()
93 // at maximum 1 point of intersection !
94 for (Standard_Integer l = 1 ; l <= Intp.NbPoints() ; l++) {
95 gp_Pnt2d pt(Intp.Point(l).Value());
97 Standard_Real Radius = L1.Distance(pt);
98 if (!L1.Contains(pt,Tol) && Radius<1.0/Tol && NbrSol<2) {
99 // acceptable solution : the radius is correct
101 cirsol(NbrSol) = gp_Circ2d(axe,Radius);
112 // parce following the qualifiers NbrSol acceptable solutions
114 for (Standard_Integer i=1 ; i <= NbrSol ; i++) {
116 gp_Pnt2d pbid(cirsol(i).Location());
117 Standard_Real Radius = cirsol(i).Radius();
118 Standard_Boolean ok = Standard_False;
120 // solution Outside or Enclosed / L1
121 gp_Dir2d dc1(originL1.XY()-pbid.XY());
122 Standard_Real sign1 = dc1.Dot(gp_Dir2d(-L1.Direction().Y(),
123 L1.Direction().X()));
124 if (sign1>0.0) ok = (Qualified1.IsUnqualified()
125 || Qualified1.IsOutside());
126 else ok = (Qualified1.IsUnqualified()
127 || Qualified1.IsEnclosed());
129 // solution Outside or Enclosed / L2
130 gp_Dir2d dc2(originL2.XY()-pbid.XY());
131 Standard_Real sign2 = dc2.Dot(gp_Dir2d(-L2.Direction().Y(),
132 L2.Direction().X()));
133 if (sign2>0.0) ok = ok && (Qualified2.IsUnqualified()
134 || Qualified2.IsOutside());
135 else ok = ok &&(Qualified2.IsUnqualified()
136 || Qualified2.IsEnclosed());
139 // solution to be preserved
140 dc1 = gp_Dir2d(sign1*gp_XY(-L1.Direction().Y(),
141 L1.Direction().X()));
142 pnttg1sol(i) = gp_Pnt2d(pbid.XY()+Radius*dc1.XY());
143 if (sign1>0.0) qualifier1(i) = GccEnt_outside;
144 else qualifier1(i) = GccEnt_enclosed;
145 dc2 = gp_Dir2d(sign2*gp_XY(-L2.Direction().Y(),
146 L2.Direction().X()));
147 pnttg2sol(i) = gp_Pnt2d(pbid.XY()+Radius*dc2.XY());
148 if (sign2>0.0) qualifier2(i) = GccEnt_outside;
149 else qualifier2(i) = GccEnt_enclosed;
151 par1sol(i)=ElCLib::Parameter(cirsol(i),pnttg1sol(i));
152 pararg1(i)=ElCLib::Parameter(L1,pnttg1sol(i));
153 par2sol(i)=ElCLib::Parameter(cirsol(i),pnttg2sol(i));
154 pararg2(i)=ElCLib::Parameter(L2,pnttg2sol(i));
155 parcen3(i)=ElCLib::Parameter(OnLine,pntcen(i));
158 // solution to be rejected
159 if (i==NbrSol) NbrSol--;
161 for (Standard_Integer k = i+1 ; k <= NbrSol ; k++) {
162 cirsol(k-1) = cirsol(k);