aa21a3f1befaf253b39572ca0efd49cc90605ebe
[occt.git] / src / IntCurve / IntCurve_IConicTool.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
16 #include <ElCLib.hxx>
17 #include <gp.hxx>
18 #include <gp_Circ2d.hxx>
19 #include <gp_Elips2d.hxx>
20 #include <gp_Hypr2d.hxx>
21 #include <gp_Lin2d.hxx>
22 #include <gp_Parab2d.hxx>
23 #include <gp_Pnt2d.hxx>
24 #include <gp_Vec2d.hxx>
25 #include <IntCurve_IConicTool.hxx>
26
27 #define Object_To_Abs  Abs_To_Object.Inverted()
28 //======================================================================
29 #define Elips_a prm1
30 #define Elips_b prm2
31 #define Elips_c prm3
32
33 #define Elips_aa (Elips_a*Elips_a)
34 #define Elips_bb (Elips_b*Elips_b)
35 #define Elips_x0 (Axis.Location().X())
36 #define Elips_y0 (Axis.Location().Y())
37 //======================================================================
38 #define Hypr_a prm1
39 #define Hypr_b prm2
40 #define Hypr_aa (Hypr_a * Hypr_a)
41 #define Hypr_bb (Hypr_b * Hypr_b)
42 //======================================================================
43 #define Line_a prm1
44 #define Line_b prm2
45 #define Line_c prm3
46 //======================================================================
47 #define Circle_r  prm1
48 #define Circle_x0 prm2
49 #define Circle_y0 prm3
50 //======================================================================
51 #define Parab_f   prm1
52 #define Parab_2p  prm2
53
54 //======================================================================
55 IntCurve_IConicTool::IntCurve_IConicTool(void)
56 : prm1(0.0),
57   prm2(0.0),
58   prm3(0.0),
59   type(GeomAbs_OtherCurve)
60 {
61 //###### PLACER LE TYPE NON DEFINI ######
62 }
63
64
65 IntCurve_IConicTool::IntCurve_IConicTool(const IntCurve_IConicTool& ITool) {
66   prm1=ITool.prm1;
67   prm2=ITool.prm2;
68   prm3=ITool.prm3;
69   Axis=ITool.Axis;
70   Abs_To_Object=ITool.Abs_To_Object;
71   type=ITool.type;
72 }
73 //======================================================================
74 //======================================================================
75 IntCurve_IConicTool::IntCurve_IConicTool(const gp_Lin2d& Line)
76 : prm1(0.0),
77   prm2(0.0),
78   prm3(0.0) 
79 {
80   Line.Coefficients(Line_a,Line_b,Line_c);
81   Axis = gp_Ax22d(Line.Position(),Standard_True);
82   type = GeomAbs_Line;
83 }
84 //======================================================================
85 IntCurve_IConicTool::IntCurve_IConicTool(const gp_Elips2d& Elips)
86 : prm1(0.0),
87   prm2(0.0),
88   prm3(0.0) 
89 {
90   Elips_a = Elips.MajorRadius();
91   Elips_b = Elips.MinorRadius();
92   Elips_c = sqrt(Elips_a*Elips_a-Elips_b*Elips_b);
93   Axis = Elips.Axis();
94   Abs_To_Object.SetTransformation(gp::OX2d(),Axis.XAxis());
95   type = GeomAbs_Ellipse;
96 }
97 //======================================================================
98 IntCurve_IConicTool::IntCurve_IConicTool(const gp_Circ2d& C)
99 : prm1(0.0),
100   prm2(0.0),
101   prm3(0.0)
102 {
103   Circle_r=C.Radius();
104   Axis=C.Axis();
105   Circle_x0=Axis.Location().X();
106   Circle_y0=Axis.Location().Y();
107   Abs_To_Object.SetTransformation(gp::OX2d(),Axis.XAxis());
108   type = GeomAbs_Circle;
109 }
110 //======================================================================
111 IntCurve_IConicTool::IntCurve_IConicTool(const gp_Parab2d& P)
112 : prm1(0.0),
113   prm2(0.0),
114   prm3(0.0)
115 {
116   Parab_f=P.Focal();
117   Parab_2p=4.0*Parab_f;
118   Axis=P.Axis();
119   Abs_To_Object.SetTransformation(gp::OX2d(),Axis.XAxis());
120   type = GeomAbs_Parabola;
121 }
122 //======================================================================
123 IntCurve_IConicTool::IntCurve_IConicTool(const gp_Hypr2d& H)
124 : prm1(0.0),
125   prm2(0.0),
126   prm3(0.0)
127 {
128   Hypr_a = H.MajorRadius();
129   Hypr_b = H.MinorRadius();
130   Axis = H.Axis();
131   Abs_To_Object.SetTransformation(gp::OX2d(),Axis.XAxis());
132   type = GeomAbs_Hyperbola;
133 }
134 //----------------------------------------------------------------------
135 gp_Pnt2d IntCurve_IConicTool::Value(const Standard_Real X) const {
136   switch(type) {
137   case GeomAbs_Line:      return(ElCLib::LineValue(X,Axis.XAxis()));
138   case GeomAbs_Ellipse:   return(ElCLib::EllipseValue(X,Axis,Elips_a,Elips_b));
139   case GeomAbs_Circle:    return(ElCLib::CircleValue(X,Axis,Circle_r));
140   case GeomAbs_Parabola:  return(ElCLib::ParabolaValue(X,Axis,Parab_f));
141   case GeomAbs_Hyperbola: return(ElCLib::HyperbolaValue(X,Axis,Hypr_a,Hypr_b));
142   default: { std::cout<<"### Erreur sur le  type de la courbe ###";
143             return(gp_Pnt2d(0.0,0.0)); }
144   }
145 }
146
147 //----------------------------------------------------------------------
148 void IntCurve_IConicTool::D1(const Standard_Real X,
149                            gp_Pnt2d& Pt,
150                            gp_Vec2d& Tan) const { 
151                  
152   switch(type) {
153   case GeomAbs_Line:     ElCLib::LineD1(X,Axis.XAxis(),Pt,Tan); break;
154   case GeomAbs_Ellipse:     ElCLib::EllipseD1(X,Axis,Elips_a,Elips_b,Pt,Tan); break;
155   case GeomAbs_Circle:     ElCLib::CircleD1(X,Axis,Circle_r,Pt,Tan); break;
156   case GeomAbs_Parabola:     ElCLib::ParabolaD1(X,Axis,Parab_f,Pt,Tan); break;
157   case GeomAbs_Hyperbola:     ElCLib::HyperbolaD1(X,Axis,Hypr_a,Hypr_b,Pt,Tan); break;
158   default: { std::cout<<"### Erreur sur le  type de la courbe ###"; }
159   }
160 }
161
162 //----------------------------------------------------------------------
163 void IntCurve_IConicTool::D2(const Standard_Real X,
164                            gp_Pnt2d& Pt,
165                            gp_Vec2d& Tan,
166                            gp_Vec2d& Norm) const { 
167                  
168   switch(type) {
169   case GeomAbs_Line:     ElCLib::LineD1(X,Axis.XAxis(),Pt,Tan); Norm.SetCoord(0.0,0.0); break;
170   case GeomAbs_Ellipse:     ElCLib::EllipseD2(X,Axis,Elips_a,Elips_b,Pt,Tan,Norm); break;
171   case GeomAbs_Circle:     ElCLib::CircleD2(X,Axis,Circle_r,Pt,Tan,Norm); break;
172   case GeomAbs_Parabola:     ElCLib::ParabolaD2(X,Axis,Parab_f,Pt,Tan,Norm); break;
173   case GeomAbs_Hyperbola:     ElCLib::HyperbolaD2(X,Axis,Hypr_a,Hypr_b,Pt,Tan,Norm); break;
174   default: { std::cout<<"### Erreur sur le  type de la courbe ###"; }
175   }                          
176 }
177 //----------------------------------------------------------------------
178 #define AN_ELIPS 0 
179 //----------------------------------------------------------------------
180 Standard_Real IntCurve_IConicTool::Distance(const gp_Pnt2d& ThePoint) const {
181
182   switch(type) {
183   case GeomAbs_Line:
184     {
185       return(Line_a*ThePoint.X()+Line_b*ThePoint.Y()+Line_c);
186     }
187
188   case GeomAbs_Ellipse:
189     {
190 #if AN_ELIPS
191       gp_Pnt2d P=ThePoint;
192       P.Transform(Abs_To_Object);
193       Standard_Real x=P.X();
194       Standard_Real y2=P.Y() * P.Y();
195       return(sqrt(y2+(x+Elips_c)*(x+Elips_c))
196              +sqrt(y2+(x-Elips_c)*(x-Elips_c))-Elips_a-Elips_a);
197 #else
198       gp_Pnt2d P=ThePoint;
199       P.Transform(Abs_To_Object);
200       Standard_Real x=P.X();
201       Standard_Real y=P.Y()*(Elips_a/Elips_b);
202       Standard_Real d=sqrt(x*x+y*y)-Elips_a;
203       return(d);
204 #endif
205     }
206
207   case GeomAbs_Circle:
208     {
209       Standard_Real Dx=Circle_x0-ThePoint.X();
210       Standard_Real Dy=Circle_y0-ThePoint.Y();
211       return(sqrt(Dx*Dx+Dy*Dy)-Circle_r);
212     }
213
214   case GeomAbs_Parabola:
215     {    //-- Distance(X,Y) = Y**2 - 2 P X 
216       gp_Pnt2d P=ThePoint;
217       P.Transform(Abs_To_Object);
218       return(P.Y()*P.Y()-Parab_2p*P.X());
219     }
220     
221   case GeomAbs_Hyperbola:
222     { //-- Distance(X,Y) = (X/a)**2 - (Y/b)**2 -1
223       //--                 pour x>0
224       //--     -(Y/b)**2 - 1  sinon ?? 
225       //--     avec un gradient avec x -> Abs(x)
226       gp_Pnt2d P=ThePoint;
227       P.Transform(Abs_To_Object);
228       if(P.X()>0.0) 
229         return((P.X()*P.X())/Hypr_aa 
230                -(P.Y()*P.Y())/Hypr_bb -1.0);
231       else
232         return((-P.X()*P.X())/Hypr_aa 
233                -(P.Y()*P.Y())/Hypr_bb -1.0);
234     }                        
235   default: { std::cout<<"### Erreur sur le  type de la courbe ###";
236             return(0.0); }
237   }
238 }
239
240
241 gp_Vec2d IntCurve_IConicTool::GradDistance(const gp_Pnt2d& ThePoint) const {
242
243   switch(type) {
244   case GeomAbs_Line: return(gp_Vec2d(Line_a,Line_b));
245
246   case GeomAbs_Circle: {
247     gp_Pnt2d P=ThePoint;
248     P.Transform(Abs_To_Object);
249     Standard_Real Gradx=0.0;
250     Standard_Real Grady=0.0;
251     Standard_Real x=P.X();
252     Standard_Real y=P.Y();
253     Standard_Real temp1=sqrt(y*y+x*x);
254     if(temp1) {
255       Gradx=x/temp1;
256       Grady=y/temp1;
257     }
258     gp_Vec2d Gradient(Gradx,Grady);
259     Gradient.Transform(Object_To_Abs);
260     return(Gradient);
261   }
262   case GeomAbs_Ellipse: {
263 #if AN_ELIPS
264     gp_Pnt2d P=ThePoint;
265     P.Transform(Abs_To_Object);
266     Standard_Real Gradx=0.0;
267     Standard_Real Grady=0.0;
268     Standard_Real x=P.X();
269     Standard_Real y=P.Y();
270     Standard_Real xmc=x-Elips_c;
271     Standard_Real xpc=x+Elips_c;
272     Standard_Real temp1=sqrt(y*y+xmc*xmc);
273     Standard_Real temp2=sqrt(y*y+xpc*xpc);
274     if(temp2) {
275       Gradx=xpc/temp2;
276       Grady=y/temp2;
277     }
278     if(temp1) {
279       Gradx+=xmc/temp1;
280       Grady+=y/temp1;
281     }
282     gp_Vec2d Gradient(Gradx,Grady);
283     Gradient.Transform(Object_To_Abs);
284     return(Gradient);
285 #else
286     gp_Pnt2d P=ThePoint;
287     P.Transform(Abs_To_Object);
288     Standard_Real Gradx=0.0;
289     Standard_Real Grady=0.0;
290     Standard_Real x=P.X();
291     Standard_Real y=P.Y()*(Elips_a/Elips_b);
292     Standard_Real temp1=sqrt(y*y+x*x);
293     if(temp1) {
294       Gradx=x/temp1;
295       Grady=(y*(Elips_a/Elips_b))/temp1;
296     }
297     gp_Vec2d Gradient(Gradx,Grady);
298     Gradient.Transform(Object_To_Abs);
299     return(Gradient);
300 #endif
301   }
302     
303   case GeomAbs_Parabola: {    //-- Distance(X,Y) = Y**2 - 2 P X 
304     gp_Pnt2d P=ThePoint;
305     P.Transform(Abs_To_Object);
306     gp_Vec2d Gradient(-Parab_2p,P.Y()+P.Y());
307     Gradient.Transform(Object_To_Abs);
308     return(Gradient);
309   }
310   case GeomAbs_Hyperbola: { //-- Distance(X,Y) = (X/a)**2 - (Y/b)**2 -1
311     gp_Pnt2d P=ThePoint;
312     P.Transform(Abs_To_Object);
313     //--### la Branche a X negatif doit ramener vers les X positifs
314     gp_Vec2d Gradient(2.0*Abs(P.X())/Hypr_aa,-2.0*P.Y()/Hypr_bb);
315     Gradient.Transform(Object_To_Abs);
316     return(Gradient);
317   }
318   default: { std::cout<<"### Erreur sur le  type de la courbe ###";
319             return(gp_Vec2d(0.0,0.0)); }
320   }
321 }
322
323
324 Standard_Real IntCurve_IConicTool::FindParameter(const gp_Pnt2d& P) const {
325
326   Standard_Real Param=0;
327   
328   switch(type) {
329     
330   case GeomAbs_Line: 
331     Param=ElCLib::LineParameter(Axis.XAxis(),P);
332     break;
333     
334   case GeomAbs_Circle:
335     Param=ElCLib::CircleParameter(Axis,P);
336     if(Param<0.0) { Param+=M_PI+M_PI; }
337     break;
338     
339   case GeomAbs_Ellipse: {
340     Param=ElCLib::EllipseParameter(Axis
341                                    ,Elips_a
342                                    ,Elips_b
343                                    ,P);
344     if (Param < 0.0) { Param+=M_PI+M_PI; }
345     break;
346   }
347     
348   case GeomAbs_Parabola: {
349     Param=ElCLib::ParabolaParameter(Axis,P);
350     break;
351   }
352   case GeomAbs_Hyperbola: { 
353     Param=ElCLib::HyperbolaParameter(Axis
354                                      ,Hypr_a
355                                      ,Hypr_b
356                                      ,P);
357     break;
358   }
359   default:
360     break;
361   }
362   
363   return(Param);
364 }
365
366