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_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>
31 
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 //=========================================================================
41 GccAna_Circ2d3Tan::
GccAna_Circ2d3Tan(const GccEnt_QualifiedLin & Qualified1,const GccEnt_QualifiedLin & Qualified2,const GccEnt_QualifiedLin & Qualified3,const Standard_Real)42    GccAna_Circ2d3Tan (const GccEnt_QualifiedLin& Qualified1,
43                       const GccEnt_QualifiedLin& Qualified2,
44                       const GccEnt_QualifiedLin& Qualified3,
45                       const Standard_Real
46                      ):
47 
48 //=========================================================================
49 //   Initialization of fields.                                           +
50 //=========================================================================
51 
52    cirsol(1,4)     ,
53    qualifier1(1,4) ,
54    qualifier2(1,4) ,
55    qualifier3(1,4) ,
56    TheSame1(1,4)   ,
57    TheSame2(1,4)   ,
58    TheSame3(1,4)   ,
59    pnttg1sol(1,4)  ,
60    pnttg2sol(1,4)  ,
61    pnttg3sol(1,4)  ,
62    par1sol(1,4)    ,
63    par2sol(1,4)    ,
64    par3sol(1,4)    ,
65    pararg1(1,4)    ,
66    pararg2(1,4)    ,
67    pararg3(1,4)
68 {
69 
70    TheSame1.Init(0);
71    TheSame2.Init(0);
72    TheSame3.Init(0);
73    gp_Dir2d dirx(1.0,0.0);
74    WellDone = Standard_False;
75    NbrSol = 0;
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();
83      return;
84    }
85 
86 //=========================================================================
87 //   Processing.                                                          +
88 //=========================================================================
89 
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));
128 	 if (Intp.IsDone()) {
129 	   if (!Intp.IsEmpty()) {
130 	     for (Standard_Integer k = 1 ; k <= Intp.NbPoints() ; k++) {
131 	       nbsol++;
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();
143 	       }
144 	       else if (dc1.Dot(normL1) > 0.0) {
145 		 qualifier1(nbsol) = GccEnt_outside;
146 	       }
147 	       else { qualifier1(nbsol) = GccEnt_enclosed; }
148 	       gp_Dir2d dc2(origin2.XY()-Center.XY());
149 	       if (!Qualified2.IsUnqualified()) {
150 		 qualifier2(nbsol) = Qualified2.Qualifier();
151 	       }
152 	       else if (dc2.Dot(normL2) > 0.0) {
153 		 qualifier2(nbsol) = GccEnt_outside;
154 	       }
155 	       else { qualifier2(nbsol) = GccEnt_enclosed; }
156 	       gp_Dir2d dc3(origin3.XY()-Center.XY());
157 	       if (!Qualified3.IsUnqualified()) {
158 		 qualifier3(nbsol) = Qualified3.Qualifier();
159 	       }
160 	       else if (dc3.Dot(normL3) > 0.0) {
161 		 qualifier3(nbsol) = GccEnt_outside;
162 	       }
163 	       else { qualifier3(nbsol) = GccEnt_enclosed; }
164 
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));
171 	       if (cross1 != 0.0) {
172 		 cross1 = cross1/Abs(cross1);
173 	       }
174 	       pnttg1sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
175 					   cross1*Radius*gp_XY(-ydir1,xdir1));
176 	       if (cross2 != 0.0) {
177 		 cross2 = cross2/Abs(cross2);
178 	       }
179 	       pnttg2sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
180 					   cross2*Radius*gp_XY(-ydir2,xdir2));
181 	       if (cross3 != 0.0) {
182 		 cross3 = cross3/Abs(cross3);
183 	       }
184 	       pnttg3sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
185 					   cross3*Radius*gp_XY(-ydir3,xdir3));
186 	       par1sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
187 						pnttg1sol(nbsol));
188 	       pararg1(nbsol)=ElCLib::Parameter(L1,pnttg1sol(nbsol));
189 	       par2sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
190 						pnttg2sol(nbsol));
191 	       pararg2(nbsol)=ElCLib::Parameter(L2,pnttg2sol(nbsol));
192 	       par3sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
193 						pnttg3sol(nbsol));
194 	       pararg3(nbsol)=ElCLib::Parameter(L3,pnttg3sol(nbsol));
195 	     }
196 	   }
197 	   WellDone = Standard_True;
198 	 }
199        }
200      }
201    }
202    if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() &&
203 //  =========================================================
204        Qualified3.IsEnclosed()) {
205 //     ========================
206      ncote1 = 1;
207      ncote2 = 1;
208      ncote3 = 1;
209      cote1(1) = 1.0;
210      cote2(1) = 1.0;
211      cote3(1) = 1.0;
212    }
213    else if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() &&
214 // ==============================================================
215 	    Qualified3.IsOutside()) {
216 //          =======================
217      ncote1 = 1;
218      ncote2 = 1;
219      ncote3 = 1;
220      cote1(1) = 1.0;
221      cote2(1) = 1.0;
222      cote3(1) = -1.0;
223    }
224    else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() &&
225 // =============================================================
226 	    Qualified3.IsEnclosed()) {
227 //          ========================
228      ncote1 = 1;
229      ncote2 = 1;
230      ncote3 = 1;
231      cote1(1) = 1.0;
232      cote2(1) = -1.0;
233      cote3(1) = 1.0;
234    }
235    else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() &&
236 // =============================================================
237 	    Qualified3.IsOutside()) {
238 //          =======================
239      ncote1 = 1;
240      ncote2 = 1;
241      ncote3 = 1;
242      cote1(1) = 1.0;
243      cote2(1) = -1.0;
244      cote3(1) = -1.0;
245    }
246    else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() &&
247 // =============================================================
248 	    Qualified3.IsEnclosed()) {
249 //          ========================
250      ncote1 = 1;
251      ncote2 = 1;
252      ncote3 = 1;
253      cote1(1) = -1.0;
254      cote2(1) = 1.0;
255      cote3(1) = 1.0;
256    }
257    else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() &&
258 // =============================================================
259 	    Qualified3.IsOutside()) {
260 //          =======================
261      ncote1 = 1;
262      ncote2 = 1;
263      ncote3 = 1;
264      cote1(1) = -1.0;
265      cote2(1) = 1.0;
266      cote3(1) = -1.0;
267    }
268    else if (Qualified1.IsOutside() && Qualified2.IsOutside() &&
269 // ============================================================
270 	    Qualified3.IsEnclosed()) {
271 //          ========================
272      ncote1 = 1;
273      ncote2 = 1;
274      ncote3 = 1;
275      cote1(1) = -1.0;
276      cote2(1) = -1.0;
277      cote3(1) = 1.0;
278    }
279    else if (Qualified1.IsOutside() && Qualified2.IsOutside() &&
280 // ============================================================
281 	    Qualified3.IsOutside()) {
282 //          =======================
283      ncote1 = 1;
284      ncote2 = 1;
285      ncote3 = 1;
286      cote1(1) = -1.0;
287      cote2(1) = -1.0;
288      cote3(1) = -1.0;
289    }
290    else {
291      if (Qualified1.IsUnqualified()) {
292 //   ====================================
293        ncote1 = 2;
294        cote1(1) = 1.0;
295        cote1(2) = -1.0;
296        if (Qualified2.IsUnqualified()) {
297 //     ===============================
298 	 ncote2 = 2;
299 	 cote2(1) = 1.0;
300 	 cote2(2) = -1.0;
301 	 if (Qualified3.IsUnqualified()) {
302 //       ===============================
303 	   ncote3 = 2;
304 	   cote2(1) = 1.0;
305 	   cote2(2) = -1.0;
306            NbrSol = nbsol;
307            WellDone = Standard_True;
308 	 }
309 	 else if (Qualified3.IsEnclosed()) {
310 //       ===============================
311 	   ncote3 = 1;
312 	   cote3(1) = 1.0;
313 	 }
314 	 else if (Qualified3.IsOutside()) {
315 //       ================================
316 	   ncote3 = 1;
317 	   cote3(1) = -1.0;
318 	 }
319        }
320        else if (Qualified2.IsEnclosed()) {
321 //     =================================
322 	 ncote2 = 1;
323 	 cote2(1) = 1.0;
324 	 if (Qualified3.IsUnqualified()) {
325 //       ===============================
326 	   ncote3 = 2;
327 	   cote3(1) = 1.0;
328 	   cote3(1) = -1.0;
329 	 }
330 	 else if (Qualified3.IsEnclosed()) {
331 //       =================================
332 	   ncote3 = 1;
333 	   cote3(1) = 1.0;
334 	 }
335 	 else if (Qualified3.IsOutside()) {
336 //       ================================
337 	   ncote3 = 1;
338 	   cote3(1) = -1.0;
339 	 }
340        }
341        else if (Qualified2.IsOutside()) {
342 //     ================================
343 	 ncote2 = 1;
344 	 cote2(1) = -1.0;
345 	 if (Qualified3.IsUnqualified()) {
346 //       ===============================
347 	   ncote3 = 2;
348 	   cote3(1) = 1.0;
349 	   cote3(2) = -1.0;
350 	 }
351 	 else if (Qualified3.IsEnclosed()) {
352 //       =================================
353 	   ncote3 = 1;
354 	   cote3(1) = 1.0;
355 	 }
356 	 else if (Qualified3.IsOutside()) {
357 //       ================================
358 	   ncote3 = 1;
359 	   cote3(1) = -1.0;
360 	 }
361        }
362      }
363      else if (Qualified2.IsUnqualified()) {
364 //   ===================================
365        ncote2 = 2;
366        cote2(1) = 1.0;
367        cote2(2) = -1.0;
368        if (Qualified1.IsEnclosed()) {
369 //     ============================
370 	 ncote1 = 1;
371 	 cote1(1) = 1.0;
372 	 if (Qualified3.IsUnqualified()) {
373 //       ===============================
374 	   ncote3 = 2;
375 	   cote3(1) = -1.0;
376 	   cote3(1) = -1.0;
377 	 }
378 	 else if (Qualified3.IsEnclosed()) {
379 //       =================================
380 	   ncote3 = 1;
381 	   cote3(1) = 1.0;
382 	 }
383 	 else if (Qualified3.IsOutside()) {
384 //       ================================
385 	   ncote3 = 1;
386 	   cote3(1) = -1.0;
387 	 }
388        }
389        else if (Qualified1.IsOutside()) {
390 //     ================================
391 	 ncote1 = 1;
392 	 cote1(1) = 1.0;
393 	 if (Qualified3.IsUnqualified()) {
394 //       ===============================
395 	   ncote3 = 2;
396 	   cote3(1) = 1.0;
397 	   cote3(2) = -1.0;
398 	 }
399 	 else if (Qualified3.IsEnclosed()) {
400 //       =================================
401 	   ncote3 = 1;
402 	   cote3(1) = 1.0;
403 	 }
404 	 else if (Qualified3.IsOutside()) {
405 //       ================================
406 	   ncote3 = 1;
407 	   cote3(1) = -1.0;
408 	 }
409        }
410      }
411      else if (Qualified3.IsUnqualified()) {
412 //   ===================================
413        ncote3 = 2;
414        cote3(1) = 1.0;
415        cote3(2) = -1.0;
416        if (Qualified1.IsEnclosed()) {
417 //     ============================
418 	 ncote1 = 1;
419 	 cote1(1) = 1.0;
420 	 if (Qualified2.IsEnclosed()) {
421 //       ============================
422 	   ncote2 = 1;
423 	   cote2(1) = 1.0;
424 	 }
425 	 else if (Qualified2.IsOutside()) {
426 //       ===============================
427 	   ncote2 = 1;
428 	   cote2(1) = -1.0;
429 	 }
430        }
431        else if (Qualified1.IsOutside()) {
432 //     ================================
433 	 ncote1 = 1;
434 	 cote1(1) = -1.0;
435 	 if (Qualified2.IsEnclosed()) {
436 //       ============================
437 	   ncote2 = 1;
438 	   cote2(1) = 1.0;
439 	 }
440 	 else if (Qualified2.IsOutside()) {
441 //       ===============================
442 	   ncote2 = 1;
443 	   cote2(1) = -1.0;
444 	 }
445        }
446      }
447    }
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)) {
462 	     NbrSol++;
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),
480 					      pnttg1sol(NbrSol));
481 	     pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
482 	     par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
483 					      pnttg2sol(NbrSol));
484 	     pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
485 	     par3sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
486 					      pnttg3sol(NbrSol));
487 	     pararg3(NbrSol)=ElCLib::Parameter(L3,pnttg3sol(NbrSol));
488 	   }
489 	 }
490        }
491      }
492    }
493  }
494