moab
|
00001 00017 #ifndef MOAB_AFFINE_XFORM_HPP 00018 #define MOAB_AFFINE_XFORM_HPP 00019 00020 #include "moab/Forward.hpp" 00021 #include "moab/CartVect.hpp" 00022 #include "moab/Matrix3.hpp" 00023 00024 #include <cmath> 00025 #include <limits> 00026 00027 namespace moab { 00028 00034 class AffineXform 00035 { 00036 public: 00037 00038 inline AffineXform(); 00039 00040 inline AffineXform( const double* three_by_three, 00041 const double* translation ); 00042 00043 inline AffineXform( const Matrix3& mat, const CartVect& off ); 00044 00046 static inline AffineXform translation( const double* vector ); 00048 static inline AffineXform rotation( double radians, const double* axis ); 00050 static AffineXform rotation( const double* from_vec, const double* to_vec ); 00052 static inline AffineXform reflection( const double* plane_normal ); 00054 static inline AffineXform scale( double f ); 00056 static inline AffineXform scale( const double* fractions ); 00058 static inline AffineXform scale( double f, const double* point ); 00060 static inline AffineXform scale( const double* fractions, const double* point ); 00061 00065 inline void accumulate( const AffineXform& other ); 00066 00068 inline void xform_point( const double* input, double* output ) const; 00070 inline void xform_point( double* in_out ) const; 00071 00073 inline void xform_vector( const double* input, double* output ) const; 00075 inline void xform_vector( double* in_out ) const; 00076 00078 AffineXform inverse() const; 00079 00081 static ErrorCode get_tag( Tag& tag_handle_out, 00082 Interface* moab, 00083 const char* tagname = 0 ); 00084 00086 const Matrix3& matrix() const { return mMatrix; } 00088 const CartVect& offset() const { return mOffset; } 00089 00102 inline bool reflection() const; 00103 00105 inline bool scale() const; 00106 00107 private: 00108 00109 static inline AffineXform rotation( double cos_angle, 00110 double sin_angle, 00111 const CartVect& unit_axis ); 00112 00113 Matrix3 mMatrix; 00114 CartVect mOffset; 00115 }; 00116 00120 inline AffineXform operator*( const AffineXform& A, const AffineXform& B ) 00121 { 00122 AffineXform result(A); 00123 result.accumulate(B); 00124 return result; 00125 } 00126 00127 inline AffineXform::AffineXform() 00128 : mMatrix(1.0), mOffset(0.0) 00129 {} 00130 00131 inline AffineXform::AffineXform( const double* three_by_three, 00132 const double* trans ) 00133 : mMatrix(three_by_three), mOffset(trans) 00134 {} 00135 00136 inline AffineXform::AffineXform( const Matrix3& mat, const CartVect& off ) 00137 : mMatrix(mat), mOffset(off) 00138 {} 00139 00140 inline AffineXform AffineXform::translation( const double* vector ) 00141 { 00142 return AffineXform( Matrix3(1.0), CartVect(vector) ); 00143 } 00144 00145 inline AffineXform AffineXform::rotation( double angle, const double* axis ) 00146 { 00147 CartVect a(axis); 00148 a.normalize(); 00149 return AffineXform::rotation( std::cos(angle), std::sin(angle), a ); 00150 } 00151 00152 inline AffineXform AffineXform::rotation( double c, 00153 double s, 00154 const CartVect& a ) 00155 { 00156 const Matrix3 m1( c, -a[2]*s, a[1]*s, 00157 a[2]*s, c, -a[0]*s, 00158 -a[1]*s, a[0]*s, c ); 00159 return AffineXform( m1 + (1.0-c)*outer_product( a, a ), CartVect(0.0) ); 00160 } 00161 00162 inline AffineXform AffineXform::reflection( const double* plane_normal ) 00163 { 00164 double i = plane_normal[0]; 00165 double j = plane_normal[1]; 00166 double k = plane_normal[2]; 00167 Matrix3 m( j*j+k*k-i*i, -2.0*i*j, -2.0*i*k, 00168 -2.0*i*j, i*i+k*k-j*j, -2.0*j*k, 00169 -2.0*i*k, -2.0*j*k, i*i+j*j-k*k ); 00170 m *= 1.0 / (i*i + j*j + k*k); //normalize 00171 return AffineXform( m, CartVect(0.0) ); 00172 } 00173 00174 inline AffineXform AffineXform::scale( const double* f ) 00175 { 00176 return AffineXform( Matrix3( CartVect(f) ), CartVect( 0.0 ) ); 00177 } 00178 00179 inline AffineXform AffineXform::scale( double f ) 00180 { 00181 return AffineXform( Matrix3( CartVect(f) ), CartVect( 0.0 ) ); 00182 } 00183 00184 inline AffineXform AffineXform::scale( double f, const double* point ) 00185 { 00186 double fs[] = { f, f, f }; 00187 return AffineXform::scale( fs, point ); 00188 } 00189 00190 inline AffineXform AffineXform::scale( const double* f, const double* p ) 00191 { 00192 double offset[] = { p[0] * (1 - f[0]), 00193 p[1] * (1 - f[1]), 00194 p[2] * (1 - f[2]) }; 00195 return AffineXform( Matrix3( CartVect(f) ), CartVect(offset) ); 00196 } 00197 00198 inline void AffineXform::accumulate( const AffineXform& other ) 00199 { 00200 mMatrix = other.mMatrix * mMatrix; 00201 other.xform_point( mOffset.array() ); 00202 } 00203 00204 inline void AffineXform::xform_point( const double* input, double* output ) const 00205 { 00206 xform_vector( input, output ); 00207 output[0] += mOffset[0]; 00208 output[1] += mOffset[1]; 00209 output[2] += mOffset[2]; 00210 } 00211 00212 inline void AffineXform::xform_point( double* in_out ) const 00213 { 00214 xform_vector( in_out ); 00215 in_out[0] += mOffset[0]; 00216 in_out[1] += mOffset[1]; 00217 in_out[2] += mOffset[2]; 00218 } 00219 00220 inline void AffineXform::xform_vector( const double* input, double* output ) const 00221 { 00222 output[0] = input[0]*mMatrix[0][0] + input[1]*mMatrix[0][1] + input[2]*mMatrix[0][2]; 00223 output[1] = input[0]*mMatrix[1][0] + input[1]*mMatrix[1][1] + input[2]*mMatrix[1][2]; 00224 output[2] = input[0]*mMatrix[2][0] + input[1]*mMatrix[2][1] + input[2]*mMatrix[2][2]; 00225 } 00226 00227 inline void AffineXform::xform_vector( double* in_out ) const 00228 { 00229 double input[] = { in_out[0], in_out[1], in_out[2] }; 00230 xform_vector( input, in_out ); 00231 } 00232 00233 inline AffineXform AffineXform::inverse() const 00234 { 00235 Matrix3 m = mMatrix.inverse(); 00236 return AffineXform( m, m * -mOffset ); 00237 } 00238 00239 inline bool AffineXform::reflection() const 00240 { 00241 return mMatrix.determinant() < 0.0; 00242 } 00243 00244 inline bool AffineXform::scale() const 00245 { 00246 return fabs(fabs(mMatrix.determinant()) - 1) > std::numeric_limits<double>::epsilon(); 00247 } 00248 00249 } // namespace moab 00250 00251 #endif