Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AffineXform.hpp
Go to the documentation of this file.
1 /** 2  * MOAB, a Mesh-Oriented datABase, is a software component for creating, 3  * storing and accessing finite element mesh data. 4  * 5  * Copyright 2004 Sandia Corporation. Under the terms of Contract 6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 7  * retains certain rights in this software. 8  * 9  * This library is free software; you can redistribute it and/or 10  * modify it under the terms of the GNU Lesser General Public 11  * License as published by the Free Software Foundation; either 12  * version 2.1 of the License, or (at your option) any later version. 13  * 14  */ 15  16 #ifndef MOAB_AFFINE_XFORM_HPP 17 #define MOAB_AFFINE_XFORM_HPP 18  19 #include "moab/Forward.hpp" 20 #include "moab/CartVect.hpp" 21 #include "moab/Matrix3.hpp" 22  23 #include <cmath> 24 #include <limits> 25  26 namespace moab 27 { 28  29 /** 30  * \brief Define an affine transformation 31  * \author Jason Kraftcheck (kraftche@cae.wisc.edu) 32  * \date August, 2006 33  */ 34 class AffineXform 35 { 36  public: 37  inline AffineXform(); 38  39  inline AffineXform( const double* three_by_three, const double* translation ); 40  41  inline AffineXform( const Matrix3& mat, const CartVect& off ); 42  43  /** move */ 44  static inline AffineXform translation( const double* vector ); 45  /** rotate about axis through origin */ 46  static inline AffineXform rotation( double radians, const double* axis ); 47  /** define rotation such that if applied to \c from_vec the result aligned with \c to_vec */ 48  static AffineXform rotation( const double* from_vec, const double* to_vec ); 49  /** reflect about plane through origin */ 50  static inline AffineXform reflection( const double* plane_normal ); 51  /** scale about origin */ 52  static inline AffineXform scale( double f ); 53  /** scale about origin */ 54  static inline AffineXform scale( const double* fractions ); 55  /** scale about a point */ 56  static inline AffineXform scale( double f, const double* point ); 57  /** scale about a point */ 58  static inline AffineXform scale( const double* fractions, const double* point ); 59  60  /** incorporate the passed transform into this one such that the 61  * resulting transform is the cumulative affect of this initial 62  * transform followed by the passed transform */ 63  inline void accumulate( const AffineXform& other ); 64  65  /** apply transform to a point */ 66  inline void xform_point( const double* input, double* output ) const; 67  /** apply transform to a point */ 68  inline void xform_point( double* in_out ) const; 69  70  /** apply transform to a vector */ 71  inline void xform_vector( const double* input, double* output ) const; 72  /** apply transform to a vector */ 73  inline void xform_vector( double* in_out ) const; 74  75  /** get transform that is the inverse of this transform */ 76  AffineXform inverse() const; 77  78  /** get a tag that can be used to store an instance of this class */ 79  static ErrorCode get_tag( Tag& tag_handle_out, Interface* moab, const char* tagname = 0 ); 80  81  /** get 3x3 matrix portion of transform */ 82  const Matrix3& matrix() const 83  { 84  return mMatrix; 85  } 86  /** get translation portion of transform */ 87  const CartVect& offset() const 88  { 89  return mOffset; 90  } 91  92  /** Is this transform a reflection 93  * 94  * A relfecting transform will require the reversal of the 95  * order of edges in a loop, etc. because it produces a 96  * mirror-image of the input geometry. This method tests 97  * if this is such a transform. A reflection may be created 98  * with by an explicit transform, scaling with a negative 99  * scale factor, etc. If multiple transforms are combined 100  * such that the transform is no longer a reflection (e.g. 101  * two reflections that are effectively a rotation), this method 102  * will return false. 103  */ 104  inline bool reflection() const; 105  106  /** Does this transform do any scaling */ 107  inline bool scale() const; 108  109  private: 110  static inline AffineXform rotation( double cos_angle, double sin_angle, const CartVect& unit_axis ); 111  112  Matrix3 mMatrix; 113  CartVect mOffset; 114 }; 115  116 /** create a new transform equivalent to transform \c A followed 117  * by transform \c B 118  */ 119 inline AffineXform operator*( const AffineXform& A, const AffineXform& B ) 120 { 121  AffineXform result( A ); 122  result.accumulate( B ); 123  return result; 124 } 125  126 inline AffineXform::AffineXform() : mMatrix( 1.0 ), mOffset( 0.0 ) {} 127  128 inline AffineXform::AffineXform( const double* three_by_three, const double* trans ) 129  : mMatrix( three_by_three ), mOffset( trans ) 130 { 131 } 132  133 inline AffineXform::AffineXform( const Matrix3& mat, const CartVect& off ) : mMatrix( mat ), mOffset( off ) {} 134  135 inline AffineXform AffineXform::translation( const double* vector ) 136 { 137  return AffineXform( Matrix3( 1.0 ), CartVect( vector ) ); 138 } 139  140 inline AffineXform AffineXform::rotation( double angle, const double* axis ) 141 { 142  CartVect a( axis ); 143  a.normalize(); 144  return AffineXform::rotation( std::cos( angle ), std::sin( angle ), a ); 145 } 146  147 inline AffineXform AffineXform::rotation( double c, double s, const CartVect& a ) 148 { 149  const Matrix3 m1( c, -a[2] * s, a[1] * s, a[2] * s, c, -a[0] * s, -a[1] * s, a[0] * s, c ); 150  return AffineXform( m1 + ( 1.0 - c ) * outer_product( a, a ), CartVect( 0.0 ) ); 151 } 152  153 inline AffineXform AffineXform::reflection( const double* plane_normal ) 154 { 155  double i = plane_normal[0]; 156  double j = plane_normal[1]; 157  double k = plane_normal[2]; 158  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, 159  -2.0 * i * k, -2.0 * j * k, i * i + j * j - k * k ); 160  m *= 1.0 / ( i * i + j * j + k * k ); // normalize 161  return AffineXform( m, CartVect( 0.0 ) ); 162 } 163  164 inline AffineXform AffineXform::scale( const double* f ) 165 { 166  return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) ); 167 } 168  169 inline AffineXform AffineXform::scale( double f ) 170 { 171  return AffineXform( Matrix3( CartVect( f ) ), CartVect( 0.0 ) ); 172 } 173  174 inline AffineXform AffineXform::scale( double f, const double* point ) 175 { 176  double fs[] = { f, f, f }; 177  return AffineXform::scale( fs, point ); 178 } 179  180 inline AffineXform AffineXform::scale( const double* f, const double* p ) 181 { 182  double offset[] = { p[0] * ( 1 - f[0] ), p[1] * ( 1 - f[1] ), p[2] * ( 1 - f[2] ) }; 183  return AffineXform( Matrix3( CartVect( f ) ), CartVect( offset ) ); 184 } 185  186 inline void AffineXform::accumulate( const AffineXform& other ) 187 { 188  mMatrix = other.mMatrix * mMatrix; 189  other.xform_point( mOffset.array() ); 190 } 191  192 inline void AffineXform::xform_point( const double* input, double* output ) const 193 { 194  xform_vector( input, output ); 195  output[0] += mOffset[0]; 196  output[1] += mOffset[1]; 197  output[2] += mOffset[2]; 198 } 199  200 inline void AffineXform::xform_point( double* in_out ) const 201 { 202  xform_vector( in_out ); 203  in_out[0] += mOffset[0]; 204  in_out[1] += mOffset[1]; 205  in_out[2] += mOffset[2]; 206 } 207  208 inline void AffineXform::xform_vector( const double* input, double* output ) const 209 { 210  output[0] = input[0] * mMatrix[0][0] + input[1] * mMatrix[0][1] + input[2] * mMatrix[0][2]; 211  output[1] = input[0] * mMatrix[1][0] + input[1] * mMatrix[1][1] + input[2] * mMatrix[1][2]; 212  output[2] = input[0] * mMatrix[2][0] + input[1] * mMatrix[2][1] + input[2] * mMatrix[2][2]; 213 } 214  215 inline void AffineXform::xform_vector( double* in_out ) const 216 { 217  double input[] = { in_out[0], in_out[1], in_out[2] }; 218  xform_vector( input, in_out ); 219 } 220  221 inline AffineXform AffineXform::inverse() const 222 { 223  Matrix3 m = mMatrix.inverse(); 224  return AffineXform( m, m * -mOffset ); 225 } 226  227 inline bool AffineXform::reflection() const 228 { 229  return mMatrix.determinant() < 0.0; 230 } 231  232 inline bool AffineXform::scale() const 233 { 234  return fabs( fabs( mMatrix.determinant() ) - 1 ) > std::numeric_limits< double >::epsilon(); 235 } 236  237 } // namespace moab 238  239 #endif