0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / GccAna / GccAna_Circ2dBisec.cxx
1 // Created on: 1991-10-07
2 // Created by: Remi GILET
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //=========================================================================
18 //   CREATION of the BISSECTICE between two CIRCLES.                        +
19 //=========================================================================
20
21 #include <GccAna_Circ2dBisec.hxx>
22 #include <GccEnt_BadQualifier.hxx>
23 #include <GccInt_BCirc.hxx>
24 #include <GccInt_BElips.hxx>
25 #include <GccInt_BHyper.hxx>
26 #include <GccInt_Bisec.hxx>
27 #include <GccInt_BLine.hxx>
28 #include <GccInt_BParab.hxx>
29 #include <gp.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <gp_Dir2d.hxx>
32 #include <gp_Hypr2d.hxx>
33 #include <gp_Vec2d.hxx>
34 #include <gp_XY.hxx>
35 #include <IntAna2d_AnaIntersection.hxx>
36 #include <Precision.hxx>
37 #include <Standard_ConstructionError.hxx>
38 #include <Standard_OutOfRange.hxx>
39 #include <StdFail_NotDone.hxx>
40
41 //=========================================================================
42 GccAna_Circ2dBisec::
43    GccAna_Circ2dBisec (const gp_Circ2d& Circ1    ,
44                        const gp_Circ2d& Circ2    ) {
45
46 //=========================================================================
47 //  Initialization of fields :                                            +
48 //            - circle1  (Circle : first argument.)                       +
49 //            - circle2  (Line   : second argument.)                      +
50 //            - intersection (Integer showing the smallest position       +
51 //                            of two circles correspondingly to each other.) +
52 //            - sameradius   (Booleen showing if the two circles have   +
53 //                            the same radius or not.)                         +
54 //            - NbrSol   (Integer showing the number of solutions.)       +
55 //            - WellDone (Boolean showing succes or failure of the algo.). +
56 //=========================================================================
57
58    WellDone = Standard_False;
59    Standard_Real Tol=Precision::Confusion();
60
61    Standard_Real R1 = Circ1.Radius();
62    Standard_Real R2 = Circ2.Radius();
63    if (Abs(R1-R2) <= Tol) { sameradius = Standard_True; }
64    else { sameradius = Standard_False; }
65    if (R1 < R2) {
66      circle1 = gp_Circ2d(Circ2);
67      circle2 = gp_Circ2d(Circ1);
68      R1 = circle1.Radius();
69      R2 = circle2.Radius();
70    }
71    else {
72      circle1 = gp_Circ2d(Circ1);
73      circle2 = gp_Circ2d(Circ2);
74    }
75    Standard_Real dist = circle2.Location().Distance(circle1.Location());
76    if (R1-dist-R2 > Tol) {
77      intersection = 0;
78      NbrSol = 2;
79      WellDone = Standard_True;
80    }
81    else if (Abs(R1-dist-R2) <= Tol) {
82      intersection = 1;
83      if (sameradius) {
84        NbrSol = 0;
85        WellDone = Standard_True;
86      }
87      else {
88        NbrSol = 2;
89        WellDone = Standard_True;
90      }
91    }
92    else if ((dist+R2-R1 > Tol) && (R1-dist+R2 > Tol)) {
93      intersection = 2;
94      if (sameradius) {
95        NbrSol = 2;
96        WellDone = Standard_True;
97      }
98      else {
99        NbrSol = 3;
100        WellDone = Standard_True;
101      }
102    }
103    else if (Abs(R1-dist+R2) <= Tol) {
104      intersection = 3;
105      if (sameradius) {
106        NbrSol = 2;
107        WellDone = Standard_True;
108      }
109      else {
110        NbrSol = 3;
111        WellDone = Standard_True;
112      }
113    }
114    else {
115      intersection = 4;
116      if (sameradius) {
117        NbrSol = 3;
118        WellDone = Standard_True;
119      }
120      else {
121        NbrSol = 4;
122        WellDone = Standard_True;
123      }
124    }
125  }
126
127 //=========================================================================
128 //  Processing.                                                           +
129 //  Return the coordinates of centers of circles circle1 and circle2      +
130 //  (xcencir1, ycencir1, xcencir2, ycencir2).                             +
131 //  Also return the radiuses of two circles R1 and R2.                    +
132 //=========================================================================
133
134 Handle(GccInt_Bisec) GccAna_Circ2dBisec::
135    ThisSolution (const Standard_Integer Index) const {
136
137    Standard_Real Tol = 1.e-14;
138    Handle(GccInt_Bisec) bissol;
139
140    if (!WellDone) { throw StdFail_NotDone(); }
141    else if (Index <= 0 || Index > NbrSol) { throw Standard_OutOfRange(); }
142    else {
143      Standard_Real xcencir1 = circle1.Location().X();
144      Standard_Real ycencir1 = circle1.Location().Y();
145      Standard_Real xcencir2 = circle2.Location().X();
146      Standard_Real ycencir2 = circle2.Location().Y();
147      Standard_Real dist     = circle1.Location().Distance(circle2.Location());
148
149      gp_Pnt2d pcen((xcencir1+xcencir2)/2.0,(ycencir1+ycencir2)/2.0);
150      gp_Dir2d dircen,medcen;
151      if (dist > Tol) {
152        dircen.SetCoord(xcencir2-xcencir1,ycencir2-ycencir1);
153        medcen.SetCoord(ycencir2-ycencir1,xcencir1-xcencir2);
154      }
155      gp_Dir2d dirx(1.0,0.0);
156      gp_Ax2d  acenx(pcen,dirx);
157      gp_Ax2d  acencen(pcen,dircen);
158      
159      Standard_Real R1 = circle1.Radius();
160      Standard_Real R2 = circle2.Radius();
161
162      if ((NbrSol == 1) && (intersection == 0)) {
163        Standard_Real R;
164        if (Index == 1) 
165          R = (R1+R2)/2.0;
166        else 
167          R = (R1-R2)/2.0;
168        gp_Circ2d C(acenx,R);
169        bissol = new GccInt_BCirc(C);
170 //     =============================
171      }
172      else if ((NbrSol == 2) && (intersection == 1)) {
173        if (Index == 1) {
174          gp_Elips2d E(acencen,
175                       (R1+R2)/2.0,Sqrt((R1*R1+R2*R2-dist*dist)/4.+R1*R2/2.));
176          bissol = new GccInt_BElips(E);
177 //       =============================
178        }
179        else if (Index == 2) {
180          gp_Lin2d L(circle1.Location(),
181                     dircen);
182          bissol = new GccInt_BLine(L);
183 //       =============================
184        }
185      }
186      else if ((NbrSol == 2) && (intersection == 0)) {
187        if (Index == 1) {
188          if (Abs(xcencir2-xcencir1)<Tol && Abs(ycencir2-ycencir1)< Tol) {
189            gp_Circ2d C(acenx,(R1+R2)/2.0);
190            bissol = new GccInt_BCirc(C);
191 //         =============================
192          }
193          else {
194            gp_Elips2d E(acencen,
195                         (R1+R2)/2.0,Sqrt((R1*R1+R2*R2-dist*dist)/4.+R1*R2/2.));
196            bissol = new GccInt_BElips(E);
197 //         ==============================
198          }
199        }
200        else if (Index == 2) {
201          if (Abs(xcencir2-xcencir1)< Tol && Abs(ycencir2-ycencir1)< Tol) {
202            gp_Circ2d C(acencen,(R1-R2)/2.);
203            bissol = new GccInt_BCirc(C);
204 //         =============================
205          }
206          else {
207            gp_Elips2d E(acencen,
208                         (R1-R2)/2.0,Sqrt((R1*R1+R2*R2-dist*dist)/4.-R1*R2/2.));
209            bissol = new GccInt_BElips(E);
210 //         ==============================
211          }
212        }
213      }
214      else if (intersection == 2) {
215        if (sameradius) {
216          if (Index == 1) {
217            gp_Lin2d L(pcen,medcen);
218            bissol = new GccInt_BLine(L);
219 //         =============================
220          }
221          else if (Index == 2) {
222            gp_Elips2d E(acencen,
223                         R1,Sqrt(R1*R1-dist*dist/4.0));
224            bissol = new GccInt_BElips(E);
225 //         ==============================
226          }
227        }
228        else {
229          if (Index == 1) {
230            gp_Hypr2d H1;
231            H1 = gp_Hypr2d(acencen,
232                           (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
233            bissol = new GccInt_BHyper(H1);
234 //         ===============================
235          }
236          else if (Index == 2) {
237            gp_Hypr2d H1(acencen,
238                         (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
239            bissol = new GccInt_BHyper(H1.OtherBranch());
240 //         ===============================
241          }
242          else if (Index == 3) {
243            gp_Elips2d E(acencen,
244                         (R1+R2)/2.0,Sqrt((R1*R1+R2*R2-dist*dist)/4.+R1*R2/2.));
245            bissol = new GccInt_BElips(E);
246 //         ==============================
247          }
248        }
249      }
250      else if (intersection == 3) {
251        if (sameradius) {
252          if (Index == 1) {
253            gp_Lin2d L(pcen, dircen);
254            bissol = new GccInt_BLine(L);
255 //         =============================
256          }
257          else if (Index == 2) {
258            gp_Lin2d L(pcen, medcen);
259            bissol = new GccInt_BLine(L);
260 //         =============================
261          }
262        }
263        else {
264          if (Index == 1) {
265            gp_Lin2d L(pcen, dircen);
266            bissol = new GccInt_BLine(L);
267 //         =============================
268          }
269          else if (Index == 2) {
270            gp_Hypr2d H1(acencen,
271                         (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
272            bissol = new GccInt_BHyper(H1);
273 //         ===============================
274          }
275          else if (Index == 3) {
276            gp_Hypr2d H1(acencen,
277                         (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
278            bissol = new GccInt_BHyper(H1.OtherBranch());
279 //         ===============================
280          }
281        }
282      }
283      else if (intersection == 4) {
284        if (sameradius) {
285          if (Index == 1) {
286            gp_Lin2d L(pcen,medcen);
287            bissol = new GccInt_BLine(L);
288 //         =============================
289          }
290          else if (Index == 2) {
291            gp_Hypr2d H1(acencen,R1,Sqrt(dist*dist-4*R1*R1)/2.0);
292            bissol = new GccInt_BHyper(H1);
293 //         ===============================
294          }
295          else if (Index == 3) {
296            gp_Hypr2d H1(acencen,R1,Sqrt(dist*dist-4*R1*R1)/2.0);
297            bissol = new GccInt_BHyper(H1.OtherBranch());
298 //         ===============================
299          }
300        }
301        else {
302          if (Index == 1) {
303            gp_Hypr2d H1(acencen,
304                         (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
305            bissol = new GccInt_BHyper(H1);
306 //         ===============================
307          }
308          else if (Index == 2) {
309            gp_Hypr2d H1(acencen,
310                         (R1-R2)/2.0,Sqrt(dist*dist-(R1-R2)*(R1-R2))/2.0);
311            bissol = new GccInt_BHyper(H1.OtherBranch());
312 //         ===============================
313          }
314          else if (Index == 3) {
315            gp_Hypr2d H1(acencen,
316                         (R1+R2)/2.0,Sqrt(dist*dist-(R1+R2)*(R1+R2))/2.0);
317            bissol = new GccInt_BHyper(H1);
318 //         ===============================
319          }
320          else if (Index == 4) {
321            gp_Hypr2d H1(acencen,
322                         (R1+R2)/2.0,Sqrt(dist*dist-(R1+R2)*(R1+R2))/2.0);
323            bissol = new GccInt_BHyper(H1.OtherBranch());
324 //         ===============================
325          }
326        }
327      }
328    }
329    return bissol;
330  }
331
332 //=========================================================================
333
334 Standard_Boolean GccAna_Circ2dBisec::
335    IsDone () const { return WellDone; }
336
337 Standard_Integer GccAna_Circ2dBisec::NbSolutions () const 
338 {
339   if (!WellDone) throw StdFail_NotDone();
340
341   return NbrSol;
342 }