MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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