1 // Created on: 1993-08-02
2 // Created by: Laurent BOURESCHE
3 // Copyright (c) 1993-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 #ifndef _gp_Ax3_HeaderFile
18 #define _gp_Ax3_HeaderFile
19 
20 #include <gp_Ax1.hxx>
21 #include <gp_Ax2.hxx>
22 #include <gp_Dir.hxx>
23 #include <gp_Pnt.hxx>
24 #include <gp_Vec.hxx>
25 
26 class gp_Trsf;
27 
28 //! Describes a coordinate system in 3D space. Unlike a
29 //! gp_Ax2 coordinate system, a gp_Ax3 can be
30 //! right-handed ("direct sense") or left-handed ("indirect sense").
31 //! A coordinate system is defined by:
32 //! -   its origin (also referred to as its "Location point"), and
33 //! -   three orthogonal unit vectors, termed the "X
34 //! Direction", the "Y Direction" and the "Direction" (also
35 //! referred to as the "main Direction").
36 //! The "Direction" of the coordinate system is called its
37 //! "main Direction" because whenever this unit vector is
38 //! modified, the "X Direction" and the "Y Direction" are
39 //! recomputed. However, when we modify either the "X
40 //! Direction" or the "Y Direction", "Direction" is not modified.
41 //! "Direction" is also the "Z Direction".
42 //! The "main Direction" is always parallel to the cross
43 //! product of its "X Direction" and "Y Direction".
44 //! If the coordinate system is right-handed, it satisfies the equation:
45 //! "main Direction" = "X Direction" ^ "Y Direction"
46 //! and if it is left-handed, it satisfies the equation:
47 //! "main Direction" = -"X Direction" ^ "Y Direction"
48 //! A coordinate system is used:
49 //! -   to describe geometric entities, in particular to position
50 //! them. The local coordinate system of a geometric
51 //! entity serves the same purpose as the STEP function
52 //! "axis placement three axes", or
53 //! -   to define geometric transformations.
54 //! Note:
55 //! -   We refer to the "X Axis", "Y Axis" and "Z Axis",
56 //! respectively, as the axes having:
57 //! -   the origin of the coordinate system as their origin, and
58 //! -   the unit vectors "X Direction", "Y Direction" and
59 //! "main Direction", respectively, as their unit vectors.
60 //! -   The "Z Axis" is also the "main Axis".
61 //! -   gp_Ax2 is used to define a coordinate system that must be always right-handed.
62 class gp_Ax3
63 {
64 public:
65 
66   DEFINE_STANDARD_ALLOC
67 
68   //! Creates an object corresponding to the reference
69   //! coordinate system (OXYZ).
gp_Ax3()70   gp_Ax3() : vydir (0., 1., 0.)
71   // vxdir(1.,0.,0.) use default ctor of gp_Dir, as it creates the same dir(1,0,0)
72   {}
73 
74   //! Creates  a  coordinate  system from a right-handed
75   //! coordinate system.
76   gp_Ax3 (const gp_Ax2& theA);
77 
78   //! Creates a  right handed axis placement with the
79   //! "Location" point theP and  two directions, theN gives the
80   //! "Direction" and theVx gives the "XDirection".
81   //! Raises ConstructionError if theN and theVx are parallel (same or opposite orientation).
gp_Ax3(const gp_Pnt & theP,const gp_Dir & theN,const gp_Dir & theVx)82   gp_Ax3 (const gp_Pnt& theP, const gp_Dir& theN, const gp_Dir& theVx)
83   : axis (theP, theN),
84     vydir(theN),
85     vxdir(theN)
86   {
87     vxdir.CrossCross (theVx, theN);
88     vydir.Cross (vxdir);
89   }
90 
91   //! Creates an axis placement with the "Location" point <theP>
92   //! and the normal direction <theV>.
93   Standard_EXPORT gp_Ax3 (const gp_Pnt& theP, const gp_Dir& theV);
94 
95   //! Reverses the X direction of <me>.
XReverse()96   void XReverse() { vxdir.Reverse(); }
97 
98   //! Reverses the Y direction of <me>.
YReverse()99   void YReverse() { vydir.Reverse(); }
100 
101   //! Reverses the Z direction of <me>.
ZReverse()102   void ZReverse() { axis.Reverse(); }
103 
104   //! Assigns the origin and "main Direction" of the axis theA1 to
105   //! this coordinate system, then recomputes its "X Direction" and "Y Direction".
106   //! Note:
107   //! -   The new "X Direction" is computed as follows:
108   //! new "X Direction" = V1 ^(previous "X Direction" ^ V)
109   //! where V is the "Direction" of theA1.
110   //! -   The orientation of this coordinate system
111   //! (right-handed or left-handed) is not modified.
112   //! Raises ConstructionError  if the "Direction" of <theA1> and the "XDirection" of <me>
113   //! are parallel (same or opposite orientation) because it is
114   //! impossible to calculate the new "XDirection" and the new
115   //! "YDirection".
116   void SetAxis (const gp_Ax1& theA1);
117 
118   //! Changes the main direction of this coordinate system,
119   //! then recomputes its "X Direction" and "Y Direction".
120   //! Note:
121   //! -   The new "X Direction" is computed as follows:
122   //! new "X Direction" = theV ^ (previous "X Direction" ^ theV).
123   //! -   The orientation of this coordinate system (left- or right-handed) is not modified.
124   //! Raises ConstructionError if <theV> and the previous "XDirection" are parallel
125   //! because it is impossible to calculate the new "XDirection"
126   //! and the new "YDirection".
127   void SetDirection (const gp_Dir& theV);
128 
129   //! Changes the "Location" point (origin) of <me>.
SetLocation(const gp_Pnt & theP)130   void SetLocation (const gp_Pnt& theP) { axis.SetLocation (theP); }
131 
132   //! Changes the "Xdirection" of <me>. The main direction
133   //! "Direction" is not modified, the "Ydirection" is modified.
134   //! If <theVx> is not normal to the main direction then <XDirection>
135   //! is computed as follows XDirection = Direction ^ (theVx ^ Direction).
136   //! Raises ConstructionError if <theVx> is parallel (same or opposite
137   //! orientation) to the main direction of <me>
138   void SetXDirection (const gp_Dir& theVx);
139 
140   //! Changes the "Ydirection" of <me>. The main direction is not
141   //! modified but the "Xdirection" is changed.
142   //! If <theVy> is not normal to the main direction then "YDirection"
143   //! is computed as  follows
144   //! YDirection = Direction ^ (<theVy> ^ Direction).
145   //! Raises ConstructionError if <theVy> is parallel to the main direction of <me>
146   void SetYDirection (const gp_Dir& theVy);
147 
148   //! Computes the angular value between the main direction of
149   //! <me> and the main direction of <theOther>. Returns the angle
150   //! between 0 and PI in radians.
Angle(const gp_Ax3 & theOther) const151   Standard_Real Angle (const gp_Ax3& theOther) const { return axis.Angle (theOther.axis); }
152 
153   //! Returns the main axis of <me>. It is the "Location" point
154   //! and the main "Direction".
Axis() const155   const gp_Ax1& Axis() const { return axis; }
156 
157   //! Computes a right-handed coordinate system with the
158   //! same "X Direction" and "Y Direction" as those of this
159   //! coordinate system, then recomputes the "main Direction".
160   //! If this coordinate system is right-handed, the result
161   //! returned is the same coordinate system. If this
162   //! coordinate system is left-handed, the result is reversed.
163   gp_Ax2 Ax2() const;
164 
165   //! Returns the main direction of <me>.
Direction() const166   const gp_Dir& Direction() const { return axis.Direction(); }
167 
168   //! Returns the "Location" point (origin) of <me>.
Location() const169   const gp_Pnt& Location() const { return axis.Location(); }
170 
171   //! Returns the "XDirection" of <me>.
XDirection() const172   const gp_Dir& XDirection() const { return vxdir; }
173 
174   //! Returns the "YDirection" of <me>.
YDirection() const175   const gp_Dir& YDirection() const { return vydir; }
176 
177   //! Returns  True if  the  coordinate  system is right-handed. i.e.
178   //! XDirection().Crossed(YDirection()).Dot(Direction()) > 0
Direct() const179   Standard_Boolean Direct() const { return (vxdir.Crossed (vydir).Dot (axis.Direction()) > 0.); }
180 
181   //! Returns True if
182   //! . the distance between the "Location" point of <me> and
183   //! <theOther> is lower or equal to theLinearTolerance and
184   //! . the distance between the "Location" point of <theOther> and
185   //! <me> is lower or equal to theLinearTolerance and
186   //! . the main direction of <me> and the main direction of
187   //! <theOther> are parallel (same or opposite orientation).
188   Standard_Boolean IsCoplanar (const gp_Ax3& theOther, const Standard_Real theLinearTolerance, const Standard_Real theAngularTolerance) const;
189 
190   //! Returns True if
191   //! . the distance between <me> and the "Location" point of theA1
192   //! is lower of equal to theLinearTolerance and
193   //! . the distance between theA1 and the "Location" point of <me>
194   //! is lower or equal to theLinearTolerance and
195   //! . the main direction of <me> and the direction of theA1 are normal.
196   Standard_Boolean IsCoplanar (const gp_Ax1& theA1, const Standard_Real theLinearTolerance, const Standard_Real theAngularTolerance) const;
197 
198   Standard_EXPORT void Mirror (const gp_Pnt& theP);
199 
200   //! Performs the symmetrical transformation of an axis
201   //! placement with respect to the point theP which is the
202   //! center of the symmetry.
203   //! Warnings :
204   //! The main direction of the axis placement is not changed.
205   //! The "XDirection" and the "YDirection" are reversed.
206   //! So the axis placement stay right handed.
207   Standard_NODISCARD Standard_EXPORT gp_Ax3 Mirrored (const gp_Pnt& theP) const;
208 
209   Standard_EXPORT void Mirror (const gp_Ax1& theA1);
210 
211   //! Performs the symmetrical transformation of an axis
212   //! placement with respect to an axis placement which
213   //! is the axis of the symmetry.
214   //! The transformation is performed on the "Location"
215   //! point, on the "XDirection" and "YDirection".
216   //! The resulting main "Direction" is the cross product between
217   //! the "XDirection" and the "YDirection" after transformation.
218   Standard_NODISCARD Standard_EXPORT gp_Ax3 Mirrored (const gp_Ax1& theA1) const;
219 
220   Standard_EXPORT void Mirror (const gp_Ax2& theA2);
221 
222   //! Performs the symmetrical transformation of an axis
223   //! placement with respect to a plane.
224   //! The axis placement  <theA2> locates the plane of the symmetry :
225   //! (Location, XDirection, YDirection).
226   //! The transformation is performed on the "Location"
227   //! point, on the "XDirection" and "YDirection".
228   //! The resulting main "Direction" is the cross product between
229   //! the "XDirection" and the "YDirection" after transformation.
230   Standard_NODISCARD Standard_EXPORT gp_Ax3 Mirrored (const gp_Ax2& theA2) const;
231 
Rotate(const gp_Ax1 & theA1,const Standard_Real theAng)232   void Rotate (const gp_Ax1& theA1, const Standard_Real theAng)
233   {
234     axis.Rotate (theA1, theAng);
235     vxdir.Rotate (theA1, theAng);
236     vydir.Rotate (theA1, theAng);
237   }
238 
239   //! Rotates an axis placement. <theA1> is the axis of the
240   //! rotation . theAng is the angular value of the rotation
241   //! in radians.
Rotated(const gp_Ax1 & theA1,const Standard_Real theAng) const242   Standard_NODISCARD gp_Ax3 Rotated (const gp_Ax1& theA1, const Standard_Real theAng) const
243   {
244     gp_Ax3 aTemp = *this;
245     aTemp.Rotate (theA1, theAng);
246     return aTemp;
247   }
248 
Scale(const gp_Pnt & theP,const Standard_Real theS)249   void Scale (const gp_Pnt& theP, const Standard_Real theS)
250   {
251     axis.Scale (theP, theS);
252     if (theS < 0.)
253     {
254       vxdir.Reverse();
255       vydir.Reverse();
256     }
257   }
258 
259   //! Applies a scaling transformation on the axis placement.
260   //! The "Location" point of the axisplacement is modified.
261   //! Warnings :
262   //! If the scale <theS> is negative :
263   //! . the main direction of the axis placement is not changed.
264   //! . The "XDirection" and the "YDirection" are reversed.
265   //! So the axis placement stay right handed.
Scaled(const gp_Pnt & theP,const Standard_Real theS) const266   Standard_NODISCARD gp_Ax3 Scaled (const gp_Pnt& theP, const Standard_Real theS) const
267   {
268     gp_Ax3 aTemp = *this;
269     aTemp.Scale (theP, theS);
270     return aTemp;
271   }
272 
Transform(const gp_Trsf & theT)273   void Transform (const gp_Trsf& theT)
274   {
275     axis.Transform (theT);
276     vxdir.Transform (theT);
277     vydir.Transform (theT);
278   }
279 
280   //! Transforms an axis placement with a Trsf.
281   //! The "Location" point, the "XDirection" and the
282   //! "YDirection" are transformed with theT.  The resulting
283   //! main "Direction" of <me> is the cross product between
284   //! the "XDirection" and the "YDirection" after transformation.
Transformed(const gp_Trsf & theT) const285   Standard_NODISCARD gp_Ax3 Transformed (const gp_Trsf& theT) const
286   {
287     gp_Ax3 aTemp = *this;
288     aTemp.Transform (theT);
289     return aTemp;
290   }
291 
Translate(const gp_Vec & theV)292   void Translate (const gp_Vec& theV) { axis.Translate (theV); }
293 
294   //! Translates an axis plaxement in the direction of the vector
295   //! <theV>. The magnitude of the translation is the vector's magnitude.
Translated(const gp_Vec & theV) const296   Standard_NODISCARD gp_Ax3 Translated (const gp_Vec& theV) const
297   {
298     gp_Ax3 aTemp = *this;
299     aTemp.Translate (theV);
300     return aTemp;
301   }
302 
Translate(const gp_Pnt & theP1,const gp_Pnt & theP2)303   void Translate (const gp_Pnt& theP1, const gp_Pnt& theP2) { Translate (gp_Vec (theP1, theP2)); }
304 
305   //! Translates an axis placement from the point <theP1> to the
306   //! point <theP2>.
Translated(const gp_Pnt & theP1,const gp_Pnt & theP2) const307   Standard_NODISCARD gp_Ax3 Translated (const gp_Pnt& theP1, const gp_Pnt& theP2) const { return Translated (gp_Vec (theP1, theP2)); }
308 
309   //! Dumps the content of me into the stream
310   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
311 
312   //! Inits the content of me from the stream
313   Standard_EXPORT Standard_Boolean InitFromJson (const Standard_SStream& theSStream, Standard_Integer& theStreamPos);
314 
315 private:
316 
317   gp_Ax1 axis;
318   gp_Dir vydir;
319   gp_Dir vxdir;
320 
321 };
322 
323 // =======================================================================
324 // function : gp_Ax3
325 // purpose  :
326 // =======================================================================
gp_Ax3(const gp_Ax2 & theA)327 inline gp_Ax3::gp_Ax3 (const gp_Ax2& theA)
328 : axis (theA.Axis()),
329   vydir (theA.YDirection()),
330   vxdir (theA.XDirection())
331 {}
332 
333 // =======================================================================
334 // function : Ax2
335 // purpose  :
336 // =======================================================================
Ax2() const337 inline gp_Ax2  gp_Ax3::Ax2()const
338 {
339   gp_Dir aZz = axis.Direction();
340   if (!Direct())
341   {
342     aZz.Reverse();
343   }
344   return gp_Ax2 (axis.Location(), aZz, vxdir);
345 }
346 
347 // =======================================================================
348 // function : SetAxis
349 // purpose  :
350 // =======================================================================
SetAxis(const gp_Ax1 & theA1)351 inline void  gp_Ax3::SetAxis (const gp_Ax1& theA1)
352 {
353   Standard_Boolean isDirect = Direct();
354   axis = theA1;
355   vxdir = axis.Direction().CrossCrossed (vxdir, axis.Direction());
356   if (isDirect)
357   {
358     vydir = axis.Direction().Crossed (vxdir);
359   }
360   else
361   {
362     vydir = vxdir.Crossed (axis.Direction());
363   }
364 }
365 
366 // =======================================================================
367 // function : SetDirection
368 // purpose  :
369 // =======================================================================
SetDirection(const gp_Dir & theV)370 inline void  gp_Ax3::SetDirection (const gp_Dir& theV)
371 {
372   Standard_Boolean isDirect = Direct();
373   axis.SetDirection (theV);
374   vxdir = theV.CrossCrossed (vxdir, theV);
375   if (isDirect)
376   {
377     vydir = theV.Crossed (vxdir);
378   }
379   else
380   {
381     vydir = vxdir.Crossed (theV);
382   }
383 }
384 
385 // =======================================================================
386 // function : SetXDirection
387 // purpose  :
388 // =======================================================================
SetXDirection(const gp_Dir & theVx)389 inline void  gp_Ax3::SetXDirection (const gp_Dir& theVx)
390 {
391   Standard_Boolean isDirect = Direct();
392   vxdir = axis.Direction().CrossCrossed (theVx, axis.Direction());
393   if (isDirect)
394   {
395     vydir = axis.Direction().Crossed (vxdir);
396   }
397   else
398   {
399     vydir = vxdir.Crossed (axis.Direction());
400   }
401 }
402 
403 // =======================================================================
404 // function : SetYDirection
405 // purpose  :
406 // =======================================================================
SetYDirection(const gp_Dir & theVy)407 inline void  gp_Ax3::SetYDirection (const gp_Dir& theVy)
408 {
409   Standard_Boolean isDirect = Direct();
410   vxdir = theVy.Crossed (axis.Direction());
411   vydir = (axis.Direction()).Crossed (vxdir);
412   if (!isDirect)
413   {
414     vxdir.Reverse();
415   }
416 }
417 
418 // =======================================================================
419 // function : IsCoplanar
420 // purpose  :
421 // =======================================================================
IsCoplanar(const gp_Ax3 & theOther,const Standard_Real theLinearTolerance,const Standard_Real theAngularTolerance) const422 inline Standard_Boolean gp_Ax3::IsCoplanar (const gp_Ax3& theOther,
423                                             const Standard_Real theLinearTolerance,
424                                             const Standard_Real theAngularTolerance)const
425 {
426   gp_Vec aVec (axis.Location(), theOther.axis.Location());
427   Standard_Real aD1 = gp_Vec (axis.Direction()).Dot(aVec);
428   if (aD1 < 0)
429   {
430     aD1 = -aD1;
431   }
432   Standard_Real aD2 = gp_Vec (theOther.axis.Direction()).Dot(aVec);
433   if (aD2 < 0)
434   {
435     aD2 = -aD2;
436   }
437   return (aD1 <= theLinearTolerance && aD2 <= theLinearTolerance &&
438           axis.IsParallel (theOther.axis, theAngularTolerance));
439 }
440 
441 // =======================================================================
442 // function : IsCoplanar
443 // purpose  :
444 // =======================================================================
IsCoplanar(const gp_Ax1 & theA1,const Standard_Real theLinearTolerance,const Standard_Real theAngularTolerance) const445 inline Standard_Boolean gp_Ax3::IsCoplanar (const gp_Ax1& theA1,
446                                             const Standard_Real theLinearTolerance,
447                                             const Standard_Real theAngularTolerance)const
448 {
449   gp_Vec aVec (axis.Location(), theA1.Location());
450   Standard_Real aD1 = gp_Vec (axis.Direction()).Dot (aVec);
451   if (aD1 < 0)
452   {
453     aD1 = -aD1;
454   }
455   Standard_Real aD2 = (gp_Vec (theA1.Direction()).Crossed (aVec)).Magnitude();
456   if (aD2 < 0)
457   {
458     aD2 = -aD2;
459   }
460   return (aD1 <= theLinearTolerance && aD2 <= theLinearTolerance &&
461           axis.IsNormal (theA1, theAngularTolerance));
462 }
463 
464 #endif // _gp_Ax3_HeaderFile
465