1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
17 #include <GccAna_Circ2d3Tan.hxx>
18 #include <GccAna_Lin2dBisec.hxx>
19 #include <GccEnt_BadQualifier.hxx>
20 #include <GccEnt_QualifiedCirc.hxx>
21 #include <GccEnt_QualifiedLin.hxx>
22 #include <gp_Circ2d.hxx>
23 #include <gp_Dir2d.hxx>
24 #include <gp_Lin2d.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <IntAna2d_AnaIntersection.hxx>
27 #include <IntAna2d_IntPoint.hxx>
28 #include <Standard_OutOfRange.hxx>
29 #include <StdFail_NotDone.hxx>
30 #include <TColStd_Array1OfReal.hxx>
32 //=========================================================================
33 // Creation of a circle tangent to three straight lines. +
34 // Create Bissectrices at Qualified1 and Qualified2 and +
35 // Bissectrices at Qualified1 and Qualified3. +
36 // Intersect bissectrices calculated in this way ==> Center points +
37 // Choose the center point that corresponds to qualifiers and +
38 // construct the solution of radius equal to the distance between the +
39 // chosen center point and straight line Qualified1. +
40 //=========================================================================
42 GccAna_Circ2d3Tan (const GccEnt_QualifiedLin& Qualified1,
43 const GccEnt_QualifiedLin& Qualified2,
44 const GccEnt_QualifiedLin& Qualified3,
48 //=========================================================================
49 // Initialization of fields. +
50 //=========================================================================
73 gp_Dir2d dirx(1.0,0.0);
74 WellDone = Standard_False;
76 if (!(Qualified1.IsEnclosed() ||
77 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
78 !(Qualified2.IsEnclosed() ||
79 Qualified2.IsOutside() || Qualified2.IsUnqualified()) ||
80 !(Qualified3.IsEnclosed() ||
81 Qualified3.IsOutside() || Qualified3.IsUnqualified())) {
82 throw GccEnt_BadQualifier();
86 //=========================================================================
88 //=========================================================================
90 gp_Lin2d L1(Qualified1.Qualified());
91 gp_Lin2d L2(Qualified2.Qualified());
92 gp_Lin2d L3(Qualified3.Qualified());
93 gp_Pnt2d origin1(L1.Location());
94 gp_Dir2d dir1(L1.Direction());
95 gp_Dir2d normL1(-dir1.Y(),dir1.X());
96 gp_Pnt2d origin2(L2.Location());
97 gp_Dir2d dir2(L2.Direction());
98 gp_Dir2d normL2(-dir2.Y(),dir2.X());
99 gp_Pnt2d origin3(L3.Location());
100 gp_Dir2d dir3(L3.Direction());
101 gp_Dir2d normL3(-dir3.Y(),dir3.X());
102 Standard_Real xloc1 = origin1.X();
103 Standard_Real xloc2 = origin2.X();
104 Standard_Real xloc3 = origin3.X();
105 Standard_Real yloc1 = origin1.Y();
106 Standard_Real yloc2 = origin2.Y();
107 Standard_Real yloc3 = origin3.Y();
108 Standard_Real xdir1 = dir1.X();
109 Standard_Real xdir2 = dir2.X();
110 Standard_Real xdir3 = dir3.X();
111 Standard_Real ydir1 = dir1.Y();
112 Standard_Real ydir2 = dir2.Y();
113 Standard_Real ydir3 = dir3.Y();
114 GccAna_Lin2dBisec Bisec1(L1,L2);
115 GccAna_Lin2dBisec Bisec2(L1,L3);
116 Standard_Integer ncote1=0;
117 Standard_Integer ncote2=0;
118 Standard_Integer ncote3=0;
119 TColStd_Array1OfReal cote1(1,2);
120 TColStd_Array1OfReal cote2(1,2);
121 TColStd_Array1OfReal cote3(1,2);
122 Standard_Integer nbsol = 0;
123 if (Bisec1.IsDone() && Bisec2.IsDone()) {
124 for (Standard_Integer i = 1 ; i <= Bisec1.NbSolutions() ; i++) {
125 for (Standard_Integer j = 1 ; j <= Bisec2.NbSolutions() ; j++) {
126 IntAna2d_AnaIntersection Intp(Bisec1.ThisSolution(i),
127 Bisec2.ThisSolution(j));
129 if (!Intp.IsEmpty()) {
130 for (Standard_Integer k = 1 ; k <= Intp.NbPoints() ; k++) {
132 Standard_Real Radius = (L1.Distance(Intp.Point(k).Value())+
133 L2.Distance(Intp.Point(k).Value())+
134 L3.Distance(Intp.Point(k).Value()))/3.0;
135 gp_Pnt2d Center(Intp.Point(k).Value());
136 Standard_Real cx = Center.X();
137 Standard_Real cy = Center.Y();
138 cirsol(nbsol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
139 // ======================================================
140 gp_Dir2d dc1(origin1.XY()-Center.XY());
141 if (!Qualified1.IsUnqualified()) {
142 qualifier1(nbsol) = Qualified1.Qualifier();
144 else if (dc1.Dot(normL1) > 0.0) {
145 qualifier1(nbsol) = GccEnt_outside;
147 else { qualifier1(nbsol) = GccEnt_enclosed; }
148 gp_Dir2d dc2(origin2.XY()-Center.XY());
149 if (!Qualified2.IsUnqualified()) {
150 qualifier2(nbsol) = Qualified2.Qualifier();
152 else if (dc2.Dot(normL2) > 0.0) {
153 qualifier2(nbsol) = GccEnt_outside;
155 else { qualifier2(nbsol) = GccEnt_enclosed; }
156 gp_Dir2d dc3(origin3.XY()-Center.XY());
157 if (!Qualified3.IsUnqualified()) {
158 qualifier3(nbsol) = Qualified3.Qualifier();
160 else if (dc3.Dot(normL3) > 0.0) {
161 qualifier3(nbsol) = GccEnt_outside;
163 else { qualifier3(nbsol) = GccEnt_enclosed; }
165 Standard_Real cross1=gp_Dir2d(-ydir1,xdir1)
166 .Dot(gp_Dir2d(xloc1-cx,yloc1-cy));
167 Standard_Real cross2=gp_Dir2d(-ydir2,xdir2)
168 .Dot(gp_Dir2d(xloc2-cx,yloc2-cy));
169 Standard_Real cross3=gp_Dir2d(-ydir3,xdir3)
170 .Dot(gp_Dir2d(xloc3-cx,yloc3-cy));
172 cross1 = cross1/Abs(cross1);
174 pnttg1sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
175 cross1*Radius*gp_XY(-ydir1,xdir1));
177 cross2 = cross2/Abs(cross2);
179 pnttg2sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
180 cross2*Radius*gp_XY(-ydir2,xdir2));
182 cross3 = cross3/Abs(cross3);
184 pnttg3sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
185 cross3*Radius*gp_XY(-ydir3,xdir3));
186 par1sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
188 pararg1(nbsol)=ElCLib::Parameter(L1,pnttg1sol(nbsol));
189 par2sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
191 pararg2(nbsol)=ElCLib::Parameter(L2,pnttg2sol(nbsol));
192 par3sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
194 pararg3(nbsol)=ElCLib::Parameter(L3,pnttg3sol(nbsol));
197 WellDone = Standard_True;
202 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() &&
203 // =========================================================
204 Qualified3.IsEnclosed()) {
205 // ========================
213 else if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() &&
214 // ==============================================================
215 Qualified3.IsOutside()) {
216 // =======================
224 else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() &&
225 // =============================================================
226 Qualified3.IsEnclosed()) {
227 // ========================
235 else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() &&
236 // =============================================================
237 Qualified3.IsOutside()) {
238 // =======================
246 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() &&
247 // =============================================================
248 Qualified3.IsEnclosed()) {
249 // ========================
257 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() &&
258 // =============================================================
259 Qualified3.IsOutside()) {
260 // =======================
268 else if (Qualified1.IsOutside() && Qualified2.IsOutside() &&
269 // ============================================================
270 Qualified3.IsEnclosed()) {
271 // ========================
279 else if (Qualified1.IsOutside() && Qualified2.IsOutside() &&
280 // ============================================================
281 Qualified3.IsOutside()) {
282 // =======================
291 if (Qualified1.IsUnqualified()) {
292 // ====================================
296 if (Qualified2.IsUnqualified()) {
297 // ===============================
301 if (Qualified3.IsUnqualified()) {
302 // ===============================
307 WellDone = Standard_True;
309 else if (Qualified3.IsEnclosed()) {
310 // ===============================
314 else if (Qualified3.IsOutside()) {
315 // ================================
320 else if (Qualified2.IsEnclosed()) {
321 // =================================
324 if (Qualified3.IsUnqualified()) {
325 // ===============================
330 else if (Qualified3.IsEnclosed()) {
331 // =================================
335 else if (Qualified3.IsOutside()) {
336 // ================================
341 else if (Qualified2.IsOutside()) {
342 // ================================
345 if (Qualified3.IsUnqualified()) {
346 // ===============================
351 else if (Qualified3.IsEnclosed()) {
352 // =================================
356 else if (Qualified3.IsOutside()) {
357 // ================================
363 else if (Qualified2.IsUnqualified()) {
364 // ===================================
368 if (Qualified1.IsEnclosed()) {
369 // ============================
372 if (Qualified3.IsUnqualified()) {
373 // ===============================
378 else if (Qualified3.IsEnclosed()) {
379 // =================================
383 else if (Qualified3.IsOutside()) {
384 // ================================
389 else if (Qualified1.IsOutside()) {
390 // ================================
393 if (Qualified3.IsUnqualified()) {
394 // ===============================
399 else if (Qualified3.IsEnclosed()) {
400 // =================================
404 else if (Qualified3.IsOutside()) {
405 // ================================
411 else if (Qualified3.IsUnqualified()) {
412 // ===================================
416 if (Qualified1.IsEnclosed()) {
417 // ============================
420 if (Qualified2.IsEnclosed()) {
421 // ============================
425 else if (Qualified2.IsOutside()) {
426 // ===============================
431 else if (Qualified1.IsOutside()) {
432 // ================================
435 if (Qualified2.IsEnclosed()) {
436 // ============================
440 else if (Qualified2.IsOutside()) {
441 // ===============================
448 if (NbrSol > 0) { return; }
449 for (Standard_Integer i = 1 ; i <= nbsol ; i++) {
450 for (Standard_Integer j1 = 1 ; j1 <= ncote1 ; j1++) {
451 for (Standard_Integer j2 = 1 ; j2 <= ncote2 ; j2++) {
452 for (Standard_Integer j3 = 1 ; j3 <= ncote3 ; j3++) {
453 if ((cote2(j2)*((cirsol(i).Location().X()-origin2.X())*
454 (-dir2.Y())+(cirsol(i).Location().Y()-
455 origin2.Y())*(dir2.X())) > 0.0) &&
456 (cote3(j3)*((cirsol(i).Location().X()-origin3.X())*
457 (-dir3.Y())+(cirsol(i).Location().Y()-
458 origin3.Y())*(dir3.X())) > 0.0) &&
459 (cote1(j1)*((cirsol(i).Location().X()-origin1.X())*
460 (-dir1.Y())+(cirsol(i).Location().Y()-
461 origin1.Y())*(dir1.X())) > 0.0)) {
463 cirsol(NbrSol) = gp_Circ2d(cirsol(i));
464 // =====================================
465 Standard_Real Radius = cirsol(NbrSol).Radius();
466 gp_Pnt2d Center(cirsol(NbrSol).Location());
467 gp_Dir2d dc(origin1.XY()-Center.XY());
468 Standard_Real sign = dc.Dot(gp_Dir2d(-dir1.Y(),dir1.X()));
469 dc = gp_Dir2d(sign*gp_XY(-dir1.Y(),dir1.X()));
470 pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
471 dc = gp_Dir2d(origin2.XY()-Center.XY());
472 sign = dc.Dot(gp_Dir2d(-dir2.Y(),dir2.X()));
473 dc = gp_Dir2d(sign*gp_XY(-dir2.Y(),dir2.X()));
474 pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
475 dc = gp_Dir2d(origin3.XY()-Center.XY());
476 sign = dc.Dot(gp_Dir2d(-dir3.Y(),dir3.X()));
477 dc = gp_Dir2d(sign*gp_XY(-dir3.Y(),dir3.X()));
478 pnttg3sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
479 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
481 pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
482 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
484 pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
485 par3sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
487 pararg3(NbrSol)=ElCLib::Parameter(L3,pnttg3sol(NbrSol));