0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / GccAna / GccAna_Circ2d3Tan_3.cxx
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 #include <ElCLib.hxx>
16 #include <GccAna_Circ2d3Tan.jxx>
17 #include <IntAna2d_AnaIntersection.hxx>
18 #include <IntAna2d_IntPoint.hxx>
19 #include <gp_Lin2d.hxx>
20 #include <gp_Circ2d.hxx>
21 #include <gp_Dir2d.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <GccAna_Lin2dBisec.hxx>
24 #include <GccEnt_BadQualifier.hxx>
25
26 //=========================================================================
27 //   Creation of a circle tangent to three straight lines.                +
28 //   Create Bissectrices at Qualified1 and Qualified2 and                 +
29 //          Bissectrices at Qualified1 and Qualified3.                    +
30 //   Intersect bissectrices calculated in this way ==> Center points      +
31 //   Choose the center point that corresponds to qualifiers and           +
32 //   construct the solution of radius equal to the distance between the   +
33 //   chosen center point and straight line Qualified1.                               +
34 //=========================================================================
35
36 GccAna_Circ2d3Tan::
37    GccAna_Circ2d3Tan (const GccEnt_QualifiedLin& Qualified1,
38                       const GccEnt_QualifiedLin& Qualified2,
39                       const GccEnt_QualifiedLin& Qualified3,
40                       const Standard_Real
41                      ):
42
43 //=========================================================================
44 //   Initialization of fields.                                           +
45 //=========================================================================
46
47    cirsol(1,4)     ,
48    qualifier1(1,4) ,
49    qualifier2(1,4) ,
50    qualifier3(1,4) ,
51    TheSame1(1,4)   ,
52    TheSame2(1,4)   ,
53    TheSame3(1,4)   ,
54    pnttg1sol(1,4)  ,
55    pnttg2sol(1,4)  ,
56    pnttg3sol(1,4)  ,
57    par1sol(1,4)    ,
58    par2sol(1,4)    ,
59    par3sol(1,4)    ,
60    pararg1(1,4)    ,
61    pararg2(1,4)    ,
62    pararg3(1,4)    
63 {
64
65    TheSame1.Init(0);
66    TheSame2.Init(0);
67    TheSame3.Init(0);
68    gp_Dir2d dirx(1.0,0.0);
69    WellDone = Standard_False;
70    NbrSol = 0;
71    if (!(Qualified1.IsEnclosed() ||
72          Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
73        !(Qualified2.IsEnclosed() ||
74          Qualified2.IsOutside() || Qualified2.IsUnqualified()) ||
75        !(Qualified3.IsEnclosed() ||
76          Qualified3.IsOutside() || Qualified3.IsUnqualified())) {
77      GccEnt_BadQualifier::Raise();
78      return;
79    }
80
81 //=========================================================================
82 //   Processing.                                                          +
83 //=========================================================================
84
85    gp_Lin2d L1(Qualified1.Qualified());
86    gp_Lin2d L2(Qualified2.Qualified());
87    gp_Lin2d L3(Qualified3.Qualified());
88    gp_Pnt2d origin1(L1.Location());
89    gp_Dir2d dir1(L1.Direction());
90    gp_Dir2d normL1(-dir1.Y(),dir1.X());
91    gp_Pnt2d origin2(L2.Location());
92    gp_Dir2d dir2(L2.Direction());
93    gp_Dir2d normL2(-dir2.Y(),dir2.X());
94    gp_Pnt2d origin3(L3.Location());
95    gp_Dir2d dir3(L3.Direction());
96    gp_Dir2d normL3(-dir3.Y(),dir3.X());
97    Standard_Real xloc1 = origin1.X();
98    Standard_Real xloc2 = origin2.X();
99    Standard_Real xloc3 = origin3.X();
100    Standard_Real yloc1 = origin1.Y();
101    Standard_Real yloc2 = origin2.Y();
102    Standard_Real yloc3 = origin3.Y();
103    Standard_Real xdir1 = dir1.X();
104    Standard_Real xdir2 = dir2.X();
105    Standard_Real xdir3 = dir3.X();
106    Standard_Real ydir1 = dir1.Y();
107    Standard_Real ydir2 = dir2.Y();
108    Standard_Real ydir3 = dir3.Y();
109    GccAna_Lin2dBisec Bisec1(L1,L2);
110    GccAna_Lin2dBisec Bisec2(L1,L3);
111    Standard_Integer ncote1=0;
112    Standard_Integer ncote2=0;
113    Standard_Integer ncote3=0;
114    TColStd_Array1OfReal cote1(1,2);
115    TColStd_Array1OfReal cote2(1,2);
116    TColStd_Array1OfReal cote3(1,2);
117    Standard_Integer nbsol = 0;
118    if (Bisec1.IsDone() && Bisec2.IsDone()) {
119      for (Standard_Integer i = 1 ; i <= Bisec1.NbSolutions() ; i++) {
120        for (Standard_Integer j = 1 ; j <= Bisec2.NbSolutions() ; j++) {
121          IntAna2d_AnaIntersection Intp(Bisec1.ThisSolution(i),
122                                        Bisec2.ThisSolution(j));
123          if (Intp.IsDone()) {
124            if (!Intp.IsEmpty()) {
125              for (Standard_Integer k = 1 ; k <= Intp.NbPoints() ; k++) {
126                nbsol++;
127                Standard_Real Radius = (L1.Distance(Intp.Point(k).Value())+
128                               L2.Distance(Intp.Point(k).Value())+
129                               L3.Distance(Intp.Point(k).Value()))/3.0;
130                gp_Pnt2d Center(Intp.Point(k).Value());
131                Standard_Real cx = Center.X();
132                Standard_Real cy = Center.Y();
133                cirsol(nbsol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
134 //             ======================================================
135                gp_Dir2d dc1(origin1.XY()-Center.XY());
136                if (!Qualified1.IsUnqualified()) { 
137                  qualifier1(nbsol) = Qualified1.Qualifier();
138                }
139                else if (dc1.Dot(normL1) > 0.0) {
140                  qualifier1(nbsol) = GccEnt_outside;
141                }
142                else { qualifier1(nbsol) = GccEnt_enclosed; }
143                gp_Dir2d dc2(origin2.XY()-Center.XY());
144                if (!Qualified2.IsUnqualified()) { 
145                  qualifier2(nbsol) = Qualified2.Qualifier();
146                }
147                else if (dc2.Dot(normL2) > 0.0) {
148                  qualifier2(nbsol) = GccEnt_outside;
149                }
150                else { qualifier2(nbsol) = GccEnt_enclosed; }
151                gp_Dir2d dc3(origin3.XY()-Center.XY());
152                if (!Qualified3.IsUnqualified()) { 
153                  qualifier3(nbsol) = Qualified3.Qualifier();
154                }
155                else if (dc3.Dot(normL3) > 0.0) {
156                  qualifier3(nbsol) = GccEnt_outside;
157                }
158                else { qualifier3(nbsol) = GccEnt_enclosed; }
159                
160                Standard_Real cross1=gp_Dir2d(-ydir1,xdir1)
161                                    .Dot(gp_Dir2d(xloc1-cx,yloc1-cy));
162                Standard_Real cross2=gp_Dir2d(-ydir2,xdir2)
163                                    .Dot(gp_Dir2d(xloc2-cx,yloc2-cy));
164                Standard_Real cross3=gp_Dir2d(-ydir3,xdir3)
165                                    .Dot(gp_Dir2d(xloc3-cx,yloc3-cy));
166                if (cross1 != 0.0) {
167                  cross1 = cross1/Abs(cross1);
168                }
169                pnttg1sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
170                                            cross1*Radius*gp_XY(-ydir1,xdir1));
171                if (cross2 != 0.0) {
172                  cross2 = cross2/Abs(cross2);
173                }
174                pnttg2sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
175                                            cross2*Radius*gp_XY(-ydir2,xdir2));
176                if (cross3 != 0.0) {
177                  cross3 = cross3/Abs(cross3);
178                }
179                pnttg3sol(nbsol) = gp_Pnt2d(gp_XY(cx,cy)+
180                                            cross3*Radius*gp_XY(-ydir3,xdir3));
181                par1sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
182                                                 pnttg1sol(nbsol));
183                pararg1(nbsol)=ElCLib::Parameter(L1,pnttg1sol(nbsol));
184                par2sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
185                                                 pnttg2sol(nbsol));
186                pararg2(nbsol)=ElCLib::Parameter(L2,pnttg2sol(nbsol));
187                par3sol(nbsol)=ElCLib::Parameter(cirsol(nbsol),
188                                                 pnttg3sol(nbsol));
189                pararg3(nbsol)=ElCLib::Parameter(L3,pnttg3sol(nbsol));
190              }
191            }
192            WellDone = Standard_True;
193          }
194        }
195      }
196    }
197    if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() && 
198 //  =========================================================
199        Qualified3.IsEnclosed()) {
200 //     ========================
201      ncote1 = 1;
202      ncote2 = 1;
203      ncote3 = 1;
204      cote1(1) = 1.0;
205      cote2(1) = 1.0;
206      cote3(1) = 1.0;
207    }
208    else if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed() && 
209 // ==============================================================
210             Qualified3.IsOutside()) {
211 //          =======================
212      ncote1 = 1;
213      ncote2 = 1;
214      ncote3 = 1;
215      cote1(1) = 1.0;
216      cote2(1) = 1.0;
217      cote3(1) = -1.0;
218    }
219    else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() && 
220 // =============================================================
221             Qualified3.IsEnclosed()) {
222 //          ========================
223      ncote1 = 1;
224      ncote2 = 1;
225      ncote3 = 1;
226      cote1(1) = 1.0;
227      cote2(1) = -1.0;
228      cote3(1) = 1.0;
229    }
230    else if (Qualified1.IsEnclosed() && Qualified2.IsOutside() && 
231 // =============================================================
232             Qualified3.IsOutside()) {
233 //          =======================
234      ncote1 = 1;
235      ncote2 = 1;
236      ncote3 = 1;
237      cote1(1) = 1.0;
238      cote2(1) = -1.0;
239      cote3(1) = -1.0;
240    }
241    else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() && 
242 // =============================================================
243             Qualified3.IsEnclosed()) {
244 //          ========================
245      ncote1 = 1;
246      ncote2 = 1;
247      ncote3 = 1;
248      cote1(1) = -1.0;
249      cote2(1) = 1.0;
250      cote3(1) = 1.0;
251    }
252    else if (Qualified1.IsOutside() && Qualified2.IsEnclosed() && 
253 // =============================================================
254             Qualified3.IsOutside()) {
255 //          =======================
256      ncote1 = 1;
257      ncote2 = 1;
258      ncote3 = 1;
259      cote1(1) = -1.0;
260      cote2(1) = 1.0;
261      cote3(1) = -1.0;
262    }
263    else if (Qualified1.IsOutside() && Qualified2.IsOutside() && 
264 // ============================================================
265             Qualified3.IsEnclosed()) {
266 //          ========================
267      ncote1 = 1;
268      ncote2 = 1;
269      ncote3 = 1;
270      cote1(1) = -1.0;
271      cote2(1) = -1.0;
272      cote3(1) = 1.0;
273    }
274    else if (Qualified1.IsOutside() && Qualified2.IsOutside() && 
275 // ============================================================
276             Qualified3.IsOutside()) {
277 //          =======================
278      ncote1 = 1;
279      ncote2 = 1;
280      ncote3 = 1;
281      cote1(1) = -1.0;
282      cote2(1) = -1.0;
283      cote3(1) = -1.0;
284    }
285    else {
286      if (Qualified1.IsUnqualified()) {
287 //   ====================================
288        ncote1 = 2;
289        cote1(1) = 1.0;
290        cote1(2) = -1.0;
291        if (Qualified2.IsUnqualified()) {
292 //     ===============================
293          ncote2 = 2;
294          cote2(1) = 1.0;
295          cote2(2) = -1.0;
296          if (Qualified3.IsUnqualified()) {
297 //       ===============================
298            ncote3 = 2;
299            cote2(1) = 1.0;
300            cote2(2) = -1.0;
301            NbrSol = nbsol;
302            WellDone = Standard_True;
303          }
304          else if (Qualified3.IsEnclosed()) {
305 //       ===============================
306            ncote3 = 1;
307            cote3(1) = 1.0;
308          }
309          else if (Qualified3.IsOutside()) {
310 //       ================================
311            ncote3 = 1;
312            cote3(1) = -1.0;
313          }
314        }
315        else if (Qualified2.IsEnclosed()) {
316 //     =================================
317          ncote2 = 1;
318          cote2(1) = 1.0;
319          if (Qualified3.IsUnqualified()) {
320 //       ===============================
321            ncote3 = 2;
322            cote3(1) = 1.0;
323            cote3(1) = -1.0;
324          }
325          else if (Qualified3.IsEnclosed()) {
326 //       =================================
327            ncote3 = 1;
328            cote3(1) = 1.0;
329          }
330          else if (Qualified3.IsOutside()) {
331 //       ================================
332            ncote3 = 1;
333            cote3(1) = -1.0;
334          }
335        }
336        else if (Qualified2.IsOutside()) {
337 //     ================================
338          ncote2 = 1;
339          cote2(1) = -1.0;
340          if (Qualified3.IsUnqualified()) {
341 //       ===============================
342            ncote3 = 2;
343            cote3(1) = 1.0;
344            cote3(2) = -1.0;
345          }
346          else if (Qualified3.IsEnclosed()) {
347 //       =================================
348            ncote3 = 1;
349            cote3(1) = 1.0;
350          }
351          else if (Qualified3.IsOutside()) {
352 //       ================================
353            ncote3 = 1;
354            cote3(1) = -1.0;
355          }
356        }
357      }
358      else if (Qualified2.IsUnqualified()) {
359 //   ===================================
360        ncote2 = 2;
361        cote2(1) = 1.0;
362        cote2(2) = -1.0;
363        if (Qualified1.IsEnclosed()) {
364 //     ============================
365          ncote1 = 1;
366          cote1(1) = 1.0;
367          if (Qualified3.IsUnqualified()) {
368 //       ===============================
369            ncote3 = 2;
370            cote3(1) = -1.0;
371            cote3(1) = -1.0;
372          }
373          else if (Qualified3.IsEnclosed()) {
374 //       =================================
375            ncote3 = 1;
376            cote3(1) = 1.0;
377          }
378          else if (Qualified3.IsOutside()) {
379 //       ================================
380            ncote3 = 1;
381            cote3(1) = -1.0;
382          }
383        }
384        else if (Qualified1.IsOutside()) {
385 //     ================================
386          ncote1 = 1;
387          cote1(1) = 1.0;
388          if (Qualified3.IsUnqualified()) {
389 //       ===============================
390            ncote3 = 2;
391            cote3(1) = 1.0;
392            cote3(2) = -1.0;
393          }
394          else if (Qualified3.IsEnclosed()) {
395 //       =================================
396            ncote3 = 1;
397            cote3(1) = 1.0;
398          }
399          else if (Qualified3.IsOutside()) {
400 //       ================================
401            ncote3 = 1;
402            cote3(1) = -1.0;
403          }
404        }
405      }
406      else if (Qualified3.IsUnqualified()) {
407 //   ===================================
408        ncote3 = 2;
409        cote3(1) = 1.0;
410        cote3(2) = -1.0;
411        if (Qualified1.IsEnclosed()) {
412 //     ============================
413          ncote1 = 1;
414          cote1(1) = 1.0;
415          if (Qualified2.IsEnclosed()) {
416 //       ============================
417            ncote2 = 1;
418            cote2(1) = 1.0;
419          }
420          else if (Qualified2.IsOutside()) {
421 //       ===============================
422            ncote2 = 1;
423            cote2(1) = -1.0;
424          }
425        }
426        else if (Qualified1.IsOutside()) {
427 //     ================================
428          ncote1 = 1;
429          cote1(1) = -1.0;
430          if (Qualified2.IsEnclosed()) {
431 //       ============================
432            ncote2 = 1;
433            cote2(1) = 1.0;
434          }
435          else if (Qualified2.IsOutside()) {
436 //       ===============================
437            ncote2 = 1;
438            cote2(1) = -1.0;
439          }
440        }
441      }
442    }
443    if (NbrSol > 0) { return; }
444    for (Standard_Integer i = 1 ; i <= nbsol ; i++) {
445      for (Standard_Integer j1 = 1 ; j1 <= ncote1 ; j1++) {
446        for (Standard_Integer j2 = 1 ; j2 <= ncote2 ; j2++) {
447          for (Standard_Integer j3 = 1 ; j3 <= ncote3 ; j3++) {
448            if ((cote2(j2)*((cirsol(i).Location().X()-origin2.X())*
449                (-dir2.Y())+(cirsol(i).Location().Y()-
450                origin2.Y())*(dir2.X())) > 0.0) &&
451                (cote3(j3)*((cirsol(i).Location().X()-origin3.X())*
452                (-dir3.Y())+(cirsol(i).Location().Y()-
453                origin3.Y())*(dir3.X())) > 0.0) &&
454                (cote1(j1)*((cirsol(i).Location().X()-origin1.X())*
455                (-dir1.Y())+(cirsol(i).Location().Y()-
456                origin1.Y())*(dir1.X())) > 0.0)) {
457              NbrSol++;
458              cirsol(NbrSol) = gp_Circ2d(cirsol(i));
459 //           =====================================
460              Standard_Real Radius = cirsol(NbrSol).Radius();
461              gp_Pnt2d Center(cirsol(NbrSol).Location());
462              gp_Dir2d dc(origin1.XY()-Center.XY());
463              Standard_Real sign = dc.Dot(gp_Dir2d(-dir1.Y(),dir1.X()));
464              dc = gp_Dir2d(sign*gp_XY(-dir1.Y(),dir1.X()));
465              pnttg1sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
466              dc = gp_Dir2d(origin2.XY()-Center.XY());
467              sign = dc.Dot(gp_Dir2d(-dir2.Y(),dir2.X()));
468              dc = gp_Dir2d(sign*gp_XY(-dir2.Y(),dir2.X()));
469              pnttg2sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
470              dc = gp_Dir2d(origin3.XY()-Center.XY());
471              sign = dc.Dot(gp_Dir2d(-dir3.Y(),dir3.X()));
472              dc = gp_Dir2d(sign*gp_XY(-dir3.Y(),dir3.X()));
473              pnttg3sol(NbrSol) = gp_Pnt2d(Center.XY()+Radius*dc.XY());
474              par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
475                                               pnttg1sol(NbrSol));
476              pararg1(NbrSol)=ElCLib::Parameter(L1,pnttg1sol(NbrSol));
477              par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
478                                               pnttg2sol(NbrSol));
479              pararg2(NbrSol)=ElCLib::Parameter(L2,pnttg2sol(NbrSol));
480              par3sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
481                                               pnttg3sol(NbrSol));
482              pararg3(NbrSol)=ElCLib::Parameter(L3,pnttg3sol(NbrSol));
483            }
484          }
485        }
486      }
487    }
488  }