Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
AffineXform.hpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 #ifndef MOAB_AFFINE_XFORM_HPP
00017 #define MOAB_AFFINE_XFORM_HPP
00018 
00019 #include "moab/Forward.hpp"
00020 #include "moab/CartVect.hpp"
00021 #include "moab/Matrix3.hpp"
00022 
00023 #include <cmath>
00024 #include <limits>
00025 
00026 namespace moab
00027 {
00028 
00029 /**
00030  * \brief Define an affine transformation
00031  * \author Jason Kraftcheck ([email protected])
00032  * \date August, 2006
00033  */
00034 class AffineXform
00035 {
00036   public:
00037     inline AffineXform();
00038 
00039     inline AffineXform( const double* three_by_three, const double* translation );
00040 
00041     inline AffineXform( const Matrix3& mat, const CartVect& off );
00042 
00043     /** move */
00044     static inline AffineXform translation( const double* vector );
00045     /** rotate about axis through origin */
00046     static inline AffineXform rotation( double radians, const double* axis );
00047     /** define rotation such that if applied to \c from_vec the result aligned with \c to_vec */
00048     static AffineXform rotation( const double* from_vec, const double* to_vec );
00049     /** reflect about plane through origin */
00050     static inline AffineXform reflection( const double* plane_normal );
00051     /** scale about origin */
00052     static inline AffineXform scale( double f );
00053     /** scale about origin */
00054     static inline AffineXform scale( const double* fractions );
00055     /** scale about a point */
00056     static inline AffineXform scale( double f, const double* point );
00057     /** scale about a point */
00058     static inline AffineXform scale( const double* fractions, const double* point );
00059 
00060     /** incorporate the passed transform into this one such that the
00061      *  resulting transform is the cumulative affect of this initial
00062      *  transform followed by the passed transform */
00063     inline void accumulate( const AffineXform& other );
00064 
00065     /** apply transform to a point */
00066     inline void xform_point( const double* input, double* output ) const;
00067     /** apply transform to a point */
00068     inline void xform_point( double* in_out ) const;
00069 
00070     /** apply transform to a vector */
00071     inline void xform_vector( const double* input, double* output ) const;
00072     /** apply transform to a vector */
00073     inline void xform_vector( double* in_out ) const;
00074 
00075     /** get transform that is the inverse of this transform */
00076     AffineXform inverse() const;
00077 
00078     /** get a tag that can be used to store an instance of this class */
00079     static ErrorCode get_tag( Tag& tag_handle_out, Interface* moab, const char* tagname = 0 );
00080 
00081     /** get 3x3 matrix portion of transform */
00082     const Matrix3& matrix() const
00083     {
00084         return mMatrix;
00085     }
00086     /** get translation portion of transform */
00087     const CartVect& offset() const
00088     {
00089         return mOffset;
00090     }
00091 
00092     /** Is this transform a reflection
00093      *
00094      * A relfecting transform will require the reversal of the
00095      * order of edges in a loop, etc. because it produces a
00096      * mirror-image of the input geometry.  This method tests
00097      * if this is such a transform.  A reflection may be created
00098      * with by an explicit transform, scaling with a negative
00099      * scale factor, etc.  If multiple transforms are combined
00100      * such that the transform is no longer a reflection (e.g.
00101      * two reflections that are effectively a rotation), this method
00102      * will return false.
00103      */
00104     inline bool reflection() const;
00105 
00106     /** Does this transform do any scaling */
00107     inline bool scale() const;
00108 
00109   private:
00110     static inline AffineXform rotation( double cos_angle, double sin_angle, const CartVect& unit_axis );
00111 
00112     Matrix3 mMatrix;
00113     CartVect mOffset;
00114 };
00115 
00116 /** create a new transform equivalent to transform \c A followed
00117  *  by transform \c B
00118  */
00119 inline AffineXform operator*( const AffineXform& A, const AffineXform& B )
00120 {
00121     AffineXform result( A );
00122     result.accumulate( B );
00123     return result;
00124 }
00125 
00126 inline AffineXform::AffineXform() : mMatrix( 1.0 ), mOffset( 0.0 ) {}
00127 
00128 inline AffineXform::AffineXform( const double* three_by_three, const double* trans )
00129     : mMatrix( three_by_three ), mOffset( trans )
00130 {
00131 }
00132 
00133 inline AffineXform::AffineXform( const Matrix3& mat, const CartVect& off ) : mMatrix( mat ), mOffset( off ) {}
00134 
00135 inline AffineXform AffineXform::translation( const double* vector )
00136 {
00137     return AffineXform( Matrix3( 1.0 ), CartVect( vector ) );
00138 }
00139 
00140 inline AffineXform AffineXform::rotation( double angle, const double* axis )
00141 {
00142     CartVect a( axis );
00143     a.normalize();
00144     return AffineXform::rotation( std::cos( angle ), std::sin( angle ), a );
00145 }
00146 
00147 inline AffineXform AffineXform::rotation( double c, double s, const CartVect& a )
00148 {
00149     const Matrix3 m1( c, -a[2] * s, a[1] * s, a[2] * s, c, -a[0] * s, -a[1] * s, a[0] * s, c );
00150     return AffineXform( m1 + ( 1.0 - c ) * outer_product( a, a ), CartVect( 0.0 ) );
00151 }
00152 
00153 inline AffineXform AffineXform::reflection( const double* plane_normal )
00154 {
00155     double i = plane_normal[0];
00156     double j = plane_normal[1];
00157     double k = plane_normal[2];
00158     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,
00159                -2.0 * i * k, -2.0 * j * k, i * i + j * j - k * k );
00160     m *= 1.0 / ( i * i + j * j + k * k );  // normalize
00161     return AffineXform( m, CartVect( 0.0 ) );
00162 }
00163 
00164 inline AffineXform AffineXform::scale( const double* f )
00165 {
00166     return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) );
00167 }
00168 
00169 inline AffineXform AffineXform::scale( double f )
00170 {
00171     return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) );
00172 }
00173 
00174 inline AffineXform AffineXform::scale( double f, const double* point )
00175 {
00176     double fs[] = { f, f, f };
00177     return AffineXform::scale( fs, point );
00178 }
00179 
00180 inline AffineXform AffineXform::scale( const double* f, const double* p )
00181 {
00182     double offset[] = { p[0] * ( 1 - f[0] ), p[1] * ( 1 - f[1] ), p[2] * ( 1 - f[2] ) };
00183     return AffineXform( Matrix3( CartVect( f ) ), CartVect( offset ) );
00184 }
00185 
00186 inline void AffineXform::accumulate( const AffineXform& other )
00187 {
00188     mMatrix = other.mMatrix * mMatrix;
00189     other.xform_point( mOffset.array() );
00190 }
00191 
00192 inline void AffineXform::xform_point( const double* input, double* output ) const
00193 {
00194     xform_vector( input, output );
00195     output[0] += mOffset[0];
00196     output[1] += mOffset[1];
00197     output[2] += mOffset[2];
00198 }
00199 
00200 inline void AffineXform::xform_point( double* in_out ) const
00201 {
00202     xform_vector( in_out );
00203     in_out[0] += mOffset[0];
00204     in_out[1] += mOffset[1];
00205     in_out[2] += mOffset[2];
00206 }
00207 
00208 inline void AffineXform::xform_vector( const double* input, double* output ) const
00209 {
00210     output[0] = input[0] * mMatrix[0][0] + input[1] * mMatrix[0][1] + input[2] * mMatrix[0][2];
00211     output[1] = input[0] * mMatrix[1][0] + input[1] * mMatrix[1][1] + input[2] * mMatrix[1][2];
00212     output[2] = input[0] * mMatrix[2][0] + input[1] * mMatrix[2][1] + input[2] * mMatrix[2][2];
00213 }
00214 
00215 inline void AffineXform::xform_vector( double* in_out ) const
00216 {
00217     double input[] = { in_out[0], in_out[1], in_out[2] };
00218     xform_vector( input, in_out );
00219 }
00220 
00221 inline AffineXform AffineXform::inverse() const
00222 {
00223     Matrix3 m = mMatrix.inverse();
00224     return AffineXform( m, m * -mOffset );
00225 }
00226 
00227 inline bool AffineXform::reflection() const
00228 {
00229     return mMatrix.determinant() < 0.0;
00230 }
00231 
00232 inline bool AffineXform::scale() const
00233 {
00234     return fabs( fabs( mMatrix.determinant() ) - 1 ) > std::numeric_limits< double >::epsilon();
00235 }
00236 
00237 }  // namespace moab
00238 
00239 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines