MOAB: Mesh Oriented datABase  (version 5.4.1)
Vector3D.hpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government retains certain
00007     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     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     [email protected], [email protected], [email protected],
00024     [email protected], [email protected], [email protected]
00025 
00026   ***************************************************************** */
00027 #ifndef MESQUITE_VECTOR3D_HPP
00028 #define MESQUITE_VECTOR3D_HPP
00029 
00030 #include "Mesquite.hpp"
00031 
00032 #include <iosfwd>
00033 #include <cassert>
00034 #include <cstring>
00035 #include <vector>
00036 
00037 /*! \file Vector3D.hpp
00038   \brief Vector object with exactly 3 dimensions.
00039 
00040   This is as fast as a C array.
00041 
00042   \author Darryl Melander
00043   \author Thomas Leurent
00044 */
00045 namespace MBMesquite
00046 {
00047 class Matrix3D;
00048 class MsqError;
00049 
00050 /*!
00051    \class Vector3D
00052    \brief Vector3D is the object that effeciently stores information about
00053    about three-deminsional vectors.  It is also the parent class of
00054    MsqVertex.      */
00055 class MESQUITE_EXPORT Vector3D
00056 {
00057   public:
00058     // Constructors
00059     Vector3D();
00060     Vector3D( double xyz );
00061     Vector3D( double x, double y, double z );
00062     Vector3D( const double xyz[3] );
00063     Vector3D( const Vector3D& to_copy );
00064 
00065     // *** virtual destructor *** Do not use for Vector3D, we need to keep
00066     // the deallocation of those objects very fast
00067 
00068     // Functions to get the coordinates
00069     double x() const;
00070     double y() const;
00071     double z() const;
00072     void get_coordinates( double& x, double& y, double& z ) const;
00073     void get_coordinates( double xyz[3] ) const;
00074     const double& operator[]( size_t index ) const;  // 0-based
00075 
00076     // Functions to set the coordinates.
00077     void x( const double x );
00078     void y( const double y );
00079     void z( const double z );
00080     void set( const double x, const double y, const double z );
00081     void set( const double xyz[3] );
00082     void set( const Vector3D& to_copy );
00083     // Subscripts on non-consts both get and set coords
00084     double& operator[]( size_t index );  // 0-based
00085     Vector3D& operator=( const Vector3D& to_copy );
00086     Vector3D& operator=( const double& to_copy );
00087 
00088     // Functions to modify existing coordinates
00089     Vector3D operator-() const;  //- unary negation.
00090     Vector3D& operator*=( const double scalar );
00091     Vector3D& operator/=( const double scalar );
00092     Vector3D& operator*=( const Vector3D& rhs );  //- cross product
00093     Vector3D& operator+=( const Vector3D& rhs );
00094     Vector3D& operator-=( const Vector3D& rhs );
00095 
00096     // Binary operators (like a+b).
00097     friend const Vector3D operator+( const Vector3D& lhs, const Vector3D& rhs );
00098     friend const Vector3D operator-( const Vector3D& lhs, const Vector3D& rhs );
00099     friend const Vector3D operator*( const Vector3D& lhs,
00100                                      const double scalar );  //!< lhs * scalar
00101     friend const Vector3D operator*( const double scalar,
00102                                      const Vector3D& rhs );  //!< scalar * rhs
00103     friend const Vector3D operator/( const Vector3D& lhs,
00104                                      const double scalar );  //- lhs / scalar
00105     friend double operator%( const Vector3D& v1,
00106                              const Vector3D& v2 );  //!< dot product
00107     friend double inner( const Vector3D v1[], const Vector3D v2[],
00108                          int n );  //!< dot product for array
00109     friend double operator%( const double scalar,
00110                              const Vector3D& v2 );  //!< scalar * sum_i v2[i]
00111     friend double operator%( const Vector3D& v1,
00112                              const double scalar );  //!< scalar * sum_i v1[i]
00113     friend const Vector3D operator*( const Vector3D& v1,
00114                                      const Vector3D& v2 );  //!< cross product
00115 
00116     //! \f$ v = A*x \f$
00117     friend void eqAx( Vector3D& v, const Matrix3D& A, const Vector3D& x );
00118     //! \f$ v += A*x \f$
00119     friend void plusEqAx( Vector3D& v, const Matrix3D& A, const Vector3D& x );
00120     //! \f$ v += A^T*x \f$
00121     friend void plusEqTransAx( Vector3D& v, const Matrix3D& A, const Vector3D& x );
00122     friend void eqTransAx( Vector3D& v, const Matrix3D& A, const Vector3D& x );
00123 
00124     // Comparison functions
00125     friend bool operator==( const Vector3D& lhs, const Vector3D& rhs );
00126     friend bool operator!=( const Vector3D& lhs, const Vector3D& rhs );
00127     static double distance_between( const Vector3D& p1, const Vector3D& p2 );
00128     int within_tolerance_box( const Vector3D& compare_to, double tolerance ) const;
00129     //- Compare two Vector3Ds to see if they are spatially equal.
00130     // Return TRUE if difference in x, y, and z are all within tolerance.
00131     // Essentially checks to see if 'this' lies within a box centered on
00132     // 'compare_to' with sides of length ('tolerance' * 2).
00133 
00134     // Length functions
00135     inline double length_squared() const;
00136     inline double length() const;
00137     friend double length( const Vector3D* v, int n );  //!< L2 norm for an array of Vector3Ds
00138     friend double Linf( const Vector3D* v, int n );    //!< L inf norm for array of Vector3Ds
00139 
00140     inline void set_length( const double new_length );
00141     inline void normalize();
00142     Vector3D operator~() const
00143     {
00144         return *this * ( 1.0 / length() );
00145     }
00146 
00147     // Utility functions.  All angle functions work in radians.
00148     static double interior_angle( const Vector3D& a, const Vector3D& b, MsqError& err );
00149     //- Interior angle: acos((a%b)/(|a||b|))
00150     static Vector3D interpolate( const double param, const Vector3D& p1, const Vector3D& p2 );
00151     //- Interpolate between two points. Returns (1-param)*v1 + param*v2.
00152 
00153     const double* to_array() const
00154     {
00155         return mCoords;
00156     }
00157 
00158     double* to_array()
00159     {
00160         return mCoords;
00161     }
00162 
00163   protected:
00164     double mCoords[3];
00165 };
00166 
00167 // Constructors
00168 inline Vector3D::Vector3D()
00169 {
00170     mCoords[0] = 0;
00171     mCoords[1] = 0;
00172     mCoords[2] = 0;
00173 }
00174 inline Vector3D::Vector3D( double p_x )
00175 {
00176     mCoords[0] = p_x;
00177     mCoords[1] = p_x;
00178     mCoords[2] = p_x;
00179 }
00180 inline Vector3D::Vector3D( double p_x, double p_y, double p_z )
00181 {
00182     mCoords[0] = p_x;
00183     mCoords[1] = p_y;
00184     mCoords[2] = p_z;
00185 }
00186 inline Vector3D::Vector3D( const double xyz[3] )
00187 {
00188     std::memcpy( mCoords, xyz, 3 * sizeof( double ) );
00189 }
00190 inline Vector3D::Vector3D( const Vector3D& to_copy )
00191 {
00192     std::memcpy( mCoords, to_copy.mCoords, 3 * sizeof( double ) );
00193 }
00194 
00195 // Functions to get coordinates
00196 inline double Vector3D::x() const
00197 {
00198     return mCoords[0];
00199 }
00200 inline double Vector3D::y() const
00201 {
00202     return mCoords[1];
00203 }
00204 inline double Vector3D::z() const
00205 {
00206     return mCoords[2];
00207 }
00208 inline void Vector3D::get_coordinates( double& p_x, double& p_y, double& p_z ) const
00209 {
00210     p_x = mCoords[0];
00211     p_y = mCoords[1];
00212     p_z = mCoords[2];
00213 }
00214 inline void Vector3D::get_coordinates( double xyz[3] ) const
00215 {
00216     std::memcpy( xyz, mCoords, 3 * sizeof( double ) );
00217 }
00218 inline const double& Vector3D::operator[]( size_t index ) const
00219 {
00220     return mCoords[index];
00221 }
00222 
00223 // Functions to set coordinates
00224 inline void Vector3D::x( const double p_x )
00225 {
00226     mCoords[0] = p_x;
00227 }
00228 inline void Vector3D::y( const double p_y )
00229 {
00230     mCoords[1] = p_y;
00231 }
00232 inline void Vector3D::z( const double p_z )
00233 {
00234     mCoords[2] = p_z;
00235 }
00236 inline void Vector3D::set( const double p_x, const double p_y, const double p_z )
00237 {
00238     mCoords[0] = p_x;
00239     mCoords[1] = p_y;
00240     mCoords[2] = p_z;
00241 }
00242 inline void Vector3D::set( const double xyz[3] )
00243 {
00244     std::memcpy( mCoords, xyz, 3 * sizeof( double ) );
00245 }
00246 inline void Vector3D::set( const Vector3D& to_copy )
00247 {
00248     std::memcpy( mCoords, to_copy.mCoords, 3 * sizeof( double ) );
00249 }
00250 inline double& Vector3D::operator[]( size_t index )
00251 {
00252     return mCoords[index];
00253 }
00254 
00255 inline Vector3D& Vector3D::operator=( const Vector3D& to_copy )
00256 {
00257     mCoords[0] = to_copy.mCoords[0];
00258     mCoords[1] = to_copy.mCoords[1];
00259     mCoords[2] = to_copy.mCoords[2];
00260     //    memcpy(mCoords, to_copy.mCoords, 3*sizeof(double));
00261     return *this;
00262 }
00263 
00264 inline Vector3D& Vector3D::operator=( const double& to_copy )
00265 {
00266     mCoords[0] = to_copy;
00267     mCoords[1] = to_copy;
00268     mCoords[2] = to_copy;
00269     return *this;
00270 }
00271 
00272 // Functions that modify existing coordinates
00273 inline Vector3D Vector3D::operator-() const
00274 {
00275     return Vector3D( -mCoords[0], -mCoords[1], -mCoords[2] );
00276 }
00277 inline Vector3D& Vector3D::operator*=( const double scalar )
00278 {
00279     mCoords[0] *= scalar;
00280     mCoords[1] *= scalar;
00281     mCoords[2] *= scalar;
00282     return *this;
00283 }
00284 //! divides each Vector3D entry by the given scalar.
00285 inline Vector3D& Vector3D::operator/=( const double scalar )
00286 {
00287     mCoords[0] /= scalar;
00288     mCoords[1] /= scalar;
00289     mCoords[2] /= scalar;
00290     return *this;
00291 }
00292 inline Vector3D& Vector3D::operator*=( const Vector3D& rhs )
00293 {
00294     double new_coords[3] = { mCoords[1] * rhs.mCoords[2] - mCoords[2] * rhs.mCoords[1],
00295                              mCoords[2] * rhs.mCoords[0] - mCoords[0] * rhs.mCoords[2],
00296                              mCoords[0] * rhs.mCoords[1] - mCoords[1] * rhs.mCoords[0] };
00297     std::memcpy( mCoords, new_coords, 3 * sizeof( double ) );
00298     return *this;
00299 }
00300 inline Vector3D& Vector3D::operator+=( const Vector3D& rhs )
00301 {
00302     mCoords[0] += rhs.mCoords[0];
00303     mCoords[1] += rhs.mCoords[1];
00304     mCoords[2] += rhs.mCoords[2];
00305     return *this;
00306 }
00307 inline Vector3D& Vector3D::operator-=( const Vector3D& rhs )
00308 {
00309     mCoords[0] -= rhs.mCoords[0];
00310     mCoords[1] -= rhs.mCoords[1];
00311     mCoords[2] -= rhs.mCoords[2];
00312     return *this;
00313 }
00314 
00315 // Binary operators
00316 inline const Vector3D operator+( const Vector3D& lhs, const Vector3D& rhs )
00317 {
00318     return Vector3D( lhs.x() + rhs.x(), lhs.y() + rhs.y(), lhs.z() + rhs.z() );
00319 }
00320 inline const Vector3D operator-( const Vector3D& lhs, const Vector3D& rhs )
00321 {
00322     return Vector3D( lhs.x() - rhs.x(), lhs.y() - rhs.y(), lhs.z() - rhs.z() );
00323 }
00324 inline const Vector3D operator*( const Vector3D& lhs, const double scalar )
00325 {
00326     return Vector3D( lhs.x() * scalar, lhs.y() * scalar, lhs.z() * scalar );
00327 }
00328 inline const Vector3D operator*( const double scalar, const Vector3D& rhs )
00329 {
00330     return Vector3D( rhs.x() * scalar, rhs.y() * scalar, rhs.z() * scalar );
00331 }
00332 inline const Vector3D operator/( const Vector3D& lhs, const double scalar )
00333 {
00334     assert( scalar != 0 );
00335     return Vector3D( lhs.x() / scalar, lhs.y() / scalar, lhs.z() / scalar );
00336 }
00337 inline double operator%( const Vector3D& lhs,
00338                          const Vector3D& rhs )  // Dot Product
00339 {
00340     return ( lhs.mCoords[0] * rhs.mCoords[0] + lhs.mCoords[1] * rhs.mCoords[1] + lhs.mCoords[2] * rhs.mCoords[2] );
00341 }
00342 
00343 /*! Dot product for arrays of Vector3Ds. see also operator% .*/
00344 inline double inner( const Vector3D lhs[], const Vector3D rhs[], int n )
00345 {
00346     int i;
00347     double dot = 0;
00348     for( i = 0; i < n; ++i )
00349         dot += lhs[i].mCoords[0] * rhs[i].mCoords[0] + lhs[i].mCoords[1] * rhs[i].mCoords[1] +
00350                lhs[i].mCoords[2] * rhs[i].mCoords[2];
00351     return dot;
00352 }
00353 /*! Dot product for arrays of Vector3Ds. see also operator% .*/
00354 inline double inner( const std::vector< Vector3D >& lhs, const std::vector< Vector3D >& rhs )
00355 {
00356     double dot = 0;
00357     assert( lhs.size() == rhs.size() );
00358     for( size_t i = 0; i < lhs.size(); ++i )
00359         dot = lhs[i] % rhs[i];
00360     return dot;
00361 }
00362 
00363 inline double operator%( const double scalar,
00364                          const Vector3D& rhs )  // Dot Product
00365 {
00366     return ( scalar * ( rhs.mCoords[0] + rhs.mCoords[1] + rhs.mCoords[2] ) );
00367 }
00368 inline double operator%( const Vector3D& lhs,
00369                          const double scalar )  // Dot Product
00370 {
00371     return ( scalar * ( lhs.mCoords[0] + lhs.mCoords[1] + lhs.mCoords[2] ) );
00372 }
00373 inline const Vector3D operator*( const Vector3D& lhs,
00374                                  const Vector3D& rhs )  // Cross Product
00375 {
00376     return Vector3D( lhs.mCoords[1] * rhs.mCoords[2] - lhs.mCoords[2] * rhs.mCoords[1],
00377                      lhs.mCoords[2] * rhs.mCoords[0] - lhs.mCoords[0] * rhs.mCoords[2],
00378                      lhs.mCoords[0] * rhs.mCoords[1] - lhs.mCoords[1] * rhs.mCoords[0] );
00379 }
00380 
00381 // output operator
00382 MESQUITE_EXPORT std::ostream& operator<<( std::ostream& s, const MBMesquite::Vector3D& v );
00383 
00384 inline double Vector3D::distance_between( const Vector3D& p1, const Vector3D& p2 )
00385 {
00386     Vector3D v = p2 - p1;
00387     return v.length();
00388 }
00389 inline int Vector3D::within_tolerance_box( const Vector3D& compare_to, double tolerance ) const
00390 {
00391     return ( ( std::fabs( this->mCoords[0] - compare_to.mCoords[0] ) < tolerance ) &&
00392              ( std::fabs( this->mCoords[1] - compare_to.mCoords[1] ) < tolerance ) &&
00393              ( std::fabs( this->mCoords[2] - compare_to.mCoords[2] ) < tolerance ) );
00394 }
00395 
00396 // Length functions
00397 inline double Vector3D::length_squared() const
00398 {
00399     return ( mCoords[0] * mCoords[0] + mCoords[1] * mCoords[1] + mCoords[2] * mCoords[2] );
00400 }
00401 inline double Vector3D::length() const
00402 {
00403     return std::sqrt( mCoords[0] * mCoords[0] + mCoords[1] * mCoords[1] + mCoords[2] * mCoords[2] );
00404 }
00405 
00406 inline double inner_product( const Vector3D* v1, const Vector3D* v2, size_t n )
00407 {
00408     double result             = 0.0;
00409     const Vector3D* const end = v1 + n;
00410     while( v1 < end )
00411     {
00412         result += *v1 % *v2;
00413         ++v1;
00414         ++v2;
00415     }
00416     return result;
00417 }
00418 
00419 inline double length_squared( const Vector3D* v, int n )
00420 {
00421     double sum = 0.0;
00422     for( int i = 0; i < n; ++i )
00423         sum += v[i].length_squared();
00424     return sum;
00425 }
00426 inline double length_squared( const std::vector< Vector3D >& v )
00427 {
00428     double sum = 0.0;
00429     for( size_t i = 0; i < v.size(); ++i )
00430         sum += v[i].length_squared();
00431     return sum;
00432 }
00433 
00434 inline double length( const Vector3D* v, int n )  // norm for an array of Vector3Ds
00435 {
00436     return std::sqrt( length_squared( v, n ) );
00437 }
00438 inline double length( const std::vector< Vector3D >& v )
00439 {
00440     return std::sqrt( length_squared( v ) );
00441 }
00442 
00443 inline double Linf( const Vector3D* v, int n )  // max entry for an array of Vector3Ds
00444 {
00445     double max = 0;
00446     // loop over the length of the array
00447     for( int i = 0; i < n; ++i )
00448     {
00449         if( max < std::fabs( v[i][0] ) ) max = std::fabs( v[i][0] );
00450         if( max < std::fabs( v[i][1] ) ) max = std::fabs( v[i][1] );
00451         if( max < std::fabs( v[i][2] ) ) max = std::fabs( v[i][2] );
00452     }
00453     // return the value of the largest entry in the array
00454     return max;
00455 }
00456 
00457 inline double Linf( const std::vector< Vector3D >& v )  // max entry for an array of Vector3Ds
00458 {
00459     double max = 0;
00460     // loop over the length of the array
00461     for( size_t i = 0; i < v.size(); ++i )
00462     {
00463         if( max < std::fabs( v[i][0] ) ) max = std::fabs( v[i][0] );
00464         if( max < std::fabs( v[i][1] ) ) max = std::fabs( v[i][1] );
00465         if( max < std::fabs( v[i][2] ) ) max = std::fabs( v[i][2] );
00466     }
00467     // return the value of the largest entry in the array
00468     return max;
00469 }
00470 
00471 inline void Vector3D::set_length( const double new_length )
00472 {
00473     double factor = new_length / length();
00474     *this *= factor;
00475 }
00476 inline void Vector3D::normalize()
00477 {
00478     set_length( 1.0 );
00479 }
00480 
00481 // Utility functions.
00482 inline Vector3D Vector3D::interpolate( const double param, const Vector3D& p1, const Vector3D& p2 )
00483 {
00484     return ( 1 - param ) * p1 + param * p2;
00485 }
00486 
00487 inline bool operator==( const Vector3D& v1, const Vector3D& v2 )
00488 {
00489     return v1.mCoords[0] == v2.mCoords[0] && v1.mCoords[1] == v2.mCoords[1] && v1.mCoords[2] == v2.mCoords[2];
00490 }
00491 
00492 inline bool operator!=( const Vector3D& v1, const Vector3D& v2 )
00493 {
00494     return v1.mCoords[0] != v2.mCoords[0] || v1.mCoords[1] != v2.mCoords[1] || v1.mCoords[2] != v2.mCoords[2];
00495 }
00496 
00497 }  // namespace MBMesquite
00498 
00499 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines