1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 // JCV 30/08/90 Modif passage version C++ 2.0 sur Sun
16 // JCV 1/10/90 Changement de nom du package vgeom -> gp
17 // JCV 4/10/90 codage sur la forme de la transformation shape,Scaling,negative
18 // JCV 10/12/90 Modif introduction des classes Mat et XYZ dans gp
20 #define No_Standard_OutOfRange
27 #include <gp_GTrsf.hxx>
30 #include <gp_Quaternion.hxx>
31 #include <gp_Trsf.hxx>
32 #include <gp_Trsf2d.hxx>
35 #include <Standard_ConstructionError.hxx>
36 #include <Standard_OutOfRange.hxx>
38 //=======================================================================
40 //purpose : Constructor from 2d
41 //=======================================================================
42 gp_Trsf::gp_Trsf (const gp_Trsf2d& T) :
43 scale(T.ScaleFactor()),
45 loc(T.TranslationPart().X(),T.TranslationPart().Y(), 0.0)
47 const gp_Mat2d& M = T.HVectorialPart();
53 if (shape == gp_Ax1Mirror)
60 //=======================================================================
61 //function : SetMirror
63 //=======================================================================
65 void gp_Trsf::SetMirror (const gp_Ax1& A1)
69 loc = A1.Location().XYZ();
70 matrix.SetDot(A1.Direction().XYZ());
72 matrix.SetDiagonal (matrix.Value (1,1) + 1,
73 matrix.Value (2,2) + 1,
74 matrix.Value (3,3) + 1);
76 loc.Multiply (matrix);
77 loc.Add (A1.Location().XYZ());
81 //=======================================================================
82 //function : SetMirror
84 //=======================================================================
86 void gp_Trsf::SetMirror (const gp_Ax2& A2)
90 loc = A2.Location().XYZ();
91 matrix.SetDot(A2.Direction().XYZ());
93 matrix.SetDiagonal (matrix.Value (1,1) - 1,
94 matrix.Value (2,2) - 1,
95 matrix.Value (3,3) - 1);
97 loc.Multiply (matrix);
98 loc.Add (A2.Location().XYZ());
101 //=======================================================================
102 //function : SetRotation
104 //=======================================================================
106 void gp_Trsf::SetRotation (const gp_Ax1& A1,
107 const Standard_Real Ang)
111 loc = A1.Location().XYZ();
112 matrix.SetRotation (A1.Direction().XYZ(), Ang);
114 loc.Multiply (matrix);
115 loc.Add (A1.Location().XYZ());
118 //=======================================================================
119 //function : SetRotation
121 //=======================================================================
123 void gp_Trsf::SetRotation (const gp_Quaternion& R)
127 loc.SetCoord (0., 0., 0.);
128 matrix = R.GetMatrix();
131 //=======================================================================
132 //function : SetScale
134 //=======================================================================
136 void gp_Trsf::SetScale (const gp_Pnt& P, const Standard_Real S)
141 Standard_Real As = scale;
142 if (As < 0) As = - As;
143 Standard_ConstructionError_Raise_if
144 (As <= gp::Resolution(),"gp_Trsf::SetScaleFactor");
145 matrix.SetIdentity ();
149 //=======================================================================
150 //function : SetTransformation
152 //=======================================================================
154 void gp_Trsf::SetTransformation (const gp_Ax3& FromA1,
157 shape = gp_CompoundTrsf;
159 // matrix from XOY ToA2 :
160 matrix.SetRows (ToA2.XDirection().XYZ(),
161 ToA2.YDirection().XYZ(),
162 ToA2. Direction().XYZ());
163 loc = ToA2.Location().XYZ();
164 loc.Multiply (matrix);
167 // matrix FromA1 to XOY :
168 const gp_XYZ& xDir = FromA1.XDirection().XYZ();
169 const gp_XYZ& yDir = FromA1.YDirection().XYZ();
170 const gp_XYZ& zDir = FromA1.Direction().XYZ();
172 gp_Mat MA1 (xDir, yDir, zDir);
173 gp_XYZ MA1loc = FromA1.Location().XYZ();
175 // matrix * MA1 => FromA1 ToA2 :
176 MA1loc.Multiply (matrix);
178 matrix.Multiply (MA1);
181 void gp_Trsf::SetTransformation (const gp_Ax3& A3)
183 shape = gp_CompoundTrsf;
185 matrix.SetRows (A3.XDirection().XYZ(),
186 A3.YDirection().XYZ(),
187 A3. Direction().XYZ());
188 loc = A3.Location().XYZ();
189 loc.Multiply (matrix);
193 //=======================================================================
194 //function : SetTransformation
196 //=======================================================================
198 void gp_Trsf::SetTransformation (const gp_Quaternion& R, const gp_Vec& T)
200 shape = gp_CompoundTrsf;
203 matrix = R.GetMatrix();
206 //=======================================================================
207 //function : SetDisplacement
209 //=======================================================================
211 void gp_Trsf::SetDisplacement (const gp_Ax3& FromA1,
214 shape = gp_CompoundTrsf;
216 // matrix from ToA2 to XOY :
217 matrix.SetCol (1, ToA2.XDirection().XYZ());
218 matrix.SetCol (2, ToA2.YDirection().XYZ());
219 matrix.SetCol (3, ToA2.Direction().XYZ());
220 loc = ToA2.Location().XYZ();
221 // matrix XOY to FromA1 :
222 const gp_XYZ& xDir = FromA1.XDirection().XYZ();
223 const gp_XYZ& yDir = FromA1.YDirection().XYZ();
224 const gp_XYZ& zDir = FromA1.Direction().XYZ();
225 gp_Mat MA1 (xDir, yDir, zDir);
227 gp_XYZ MA1loc = FromA1.Location().XYZ();
228 MA1loc.Multiply (MA1);
231 MA1loc.Multiply (matrix);
233 matrix.Multiply (MA1);
236 //=======================================================================
237 //function : SetTranslationPart
239 //=======================================================================
241 void gp_Trsf::SetTranslationPart (const gp_Vec& V) {
244 const Standard_Boolean locnull = (loc.SquareModulus() < gp::Resolution());
249 if (!locnull) shape = gp_Translation;
252 case gp_Translation :
253 if (locnull) shape = gp_Identity;
261 case gp_CompoundTrsf :
264 shape = gp_CompoundTrsf;
270 //=======================================================================
271 //function : SetScaleFactor
273 //=======================================================================
275 void gp_Trsf::SetScaleFactor (const Standard_Real S)
277 Standard_Real As = S;
278 if (As < 0) As = - As;
279 Standard_ConstructionError_Raise_if
280 (As <= gp::Resolution(),"gp_Trsf::SetScaleFactor");
283 if (As < 0) As = - As;
284 Standard_Boolean unit = As <= gp::Resolution(); // = (scale == 1)
286 if (As < 0) As = - As;
287 Standard_Boolean munit = As <= gp::Resolution(); // = (scale == -1)
291 case gp_Translation :
292 if (!unit) shape = gp_Scale;
293 if (munit) shape = gp_PntMirror;
296 if (!unit) shape = gp_CompoundTrsf;
301 if (!munit) shape = gp_Scale;
302 if (unit) shape = gp_Identity;
305 if (unit) shape = gp_Identity;
306 if (munit) shape = gp_PntMirror;
308 case gp_CompoundTrsf :
315 //=======================================================================
316 //function : SetValues
318 // 06-01-1998 modified by PMN : On utilise TolDist pour evaluer si les coeffs
319 // sont nuls : c'est toujours mieux que gp::Resolution !
320 //=======================================================================
322 void gp_Trsf::SetValues(const Standard_Real a11,
323 const Standard_Real a12,
324 const Standard_Real a13,
325 const Standard_Real a14,
326 const Standard_Real a21,
327 const Standard_Real a22,
328 const Standard_Real a23,
329 const Standard_Real a24,
330 const Standard_Real a31,
331 const Standard_Real a32,
332 const Standard_Real a33,
333 const Standard_Real a34)
335 gp_XYZ col1(a11,a21,a31);
336 gp_XYZ col2(a12,a22,a32);
337 gp_XYZ col3(a13,a23,a33);
338 gp_XYZ col4(a14,a24,a34);
339 // compute the determinant
340 gp_Mat M(col1,col2,col3);
341 Standard_Real s = M.Determinant();
342 Standard_Real As = s;
343 if (As < 0) As = - As;
344 Standard_ConstructionError_Raise_if
345 (As < gp::Resolution(),"gp_Trsf::SetValues, null determinant");
353 shape = gp_CompoundTrsf;
361 //=======================================================================
362 //function : GetRotation
364 //=======================================================================
366 gp_Quaternion gp_Trsf::GetRotation () const
368 return gp_Quaternion (matrix);
371 //=======================================================================
372 //function : VectorialPart
374 //=======================================================================
376 gp_Mat gp_Trsf::VectorialPart () const
378 if (scale == 1.0) return matrix;
380 if (shape == gp_Scale || shape == gp_PntMirror)
381 M.SetDiagonal(scale*M.Value(1,1),
389 //=======================================================================
392 //=======================================================================
394 void gp_Trsf::Invert()
397 // X' = scale * R * X + T => X = (R / scale) * ( X' - T)
399 // Pour les gp_Trsf puisque le scale est extrait de la gp_Matrice R
400 // on a toujours determinant (R) = 1 et R-1 = R transposee.
401 if (shape == gp_Identity) { }
402 else if (shape == gp_Translation || shape == gp_PntMirror) loc.Reverse();
403 else if (shape == gp_Scale) {
404 Standard_ConstructionError_Raise_if (Abs(scale) <= gp::Resolution(), "gp_Trsf::Invert() - transformation has zero scale");
406 loc.Multiply (-scale);
409 Standard_ConstructionError_Raise_if (Abs(scale) <= gp::Resolution(), "gp_Trsf::Invert() - transformation has zero scale");
412 loc.Multiply (matrix);
413 loc.Multiply (-scale);
417 //=======================================================================
418 //function : Multiply
420 //=======================================================================
422 void gp_Trsf::Multiply(const gp_Trsf& T)
424 if (T.shape == gp_Identity) { }
425 else if (shape == gp_Identity) {
431 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
432 if (T.loc.X() != 0.0 || T.loc.Y() != 0.0 || T.loc.Z() != 0.0) {
433 loc.Add (T.loc.Multiplied (matrix));
435 matrix.Multiply(T.matrix);
437 else if (shape == gp_Translation && T.shape == gp_Translation) {
440 else if (shape == gp_Scale && T.shape == gp_Scale) {
441 loc.Add (T.loc.Multiplied(scale));
442 scale = scale * T.scale;
444 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
446 shape = gp_Translation;
447 loc.Add (T.loc.Reversed());
449 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
451 loc.Add (T.loc.Multiplied (matrix));
452 matrix.Multiply(T.matrix);
454 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
455 shape == gp_Ax1Mirror || shape == gp_Ax2Mirror)
456 && T.shape == gp_Translation) {
458 Tloc.Multiply(matrix);
459 if (scale != 1.0) { Tloc.Multiply(scale); }
462 else if ((shape == gp_Scale || shape == gp_PntMirror)
463 && T.shape == gp_Translation) {
465 Tloc.Multiply (scale);
468 else if (shape == gp_Translation &&
469 (T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
470 T.shape == gp_Ax1Mirror || T.shape == gp_Ax2Mirror)) {
471 shape = gp_CompoundTrsf;
476 else if (shape == gp_Translation &&
477 (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
482 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
483 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
484 shape = gp_CompoundTrsf;
486 Tloc.Multiply (scale);
488 scale = scale * T.scale;
490 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
491 shape == gp_Ax1Mirror || shape == gp_Ax2Mirror)
492 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
493 shape = gp_CompoundTrsf;
497 Tloc.Multiply(matrix);
500 Tloc.Multiply (matrix);
501 Tloc.Multiply (scale);
502 scale = scale * T.scale;
506 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
507 T.shape == gp_Ax1Mirror || T.shape == gp_Ax2Mirror)
508 && (shape == gp_Scale || shape == gp_PntMirror)) {
509 shape = gp_CompoundTrsf;
511 Tloc.Multiply(scale);
513 scale = scale * T.scale;
517 shape = gp_CompoundTrsf;
519 Tloc.Multiply (matrix);
521 Tloc.Multiply (scale);
522 scale = scale * T.scale;
524 else { scale = T.scale; }
526 matrix.Multiply(T.matrix);
530 //=======================================================================
533 //=======================================================================
535 void gp_Trsf::Power (const Standard_Integer N)
537 if (shape == gp_Identity) { }
542 matrix.SetIdentity();
543 loc = gp_XYZ (0.0, 0.0, 0.0);
546 else if (N == -1) { Invert(); }
548 if (N < 0) { Invert(); }
549 if (shape == gp_Translation) {
550 Standard_Integer Npower = N;
551 if (Npower < 0) Npower = - Npower;
553 gp_XYZ Temploc = loc;
555 if (IsOdd(Npower)) loc.Add (Temploc);
556 if (Npower == 1) break;
557 Temploc.Add (Temploc);
561 else if (shape == gp_Scale) {
562 Standard_Integer Npower = N;
563 if (Npower < 0) Npower = - Npower;
565 gp_XYZ Temploc = loc;
566 Standard_Real Tempscale = scale;
569 loc.Add (Temploc.Multiplied(scale));
570 scale = scale * Tempscale;
572 if (Npower == 1) break;
573 Temploc.Add (Temploc.Multiplied(Tempscale));
574 Tempscale = Tempscale * Tempscale;
578 else if (shape == gp_Rotation) {
579 Standard_Integer Npower = N;
580 if (Npower < 0) Npower = - Npower;
582 gp_Mat Tempmatrix (matrix);
583 if (loc.X() == 0.0 && loc.Y() == 0.0 && loc.Z() == 0.0) {
585 if (IsOdd(Npower)) matrix.Multiply (Tempmatrix);
586 if (Npower == 1) break;
587 Tempmatrix.Multiply (Tempmatrix);
592 gp_XYZ Temploc = loc;
595 loc.Add (Temploc.Multiplied (matrix));
596 matrix.Multiply (Tempmatrix);
598 if (Npower == 1) break;
599 Temploc.Add (Temploc.Multiplied (Tempmatrix));
600 Tempmatrix.Multiply (Tempmatrix);
605 else if (shape == gp_PntMirror || shape == gp_Ax1Mirror ||
606 shape == gp_Ax2Mirror) {
610 matrix.SetIdentity ();
617 shape = gp_CompoundTrsf;
618 Standard_Integer Npower = N;
619 if (Npower < 0) Npower = - Npower;
621 gp_XYZ Temploc = loc;
622 Standard_Real Tempscale = scale;
623 gp_Mat Tempmatrix (matrix);
626 loc.Add ((Temploc.Multiplied (matrix)).Multiplied (scale));
627 scale = scale * Tempscale;
628 matrix.Multiply (Tempmatrix);
630 if (Npower == 1) break;
631 Tempscale = Tempscale * Tempscale;
632 Temploc.Add ( (Temploc.Multiplied (Tempmatrix)).Multiplied
635 Tempmatrix.Multiply (Tempmatrix);
643 //=======================================================================
644 //function : PreMultiply
646 //=======================================================================
648 void gp_Trsf::PreMultiply (const gp_Trsf& T)
650 if (T.shape == gp_Identity) { }
651 else if (shape == gp_Identity) {
657 else if (shape == gp_Rotation && T.shape == gp_Rotation) {
658 loc.Multiply (T.matrix);
660 matrix.PreMultiply(T.matrix);
662 else if (shape == gp_Translation && T.shape == gp_Translation) {
665 else if (shape == gp_Scale && T.shape == gp_Scale) {
666 loc.Multiply (T.scale);
668 scale = scale * T.scale;
670 else if (shape == gp_PntMirror && T.shape == gp_PntMirror) {
672 shape = gp_Translation;
676 else if (shape == gp_Ax1Mirror && T.shape == gp_Ax1Mirror) {
678 loc.Multiply (T.matrix);
680 matrix.PreMultiply(T.matrix);
682 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
683 shape == gp_Ax1Mirror || shape == gp_Ax2Mirror)
684 && T.shape == gp_Translation) {
687 else if ((shape == gp_Scale || shape == gp_PntMirror)
688 && T.shape == gp_Translation) {
691 else if (shape == gp_Translation &&
692 (T.shape == gp_CompoundTrsf || T.shape == gp_Rotation
693 || T.shape == gp_Ax1Mirror || T.shape == gp_Ax2Mirror)) {
694 shape = gp_CompoundTrsf;
696 if (T.scale == 1.0) loc.Multiply (T.matrix);
699 loc.Multiply (matrix);
700 loc.Multiply (scale);
704 else if ((T.shape == gp_Scale || T.shape == gp_PntMirror)
705 && shape == gp_Translation) {
706 loc.Multiply (T.scale);
711 else if ((shape == gp_PntMirror || shape == gp_Scale) &&
712 (T.shape == gp_PntMirror || T.shape == gp_Scale)) {
713 shape = gp_CompoundTrsf;
714 loc.Multiply (T.scale);
716 scale = scale * T.scale;
718 else if ((shape == gp_CompoundTrsf || shape == gp_Rotation ||
719 shape == gp_Ax1Mirror || shape == gp_Ax2Mirror)
720 && (T.shape == gp_Scale || T.shape == gp_PntMirror)) {
721 shape = gp_CompoundTrsf;
722 loc.Multiply (T.scale);
724 scale = scale * T.scale;
726 else if ((T.shape == gp_CompoundTrsf || T.shape == gp_Rotation ||
727 T.shape == gp_Ax1Mirror || T.shape == gp_Ax2Mirror)
728 && (shape == gp_Scale || shape == gp_PntMirror)) {
729 shape = gp_CompoundTrsf;
731 if (T.scale == 1.0) loc.Multiply (T.matrix);
733 loc.Multiply (matrix);
734 loc.Multiply (T.scale);
735 scale = T.scale * scale;
740 shape = gp_CompoundTrsf;
741 loc.Multiply (T.matrix);
742 if (T.scale != 1.0) {
743 loc.Multiply (T.scale); scale = scale * T.scale;
746 matrix.PreMultiply(T.matrix);
750 //=======================================================================
751 //function : GetRotation
752 //purpose : algorithm from A.Korn, M.Korn, "Mathematical Handbook for
753 // scientists and Engineers" McGraw-Hill, 1961, ch.14.10-2.
754 //=======================================================================
756 Standard_Boolean gp_Trsf::GetRotation (gp_XYZ& theAxis,
757 Standard_Real& theAngle) const
759 gp_Quaternion Q = GetRotation();
761 Q.GetVectorAndAngle (aVec, theAngle);
762 theAxis = aVec.XYZ();
763 return Standard_True;
766 //=======================================================================
767 //function : Orthogonalize
770 // Orthogonalization is not equivalent transformation. Therefore,
771 // transformation with source matrix and with orthogonalized matrix can
772 // lead to different results for one shape. Consequently, source matrix must
773 // be close to orthogonalized matrix for reducing these differences.
774 //=======================================================================
775 void gp_Trsf::Orthogonalize()
777 //Matrix M is called orthogonal if and only if
778 // M*Transpose(M) == E
779 //where E is identity matrix.
781 //Set of all rows (as of all columns) of matrix M (for gp_Trsf class) is
782 //orthonormal basis. If this condition is not satisfied then the basis can be
783 //orthonormalized in accordance with below described algorithm.
785 //In 3D-space, we have the linear span of three basis vectors: V1, V2 and V3.
786 //Correspond orthonormalized basis is formed by vectors Vn1, Vn2 and Vn3.
789 // Vn_{i}*Vn_{j} = (i == j)? 1 : 0.
791 //The algorithm includes following steps:
793 //1. Normalize V1 vector:
799 //After multiplication two parts of this equation by V1n,
800 //we will have following equation:
801 // 0=V2*V1n-m <==> m=V2*V1n.
804 // V2n=V2-(V2*V1n)*V1n.
807 // V3n=V3-m1*V1n-m2*V2n.
809 //After multiplication two parts of this equation by V1n,
810 //we will have following equation:
811 // 0=V3*V1n-m1 <==> m1=V3*V1n.
813 //After multiplication two parts of main equation by V2n,
814 //we will have following equation:
815 // 0=V3*V2n-m2 <==> m2=V3*V2n.
818 // V3n=V3-(V3*V1n)*V1n-(V3*V2n)*V2n.
822 gp_XYZ aV1 = aTM.Column(1);
823 gp_XYZ aV2 = aTM.Column(2);
824 gp_XYZ aV3 = aTM.Column(3);
828 aV2 -= aV1*(aV2.Dot(aV1));
831 aV3 -= aV1*(aV3.Dot(aV1)) + aV2*(aV3.Dot(aV2));
834 aTM.SetCols(aV1, aV2, aV3);
842 aV2 -= aV1*(aV2.Dot(aV1));
845 aV3 -= aV1*(aV3.Dot(aV1)) + aV2*(aV3.Dot(aV2));
848 aTM.SetRows(aV1, aV2, aV3);