libmove3d  3.13.0
/home/slemaign/softs-local/BioMove3D-git/util/vector3d.h
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright (c) 2000-2006 Torus Knot Software Ltd
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 
00024 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef __Vector3_H__
00030 #define __Vector3_H__
00031 
00032 #include <cstring>
00033 #include <iostream>
00034 #include <cassert>
00035 #include <cmath>
00036 #include "p3d_matrix.h"
00037 
00038 //namespace Ogre
00039 //{
00040 
00048 class Vector3
00049 {
00050 public:
00051     double x, y, z;
00052 
00053 public:
00054     inline Vector3()
00055     {
00056     }
00057 
00058     inline Vector3( const double fX, const double fY, const double fZ )
00059             : x( fX ), y( fY ), z( fZ )
00060     {
00061     }
00062 
00063     inline explicit Vector3( const double afCoordinate[3] )
00064             : x( afCoordinate[0] ),
00065             y( afCoordinate[1] ),
00066             z( afCoordinate[2] )
00067     {
00068     }
00069 
00070     inline explicit Vector3( const int afCoordinate[3] )
00071     {
00072         x = (double)afCoordinate[0];
00073         y = (double)afCoordinate[1];
00074         z = (double)afCoordinate[2];
00075     }
00076 
00077     inline explicit Vector3( const p3d_matrix4 m )
00078     {
00079         x = m[0][3];
00080         y = m[1][3];
00081         z = m[2][3];
00082     }
00083 
00084     inline explicit Vector3( double* const r )
00085             : x( r[0] ), y( r[1] ), z( r[2] )
00086     {
00087     }
00088 
00089     inline explicit Vector3( const double scaler )
00090             : x( scaler )
00091             , y( scaler )
00092             , z( scaler )
00093     {
00094     }
00095 
00096     inline int size() const { return 3; }
00097 
00098 
00099     inline double operator [] ( const size_t i ) const
00100     {
00101         assert( i < 3 );
00102 
00103         return *(&x+i);
00104     }
00105 
00106     inline double& operator [] ( const size_t i )
00107     {
00108         assert( i < 3 );
00109 
00110         return *(&x+i);
00111     }
00113     inline double* ptr()
00114     {
00115         return &x;
00116     }
00118     inline const double* ptr() const
00119     {
00120         return &x;
00121     }
00122 
00127     inline Vector3& operator = ( const Vector3& rkVector )
00128                                {
00129         x = rkVector.x;
00130         y = rkVector.y;
00131         z = rkVector.z;
00132 
00133         return *this;
00134     }
00135 
00136     inline Vector3& operator = ( const double fScaler )
00137                                {
00138         x = fScaler;
00139         y = fScaler;
00140         z = fScaler;
00141 
00142         return *this;
00143     }
00144 
00145     inline bool operator == ( const Vector3& rkVector ) const
00146     {
00147         return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
00148     }
00149 
00150     inline bool operator != ( const Vector3& rkVector ) const
00151     {
00152         return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
00153     }
00154 
00155     // arithmetic operations
00156     inline Vector3 operator + ( const Vector3& rkVector ) const
00157     {
00158         return Vector3(
00159                 x + rkVector.x,
00160                 y + rkVector.y,
00161                 z + rkVector.z);
00162     }
00163 
00164     inline Vector3 operator - ( const Vector3& rkVector ) const
00165     {
00166         return Vector3(
00167                 x - rkVector.x,
00168                 y - rkVector.y,
00169                 z - rkVector.z);
00170     }
00171 
00172     inline Vector3 operator * ( const double fScalar ) const
00173     {
00174         return Vector3(
00175                 x * fScalar,
00176                 y * fScalar,
00177                 z * fScalar);
00178     }
00179 
00180     inline Vector3 operator * ( const Vector3& rhs) const
00181     {
00182         return Vector3(
00183                 x * rhs.x,
00184                 y * rhs.y,
00185                 z * rhs.z);
00186     }
00187 
00188     inline Vector3 operator / ( const double fScalar ) const
00189     {
00190         assert( fScalar != 0.0 );
00191 
00192         double fInv = 1.0 / fScalar;
00193 
00194         return Vector3(
00195                 x * fInv,
00196                 y * fInv,
00197                 z * fInv);
00198     }
00199 
00200     inline Vector3 operator / ( const Vector3& rhs) const
00201     {
00202         return Vector3(
00203                 x / rhs.x,
00204                 y / rhs.y,
00205                 z / rhs.z);
00206     }
00207 
00208     inline const Vector3& operator + () const
00209     {
00210         return *this;
00211     }
00212 
00213     inline Vector3 operator - () const
00214     {
00215         return Vector3(-x, -y, -z);
00216     }
00217 
00218     // overloaded operators to help Vector3
00219     inline friend Vector3 operator * ( const double fScalar, const Vector3& rkVector )
00220     {
00221         return Vector3(
00222                 fScalar * rkVector.x,
00223                 fScalar * rkVector.y,
00224                 fScalar * rkVector.z);
00225     }
00226 
00227     inline friend Vector3 operator / ( const double fScalar, const Vector3& rkVector )
00228     {
00229         return Vector3(
00230                 fScalar / rkVector.x,
00231                 fScalar / rkVector.y,
00232                 fScalar / rkVector.z);
00233     }
00234 
00235     inline friend Vector3 operator + (const Vector3& lhs, const double rhs)
00236     {
00237         return Vector3(
00238                 lhs.x + rhs,
00239                 lhs.y + rhs,
00240                 lhs.z + rhs);
00241     }
00242 
00243     inline friend Vector3 operator + (const double lhs, const Vector3& rhs)
00244     {
00245         return Vector3(
00246                 lhs + rhs.x,
00247                 lhs + rhs.y,
00248                 lhs + rhs.z);
00249     }
00250 
00251     inline friend Vector3 operator - (const Vector3& lhs, const double rhs)
00252     {
00253         return Vector3(
00254                 lhs.x - rhs,
00255                 lhs.y - rhs,
00256                 lhs.z - rhs);
00257     }
00258 
00259     inline friend Vector3 operator - (const double lhs, const Vector3& rhs)
00260     {
00261         return Vector3(
00262                 lhs - rhs.x,
00263                 lhs - rhs.y,
00264                 lhs - rhs.z);
00265     }
00266 
00267     // arithmetic updates
00268     inline Vector3& operator += ( const Vector3& rkVector )
00269                                 {
00270         x += rkVector.x;
00271         y += rkVector.y;
00272         z += rkVector.z;
00273 
00274         return *this;
00275     }
00276 
00277     inline Vector3& operator += ( const double fScalar )
00278                                 {
00279         x += fScalar;
00280         y += fScalar;
00281         z += fScalar;
00282         return *this;
00283     }
00284 
00285     inline Vector3& operator -= ( const Vector3& rkVector )
00286                                 {
00287         x -= rkVector.x;
00288         y -= rkVector.y;
00289         z -= rkVector.z;
00290 
00291         return *this;
00292     }
00293 
00294     inline Vector3& operator -= ( const double fScalar )
00295                                 {
00296         x -= fScalar;
00297         y -= fScalar;
00298         z -= fScalar;
00299         return *this;
00300     }
00301 
00302     inline Vector3& operator *= ( const double fScalar )
00303                                 {
00304         x *= fScalar;
00305         y *= fScalar;
00306         z *= fScalar;
00307         return *this;
00308     }
00309 
00310     inline Vector3& operator *= ( const Vector3& rkVector )
00311                                 {
00312         x *= rkVector.x;
00313         y *= rkVector.y;
00314         z *= rkVector.z;
00315 
00316         return *this;
00317     }
00318 
00319     inline Vector3& operator /= ( const double fScalar )
00320                                 {
00321         assert( fScalar != 0.0 );
00322 
00323         double fInv = 1.0 / fScalar;
00324 
00325         x *= fInv;
00326         y *= fInv;
00327         z *= fInv;
00328 
00329         return *this;
00330     }
00331 
00332     inline Vector3& operator /= ( const Vector3& rkVector )
00333                                 {
00334         x /= rkVector.x;
00335         y /= rkVector.y;
00336         z /= rkVector.z;
00337 
00338         return *this;
00339     }
00340 
00341 
00349     inline double length () const
00350     {
00351         return sqrt( x * x + y * y + z * z );
00352     }
00353 
00364     inline double squaredLength () const
00365     {
00366         return x * x + y * y + z * z;
00367     }
00368 
00376     inline double distance(const Vector3& rhs) const
00377     {
00378         return (*this - rhs).length();
00379     }
00380 
00391     inline double squaredDistance(const Vector3& rhs) const
00392     {
00393         return (*this - rhs).squaredLength();
00394     }
00395 
00410     inline double dotProduct(const Vector3& vec) const
00411     {
00412         return x * vec.x + y * vec.y + z * vec.z;
00413     }
00414 
00425     inline double absDotProduct(const Vector3& vec) const
00426     {
00427         return abs(x * vec.x) + abs(y * vec.y) + abs(z * vec.z);
00428     }
00429 
00439     inline double normalise()
00440     {
00441         double fLength = sqrt( x * x + y * y + z * z );
00442 
00443         // Will also work for zero-sized vectors, but will change nothing
00444         if ( fLength > 1e-08 )
00445         {
00446             double fInvLength = 1.0 / fLength;
00447             x *= fInvLength;
00448             y *= fInvLength;
00449             z *= fInvLength;
00450         }
00451 
00452         return fLength;
00453     }
00454 
00483     inline Vector3 crossProduct( const Vector3& rkVector ) const
00484     {
00485         return Vector3(
00486                 y * rkVector.z - z * rkVector.y,
00487                 z * rkVector.x - x * rkVector.z,
00488                 x * rkVector.y - y * rkVector.x);
00489     }
00490 
00494     inline Vector3 midPoint( const Vector3& vec ) const
00495     {
00496         return Vector3(
00497                 ( x + vec.x ) * 0.5,
00498                 ( y + vec.y ) * 0.5,
00499                 ( z + vec.z ) * 0.5 );
00500     }
00501 
00505     inline bool operator < ( const Vector3& rhs ) const
00506     {
00507         if( x < rhs.x && y < rhs.y && z < rhs.z )
00508             return true;
00509         return false;
00510     }
00511 
00515     inline bool operator > ( const Vector3& rhs ) const
00516     {
00517         if( x > rhs.x && y > rhs.y && z > rhs.z )
00518             return true;
00519         return false;
00520     }
00521 
00529     inline void makeFloor( const Vector3& cmp )
00530     {
00531         if( cmp.x < x ) x = cmp.x;
00532         if( cmp.y < y ) y = cmp.y;
00533         if( cmp.z < z ) z = cmp.z;
00534     }
00535 
00543     inline void makeCeil( const Vector3& cmp )
00544     {
00545         if( cmp.x > x ) x = cmp.x;
00546         if( cmp.y > y ) y = cmp.y;
00547         if( cmp.z > z ) z = cmp.z;
00548     }
00549 
00557     inline Vector3 perpendicular(void) const
00558     {
00559         static const double fSquareZero = 1e-06 * 1e-06;
00560 
00561         Vector3 perp = this->crossProduct( Vector3::UNIT_X );
00562 
00563         // Check length
00564         if( perp.squaredLength() < fSquareZero )
00565         {
00566             /* This vector is the Y axis multiplied by a scalar, so we have
00567                    to use another axis.
00568                 */
00569             perp = this->crossProduct( Vector3::UNIT_Y );
00570         }
00571         perp.normalise();
00572 
00573         return perp;
00574     }
00594     //        inline Vector3 randomDeviant(
00595     //            const Radian& angle,
00596     //            const Vector3& up = Vector3::ZERO ) const
00597     //        {
00598     //            Vector3 newUp;
00599     //
00600     //            if (up == Vector3::ZERO)
00601     //            {
00602     //                // Generate an up vector
00603     //                newUp = this->perpendicular();
00604     //            }
00605     //            else
00606     //            {
00607     //                newUp = up;
00608     //            }
00609     //
00610     //            // Rotate up vector by random amount around this
00611     //            Quaternion q;
00612     //            q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), *this );
00613     //            newUp = q * newUp;
00614     //
00615     //            // Finally rotate this by given angle around randomised up
00616     //            q.FromAngleAxis( angle, newUp );
00617     //            return q * (*this);
00618     //        }
00619 
00624     //                inline Radian angleBetween(const Vector3& dest)
00625     //                {
00626     //                        double lenProduct = length() * dest.length();
00627     //
00628     //                        // Divide by zero check
00629     //                        if(lenProduct < 1e-6f)
00630     //                                lenProduct = 1e-6f;
00631     //
00632     //                        double f = dotProduct(dest) / lenProduct;
00633     //
00634     //                        f = Math::Clamp(f, (double)-1.0, (double)1.0);
00635     //                        return Math::ACos(f);
00636     //
00637     //                }
00646     //        Quaternion getRotationTo(const Vector3& dest,
00647     //                        const Vector3& fallbackAxis = Vector3::ZERO) const
00648     //        {
00649     //            // Based on Stan Melax's article in Game Programming Gems
00650     //            Quaternion q;
00651     //            // Copy, since cannot modify local
00652     //            Vector3 v0 = *this;
00653     //            Vector3 v1 = dest;
00654     //            v0.normalise();
00655     //            v1.normalise();
00656     //
00657     //            double d = v0.dotProduct(v1);
00658     //            // If dot == 1, vectors are the same
00659     //            if (d >= 1.0f)
00660     //            {
00661     //                return Quaternion::IDENTITY;
00662     //            }
00663     //                        if (d < (1e-6f - 1.0f))
00664     //                        {
00665     //                                if (fallbackAxis != Vector3::ZERO)
00666     //                                {
00667     //                                        // rotate 180 degrees about the fallback axis
00668     //                                        q.FromAngleAxis(Radian(Math::PI), fallbackAxis);
00669     //                                }
00670     //                                else
00671     //                                {
00672     //                                        // Generate an axis
00673     //                                        Vector3 axis = Vector3::UNIT_X.crossProduct(*this);
00674     //                                        if (axis.isZeroLength()) // pick another if colinear
00675     //                                                axis = Vector3::UNIT_Y.crossProduct(*this);
00676     //                                        axis.normalise();
00677     //                                        q.FromAngleAxis(Radian(Math::PI), axis);
00678     //                                }
00679     //                        }
00680     //                        else
00681     //                        {
00682     //                double s = Math::Sqrt( (1+d)*2 );
00683     //                    double invs = 1 / s;
00684     //
00685     //                                Vector3 c = v0.crossProduct(v1);
00686     //
00687     //                q.x = c.x * invs;
00688     //                    q.y = c.y * invs;
00689     //                q.z = c.z * invs;
00690     //                q.w = s * 0.5;
00691     //                                q.normalise();
00692     //                        }
00693     //            return q;
00694     //        }
00695 
00697     inline bool isZeroLength(void) const
00698     {
00699         double sqlen = (x * x) + (y * y) + (z * z);
00700         return (sqlen < (1e-06 * 1e-06));
00701 
00702     }
00703 
00706     inline Vector3 normalisedCopy(void) const
00707     {
00708         Vector3 ret = *this;
00709         ret.normalise();
00710         return ret;
00711     }
00712 
00716     inline Vector3 reflect(const Vector3& normal) const
00717     {
00718         return Vector3( *this - ( 2 * this->dotProduct(normal) * normal ) );
00719     }
00720 
00727     inline bool positionEquals(const Vector3& rhs, double tolerance = 1e-03) const
00728     {
00729         return doubleEqual(x, rhs.x, tolerance) &&
00730                 doubleEqual(y, rhs.y, tolerance) &&
00731                 doubleEqual(z, rhs.z, tolerance);
00732 
00733     }
00734 
00735     bool doubleEqual(const double& a, const double& b, const double& tolerance) const
00736     {
00737         if (fabs(b-a) <= tolerance)
00738             return true;
00739         else
00740             return false;
00741     }
00742 
00749     inline bool positionCloses(const Vector3& rhs, double tolerance = 1e-03f) const
00750     {
00751         return squaredDistance(rhs) <=
00752                 (squaredLength() + rhs.squaredLength()) * tolerance;
00753     }
00754 
00762     //                inline bool directionEquals(const Vector3& rhs,
00763     //                        const Radian& tolerance) const
00764     //                {
00765     //                        double dot = dotProduct(rhs);
00766     //                        Radian angle = Math::ACos(dot);
00767     //
00768     //                        return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
00769     //
00770     //                }
00771 
00772     // special points
00773     static const Vector3 ZERO;
00774     static const Vector3 UNIT_X;
00775     static const Vector3 UNIT_Y;
00776     static const Vector3 UNIT_Z;
00777     static const Vector3 NEGATIVE_UNIT_X;
00778     static const Vector3 NEGATIVE_UNIT_Y;
00779     static const Vector3 NEGATIVE_UNIT_Z;
00780     static const Vector3 UNIT_SCALE;
00781 
00784     friend std::ostream& operator <<
00785             ( std::ostream& o, const Vector3& v )
00786     {
00787         o << "Vector3(" << v.x << ", " << v.y << ", " << v.z << ")";
00788         return o;
00789     }
00790 };
00791 //}
00792 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines