0024573: Wrong result of 2d-offset algorithm on customer's shape
[occt.git] / src / GccAna / GccAna_CircPnt2dBisec.cxx
1 // Created on: 1991-10-11
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
9 // under the terms of the GNU Lesser General Public 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 a CIRCLE and a POINT.               +
19 //=========================================================================
20
21 #include <GccAna_CircPnt2dBisec.ixx>
22
23 #include <gp_XY.hxx>
24 #include <gp_Dir2d.hxx>
25 #include <gp_Ax2d.hxx>
26 #include <GccInt_BHyper.hxx>
27 #include <GccInt_BCirc.hxx>
28 #include <GccInt_BElips.hxx>
29 #include <GccInt_BLine.hxx>
30 #include <Standard_ConstructionError.hxx>
31 #include <Standard_OutOfRange.hxx>
32 #include <StdFail_NotDone.hxx>
33 #include <gp.hxx>
34
35 //=========================================================================
36
37 GccAna_CircPnt2dBisec::
38    GccAna_CircPnt2dBisec (const gp_Circ2d& Circle ,
39                           const gp_Pnt2d&  Point  )
40 {
41   circle = Circle;
42   point = Point;
43   myTolerance = 1.e-10;
44   DefineSolutions();
45 }
46
47 GccAna_CircPnt2dBisec::
48    GccAna_CircPnt2dBisec (const gp_Circ2d& Circle ,
49                           const gp_Pnt2d&  Point,
50                           const Standard_Real Tolerance)
51 {
52   circle = Circle;
53   point = Point;
54   myTolerance = 1.e-10;
55   if (myTolerance < Tolerance)
56     myTolerance = Tolerance;
57   
58   DefineSolutions();
59 }
60
61 void GccAna_CircPnt2dBisec::DefineSolutions()
62 {
63   Standard_Real dist = circle.Radius() - point.Distance(circle.Location());
64   
65   if (Abs(dist) < myTolerance)
66   {
67     theposition = 0;
68     NbrSol = 1;
69   }
70   else if (dist > 0.0)
71   {
72     theposition = -1;
73     NbrSol = 1;
74   }
75   else {
76     theposition = 1;
77     NbrSol = 2;
78   }
79   
80   WellDone = Standard_True;
81 }
82
83 //=========================================================================
84 //  Processing.                                                           +
85 //  Return the coordinates of origins of the straight line (xloc,yloc) and+
86 //  of the circle (xcencirc, ycencirc).                                       +
87 //  Also return the coordinates of the direction of the straight line (xdir,   +
88 //  ydir) and the radius of circle R1.                                       +
89 //  Check at which side of the straight line is found the center of circle    +
90 //  to orientate the parabola (sign).                                    +
91 //  Create axis of each parabola (axeparab1, axeparb2), then    +
92 //  two parabolas (biscirPnt1, biscirPnt1).                          +
93 //=========================================================================
94
95 Handle(GccInt_Bisec) GccAna_CircPnt2dBisec::
96    ThisSolution (const Standard_Integer Index) const 
97 {
98   
99   if (!WellDone)
100     StdFail_NotDone::Raise();
101   
102   if ((Index <=0) || (Index > NbrSol))
103     Standard_OutOfRange::Raise();
104
105   Handle(GccInt_Bisec) bissol;  
106   Standard_Real xpoint = point.X();
107   Standard_Real ypoint = point.Y();
108   Standard_Real xcencir = circle.Location().X();
109   Standard_Real ycencir = circle.Location().Y();
110   Standard_Real R1 = circle.Radius();
111   Standard_Real dist = point.Distance(circle.Location());
112
113   if (dist < myTolerance)
114     {
115       gp_Circ2d biscirpnt1(gp_Ax2d(point,gp_Dir2d(1.0,0.0)),R1/2.);
116       bissol = new GccInt_BCirc(biscirpnt1);
117       //       ==========================================================
118     }
119   else {
120     gp_Pnt2d center((xpoint+xcencir)/2.,(ypoint+ycencir)/2.);
121     gp_Ax2d majax(center,gp_Dir2d(xpoint-xcencir,ypoint-ycencir));
122     
123     //=========================================================================
124     //   The point is inside the circle.                                +
125     //=========================================================================
126     
127     if (theposition == -1) {
128       gp_Elips2d biscirpnt(majax,R1/2.,Sqrt(R1*R1-dist*dist)/2.);
129       bissol = new GccInt_BElips(biscirpnt);
130       //         ===========================================================
131     }
132     
133     //=========================================================================
134     //   The point is on the circle.                                          +
135     //   There is only one solution : straight line passing through point and the center +
136     //   of the circle.                                                           +
137     //=========================================================================
138     
139     else if (theposition == 0) {
140       gp_Dir2d dirsol;
141       if (circle.IsDirect()) 
142         dirsol=gp_Dir2d(xcencir-xpoint,ycencir-ypoint);
143       else dirsol = gp_Dir2d(xpoint-xcencir,ypoint-ycencir);
144       gp_Lin2d biscirpnt(point,dirsol);
145       bissol = new GccInt_BLine(biscirpnt);
146       //         =========================================================
147     }
148     
149     //=========================================================================
150     //   The point is outside of the circle.                                +
151     //   There are two solutions : two main branches of the hyperbola.+
152     //=========================================================================
153     
154     else {
155       //           Standard_Real d1 = sqrt(dist*R1-R1*R1);
156       Standard_Real d1 = sqrt(dist*dist-R1*R1)/2.0;
157       Standard_Real d2 = R1/2.;
158       if (Index == 1) {
159         gp_Hypr2d biscirpnt1(majax,d2,d1);
160         bissol = new GccInt_BHyper(biscirpnt1);
161         //           =========================================
162       }
163       else {
164         gp_Hypr2d biscirpnt1(majax,d2,d1);
165         gp_Hypr2d biscirpnt2 = biscirpnt1.OtherBranch();
166         bissol = new GccInt_BHyper(biscirpnt2);
167         //           =========================================
168       }
169     }
170   }
171   return bissol;
172 }
173
174
175 //=========================================================================
176
177 Standard_Boolean GccAna_CircPnt2dBisec::
178    IsDone () const { return WellDone; }
179
180 Standard_Integer GccAna_CircPnt2dBisec::
181    NbSolutions () const { return NbrSol; }
182
183