90270fc8b97c1c3a1a0c337173b835da11317394
[occt.git] / src / gp / gp_GTrsf2d.cxx
1 // Copyright (c) 1995-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 #include <gp_GTrsf2d.hxx>
16
17 #include <gp_Ax2d.hxx>
18 #include <gp_Mat2d.hxx>
19 #include <gp_Trsf2d.hxx>
20 #include <gp_XY.hxx>
21 #include <Precision.hxx>
22 #include <Standard_ConstructionError.hxx>
23 #include <Standard_OutOfRange.hxx>
24
25 void gp_GTrsf2d::SetAffinity (const gp_Ax2d& A,
26                               const Standard_Real Ratio)
27 {
28   shape = gp_Other;
29   scale = 0.0;
30   Standard_Real a = A.Direction().X();
31   Standard_Real b = A.Direction().Y();
32   matrix.SetValue (1, 1, (1.0 - Ratio)*a*a + Ratio);
33   matrix.SetValue (2, 2, (1.0 - Ratio)*b*b + Ratio);
34   matrix.SetValue (1, 2, (1.0 - Ratio)*a*b);
35   matrix.SetValue (2, 1, matrix.Value (1, 2));
36   loc = A.Location().XY();
37   loc.Reverse();
38   loc.Multiply (matrix);
39   loc.Add (A.Location().XY());
40 }
41
42 void gp_GTrsf2d::SetTranslationPart (const gp_XY& Coord)
43 {
44   loc = Coord;
45   if (Form() == gp_CompoundTrsf || Form() == gp_Other || 
46       Form() == gp_Translation) { }
47   else if (Form() == gp_Identity) { shape = gp_Translation; }
48   else { shape = gp_CompoundTrsf; }
49 }
50
51 void gp_GTrsf2d::Invert ()
52 {
53   if (shape == gp_Other) {
54     matrix.Invert();
55     loc.Multiply (matrix);
56     loc.Reverse();
57   }
58   else {
59     gp_Trsf2d T = Trsf2d ();
60     T.Invert ();
61     SetTrsf2d (T);
62   }
63 }
64
65 void gp_GTrsf2d::Multiply (const gp_GTrsf2d& T)
66 {
67   if (Form() == gp_Other || T.Form() == gp_Other) {
68     shape = gp_Other;
69     loc.Add (T.loc.Multiplied (matrix));
70     matrix.Multiply(T.matrix);
71   }
72   else {
73     gp_Trsf2d T1 = Trsf2d();
74     gp_Trsf2d T2 = T.Trsf2d();
75     T1.Multiply(T2);
76     matrix = T1.matrix;
77     loc = T1.loc;
78     scale = T1.scale;
79     shape = T1.shape;
80   }
81 }
82
83 void gp_GTrsf2d::Power (const Standard_Integer N)
84 {
85   if (N == 0)  {
86     scale = 1.0;
87     shape = gp_Identity;
88     matrix.SetIdentity();
89     loc = gp_XY (0., 0.);
90   }
91   else if (N == 1) { }
92   else if (N == -1) { Invert(); }
93   else {
94     if (N < 0) { Invert(); }
95     if (shape == gp_Other) {
96       Standard_Integer Npower = N;
97       if (Npower < 0) Npower = - Npower;
98       Npower--;
99       gp_XY Temploc = loc;
100 //      Standard_Real Tempscale = scale;
101       gp_Mat2d Tempmatrix (matrix);
102       for(;;) {
103         if (IsOdd(Npower)) {
104           loc.Add (Temploc.Multiplied (matrix));
105           matrix.Multiply (Tempmatrix);
106         }
107         if (Npower == 1) { break; }
108         Temploc.Add (Temploc.Multiplied (Tempmatrix));
109         Tempmatrix.Multiply (Tempmatrix);
110         Npower = Npower/2;
111       }
112     }
113     else {
114       gp_Trsf2d T = Trsf2d ();
115       T.Power (N);
116       SetTrsf2d (T);
117     }
118   }
119 }
120
121 void gp_GTrsf2d::PreMultiply (const gp_GTrsf2d& T)
122 {
123   if (Form() == gp_Other || T.Form() == gp_Other) {
124     shape = gp_Other;
125     loc.Multiply (T.matrix);
126     loc.Add (T.loc);
127     matrix.PreMultiply(T.matrix);
128   }
129   else {
130     gp_Trsf2d T1 = Trsf2d();
131     gp_Trsf2d T2 = T.Trsf2d();
132     T1.PreMultiply(T2);
133     matrix = T1.matrix;
134     loc = T1.loc;
135     scale = T1.scale;
136     shape = T1.shape;
137   }
138 }
139
140 gp_Trsf2d gp_GTrsf2d::Trsf2d () const
141 {
142   // Test of orthogonality
143   const Standard_Real aTolerance  = Precision::Angular();
144   const Standard_Real aTolerance2 = 2.0 * aTolerance;
145
146   if ( Form() == gp_Other )
147     throw Standard_ConstructionError("gp_GTrsf2d::Trsf2d() - non-orthogonal GTrsf2d(0)");
148
149   Standard_Real value = (matrix.Value(1, 1) * matrix.Value(1, 1)
150                       +  matrix.Value(2, 1) * matrix.Value(2, 1));
151   if ( Abs(value - 1.) > aTolerance2 )
152     throw Standard_ConstructionError("gp_GTrsf2d::Trsf2d() - non-orthogonal GTrsf2d(1)");
153
154   value = (matrix.Value(1, 2) * matrix.Value(1, 2)
155         +  matrix.Value(2, 2) * matrix.Value(2, 2));
156   if ( Abs(value - 1.) > aTolerance2 )
157     throw Standard_ConstructionError("gp_GTrsf2d::Trsf2d() - non-orthogonal GTrsf2d(2)");
158
159   value = (matrix.Value(1, 1) * matrix.Value(1, 2)
160         +  matrix.Value(2, 1) * matrix.Value(2, 2));
161   if ( Abs(value) > aTolerance )
162     throw Standard_ConstructionError("gp_GTrsf2d::Trsf2d() - non-orthogonal GTrsf2d(3)");
163
164
165   gp_Trsf2d aTransformation;
166   aTransformation.matrix = matrix;
167   aTransformation.shape  = shape;
168   aTransformation.scale  = scale;
169   aTransformation.loc    = loc;
170
171   return aTransformation;
172 }
173