![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00024 #include
00025
00026 namespace moab
00027 {
00028
00029 /**
00030 * \brief Define an affine transformation
00031 * \author Jason Kraftcheck (kraftche@cae.wisc.edu)
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