2f99af143740c584bb069c43e51cf870109b988e
[occt.git] / src / gp / gp_Hypr.hxx
1 // Copyright (c) 1991-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 #ifndef _gp_Hypr_HeaderFile
16 #define _gp_Hypr_HeaderFile
17
18 #include <gp.hxx>
19 #include <gp_Ax1.hxx>
20 #include <gp_Ax2.hxx>
21 #include <gp_Pnt.hxx>
22 #include <Standard_DomainError.hxx>
23 #include <Standard_ConstructionError.hxx>
24
25 //! Describes a branch of a hyperbola in 3D space.
26 //! A hyperbola is defined by its major and minor radii and
27 //! positioned in space with a coordinate system (a gp_Ax2
28 //! object) of which:
29 //! -   the origin is the center of the hyperbola,
30 //! -   the "X Direction" defines the major axis of the
31 //! hyperbola, and
32 //! - the "Y Direction" defines the minor axis of the hyperbola.
33 //! The origin, "X Direction" and "Y Direction" of this
34 //! coordinate system together define the plane of the
35 //! hyperbola. This coordinate system is the "local
36 //! coordinate system" of the hyperbola. In this coordinate
37 //! system, the equation of the hyperbola is:
38 //! X*X/(MajorRadius**2)-Y*Y/(MinorRadius**2) = 1.0
39 //! The branch of the hyperbola described is the one located
40 //! on the positive side of the major axis.
41 //! The "main Direction" of the local coordinate system is a
42 //! normal vector to the plane of the hyperbola. This vector
43 //! gives an implicit orientation to the hyperbola. We refer to
44 //! the "main Axis" of the local coordinate system as the
45 //! "Axis" of the hyperbola.
46 //! The following schema shows the plane of the hyperbola,
47 //! and in it, the respective positions of the three branches of
48 //! hyperbolas constructed with the functions OtherBranch,
49 //! ConjugateBranch1, and ConjugateBranch2:
50 //! @code
51 //! ^YAxis
52 //! |
53 //! FirstConjugateBranch
54 //! |
55 //! Other            |                Main
56 //! --------------------- C ------------------------------>XAxis
57 //! Branch           |                Branch
58 //! |
59 //! |
60 //! SecondConjugateBranch
61 //! |                  ^YAxis
62 //! @endcode
63 //! Warning
64 //! The major radius can be less than the minor radius.
65 //! See Also
66 //! gce_MakeHypr which provides functions for more
67 //! complex hyperbola constructions
68 //! Geom_Hyperbola which provides additional functions for
69 //! constructing hyperbolas and works, in particular, with the
70 //! parametric equations of hyperbolas
71 class gp_Hypr 
72 {
73 public:
74
75   DEFINE_STANDARD_ALLOC
76
77   //! Creates of an indefinite hyperbola.
78   gp_Hypr()
79   : majorRadius (RealLast()),
80     minorRadius (RealFirst())
81   {}
82
83   //! Creates a hyperbola with radius theMajorRadius and
84   //! theMinorRadius, positioned in the space by the
85   //! coordinate system theA2 such that:
86   //! -   the origin of theA2 is the center of the hyperbola,
87   //! -   the "X Direction" of theA2 defines the major axis of
88   //! the hyperbola, that is, the major radius
89   //! theMajorRadius is measured along this axis, and
90   //! -   the "Y Direction" of theA2 defines the minor axis of
91   //! the hyperbola, that is, the minor radius
92   //! theMinorRadius is measured along this axis.
93   //! Note: This class does not prevent the creation of a
94   //! hyperbola where:
95   //! -   theMajorAxis is equal to theMinorAxis, or
96   //! -   theMajorAxis is less than theMinorAxis.
97   //! Exceptions
98   //! Standard_ConstructionError if theMajorAxis or theMinorAxis is negative.
99   //! Raises ConstructionError if theMajorRadius < 0.0 or theMinorRadius < 0.0
100   //! Raised if theMajorRadius < 0.0 or theMinorRadius < 0.0
101   gp_Hypr (const gp_Ax2& theA2, const Standard_Real theMajorRadius, const Standard_Real theMinorRadius)
102   : pos (theA2),
103     majorRadius (theMajorRadius),
104     minorRadius (theMinorRadius)
105   {
106     Standard_ConstructionError_Raise_if (theMinorRadius < 0.0 || theMajorRadius < 0.0,
107       "gp_Hypr() - invalid construction parameters");
108   }
109
110   //! Modifies this hyperbola, by redefining its local coordinate
111   //! system so that:
112   //! -   its origin and "main Direction" become those of the
113   //! axis theA1 (the "X Direction" and "Y Direction" are then
114   //! recomputed in the same way as for any gp_Ax2).
115   //! Raises ConstructionError if the direction of theA1 is parallel to the direction of
116   //! the "XAxis" of the hyperbola.
117   void SetAxis (const gp_Ax1& theA1) { pos.SetAxis (theA1); }
118
119   //! Modifies this hyperbola, by redefining its local coordinate
120   //! system so that its origin becomes theP.
121   void SetLocation (const gp_Pnt& theP) { pos = gp_Ax2 (theP, pos.Direction(), pos.XDirection()); }
122
123   //! Modifies the major  radius of this hyperbola.
124   //! Exceptions
125   //! Standard_ConstructionError if theMajorRadius is negative.
126   void SetMajorRadius (const Standard_Real theMajorRadius)
127   {
128     Standard_ConstructionError_Raise_if (theMajorRadius < 0.0,
129       "gp_Hypr::SetMajorRadius() - major radius should be greater or equal zero");
130     majorRadius = theMajorRadius;
131   }
132
133   //! Modifies the minor  radius of this hyperbola.
134   //! Exceptions
135   //! Standard_ConstructionError if theMinorRadius is negative.
136   void SetMinorRadius (const Standard_Real theMinorRadius)
137   {
138     Standard_ConstructionError_Raise_if (theMinorRadius < 0.0,
139       "gp_Hypr::SetMinorRadius() - minor radius should be greater or equal zero");
140     minorRadius = theMinorRadius;
141   }
142
143   //! Modifies this hyperbola, by redefining its local coordinate
144   //! system so that it becomes A2.
145   void SetPosition (const gp_Ax2& theA2) { pos = theA2; }
146
147   //! In the local coordinate system of the hyperbola the equation of
148   //! the hyperbola is (X*X)/(A*A) - (Y*Y)/(B*B) = 1.0 and the
149   //! equation of the first asymptote is Y = (B/A)*X
150   //! where A is the major radius and B is the minor radius. Raises ConstructionError if MajorRadius = 0.0
151   gp_Ax1 Asymptote1() const;
152
153   //! In the local coordinate system of the hyperbola the equation of
154   //! the hyperbola is (X*X)/(A*A) - (Y*Y)/(B*B) = 1.0 and the
155   //! equation of the first asymptote is Y = -(B/A)*X.
156   //! where A is the major radius and B is the minor radius. Raises ConstructionError if MajorRadius = 0.0
157   gp_Ax1 Asymptote2() const;
158
159   //! Returns the axis passing through the center,
160   //! and normal to the plane of this hyperbola.
161   const gp_Ax1& Axis() const { return pos.Axis(); }
162
163   //! Computes the branch of hyperbola which is on the positive side of the
164   //! "YAxis" of <me>.
165   gp_Hypr ConjugateBranch1() const
166   {
167     return gp_Hypr (gp_Ax2 (pos.Location(), pos.Direction(), pos.YDirection()), minorRadius, majorRadius);
168   }
169
170   //! Computes the branch of hyperbola which is on the negative side of the
171   //! "YAxis" of <me>.
172   gp_Hypr ConjugateBranch2() const
173   {
174     gp_Dir aD = pos.YDirection();
175     aD.Reverse();
176     return gp_Hypr (gp_Ax2(pos.Location(), pos.Direction(), aD), minorRadius, majorRadius);
177   }
178
179   //! This directrix is the line normal to the XAxis of the hyperbola
180   //! in the local plane (Z = 0) at a distance d = MajorRadius / e
181   //! from the center of the hyperbola, where e is the eccentricity of
182   //! the hyperbola.
183   //! This line is parallel to the "YAxis". The intersection point
184   //! between the directrix1 and the "XAxis" is the "Location" point
185   //! of the directrix1. This point is on the positive side of the
186   //! "XAxis".
187   gp_Ax1 Directrix1() const;
188
189   //! This line is obtained by the symmetrical transformation
190   //! of "Directrix1" with respect to the "YAxis" of the hyperbola.
191   gp_Ax1 Directrix2() const;
192
193   //! Returns the eccentricity of the hyperbola (e > 1).
194   //! If f is the distance between the location of the hyperbola
195   //! and the Focus1 then the eccentricity e = f / MajorRadius. Raises DomainError if MajorRadius = 0.0
196   Standard_Real Eccentricity() const
197   {
198     Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(),
199       "gp_Hypr::Eccentricity() - major radius is zero");
200     return sqrt (majorRadius * majorRadius + minorRadius * minorRadius) / majorRadius;
201   }
202
203   //! Computes the focal distance. It is the distance between the
204   //! the two focus of the hyperbola.
205   Standard_Real Focal() const
206   {
207     return 2.0 * sqrt (majorRadius * majorRadius + minorRadius * minorRadius);
208   }
209
210   //! Returns the first focus of the hyperbola. This focus is on the
211   //! positive side of the "XAxis" of the hyperbola.
212   gp_Pnt Focus1() const;
213
214   //! Returns the second focus of the hyperbola. This focus is on the
215   //! negative side of the "XAxis" of the hyperbola.
216   gp_Pnt Focus2() const;
217
218   //! Returns  the location point of the hyperbola. It is the
219   //! intersection point between the "XAxis" and the "YAxis".
220   const gp_Pnt& Location() const { return pos.Location(); }
221
222   //! Returns the major radius of the hyperbola. It is the radius
223   //! on the "XAxis" of the hyperbola.
224   Standard_Real MajorRadius() const { return majorRadius; }
225
226   //! Returns the minor radius of the hyperbola. It is the radius
227   //! on the "YAxis" of the hyperbola.
228   Standard_Real MinorRadius() const { return minorRadius; }
229
230   //! Returns the branch of hyperbola obtained by doing the
231   //! symmetrical transformation of <me> with respect to the
232   //! "YAxis"  of <me>.
233   gp_Hypr OtherBranch() const
234   {
235     gp_Dir aD = pos.XDirection();
236     aD.Reverse();
237     return gp_Hypr (gp_Ax2 (pos.Location(), pos.Direction(), aD), majorRadius, minorRadius);
238   }
239
240   //! Returns p = (e * e - 1) * MajorRadius where e is the
241   //! eccentricity of the hyperbola.
242   //! Raises DomainError if MajorRadius = 0.0
243   Standard_Real Parameter() const
244   {
245     Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(),
246                                    "gp_Hypr::Parameter() - major radius is zero");
247     return (minorRadius * minorRadius) / majorRadius;
248   }
249
250   //! Returns the coordinate system of the hyperbola.
251   const gp_Ax2& Position() const { return pos; }
252
253   //! Computes an axis, whose
254   //! -   the origin is the center of this hyperbola, and
255   //! -   the unit vector is the "X Direction"
256   //! of the local coordinate system of this hyperbola.
257   //! These axes are, the major axis (the "X
258   //! Axis") and  of this hyperboReturns the "XAxis" of the hyperbola.
259   gp_Ax1 XAxis() const { return gp_Ax1 (pos.Location(), pos.XDirection()); }
260
261   //! Computes an axis, whose
262   //! -   the origin is the center of this hyperbola, and
263   //! -   the unit vector is the "Y Direction"
264   //! of the local coordinate system of this hyperbola.
265   //! These axes are the minor axis (the "Y Axis") of this hyperbola
266   gp_Ax1 YAxis() const { return gp_Ax1 (pos.Location(), pos.YDirection()); }
267
268   Standard_EXPORT void Mirror (const gp_Pnt& theP);
269
270   //! Performs the symmetrical transformation of an hyperbola with
271   //! respect  to the point theP which is the center of the symmetry.
272   Standard_NODISCARD Standard_EXPORT gp_Hypr Mirrored (const gp_Pnt& theP) const;
273
274   Standard_EXPORT void Mirror (const gp_Ax1& theA1);
275
276   //! Performs the symmetrical transformation of an hyperbola with
277   //! respect to an axis placement which is the axis of the symmetry.
278   Standard_NODISCARD Standard_EXPORT gp_Hypr Mirrored (const gp_Ax1& theA1) const;
279
280   Standard_EXPORT void Mirror (const gp_Ax2& theA2);
281
282   //! Performs the symmetrical transformation of an hyperbola with
283   //! respect to a plane. The axis placement theA2 locates the plane
284   //! of the symmetry (Location, XDirection, YDirection).
285   Standard_NODISCARD Standard_EXPORT gp_Hypr Mirrored (const gp_Ax2& theA2) const;
286
287   void Rotate (const gp_Ax1& theA1, const Standard_Real theAng) { pos.Rotate (theA1, theAng); }
288
289   //! Rotates an hyperbola. theA1 is the axis of the rotation.
290   //! theAng is the angular value of the rotation in radians.
291   Standard_NODISCARD gp_Hypr Rotated (const gp_Ax1& theA1, const Standard_Real theAng) const
292   {
293     gp_Hypr aH = *this;
294     aH.pos.Rotate (theA1, theAng);
295     return aH;
296   }
297
298   void Scale (const gp_Pnt& theP, const Standard_Real theS);
299
300   //! Scales an hyperbola. theS is the scaling value.
301   Standard_NODISCARD gp_Hypr Scaled (const gp_Pnt& theP, const Standard_Real theS) const;
302
303   void Transform (const gp_Trsf& theT);
304
305   //! Transforms an hyperbola with the transformation theT from
306   //! class Trsf.
307   Standard_NODISCARD gp_Hypr Transformed (const gp_Trsf& theT) const;
308
309   void Translate (const gp_Vec& theV) { pos.Translate (theV); }
310
311   //! Translates an hyperbola in the direction of the vector theV.
312   //! The magnitude of the translation is the vector's magnitude.
313   Standard_NODISCARD gp_Hypr Translated (const gp_Vec& theV) const
314   {
315     gp_Hypr aH = *this;
316     aH.pos.Translate (theV);
317     return aH;
318   }
319
320   void Translate (const gp_Pnt& theP1, const gp_Pnt& theP2) { pos.Translate (theP1, theP2); }
321
322   //! Translates an hyperbola from the point theP1 to the point theP2.
323   Standard_NODISCARD gp_Hypr Translated (const gp_Pnt& theP1, const gp_Pnt& theP2) const
324   {
325     gp_Hypr aH = *this;
326     aH.pos.Translate (theP1, theP2);
327     return aH;
328   }
329
330 private:
331
332   gp_Ax2 pos;
333   Standard_Real majorRadius;
334   Standard_Real minorRadius;
335
336 };
337
338 //=======================================================================
339 //function : Asymptote1
340 // purpose :
341 //=======================================================================
342 inline gp_Ax1 gp_Hypr::Asymptote1() const
343 {
344   Standard_ConstructionError_Raise_if (majorRadius <= gp::Resolution(),
345                                        "gp_Hypr::Asymptote1() - major radius is zero");
346   gp_Vec aV1 = gp_Vec (pos.YDirection());
347   aV1.Multiply (minorRadius / majorRadius);
348   gp_Vec aV = gp_Vec (pos.XDirection());
349   aV.Add (aV1);
350   return  gp_Ax1 (pos.Location(), gp_Dir (aV));
351 }
352
353 //=======================================================================
354 //function : Asymptote2
355 // purpose :
356 //=======================================================================
357 inline gp_Ax1 gp_Hypr::Asymptote2() const
358 {
359   Standard_ConstructionError_Raise_if (majorRadius <= gp::Resolution(),
360                                        "gp_Hypr::Asymptote1() - major radius is zero");
361   gp_Vec aV1 = gp_Vec (pos.YDirection());
362   aV1.Multiply (-minorRadius / majorRadius);
363   gp_Vec aV = gp_Vec (pos.XDirection());
364   aV.Add (aV1);
365   return  gp_Ax1 ( pos.Location(), gp_Dir (aV));
366 }
367
368 //=======================================================================
369 //function : Focus1
370 // purpose :
371 //=======================================================================
372 inline gp_Pnt gp_Hypr::Focus1() const
373 {
374   Standard_Real aC = sqrt (majorRadius * majorRadius + minorRadius * minorRadius);
375   const gp_Pnt& aPP = pos.Location  ();
376   const gp_Dir& aDD = pos.XDirection();
377   return gp_Pnt (aPP.X() + aC * aDD.X(),
378                  aPP.Y() + aC * aDD.Y(),
379                  aPP.Z() + aC * aDD.Z());
380 }
381
382 //=======================================================================
383 //function : Focus2
384 // purpose :
385 //=======================================================================
386 inline gp_Pnt gp_Hypr::Focus2 () const
387 {
388   Standard_Real aC = sqrt (majorRadius * majorRadius + minorRadius * minorRadius);
389   const gp_Pnt& aPP = pos.Location  ();
390   const gp_Dir& aDD = pos.XDirection();
391   return gp_Pnt (aPP.X() - aC * aDD.X(),
392                  aPP.Y() - aC * aDD.Y(),
393                  aPP.Z() - aC * aDD.Z());
394 }
395
396 //=======================================================================
397 //function : Scale
398 // purpose :
399 //=======================================================================
400 inline void gp_Hypr::Scale (const gp_Pnt& theP,
401                             const Standard_Real theS)
402 {
403   majorRadius *= theS;
404   if (majorRadius < 0)
405   {
406     majorRadius = -majorRadius;
407   }
408   minorRadius *= theS;
409   if (minorRadius < 0)
410   {
411     minorRadius = -minorRadius;
412   }
413   pos.Scale (theP, theS);
414 }
415
416 //=======================================================================
417 //function : Scaled
418 // purpose :
419 //=======================================================================
420 inline gp_Hypr gp_Hypr::Scaled (const gp_Pnt& theP,
421                                 const Standard_Real theS) const
422 {
423   gp_Hypr aH = *this;
424   aH.majorRadius *= theS;
425   if (aH.majorRadius < 0)
426   {
427     aH.majorRadius = -aH.majorRadius;
428   }
429   aH.minorRadius *= theS;
430   if (aH.minorRadius < 0)
431   {
432     aH.minorRadius = -aH.minorRadius;
433   }
434   aH.pos.Scale (theP, theS);
435   return aH; 
436 }
437
438 //=======================================================================
439 //function : Transform
440 // purpose :
441 //=======================================================================
442 inline void gp_Hypr::Transform (const gp_Trsf& theT)
443
444   majorRadius *= theT.ScaleFactor();
445   if (majorRadius < 0)
446   {
447     majorRadius = -majorRadius;
448   }
449   minorRadius *= theT.ScaleFactor();
450   if (minorRadius < 0)
451   {
452     minorRadius = -minorRadius;
453   }
454   pos.Transform (theT);
455 }
456
457 //=======================================================================
458 //function : Transformed
459 // purpose :
460 //=======================================================================
461 inline gp_Hypr gp_Hypr::Transformed (const gp_Trsf& theT) const
462 {
463   gp_Hypr aH = *this;
464   aH.majorRadius *= theT.ScaleFactor();
465   if (aH.majorRadius < 0)
466   {
467     aH.majorRadius = -aH.majorRadius;
468   }
469   aH.minorRadius *= theT.ScaleFactor();
470   if (aH.minorRadius < 0)
471   {
472     aH.minorRadius = -aH.minorRadius;
473   }
474   aH.pos.Transform (theT);
475   return aH; 
476 }
477
478 //=======================================================================
479 //function : Directrix1
480 // purpose :
481 //=======================================================================
482 inline gp_Ax1 gp_Hypr::Directrix1 () const
483 {
484   Standard_Real anE = Eccentricity();
485   gp_XYZ anOrig = pos.XDirection().XYZ();
486   anOrig.Multiply (majorRadius / anE);
487   anOrig.Add (pos.Location().XYZ());
488   return gp_Ax1 (gp_Pnt (anOrig), pos.YDirection());
489 }
490
491 //=======================================================================
492 //function : Directrix2
493 // purpose :
494 //=======================================================================
495 inline gp_Ax1 gp_Hypr::Directrix2 () const
496 {
497   Standard_Real anE = Eccentricity();
498   gp_XYZ anOrig = pos.XDirection().XYZ();
499   anOrig.Multiply (-majorRadius / anE);
500   anOrig.Add (pos.Location().XYZ());
501   return gp_Ax1 (gp_Pnt (anOrig), pos.YDirection());
502 }
503
504 #endif // _gp_Hypr_HeaderFile