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