1
15
16 #ifndef MOAB_AFFINE_XFORM_HPP
17 #define MOAB_AFFINE_XFORM_HPP
18
19 #include "moab/Forward.hpp"
20 #include "moab/CartVect.hpp"
21 #include "moab/Matrix3.hpp"
22
23 #include <cmath>
24 #include <limits>
25
26 namespace moab
27 {
28
29
34 class AffineXform
35 {
36 public:
37 inline AffineXform();
38
39 inline AffineXform( const double* three_by_three, const double* translation );
40
41 inline AffineXform( const Matrix3& mat, const CartVect& off );
42
43
44 static inline AffineXform translation( const double* vector );
45
46 static inline AffineXform rotation( double radians, const double* axis );
47
48 static AffineXform rotation( const double* from_vec, const double* to_vec );
49
50 static inline AffineXform reflection( const double* plane_normal );
51
52 static inline AffineXform scale( double f );
53
54 static inline AffineXform scale( const double* fractions );
55
56 static inline AffineXform scale( double f, const double* point );
57
58 static inline AffineXform scale( const double* fractions, const double* point );
59
60
63 inline void accumulate( const AffineXform& other );
64
65
66 inline void xform_point( const double* input, double* output ) const;
67
68 inline void xform_point( double* in_out ) const;
69
70
71 inline void xform_vector( const double* input, double* output ) const;
72
73 inline void xform_vector( double* in_out ) const;
74
75
76 AffineXform inverse() const;
77
78
79 static ErrorCode get_tag( Tag& tag_handle_out, Interface* moab, const char* tagname = 0 );
80
81
82 const Matrix3& matrix() const
83 {
84 return mMatrix;
85 }
86
87 const CartVect& offset() const
88 {
89 return mOffset;
90 }
91
92
104 inline bool reflection() const;
105
106
107 inline bool scale() const;
108
109 private:
110 static inline AffineXform rotation( double cos_angle, double sin_angle, const CartVect& unit_axis );
111
112 Matrix3 mMatrix;
113 CartVect mOffset;
114 };
115
116
119 inline AffineXform operator*( const AffineXform& A, const AffineXform& B )
120 {
121 AffineXform result( A );
122 result.accumulate( B );
123 return result;
124 }
125
126 inline AffineXform::AffineXform() : mMatrix( 1.0 ), mOffset( 0.0 ) {}
127
128 inline AffineXform::AffineXform( const double* three_by_three, const double* trans )
129 : mMatrix( three_by_three ), mOffset( trans )
130 {
131 }
132
133 inline AffineXform::AffineXform( const Matrix3& mat, const CartVect& off ) : mMatrix( mat ), mOffset( off ) {}
134
135 inline AffineXform AffineXform::translation( const double* vector )
136 {
137 return AffineXform( Matrix3( 1.0 ), CartVect( vector ) );
138 }
139
140 inline AffineXform AffineXform::rotation( double angle, const double* axis )
141 {
142 CartVect a( axis );
143 a.normalize();
144 return AffineXform::rotation( std::cos( angle ), std::sin( angle ), a );
145 }
146
147 inline AffineXform AffineXform::rotation( double c, double s, const CartVect& a )
148 {
149 const Matrix3 m1( c, -a[2] * s, a[1] * s, a[2] * s, c, -a[0] * s, -a[1] * s, a[0] * s, c );
150 return AffineXform( m1 + ( 1.0 - c ) * outer_product( a, a ), CartVect( 0.0 ) );
151 }
152
153 inline AffineXform AffineXform::reflection( const double* plane_normal )
154 {
155 double i = plane_normal[0];
156 double j = plane_normal[1];
157 double k = plane_normal[2];
158 Matrix3 m( j * j + k * k - i * i, -2.0 * i * j, -2.0 * i * k, -2.0 * i * j, i * i + k * k - j * j, -2.0 * j * k,
159 -2.0 * i * k, -2.0 * j * k, i * i + j * j - k * k );
160 m *= 1.0 / ( i * i + j * j + k * k );
161 return AffineXform( m, CartVect( 0.0 ) );
162 }
163
164 inline AffineXform AffineXform::scale( const double* f )
165 {
166 return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) );
167 }
168
169 inline AffineXform AffineXform::scale( double f )
170 {
171 return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) );
172 }
173
174 inline AffineXform AffineXform::scale( double f, const double* point )
175 {
176 double fs[] = { f, f, f };
177 return AffineXform::scale( fs, point );
178 }
179
180 inline AffineXform AffineXform::scale( const double* f, const double* p )
181 {
182 double offset[] = { p[0] * ( 1 - f[0] ), p[1] * ( 1 - f[1] ), p[2] * ( 1 - f[2] ) };
183 return AffineXform( Matrix3( CartVect( f ) ), CartVect( offset ) );
184 }
185
186 inline void AffineXform::accumulate( const AffineXform& other )
187 {
188 mMatrix = other.mMatrix * mMatrix;
189 other.xform_point( mOffset.array() );
190 }
191
192 inline void AffineXform::xform_point( const double* input, double* output ) const
193 {
194 xform_vector( input, output );
195 output[0] += mOffset[0];
196 output[1] += mOffset[1];
197 output[2] += mOffset[2];
198 }
199
200 inline void AffineXform::xform_point( double* in_out ) const
201 {
202 xform_vector( in_out );
203 in_out[0] += mOffset[0];
204 in_out[1] += mOffset[1];
205 in_out[2] += mOffset[2];
206 }
207
208 inline void AffineXform::xform_vector( const double* input, double* output ) const
209 {
210 output[0] = input[0] * mMatrix[0][0] + input[1] * mMatrix[0][1] + input[2] * mMatrix[0][2];
211 output[1] = input[0] * mMatrix[1][0] + input[1] * mMatrix[1][1] + input[2] * mMatrix[1][2];
212 output[2] = input[0] * mMatrix[2][0] + input[1] * mMatrix[2][1] + input[2] * mMatrix[2][2];
213 }
214
215 inline void AffineXform::xform_vector( double* in_out ) const
216 {
217 double input[] = { in_out[0], in_out[1], in_out[2] };
218 xform_vector( input, in_out );
219 }
220
221 inline AffineXform AffineXform::inverse() const
222 {
223 Matrix3 m = mMatrix.inverse();
224 return AffineXform( m, m * -mOffset );
225 }
226
227 inline bool AffineXform::reflection() const
228 {
229 return mMatrix.determinant() < 0.0;
230 }
231
232 inline bool AffineXform::scale() const
233 {
234 return fabs( fabs( mMatrix.determinant() ) - 1 ) > std::numeric_limits< double >::epsilon();
235 }
236
237 }
238
239 #endif