0027919: Visualization - support multiple transformation persistence groups within...
[occt.git] / src / gp / gp_GTrsf.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_GTrsf_HeaderFile
16 #define _gp_GTrsf_HeaderFile
17
18 #include <gp_Ax1.hxx>
19 #include <gp_Ax2.hxx>
20 #include <gp_Mat.hxx>
21 #include <gp_Trsf.hxx>
22 #include <gp_TrsfForm.hxx>
23 #include <gp_XYZ.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <Standard_OutOfRange.hxx>
26
27 class gp_Trsf;
28 class gp_Mat;
29
30 // Avoid possible conflict with SetForm macro defined by windows.h
31 #ifdef SetForm
32 #undef SetForm
33 #endif
34
35 //! Defines a non-persistent transformation in 3D space.
36 //! This transformation is a general transformation.
37 //! It can be a gp_Trsf, an affinity, or you can define
38 //! your own transformation giving the matrix of transformation.
39 //!
40 //! With a gp_GTrsf you can transform only a triplet of coordinates gp_XYZ.
41 //! It is not possible to transform other geometric objects
42 //! because these transformations can change the nature of non-elementary geometric objects.
43 //! The transformation gp_GTrsf can be represented as follow:
44 //! @code
45 //!    V1   V2   V3    T       XYZ        XYZ
46 //! | a11  a12  a13   a14 |   | x |      | x'|
47 //! | a21  a22  a23   a24 |   | y |      | y'|
48 //! | a31  a32  a33   a34 |   | z |   =  | z'|
49 //! |  0    0    0     1  |   | 1 |      | 1 |
50 //! @endcode
51 //! where {V1, V2, V3} define the vectorial part of the
52 //! transformation and T defines the translation part of the transformation.
53 //! Warning
54 //! A gp_GTrsf transformation is only applicable to coordinates.
55 //! Be careful if you apply such a transformation to all points of a geometric object,
56 //! as this can change the nature of the object and thus render it incoherent!
57 //! Typically, a circle is transformed into an ellipse by an affinity transformation.
58 //! To avoid modifying the nature of an object, use a gp_Trsf transformation instead,
59 //! as objects of this class respect the nature of geometric objects.
60 class gp_GTrsf 
61 {
62 public:
63
64   DEFINE_STANDARD_ALLOC
65
66   //! Returns the Identity transformation.
67   gp_GTrsf()
68   {
69     shape = gp_Identity;
70     matrix.SetScale (1.0);
71     loc.SetCoord (0.0, 0.0, 0.0);
72     scale = 1.0;
73   }
74
75   //! Converts the gp_Trsf transformation theT into a
76   //! general transformation, i.e. Returns a GTrsf with
77   //! the same matrix of coefficients as the Trsf theT.
78   gp_GTrsf (const gp_Trsf& theT)
79   {
80     shape = theT.Form();
81     matrix = theT.matrix;
82     loc = theT.TranslationPart();
83     scale = theT.ScaleFactor();
84   }
85
86   //! Creates a transformation based on the matrix theM and the
87   //! vector theV where theM defines the vectorial part of
88   //! the transformation, and V the translation part, or
89   gp_GTrsf (const gp_Mat& theM, const gp_XYZ& theV)
90   : matrix (theM),
91     loc (theV)
92   {
93     shape = gp_Other;
94     scale = 0.0;
95   }
96
97   //! Changes this transformation into an affinity of ratio theRatio
98   //! with respect to the axis theA1.
99   //! Note: an affinity is a point-by-point transformation that
100   //! transforms any point P into a point P' such that if H is
101   //! the orthogonal projection of P on the axis theA1 or the
102   //! plane A2, the vectors HP and HP' satisfy:
103   //! HP' = theRatio * HP.
104   void SetAffinity (const gp_Ax1& theA1, const Standard_Real theRatio);
105
106   //! Changes this transformation into an affinity of ratio theRatio
107   //! with respect to  the plane defined by the origin, the "X Direction" and
108   //! the "Y Direction" of coordinate system theA2.
109   //! Note: an affinity is a point-by-point transformation that
110   //! transforms any point P into a point P' such that if H is
111   //! the orthogonal projection of P on the axis A1 or the
112   //! plane theA2, the vectors HP and HP' satisfy:
113   //! HP' = theRatio * HP.
114   void SetAffinity (const gp_Ax2& theA2, const Standard_Real theRatio);
115
116   //! Replaces  the coefficient (theRow, theCol) of the matrix representing
117   //! this transformation by theValue.  Raises OutOfRange
118   //! if  theRow < 1 or theRow > 3 or theCol < 1 or theCol > 4
119   void SetValue (const Standard_Integer theRow, const Standard_Integer theCol, const Standard_Real theValue);
120
121   //! Replaces the vectorial part of this transformation by theMatrix.
122   void SetVectorialPart (const gp_Mat& theMatrix)
123   {
124     matrix = theMatrix;
125     shape = gp_Other;
126     scale = 0.0;
127   }
128
129   //! Replaces the translation part of
130   //! this transformation by the coordinates of the number triple theCoord.
131   Standard_EXPORT void SetTranslationPart (const gp_XYZ& theCoord);
132
133   //! Assigns the vectorial and translation parts of theT to this transformation.
134   void SetTrsf (const gp_Trsf& theT)
135   {
136     shape = theT.shape;
137     matrix = theT.matrix;
138     loc = theT.loc;
139     scale = theT.scale;
140   }
141
142   //! Returns true if the determinant of the vectorial part of
143   //! this transformation is negative.
144   Standard_Boolean IsNegative() const { return matrix.Determinant() < 0.0; }
145
146   //! Returns true if this transformation is singular (and
147   //! therefore, cannot be inverted).
148   //! Note: The Gauss LU decomposition is used to invert the
149   //! transformation matrix. Consequently, the transformation
150   //! is considered as singular if the largest pivot found is less
151   //! than or equal to gp::Resolution().
152   //! Warning
153   //! If this transformation is singular, it cannot be inverted.
154   Standard_Boolean IsSingular() const { return matrix.IsSingular(); }
155
156   //! Returns the nature of the transformation.  It can be an
157   //! identity transformation, a rotation, a translation, a mirror
158   //! transformation (relative to a point, an axis or a plane), a
159   //! scaling transformation, a compound transformation or
160   //! some other type of transformation.
161   gp_TrsfForm Form() const { return shape; }
162
163   //! verify and set the shape of the GTrsf Other or CompoundTrsf
164   //! Ex :
165   //! @code
166   //! myGTrsf.SetValue(row1,col1,val1);
167   //! myGTrsf.SetValue(row2,col2,val2);
168   //! ...
169   //! myGTrsf.SetForm();
170   //! @endcode
171   Standard_EXPORT void SetForm();
172
173   //! Returns the translation part of the GTrsf.
174   const gp_XYZ& TranslationPart() const { return loc; }
175
176   //! Computes the vectorial part of the GTrsf. The returned Matrix
177   //! is a  3*3 matrix.
178   const gp_Mat& VectorialPart() const { return matrix; }
179
180   //! Returns the coefficients of the global matrix of transformation.
181   //! Raises OutOfRange if theRow < 1 or theRow > 3 or theCol < 1 or theCol > 4
182   Standard_Real Value (const Standard_Integer theRow, const Standard_Integer theCol) const;
183
184   Standard_Real operator() (const Standard_Integer theRow, const Standard_Integer theCol) const { return Value (theRow, theCol); }
185
186   Standard_EXPORT void Invert();
187
188   //! Computes the reverse transformation.
189   //! Raises an exception if the matrix of the transformation
190   //! is not inversible.
191   Standard_NODISCARD gp_GTrsf Inverted() const
192   {
193     gp_GTrsf aT = *this;
194     aT.Invert();
195     return aT;
196   }
197
198   //! Computes the transformation composed from theT and <me>.
199   //! In a C++ implementation you can also write Tcomposed = <me> * theT.
200   //! Example :
201   //! @code
202   //! gp_GTrsf T1, T2, Tcomp; ...............
203   //! //composition :
204   //! Tcomp = T2.Multiplied(T1);         // or   (Tcomp = T2 * T1)
205   //! // transformation of a point
206   //! gp_XYZ P(10.,3.,4.);
207   //! gp_XYZ P1(P);
208   //! Tcomp.Transforms(P1);               //using Tcomp
209   //! gp_XYZ P2(P);
210   //! T1.Transforms(P2);                  //using T1 then T2
211   //! T2.Transforms(P2);                  // P1 = P2 !!!
212   //! @endcode
213   Standard_NODISCARD gp_GTrsf Multiplied (const gp_GTrsf& theT) const
214    {
215     gp_GTrsf aTres = *this;
216     aTres.Multiply (theT);
217     return aTres;
218   }
219
220   Standard_NODISCARD gp_GTrsf operator * (const gp_GTrsf& theT)  const { return Multiplied (theT); }
221
222   //! Computes the transformation composed with <me> and theT.
223   //! <me> = <me> * theT
224   Standard_EXPORT void Multiply (const gp_GTrsf& theT);
225
226   void operator *= (const gp_GTrsf& theT) { Multiply (theT); }
227
228   //! Computes the product of the transformation theT and this
229   //! transformation and assigns the result to this transformation.
230   //! this = theT * this
231   Standard_EXPORT void PreMultiply (const gp_GTrsf& theT);
232
233   Standard_EXPORT void Power (const Standard_Integer theN);
234
235   //! Computes:
236   //! -   the product of this transformation multiplied by itself
237   //! theN times, if theN is positive, or
238   //! -   the product of the inverse of this transformation
239   //! multiplied by itself |theN| times, if theN is negative.
240   //! If theN equals zero, the result is equal to the Identity
241   //! transformation.
242   //! I.e.:  <me> * <me> * .......* <me>, theN time.
243   //! if theN =0 <me> = Identity
244   //! if theN < 0 <me> = <me>.Inverse() *...........* <me>.Inverse().
245   //!
246   //! Raises an exception if N < 0 and if the matrix of the
247   //! transformation not inversible.
248   Standard_NODISCARD gp_GTrsf Powered (const Standard_Integer theN) const
249   {
250     gp_GTrsf aT = *this;
251     aT.Power (theN);
252     return aT;
253   }
254
255   void Transforms (gp_XYZ& theCoord) const;
256
257   //! Transforms a triplet XYZ with a GTrsf.
258   void Transforms (Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ) const;
259
260   gp_Trsf Trsf() const;
261
262   //! Convert transformation to 4x4 matrix.
263   template<class T>
264   void GetMat4 (NCollection_Mat4<T>& theMat) const
265   {
266     if (shape == gp_Identity)
267     {
268       theMat.InitIdentity();
269       return;
270     }
271
272     theMat.SetValue (0, 0, static_cast<T> (Value (1, 1)));
273     theMat.SetValue (0, 1, static_cast<T> (Value (1, 2)));
274     theMat.SetValue (0, 2, static_cast<T> (Value (1, 3)));
275     theMat.SetValue (0, 3, static_cast<T> (Value (1, 4)));
276     theMat.SetValue (1, 0, static_cast<T> (Value (2, 1)));
277     theMat.SetValue (1, 1, static_cast<T> (Value (2, 2)));
278     theMat.SetValue (1, 2, static_cast<T> (Value (2, 3)));
279     theMat.SetValue (1, 3, static_cast<T> (Value (2, 4)));
280     theMat.SetValue (2, 0, static_cast<T> (Value (3, 1)));
281     theMat.SetValue (2, 1, static_cast<T> (Value (3, 2)));
282     theMat.SetValue (2, 2, static_cast<T> (Value (3, 3)));
283     theMat.SetValue (2, 3, static_cast<T> (Value (3, 4)));
284     theMat.SetValue (3, 0, static_cast<T> (0));
285     theMat.SetValue (3, 1, static_cast<T> (0));
286     theMat.SetValue (3, 2, static_cast<T> (0));
287     theMat.SetValue (3, 3, static_cast<T> (1));
288   }
289
290   //! Convert transformation from 4x4 matrix.
291   template<class T>
292   void SetMat4 (const NCollection_Mat4<T>& theMat)
293   {
294     shape = gp_Other;
295     scale = 0.0;
296     matrix.SetValue (1, 1, theMat.GetValue (0, 0));
297     matrix.SetValue (1, 2, theMat.GetValue (0, 1));
298     matrix.SetValue (1, 3, theMat.GetValue (0, 2));
299     matrix.SetValue (2, 1, theMat.GetValue (1, 0));
300     matrix.SetValue (2, 2, theMat.GetValue (1, 1));
301     matrix.SetValue (2, 3, theMat.GetValue (1, 2));
302     matrix.SetValue (3, 1, theMat.GetValue (2, 0));
303     matrix.SetValue (3, 2, theMat.GetValue (2, 1));
304     matrix.SetValue (3, 3, theMat.GetValue (2, 2));
305     loc.SetCoord (theMat.GetValue (0, 3), theMat.GetValue (1, 3), theMat.GetValue (2, 3));
306   }
307
308   //! Dumps the content of me into the stream
309   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
310
311 private:
312
313   gp_Mat matrix;
314   gp_XYZ loc;
315   gp_TrsfForm shape;
316   Standard_Real scale;
317
318 };
319
320
321 //=======================================================================
322 //function : SetAffinity
323 // purpose :
324 //=======================================================================
325 inline void gp_GTrsf::SetAffinity (const gp_Ax1& theA1, const Standard_Real theRatio)
326 {
327   shape = gp_Other;
328   scale = 0.0;
329   matrix.SetDot (theA1.Direction().XYZ());
330   matrix.Multiply (1.0 - theRatio);
331   matrix.SetDiagonal (matrix.Value (1,1) + theRatio,
332                       matrix.Value (2,2) + theRatio,
333                       matrix.Value (3,3) + theRatio);
334   loc = theA1.Location().XYZ();
335   loc.Reverse ();
336   loc.Multiply (matrix);
337   loc.Add (theA1.Location().XYZ());
338 }
339
340 //=======================================================================
341 //function : SetAffinity
342 // purpose :
343 //=======================================================================
344 inline void gp_GTrsf::SetAffinity (const gp_Ax2& theA2, const Standard_Real theRatio)
345 {
346   shape = gp_Other;
347   scale = 0.0;
348   matrix.SetDot (theA2.Direction().XYZ());
349   matrix.Multiply (theRatio - 1.);
350   loc = theA2.Location().XYZ();
351   loc.Reverse ();
352   loc.Multiply (matrix);
353   matrix.SetDiagonal (matrix.Value (1,1) + 1.,
354                       matrix.Value (2,2) + 1.,
355                       matrix.Value (3,3) + 1.);
356 }
357
358 //=======================================================================
359 //function : SetValue
360 // purpose :
361 //=======================================================================
362 inline void gp_GTrsf::SetValue (const Standard_Integer theRow,
363                                 const Standard_Integer theCol,
364                                 const Standard_Real theValue)
365 {
366   Standard_OutOfRange_Raise_if
367     (theRow < 1 || theRow > 3 || theCol < 1 || theCol > 4, " ");
368   if (theCol == 4)
369   {
370     loc.SetCoord (theRow, theValue);
371     if (shape == gp_Identity)
372     {
373       shape = gp_Translation;
374     }
375     return;
376   }
377   else
378   {
379     if (!(shape == gp_Other) && !(scale == 1.0))
380     {
381       matrix.Multiply (scale);
382     }
383     matrix.SetValue (theRow, theCol, theValue);
384     shape = gp_Other;
385     scale = 0.0;
386     return;
387   }
388 }
389
390 //=======================================================================
391 //function : Value
392 // purpose :
393 //=======================================================================
394 inline Standard_Real gp_GTrsf::Value (const Standard_Integer theRow,
395                                       const Standard_Integer theCol) const
396 {
397   Standard_OutOfRange_Raise_if
398     (theRow < 1 || theRow > 3 || theCol < 1 || theCol > 4, " ");
399   if (theCol == 4)
400   {
401     return loc.Coord (theRow);
402   }
403   if (shape == gp_Other)
404   {
405     return matrix.Value (theRow, theCol);
406   }
407   return scale * matrix.Value (theRow, theCol);
408 }
409
410 //=======================================================================
411 //function : Transforms
412 // purpose :
413 //=======================================================================
414 inline void gp_GTrsf::Transforms (gp_XYZ& theCoord) const
415 {
416   theCoord.Multiply (matrix);
417   if (!(shape == gp_Other) && !(scale == 1.0))
418   {
419     theCoord.Multiply (scale);
420   }
421   theCoord.Add (loc);
422 }
423
424 //=======================================================================
425 //function : Transforms
426 // purpose :
427 //=======================================================================
428 inline void gp_GTrsf::Transforms (Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ) const
429 {
430   gp_XYZ aTriplet (theX, theY, theZ);
431   aTriplet.Multiply (matrix);
432   if (!(shape == gp_Other) && !(scale == 1.0))
433   {
434     aTriplet.Multiply (scale);
435   }
436   aTriplet.Add (loc);
437   aTriplet.Coord (theX, theY, theZ);
438 }
439
440 //=======================================================================
441 //function : Trsf
442 // purpose :
443 //=======================================================================
444 inline gp_Trsf gp_GTrsf::Trsf() const
445 {
446   if (Form() == gp_Other)
447   {
448     throw Standard_ConstructionError("gp_GTrsf::Trsf() - non-orthogonal GTrsf");
449   }
450   gp_Trsf aT;
451   aT.shape = shape;
452   aT.scale = scale;
453   aT.matrix = matrix;
454   aT.loc = loc;
455   return aT;
456 }
457
458 #endif // _gp_GTrsf_HeaderFile