moab
AffineXform.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines