vector3.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: vector3.h,v 1.77 2006/01/09 20:14:59 oliver Exp $
00005 //
00006 
00007 #ifndef BALL_MATHS_VECTOR3_H
00008 #define BALL_MATHS_VECTOR3_H
00009 
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013 
00014 #ifndef BALL_CONCEPT_PERSISTENCEMANAGER_H
00015 # include <BALL/CONCEPT/persistenceManager.h>
00016 #endif
00017 
00018 #ifndef BALL_MATHS_ANGLE_H
00019 # include <BALL/MATHS/angle.h>
00020 #endif
00021 
00022 #ifndef BALL_MATHS_COMMON_H
00023 # include <BALL/MATHS/common.h>
00024 #endif
00025 
00026 #ifdef BALL_HAS_IEEEFP_H
00027 # include <ieeefp.h>
00028 #endif 
00029 
00030 
00031 namespace BALL 
00032 {
00038 
00039   template <typename T>
00040   class TVector3;
00041 
00045 
00049   template <typename T>
00050   BALL_INLINE 
00051   TVector3<T> operator * (const T& a, const TVector3<T>& b)
00052     ;
00053 
00058   template <typename T>
00059   std::istream& operator >> (std::istream& s, TVector3<T>& vector)
00060     ;
00061 
00066   template <typename T>
00067   std::ostream& operator << (std::ostream& s, const TVector3<T>& vector)
00068     ;
00069 
00071 
00074   template <typename T>
00075   class TVector3
00076   {
00077     public:
00078 
00082 
00087     TVector3()
00088       ;
00089 
00096     TVector3(const T* ptr)
00097       throw(Exception::NullPointer);
00098 
00104     explicit TVector3(const T& value)
00105       ;
00106 
00113     TVector3(const T& vx, const T& vy, const T& vz)
00114       ;
00115 
00120     TVector3(const TVector3& vector)
00121       ;
00122 
00132     TVector3(const T& r, const TAngle<T>& phi, const TAngle<T>& theta)
00133       ;
00134 
00139     ~TVector3()
00140       ;
00141 
00145     void clear()
00146       ;
00147 
00149 
00153 
00160     void set(const T* ptr)
00161       throw(Exception::NullPointer);
00162 
00167     void set(const T& value)
00168       ;
00169 
00175     void set(const T& vx, const T& vy, const T& vz)
00176       ;
00177 
00181     void set(const TVector3& vector)
00182       ;
00183 
00196     void set(const T& r, const TAngle<T>& phi, const TAngle<T>& theta)
00197       ;
00198 
00203     TVector3& operator = (const TVector3& v)
00204       ;
00205 
00210     TVector3& operator = (T value)
00211       ;
00212 
00218     TVector3& operator = (const T* ptr)
00219       throw(Exception::NullPointer);
00220 
00227     void get(T* ptr) const
00228       throw(Exception::NullPointer);
00229 
00235     void get(T& x, T& y, T& z) const
00236       ;
00237 
00242     void get(TVector3& vector) const
00243       ;
00244 
00252     void get(T& r, TAngle<T>& phi, TAngle<T>& theta) const
00253       ;
00254 
00258     void swap(TVector3& vector)
00259       ;
00260 
00266     T getLength() const
00267       ;
00268 
00274     T getSquareLength() const
00275       ;
00276 
00283     TVector3& normalize()
00284       throw(Exception::DivisionByZero);
00285 
00290     TVector3& negate()
00291       ;
00292 
00295     static const TVector3& getZero()
00296       ;
00297 
00301     static const TVector3& getUnit()
00302       ;
00303 
00307     T& operator [] (Position position)
00308       throw(Exception::IndexOverflow);
00309 
00313     const T& operator [] (Position position) const
00314       throw(Exception::IndexOverflow);
00316     
00320 
00323     const TVector3& operator + () const
00324       ;
00325 
00328     TVector3 operator - () const
00329       ;
00330 
00333     TVector3 operator + (const TVector3& b) const
00334       ;
00335 
00338     TVector3 operator - (const TVector3& b) const
00339       ;
00340 
00346     TVector3& operator += (const TVector3& vector)
00347       ;
00348 
00353     TVector3& operator -= (const TVector3& vector)
00354       ;
00355 
00361     TVector3 operator * (const T& scalar) const
00362       ;
00363 
00369     TVector3& operator *= (const T& scalar)
00370       ;
00371 
00378     TVector3 operator / (const T& lambda) const
00379       throw(Exception::DivisionByZero);
00380 
00386     TVector3& operator /= (const T& lambda)
00387       throw(Exception::DivisionByZero);
00388 
00392     T operator * (const TVector3& vector) const
00393       ;
00394 
00398     TVector3 operator % (const TVector3& vector) const
00399       ;
00400 
00404     TVector3& operator %= (const TVector3& vector)
00405       ;
00406 
00408 
00412 
00415     T getDistance(const TVector3& vector) const
00416       ;
00417 
00420     T getSquareDistance(const TVector3& vector) const
00421       ;
00422 
00427     TAngle<T> getAngle(const TVector3& vector) const
00428       throw(Exception::DivisionByZero);
00429 
00433     TVector3 getOrthogonalProjection(const TVector3& direction) const
00434       ;
00435 
00442     static TVector3 getPerpendicularNormalization
00443       (const TVector3& a, const TVector3& b, const TVector3& c)
00444       ;
00445 
00453     static T getTripleProduct (const TVector3<T>& a, const TVector3<T>& b, const TVector3<T>& c)
00454       ;
00455 
00457   
00461 
00467     bool operator == (const TVector3& vector) const
00468       ;
00469   
00475     bool operator != (const TVector3& vector) const
00476       ;
00477 
00479     bool operator < (const TVector3& vector) const
00480       ;
00481 
00482 
00487     bool isZero() const
00488       ;
00489 
00492     bool isOrthogonalTo(const TVector3& vector) const
00493       ;
00494 
00496 
00497 
00501 
00504     void write(PersistenceManager& pm) const
00505       ;
00506 
00509     bool read(PersistenceManager& pm)
00510       ;
00511 
00513 
00517 
00524     void dump(std::ostream& s = std::cout, Size depth = 0) const
00525       ;
00526 
00531     bool isValid() const
00532       ;
00533 
00535 
00536 
00542   
00545     T x;
00546 
00549     T y;
00550 
00553     T z;
00555 
00556     private:
00557 
00558     TAngle<T> getAngle_(const T& a, const T& b) const
00559       
00560     {
00561       TAngle<T> angle;
00562   
00563       if (Maths::isNotZero(a))
00564       {
00565         angle = atan(b / a);
00566       } 
00567       else  
00568       {
00569         angle = BALL_SGN(b) * Constants::PI / 2;
00570       }
00571 
00572       if (Maths::isLess(a, 0)) 
00573       {
00574         angle += Constants::PI;
00575       }
00576 
00577       if (Maths::isLess(angle.value, 0)) 
00578       {
00579         return (Angle)(angle.value += 2.0 * Constants::PI);
00580       } 
00581       else 
00582       {
00583         return angle;
00584       }
00585     }
00586   };
00588 
00589   template <typename T>
00590   BALL_INLINE
00591   TVector3<T>::TVector3()
00592     
00593     : x(0),
00594       y(0),
00595       z(0)
00596   {
00597   }
00598 
00599   template <typename T>
00600   BALL_INLINE
00601   TVector3<T>::TVector3(const T* ptr)
00602     throw(Exception::NullPointer)
00603   {
00604     if (ptr == 0) 
00605     {
00606       throw Exception::NullPointer(__FILE__, __LINE__);
00607     }
00608 
00609     x = *ptr++;
00610     y = *ptr++;
00611     z = *ptr;
00612   }
00613 
00614   template <typename T>
00615   BALL_INLINE
00616   TVector3<T>::TVector3(const T& value)
00617     
00618     : x(value),
00619       y(value),
00620       z(value)
00621   {
00622   }
00623 
00624   template <typename T>
00625   BALL_INLINE
00626   TVector3<T>::TVector3(const T& vx, const T& vy, const T& vz)
00627     
00628     : x(vx),
00629       y(vy),
00630       z(vz)
00631   {
00632   }
00633 
00634   template <typename T>
00635   BALL_INLINE
00636   TVector3<T>::TVector3(const TVector3& vector)
00637     
00638     : x(vector.x),
00639       y(vector.y),
00640       z(vector.z)
00641   {
00642   }
00643 
00644   template <typename T>
00645   BALL_INLINE
00646   TVector3<T>::TVector3(const T& r, const TAngle<T>& phi, const TAngle<T>& theta)
00647     
00648     : x(r * cos(phi) * sin(theta)),
00649       y(r * sin(phi) * sin(theta)),
00650       z(r * cos(theta))
00651   {
00652   }
00653 
00654   template <typename T>
00655   BALL_INLINE
00656   TVector3<T>::~TVector3()
00657     
00658   {
00659   }
00660 
00661   template <typename T>
00662   BALL_INLINE
00663   void TVector3<T>::clear()
00664     
00665   {
00666     x = y = z = (T)0;
00667   }
00668 
00669   template <typename T>
00670   BALL_INLINE 
00671   void TVector3<T>::set(const T* ptr)
00672     throw(Exception::NullPointer)
00673   {
00674     if (ptr == 0) 
00675       throw Exception::NullPointer(__FILE__, __LINE__);
00676     
00677     x = *ptr++;
00678     y = *ptr++;
00679     z = *ptr;
00680   }
00681 
00682   template <typename T>
00683   BALL_INLINE 
00684   void TVector3<T>::set(const T& value)
00685     
00686   {
00687     x = value;
00688     y = value;
00689     z = value;
00690   }
00691 
00692   template <typename T>
00693   BALL_INLINE 
00694   void TVector3<T>::set(const T& vx, const T& vy, const T& vz)
00695     
00696   {
00697     x = vx;
00698     y = vy;
00699     z = vz;
00700   }
00701 
00702   template <typename T>
00703   BALL_INLINE 
00704   void TVector3<T>::set(const TVector3<T>& vector)
00705     
00706   {
00707     x = vector.x;
00708     y = vector.y;
00709     z = vector.z;
00710   }
00711 
00712   template <typename T>
00713   BALL_INLINE
00714   void TVector3<T>::set(const T& r, const TAngle<T> &phi, const TAngle<T> &theta)
00715     
00716   {
00717     x = r * cos(phi) * sin(theta);
00718     y = r * sin(phi) * sin(theta);
00719     z = r * cos(theta);
00720   }
00721 
00722   template <typename T>
00723   BALL_INLINE
00724   TVector3<T>& TVector3<T>::operator = (const T* ptr)
00725     throw(Exception::NullPointer)
00726   {
00727     if (ptr == 0)
00728     {
00729       throw Exception::NullPointer(__FILE__, __LINE__);
00730     }
00731 
00732     x = *ptr++;
00733     y = *ptr++;
00734     z = *ptr;
00735 
00736     return *this;
00737   }
00738 
00739   template <typename T>
00740   BALL_INLINE 
00741   TVector3<T>& TVector3<T>::operator = (const TVector3<T>& vector)
00742     
00743   {
00744     x = vector.x;
00745     y = vector.y;
00746     z = vector.z;
00747 
00748     return *this;
00749   }
00750 
00751   template <typename T>
00752   BALL_INLINE 
00753   TVector3<T>& TVector3<T>::operator = (T value)
00754     
00755   {
00756     x = y = z = value;
00757 
00758     return *this;
00759   }
00760 
00761   template <typename T>
00762   BALL_INLINE 
00763   void TVector3<T>::get(T* ptr) const
00764     throw(Exception::NullPointer)
00765   {
00766     if (ptr == 0)
00767     {
00768       throw Exception::NullPointer(__FILE__, __LINE__);
00769     }
00770 
00771     *ptr++ = x;
00772     *ptr++ = y;
00773     *ptr   = z;
00774   }
00775 
00776   template <typename T>
00777   BALL_INLINE 
00778   void TVector3<T>::get(T& new_x, T& new_y, T& new_z) const
00779     
00780   {
00781     new_x = x;
00782     new_y = y;
00783     new_z = z;
00784   }
00785 
00786   template <typename T>
00787   BALL_INLINE 
00788   void TVector3<T>::get(TVector3<T>& vector) const
00789     
00790   {
00791     vector.x = x;
00792     vector.y = y;
00793     vector.z = z;
00794   }
00795 
00796   template <typename T>
00797   BALL_INLINE 
00798   void TVector3<T>::get(T& r, TAngle<T>& phi, TAngle<T>& theta) const
00799     
00800   {
00801     r     = sqrt(x * x + y * y + z * z);
00802     phi   = (Angle)getAngle_(x, y);
00803     theta = getAngle_(z, sqrt(x * x + y * y));
00804   }
00805 
00806   template <typename T>
00807   BALL_INLINE
00808   void TVector3<T>::swap(TVector3<T>& vector)
00809     
00810   {
00811     T temp = x;
00812     x = vector.x;
00813     vector.x = temp;
00814 
00815     temp = y;
00816     y = vector.y;
00817     vector.y = temp;
00818 
00819     temp = z;
00820     z = vector.z;
00821     vector.z = temp;
00822   }
00823 
00824   template <typename T>
00825   BALL_INLINE 
00826   T TVector3<T>::getLength() const
00827     
00828   {
00829     return (T)sqrt(x * x + y * y + z * z);
00830   }
00831 
00832   template <typename T>
00833   BALL_INLINE 
00834   T TVector3<T>::getSquareLength() const
00835     
00836   {
00837     return (x * x + y * y + z * z);
00838   }
00839 
00840   template <typename T>
00841   TVector3<T>& TVector3<T>::normalize()
00842     throw(Exception::DivisionByZero)
00843   {
00844     T len = sqrt(x * x + y * y + z * z);
00845 
00846     if (Maths::isZero(len)) 
00847     {
00848       throw Exception::DivisionByZero(__FILE__, __LINE__);
00849     }
00850     
00851     x /= len;
00852     y /= len;
00853     z /= len;
00854 
00855     return *this;
00856   }
00857 
00858   template <typename T>
00859   BALL_INLINE
00860   TVector3<T>& TVector3<T>::negate()
00861     
00862   {
00863     x *= -1;
00864     y *= -1;
00865     z *= -1;
00866     return *this;
00867   }
00868 
00869   template <typename T>
00870   BALL_INLINE 
00871   const TVector3<T>& TVector3<T>::getZero()
00872     
00873   {
00874     static TVector3<T> null_vector(0, 0, 0);
00875     return null_vector;
00876   }
00877 
00878   template <typename T>
00879   BALL_INLINE 
00880   const TVector3<T>& TVector3<T>::getUnit()
00881     
00882   {
00883     static TVector3<T> unit_vector(1, 1, 1);
00884     return unit_vector;
00885   }
00886 
00887   template <typename T>
00888   BALL_INLINE 
00889   T& TVector3<T>::operator [] (Position position)
00890     throw(Exception::IndexOverflow)
00891   {
00892     if (position > 2)
00893     {
00894       throw Exception::IndexOverflow(__FILE__, __LINE__, position);
00895     }
00896     switch (position) 
00897     {
00898       case 0: return x;
00899       case 1: return y;
00900       case 2:
00901       default:
00902         return z;
00903     }
00904   }
00905 
00906   template <typename T>
00907   BALL_INLINE 
00908   const T& TVector3<T>::operator [] (Position position) const
00909     throw(Exception::IndexOverflow)
00910   {
00911     if (position > 2)
00912     {
00913       throw Exception::IndexOverflow(__FILE__, __LINE__);
00914     }
00915     switch (position) 
00916     {
00917       case 0: return x;
00918       case 1: return y;
00919       case 2:
00920       default:
00921         return z;
00922     }
00923   }
00924 
00925   template <typename T>
00926   BALL_INLINE
00927   const TVector3<T>& TVector3<T>::operator + () const 
00928     
00929   {
00930     return *this;
00931   }
00932 
00933   template <typename T>
00934   BALL_INLINE
00935   TVector3<T> TVector3<T>::operator - () const  
00936     
00937   {
00938     return TVector3<T>(-x, -y, -z);
00939   }
00940 
00941   template <typename T>
00942   BALL_INLINE 
00943   TVector3<T>& TVector3<T>::operator += (const TVector3<T>& vector)
00944     
00945   {
00946     x += vector.x;
00947     y += vector.y;
00948     z += vector.z;
00949 
00950     return *this;
00951   }
00952 
00953   template <typename T>
00954   BALL_INLINE 
00955   TVector3<T>& TVector3<T>::operator -= (const TVector3<T>& vector)
00956     
00957   {
00958     x -= vector.x;
00959     y -= vector.y;
00960     z -= vector.z;
00961 
00962     return *this;
00963   }
00964 
00965   template <typename T>
00966   BALL_INLINE 
00967   TVector3<T> TVector3<T>::operator * (const T& scalar) const 
00968     
00969   {
00970     return TVector3<T>(x * scalar, y * scalar, z * scalar);
00971   }
00972 
00973   template <typename T>
00974   BALL_INLINE 
00975   TVector3<T>& TVector3<T>::operator *= (const T &scalar)
00976     
00977   {
00978     x *= scalar;
00979     y *= scalar;
00980     z *= scalar;
00981 
00982     return *this;
00983   }
00984 
00985   template <typename T>
00986   TVector3<T> TVector3<T>::operator / (const T& lambda) const
00987     throw(Exception::DivisionByZero)
00988   {
00989     if (lambda == (T)0)
00990     {
00991       throw Exception::DivisionByZero(__FILE__, __LINE__);
00992     }
00993     return TVector3<T>(x / lambda, y / lambda, z / lambda);
00994   }
00995 
00996   template <typename T>
00997   TVector3<T>& TVector3<T>::operator /= (const T& lambda)
00998     throw(Exception::DivisionByZero)
00999   {
01000     if (lambda == (T)0)
01001     {
01002       throw Exception::DivisionByZero(__FILE__, __LINE__);    
01003     }
01004     x /= lambda;
01005     y /= lambda;
01006     z /= lambda;
01007 
01008     return *this;
01009   }
01010 
01011   template <typename T>
01012   BALL_INLINE 
01013   T TVector3<T>::operator * (const TVector3<T>& vector) const
01014     
01015   {
01016     return (x * vector.x + y * vector.y + z * vector.z);
01017   }
01018 
01019   template <typename T>
01020   TVector3<T> TVector3<T>::operator % (const TVector3<T>& v) const
01021     
01022   {
01023     return TVector3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
01024   }
01025 
01026   template <typename T>
01027   BALL_INLINE 
01028   TVector3<T>& TVector3<T>::operator %= (const TVector3<T>& v)
01029     
01030   {
01031     set(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
01032     return *this;
01033   }
01034 
01035   template <typename T>
01036   BALL_INLINE 
01037   T TVector3<T>::getDistance(const TVector3<T>& v) const
01038     
01039   {
01040     T dx = x - v.x;
01041     T dy = y - v.y;
01042     T dz = z - v.z;
01043     
01044     return (T)sqrt(dx * dx + dy * dy + dz * dz); 
01045   }
01046 
01047   template <typename T>
01048   BALL_INLINE T
01049   TVector3<T>::getSquareDistance(const TVector3<T>& v) const
01050     
01051   {
01052     T dx = x - v.x;
01053     T dy = y - v.y;
01054     T dz = z - v.z;
01055     
01056     return (dx * dx + dy * dy + dz * dz); 
01057   }
01058 
01059   template <typename T>
01060   BALL_INLINE 
01061   TAngle<T> TVector3<T>::getAngle(const TVector3<T>& vector) const
01062     throw(Exception::DivisionByZero)
01063   {
01064     T length_product = getSquareLength() * vector.getSquareLength();
01065 
01066     if (length_product == (T)0) 
01067     {
01068       throw Exception::DivisionByZero(__FILE__, __LINE__);
01069     }
01070     
01071     T acos_arg = ((*this) * vector) / sqrt(length_product);
01072 
01073     // ensure that the argument of acos is in the correct range
01074     // (might happen if the angle between the two vectors is
01075     // very close to zero)
01076     if (fabs(acos_arg) > 1.0)
01077     { 
01078       return (TAngle<T>)0.0;
01079     }
01080     
01081     return (TAngle<T>)acos(acos_arg);
01082   }
01083 
01084   template <typename T>
01085   BALL_INLINE 
01086   TVector3<T> TVector3<T>::getOrthogonalProjection(const TVector3<T>& direction) const
01087     
01088   {
01089     return ((direction * (*this)) / (direction * direction) * direction);
01090   }
01091 
01092   template <typename T>
01093   TVector3<T> TVector3<T>::getPerpendicularNormalization
01094     (const TVector3<T> &a, const TVector3<T> &b, const TVector3<T> &c)
01095     
01096   {
01097     TVector3 diff1(b.x - a.x, b.y - a.y, b.z - a.z);
01098     TVector3 diff2(b.x - c.x, b.y - c.y, b.z - c.z);
01099 
01100     return TVector3
01101       (diff1.y * diff2.z - diff1.z * diff2.y,
01102        diff1.z * diff2.x - diff1.x * diff2.z,
01103        diff1.x * diff2.y - diff1.y * diff2.x);
01104   }
01105 
01106   template <typename T>
01107   BALL_INLINE
01108   T TVector3<T>::getTripleProduct
01109     (const TVector3<T>& a,
01110      const TVector3<T>& b,
01111      const TVector3<T>& c)
01112     
01113   {
01114     return (  a.x * (b.y * c.z - b.z * c.y)
01115             + a.y * (b.z * c.x - b.x * c.z)
01116             + a.z * (b.x * c.y - b.y * c.x));
01117   }
01118 
01119   template <typename T>
01120   BALL_INLINE 
01121   bool TVector3<T>::operator == (const TVector3<T>& v) const
01122     
01123   {
01124     return (Maths::isEqual(x, v.x) && Maths::isEqual(y, v.y) && Maths::isEqual(z, v.z));
01125   }
01126 
01127   template <typename T>
01128   BALL_INLINE 
01129   bool TVector3<T>::operator < (const TVector3<T>& v) const
01130     
01131   {
01132     return (x < v.x || y < v.y || z < v.z);
01133   }
01134 
01135 
01136   template <typename T>
01137   BALL_INLINE 
01138   bool TVector3<T>::operator != (const TVector3<T>& v) const
01139     
01140   {
01141     return (Maths::isNotEqual(x, v.x) || Maths::isNotEqual(y, v.y) || Maths::isNotEqual(z, v.z));
01142   }
01143 
01144   template <typename T>
01145   BALL_INLINE 
01146   bool TVector3<T>::isOrthogonalTo(const TVector3<T>& v) const
01147     
01148   {
01149     return Maths::isZero((*this) * v);
01150   }
01151 
01152   template <typename T>
01153   BALL_INLINE 
01154   bool TVector3<T>::isValid() const
01155     
01156   {
01157     return true;
01158   }
01159 
01160   template <typename T>
01161   BALL_INLINE 
01162   bool TVector3<T>::isZero() const
01163     
01164   {
01165     return (Maths::isZero(x) && Maths::isZero(y) && Maths::isZero(z));
01166   }
01167 
01168   template <typename T>
01169   void TVector3<T>::dump(std::ostream& s, Size depth) const
01170     
01171   {
01172     BALL_DUMP_STREAM_PREFIX(s);
01173 
01174     BALL_DUMP_HEADER(s, this, this);
01175 
01176     BALL_DUMP_DEPTH(s, depth);
01177     s << "  (x =  " << x << ", y = " << y << ", z = " << z << ")" << std::endl;
01178 
01179     BALL_DUMP_STREAM_SUFFIX(s);
01180   }
01181 
01185   typedef TVector3<float> Vector3;
01186 
01187   template <typename T>
01188   BALL_INLINE 
01189   TVector3<T> TVector3<T>::operator + (const TVector3<T>& b) const
01190     
01191   {
01192     return TVector3<T>(x + b.x, y + b.y, z + b.z);
01193   }
01194   
01195   template <typename T>
01196   BALL_INLINE
01197   TVector3<T> TVector3<T>::operator - (const TVector3<T>& b) const
01198     
01199   {
01200     return TVector3<T>(x - b.x, y - b.y, z - b.z);
01201   }
01202 
01203   template <typename T>
01204   void TVector3<T>::write(PersistenceManager& pm) const
01205     
01206   {
01207     pm.writePrimitive(x, "x");
01208     pm.writePrimitive(y, "y");
01209     pm.writePrimitive(z, "z");
01210   }
01211 
01212   template <typename T>     
01213   bool TVector3<T>::read(PersistenceManager& pm)
01214     
01215   {
01216     pm.readPrimitive(x, "x");
01217     pm.readPrimitive(y, "y");
01218     pm.readPrimitive(z, "z");
01219 
01220     return true;
01221   }
01222 
01223 
01224   template <typename T>
01225   BALL_INLINE 
01226   TVector3<T> operator * (const T& scalar, const TVector3<T>& vector)
01227     
01228   {
01229     return TVector3<T>(scalar * vector.x, scalar * vector.y, scalar * vector.z);
01230   }
01231 
01232   template <typename T>
01233   std::istream& operator >> (std::istream& s, TVector3<T>& v)
01234     
01235   {
01236     char c;
01237     s >> c >> v.x >> v.y >> v.z >> c;
01238 
01239     return s;
01240   }
01241 
01242   template <typename T>
01243   std::ostream& operator << (std::ostream& s, const TVector3<T>& v)
01244     
01245   {
01246     s << "(" << v.x << ' ' << v.y << ' ' << v.z << ')';
01247 
01248     return s;
01249   }
01250 // required for visual studio
01251 #ifdef BALL_COMPILER_MSVC
01252 #include <vector>
01253 template class BALL_EXPORT std::vector<Vector3>;
01254 #endif
01255 
01256 }// namespace BALL
01257 
01258 #endif // BALL_MATHS_VECTOR3_H