Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
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 : : /**
30 : : * \brief Define an affine transformation
31 : : * \author Jason Kraftcheck ([email protected])
32 : : * \date August, 2006
33 : : */
34 : 62 : 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 : : /** move */
44 : : static inline AffineXform translation( const double* vector );
45 : : /** rotate about axis through origin */
46 : : static inline AffineXform rotation( double radians, const double* axis );
47 : : /** define rotation such that if applied to \c from_vec the result aligned with \c to_vec */
48 : : static AffineXform rotation( const double* from_vec, const double* to_vec );
49 : : /** reflect about plane through origin */
50 : : static inline AffineXform reflection( const double* plane_normal );
51 : : /** scale about origin */
52 : : static inline AffineXform scale( double f );
53 : : /** scale about origin */
54 : : static inline AffineXform scale( const double* fractions );
55 : : /** scale about a point */
56 : : static inline AffineXform scale( double f, const double* point );
57 : : /** scale about a point */
58 : : static inline AffineXform scale( const double* fractions, const double* point );
59 : :
60 : : /** incorporate the passed transform into this one such that the
61 : : * resulting transform is the cumulative affect of this initial
62 : : * transform followed by the passed transform */
63 : : inline void accumulate( const AffineXform& other );
64 : :
65 : : /** apply transform to a point */
66 : : inline void xform_point( const double* input, double* output ) const;
67 : : /** apply transform to a point */
68 : : inline void xform_point( double* in_out ) const;
69 : :
70 : : /** apply transform to a vector */
71 : : inline void xform_vector( const double* input, double* output ) const;
72 : : /** apply transform to a vector */
73 : : inline void xform_vector( double* in_out ) const;
74 : :
75 : : /** get transform that is the inverse of this transform */
76 : : AffineXform inverse() const;
77 : :
78 : : /** get a tag that can be used to store an instance of this class */
79 : : static ErrorCode get_tag( Tag& tag_handle_out, Interface* moab, const char* tagname = 0 );
80 : :
81 : : /** get 3x3 matrix portion of transform */
82 : 6 : const Matrix3& matrix() const
83 : : {
84 : 6 : return mMatrix;
85 : : }
86 : : /** get translation portion of transform */
87 : : const CartVect& offset() const
88 : : {
89 : : return mOffset;
90 : : }
91 : :
92 : : /** Is this transform a reflection
93 : : *
94 : : * A relfecting transform will require the reversal of the
95 : : * order of edges in a loop, etc. because it produces a
96 : : * mirror-image of the input geometry. This method tests
97 : : * if this is such a transform. A reflection may be created
98 : : * with by an explicit transform, scaling with a negative
99 : : * scale factor, etc. If multiple transforms are combined
100 : : * such that the transform is no longer a reflection (e.g.
101 : : * two reflections that are effectively a rotation), this method
102 : : * will return false.
103 : : */
104 : : inline bool reflection() const;
105 : :
106 : : /** Does this transform do any scaling */
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 : : /** create a new transform equivalent to transform \c A followed
117 : : * by transform \c B
118 : : */
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 : 50 : inline AffineXform::AffineXform() : mMatrix( 1.0 ), mOffset( 0.0 ) {}
127 : :
128 : 0 : inline AffineXform::AffineXform( const double* three_by_three, const double* trans )
129 : 0 : : mMatrix( three_by_three ), mOffset( trans )
130 : : {
131 : 0 : }
132 : :
133 : 68 : inline AffineXform::AffineXform( const Matrix3& mat, const CartVect& off ) : mMatrix( mat ), mOffset( off ) {}
134 : :
135 : 4 : inline AffineXform AffineXform::translation( const double* vector )
136 : : {
137 [ + - ][ + - ]: 4 : return AffineXform( Matrix3( 1.0 ), CartVect( vector ) );
138 : : }
139 : :
140 : 9 : inline AffineXform AffineXform::rotation( double angle, const double* axis )
141 : : {
142 [ + - ]: 9 : CartVect a( axis );
143 [ + - ]: 9 : a.normalize();
144 [ + - ]: 9 : return AffineXform::rotation( std::cos( angle ), std::sin( angle ), a );
145 : : }
146 : :
147 : 11 : inline AffineXform AffineXform::rotation( double c, double s, const CartVect& a )
148 : : {
149 [ + - ][ + - ]: 11 : 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 [ + - ][ + - ]: 11 : return AffineXform( m1 + ( 1.0 - c ) * outer_product( a, a ), CartVect( 0.0 ) );
[ + - ][ + - ]
[ + - ][ + - ]
151 : : }
152 : :
153 : 6 : inline AffineXform AffineXform::reflection( const double* plane_normal )
154 : : {
155 : 6 : double i = plane_normal[0];
156 : 6 : double j = plane_normal[1];
157 : 6 : double k = plane_normal[2];
158 : 36 : 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 [ + - ]: 6 : -2.0 * i * k, -2.0 * j * k, i * i + j * j - k * k );
160 [ + - ]: 6 : m *= 1.0 / ( i * i + j * j + k * k ); // normalize
161 [ + - ][ + - ]: 6 : return AffineXform( m, CartVect( 0.0 ) );
162 : : }
163 : :
164 : 5 : inline AffineXform AffineXform::scale( const double* f )
165 : : {
166 [ + - ][ + - ]: 5 : return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) );
[ + - ]
167 : : }
168 : :
169 : 2 : inline AffineXform AffineXform::scale( double f )
170 : : {
171 [ + - ][ + - ]: 2 : 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 : 2 : inline AffineXform AffineXform::scale( const double* f, const double* p )
181 : : {
182 : 2 : double offset[] = { p[0] * ( 1 - f[0] ), p[1] * ( 1 - f[1] ), p[2] * ( 1 - f[2] ) };
183 [ + - ][ + - ]: 2 : return AffineXform( Matrix3( CartVect( f ) ), CartVect( offset ) );
[ + - ][ + - ]
184 : : }
185 : :
186 : 12 : inline void AffineXform::accumulate( const AffineXform& other )
187 : : {
188 [ + - ]: 12 : mMatrix = other.mMatrix * mMatrix;
189 : 12 : other.xform_point( mOffset.array() );
190 : 12 : }
191 : :
192 : 28 : inline void AffineXform::xform_point( const double* input, double* output ) const
193 : : {
194 : 28 : xform_vector( input, output );
195 : 28 : output[0] += mOffset[0];
196 : 28 : output[1] += mOffset[1];
197 : 28 : output[2] += mOffset[2];
198 : 28 : }
199 : :
200 : 2623 : inline void AffineXform::xform_point( double* in_out ) const
201 : : {
202 : 2623 : xform_vector( in_out );
203 : 2623 : in_out[0] += mOffset[0];
204 : 2623 : in_out[1] += mOffset[1];
205 : 2623 : in_out[2] += mOffset[2];
206 : 2623 : }
207 : :
208 : 2689 : inline void AffineXform::xform_vector( const double* input, double* output ) const
209 : : {
210 : 2689 : output[0] = input[0] * mMatrix[0][0] + input[1] * mMatrix[0][1] + input[2] * mMatrix[0][2];
211 : 2689 : output[1] = input[0] * mMatrix[1][0] + input[1] * mMatrix[1][1] + input[2] * mMatrix[1][2];
212 : 2689 : output[2] = input[0] * mMatrix[2][0] + input[1] * mMatrix[2][1] + input[2] * mMatrix[2][2];
213 : 2689 : }
214 : :
215 : 2633 : inline void AffineXform::xform_vector( double* in_out ) const
216 : : {
217 : 2633 : double input[] = { in_out[0], in_out[1], in_out[2] };
218 [ + - ]: 2633 : xform_vector( input, in_out );
219 : 2633 : }
220 : :
221 : 4 : inline AffineXform AffineXform::inverse() const
222 : : {
223 [ + - ]: 4 : Matrix3 m = mMatrix.inverse();
224 [ + - ][ + - ]: 4 : return AffineXform( m, m * -mOffset );
[ + - ]
225 : : }
226 : :
227 : 10 : inline bool AffineXform::reflection() const
228 : : {
229 : 10 : return mMatrix.determinant() < 0.0;
230 : : }
231 : :
232 : 4 : inline bool AffineXform::scale() const
233 : : {
234 : 4 : return fabs( fabs( mMatrix.determinant() ) - 1 ) > std::numeric_limits< double >::epsilon();
235 : : }
236 : :
237 : : } // namespace moab
238 : :
239 : : #endif
|