00001 #ifndef OPENTISSUE_CORE_MATH_MATH_VECTORX3_H
00002 #define OPENTISSUE_CORE_MATH_MATH_VECTORX3_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_random.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014 #include <OpenTissue/core/math/math_functions.h>
00015 #include <OpenTissue/core/math/math_value_traits.h>
00016
00017 #include <boost/cast.hpp>
00018
00019
00020 #include <string>
00021 #include <cmath>
00022 #include <cassert>
00023
00024
00025
00026
00027 #include <iostream>
00028
00029
00030 namespace OpenTissue
00031 {
00032
00033 namespace math
00034 {
00035
00036 template <
00037 typename value_type_
00038
00039 >
00040 class Vector3
00041 {
00042 protected:
00043
00044 typedef typename OpenTissue::math::ValueTraits<value_type_> value_traits_ ;
00045
00046 public:
00047
00048 typedef value_traits_ value_traits;
00049 typedef value_type_ value_type;
00050 typedef size_t index_type;
00051
00052 private:
00053
00054
00055
00056 value_type x;
00057 value_type y;
00058 value_type z;
00059
00060 public:
00061
00062
00063 Vector3()
00064 : x( value_traits::zero() )
00065 , y( value_traits::zero() )
00066 , z( value_traits::zero() )
00067 {}
00068
00069 Vector3( Vector3 const & v )
00070 : x(v(0))
00071 , y(v(1))
00072 , z(v(2))
00073 {}
00074
00075 explicit Vector3( value_type const& val )
00076 : x( val )
00077 , y( val )
00078 , z( val )
00079 {}
00080
00081 template <typename T1,typename T2,typename T3>
00082 Vector3( T1 const & x_val, T2 const & y_val, T3 const & z_val )
00083 : x( boost::numeric_cast<value_type>(x_val) )
00084 , y( boost::numeric_cast<value_type>(y_val) )
00085 , z( boost::numeric_cast<value_type>(z_val) )
00086 {}
00087
00088 ~Vector3()
00089 {}
00090
00091 Vector3 & operator=(Vector3 const & cpy)
00092 {
00093 x=cpy(0);
00094 y=cpy(1);
00095 z=cpy(2);
00096 return *this;
00097 }
00098
00099 public:
00100
00101 void clear() { x = y = z = value_traits::zero(); }
00102
00103 size_t size() const { return 3u;}
00104
00105 public:
00106
00107 value_type & operator() ( index_type index )
00108 {
00109 assert( (index>=0 && index<3) || !"vecto3():index should be in range [0..2]");
00110 return *((&x) + index);
00111 }
00112
00113 value_type const & operator() ( index_type index ) const
00114 {
00115 assert( (index>=0 && index<3) || !"vecto3():index should be in range [0..2]");
00116 return *((&x) + index);
00117 }
00118
00119 value_type & operator[] ( index_type index )
00120 {
00121 assert( (index>=0 && index<3) || !"vecto3[]:index should be in range [0..2]");
00122 return *((&x) + index);
00123 }
00124
00125 value_type const & operator[] ( index_type index ) const
00126 {
00127 assert( (index>=0 && index<3) || !"vecto3[]:index should be in range [0..2]");
00128 return *((&x) + index);
00129 }
00130
00131 public:
00132
00133 bool operator< (Vector3 const & v) const
00134 {
00135 if ( x < v(0) ) return true;
00136 if ( x > v(0) ) return false;
00137 if ( y < v(1) ) return true;
00138 if ( y > v(1) ) return false;
00139 return z < v(2);
00140 }
00141
00142 bool operator> (Vector3 const & v) const
00143 {
00144 if ( x > v(0) ) return true;
00145 if ( x < v(0) ) return false;
00146 if ( y > v(1) ) return true;
00147 if ( y < v(1) ) return false;
00148 return z > v(2);
00149 }
00150
00151
00152 bool operator==(Vector3 const & cmp) const { return x==cmp.x && y==cmp.y && z==cmp.z; }
00153 bool operator!=(Vector3 const & cmp) const { return x!=cmp.x || y!=cmp.y || z!=cmp.z; }
00154
00155 public:
00156
00157 Vector3 & operator+= ( Vector3 const & v )
00158 {
00159 x += v(0);
00160 y += v(1);
00161 z += v(2);
00162 return *this;
00163 }
00164
00165 Vector3 & operator-= ( Vector3 const & v )
00166 {
00167 x -= v(0);
00168 y -= v(1);
00169 z -= v(2);
00170 return *this;
00171 }
00172
00173 Vector3 & operator*=( value_type const & s )
00174 {
00175 x *= s;
00176 y *= s;
00177 z *= s;
00178 return *this;
00179 }
00180
00181 Vector3 & operator/=( value_type const & s )
00182 {
00183 assert(s || !"Vector3::/=(): division by zero");
00184 x /= s;
00185 y /= s;
00186 z /= s;
00187 return *this;
00188 }
00189
00190 Vector3 operator+ ( Vector3 const & v ) const { return Vector3( x+v(0), y+v(1), z+v(2)); }
00191 Vector3 operator- ( Vector3 const & v ) const { return Vector3( x-v(0), y-v(1), z-v(2)); }
00192 Vector3 operator- ( ) const { return Vector3(-x,-y,-z); }
00193 Vector3 operator% ( Vector3 const & v ) const { return Vector3(y*v(2)-v(1)*z, v(0)*z-x*v(2), x*v(1)-v(0)*y); }
00194 value_type operator* ( Vector3 const & v ) const { return x*v(0) + y*v(1) + z*v(2); }
00195 bool operator<=( Vector3 const & v ) const { return x <= v(0) && y <= v(1) && z <= v(2); }
00196 bool operator>=( Vector3 const & v ) const { return x >= v(0) && y >= v(1) && z >= v(2); }
00197
00198 public:
00199
00200 friend Vector3 fabs( Vector3 const & v )
00201 {
00202 using std::fabs;
00203 return Vector3 (
00204 boost::numeric_cast<value_type>( fabs( v(0) ) )
00205 , boost::numeric_cast<value_type>( fabs( v(1) ) )
00206 , boost::numeric_cast<value_type>( fabs( v(2) ) )
00207 );
00208 }
00209
00210 friend Vector3 min( Vector3 const & A, Vector3 const & B )
00211 {
00212 using std::min;
00213 return Vector3( min( A(0), B(0) ), min( A(1), B(1) ), min( A(2), B(2) ) );
00214 }
00215
00216 friend Vector3 max( Vector3 const & A, Vector3 const & B )
00217 {
00218 using std::max;
00219 return Vector3( max( A(0), B(0) ), max( A(1), B(1) ), max( A(2), B(2) ) );
00220 }
00221
00222 friend Vector3 floor(Vector3 const & v)
00223 {
00224 using std::floor;
00225 return Vector3(
00226 boost::numeric_cast<value_type>( floor(v(0)) )
00227 , boost::numeric_cast<value_type>( floor(v(1)) )
00228 , boost::numeric_cast<value_type>( floor(v(2)) )
00229 );
00230 }
00231
00232 friend Vector3 ceil(Vector3 const & v)
00233 {
00234 using std::ceil;
00235 return Vector3(
00236 boost::numeric_cast<value_type>( ceil(v(0)) )
00237 , boost::numeric_cast<value_type>( ceil(v(1)) )
00238 , boost::numeric_cast<value_type>( ceil(v(2)) )
00239 );
00240 }
00241
00242 friend std::ostream & operator<< (std::ostream & o,Vector3 const & v)
00243 {
00244 o << "[";
00245 o << v(0);
00246 o << ",";
00247 o << v(1);
00248 o << "," << v(2) << "]";
00249 return o;
00250 }
00251
00252 friend std::istream & operator>>(std::istream & i,Vector3 & v)
00253 {
00254 char dummy;
00255 i >> dummy;
00256 i >> v(0);
00257 i >> dummy;
00258 i >> v(1);
00259 i >> dummy;
00260 i >> v(2);
00261 i >> dummy;
00262 return i;
00263 }
00264 public:
00265
00266
00267 bool is_equal(Vector3 const & v, value_type const & threshold) const
00268 {
00269 using std::fabs;
00270 return fabs(x-v.x)<=threshold && fabs(y-v.y)<=threshold && fabs(z-v.z)<=threshold;
00271 }
00272
00273 };
00274
00275
00279
00280 template <typename T>
00281 inline Vector3<T> round(Vector3<T> const & v)
00282 {
00283 using std::floor;
00284
00285 static T const half = detail::half<T>();
00286
00287 return Vector3<T> (
00288 floor( v(0) + half )
00289 , floor( v(1) + half )
00290 , floor( v(2) + half )
00291 );
00292 }
00293
00294 template <typename T>
00295 inline typename Vector3<T>::index_type min_index(Vector3<T> const & v)
00296 {
00297 return v(0) <= v(1) && v(0) < v(2) ? 0 : v(1) <= v(0) && v(1) < v(2) ? 1 : 2;
00298 }
00299
00300 template <typename T>
00301 inline typename Vector3<T>::index_type max_index(Vector3<T> const & v)
00302 {
00303 return v(2) >= v(0) && v(2) >= v(1) ? 2 : v(1) >= v(0) && v(1) > v(2) ? 1 : 0;
00304 }
00305
00306 template <typename T>
00307 inline typename Vector3<T>::index_type mid_index(Vector3<T> const & v)
00308 {
00309 typename Vector3<T>::index_type test = min_index(v) + max_index(v);
00310 return test == 2 ? 1 : test == 1 ? 2 : 0;
00311 }
00312
00313 template <typename T>
00314 inline T min_value(Vector3<T> const & v)
00315 {
00316 using std::min;
00317 return min(v(0),min(v(1),v(2)));
00318 }
00319
00320 template <typename T>
00321 inline T max_value(Vector3<T> const & v)
00322 {
00323 using std::max;
00324 return max(v(0),max(v(1),v(2)));
00325 }
00326
00327 template <typename T>
00328 inline T mid_value(Vector3<T> const & v)
00329 {
00330 return v(mid_index(v));
00331 }
00332
00333 template <typename T>
00334 inline bool is_zero(Vector3<T> const & v, T const & threshold)
00335 {
00336 using std::fabs;
00337 return fabs(v(0))<=threshold && fabs(v(1))<=threshold && fabs(v(2))<=threshold;
00338 }
00339
00340 template <typename T>
00341 inline bool is_zero(Vector3<T> const & v)
00342 {
00343 typedef typename Vector3<T>::value_traits value_traits;
00344 return is_zero(v,value_traits::zero());
00345 }
00346
00347 template <typename T1,typename T2, typename T3>
00348 inline void random(Vector3<T1> & v, T2 const & lower, T3 const & upper)
00349 {
00350 Random<T1> value(boost::numeric_cast<T1>(lower),boost::numeric_cast<T1>(upper));
00351 v(0) = value();
00352 v(1) = value();
00353 v(2) = value();
00354 }
00355
00356 template <typename T>
00357 inline void random(Vector3<T> & v, Vector3<T> const & lower, Vector3<T> const & upper)
00358 {
00359 typedef typename Vector3<T>::value_traits value_traits;
00360 random(v,value_traits::zero(),value_traits::one());
00361 v(0) = (upper(0)-lower(0))*v(0) + lower(0);
00362 v(1) = (upper(1)-lower(0))*v(1) + lower(1);
00363 v(2) = (upper(2)-lower(2))*v(2) + lower(2);
00364 }
00365
00366 template <typename T>
00367 inline void random(Vector3<T> & v)
00368 {
00369 typedef typename Vector3<T>::value_traits value_traits;
00370
00371 random(v,value_traits::zero(),value_traits::one());
00372 }
00373
00374 template <typename T>
00375 inline Vector3<T> cross( Vector3<T> const & a, Vector3<T> const & b )
00376 {
00377 return Vector3<T>( a[1] * b[2] - b[1] * a[2], -a[0] * b[2] + b[0] * a[2], a[0] * b[1] - b[0] * a[1] );
00378 }
00379
00380 template <typename T>
00381 inline T dot( Vector3<T> const & a, Vector3<T> const & b ) { return a(0)*b(0) + a(1)*b(1) + a(2)*b(2); }
00382
00383 template <typename T>
00384 inline T inner_prod( Vector3<T> const & a, Vector3<T> const & b ) { return dot(a,b); }
00385
00386 template<typename T>
00387 inline T length(Vector3<T> const & v)
00388 {
00389 using std::sqrt;
00390 return boost::numeric_cast<T>( sqrt( dot(v,v) ) );
00391 }
00392
00393 template<typename T>
00394 inline T sqr_length(Vector3<T> const & v) { return boost::numeric_cast<T>(v*v); }
00395
00396 template<typename T>
00397 inline T norm(Vector3<T> const & v) { return length(v); }
00398
00399 template<typename T>
00400 inline T norm_1(Vector3<T> const & v)
00401 {
00402 using std::fabs;
00403 using std::max;
00404 return max( fabs(v(0)), max( fabs(v(1)), fabs(v(2)) ) );
00405 }
00406
00407 template<typename T>
00408 inline T distance(Vector3<T> const & a, Vector3<T> const & b)
00409 {
00410 return length(b-a);
00411 }
00412
00413 template<typename T>
00414 inline T sqr_distance(Vector3<T> const & a, Vector3<T> const & b)
00415 {
00416 return sqr_length(b-a);
00417 }
00418
00419 template <typename T>
00420 inline Vector3<T> sgn( Vector3<T> const & v )
00421 {
00422 using OpenTissue::math::sgn;
00423 return Vector3<T>(sgn(v(0)), sgn(v(1)), sgn(v(2)));
00424 }
00425
00426 template <typename T>
00427 inline Vector3<T> unit( Vector3<T> const & v )
00428 {
00429 typedef typename Vector3<T>::value_traits value_traits;
00430
00431
00432 using std::sqrt;
00433 T const l = length(v);
00434 if (l <= value_traits::zero())
00435 {
00436 return Vector3<T>( value_traits::zero() );
00437 }
00438 T const inv = value_traits::one()/l;
00439 return Vector3<T>( inv*v(0), inv*v(1), inv*v(2) );
00440 }
00441
00442 template <typename T>
00443 inline Vector3<T> normalize( Vector3<T> const & v ) { return unit(v); }
00444
00445 template <typename T>
00446 inline void truncate(Vector3<T> & v, T const & precision_value)
00447 {
00448 typedef typename Vector3<T>::value_traits value_traits;
00449
00450 v(0) = ((v(0)>-precision_value)&&(v(0)<precision_value)) ? value_traits::zero() : v(0);
00451 v(1) = ((v(1)>-precision_value)&&(v(1)<precision_value)) ? value_traits::zero() : v(1);
00452 v(2) = ((v(2)>-precision_value)&&(v(2)<precision_value)) ? value_traits::zero() : v(2);
00453 }
00454
00455
00456 template <typename T>
00457 inline void truncate(Vector3<T> & v)
00458 {
00459 typedef typename Vector3<T>::value_traits value_traits;
00460
00461 truncate( v, value_traits::zero() );
00462 }
00463
00471 template <typename T>
00472 inline Vector3<T> orthogonal(Vector3<T> const & v)
00473 {
00474 typedef typename Vector3<T>::value_traits value_traits;
00475
00476 using std::fabs;
00477
00478
00479
00480
00481
00482 Vector3<T> tmp;
00483 if (fabs(v(1)) > fabs(v(0)))
00484 tmp = Vector3<T>(value_traits::one(),value_traits::zero(),value_traits::zero());
00485 else
00486 tmp = Vector3<T>(value_traits::zero(),value_traits::zero(),value_traits::one());
00487
00488
00489 return cross(v,tmp);
00490 }
00491
00492 template <typename T, typename T2>
00493 inline Vector3<T> operator*( Vector3<T> const& v, T2 const& s ) { return Vector3<T>( v(0)*s, v(1)*s, v(2)*s ); }
00494
00495 template <typename T2, typename T>
00496 inline Vector3<T> operator*( T2 const& s, Vector3<T> const& v ) { return Vector3<T>( v(0)*s, v(1)*s, v(2)*s ); }
00497
00498 template <typename T, typename T2>
00499 inline Vector3<T> operator/( Vector3<T> const& v, T2 const& s ) { return Vector3<T>( v(0)/s, v(1)/s, v(2)/s ); }
00500
00509 template<typename vector3_type>
00510 inline void orthonormal_vectors( vector3_type & i, vector3_type & j, vector3_type const & k )
00511 {
00512 typedef typename vector3_type::value_traits value_traits;
00513
00514 using std::fabs;
00515 vector3_type m_abs_k = fabs( k);
00516
00517 if ( m_abs_k( 0 ) > m_abs_k( 1 ) )
00518 {
00519 if ( m_abs_k( 0 ) > m_abs_k( 2 ) )
00520 i = vector3_type( value_traits::zero(), value_traits::one(), value_traits::zero() );
00521 else
00522 i = vector3_type( value_traits::one(), value_traits::zero(), value_traits::zero() );
00523 }
00524 else
00525 {
00526 if ( m_abs_k( 1 ) > m_abs_k( 2 ) )
00527 i = vector3_type( value_traits::zero(), value_traits::zero(), value_traits::one() );
00528 else
00529 i = vector3_type( value_traits::one(), value_traits::zero(), value_traits::zero() );
00530 }
00531 j = unit( cross(k,i) );
00532 i = cross(j,k);
00533 }
00534
00546 template<typename vector_type,typename permutation_container>
00547 inline void get_increasing_order( vector_type const & v, permutation_container & pi )
00548 {
00549 unsigned int n = v.size();
00550
00551 for(unsigned int i=0u;i<n;++i)
00552 pi[i] = i;
00553
00554
00555 for ( unsigned int i = 1u;i < n; ++i )
00556 {
00557 for ( unsigned int j = i;j > 0u;--j )
00558 {
00559 if ( v( pi[ j ] ) < v( pi[ j - 1 ] ) )
00560 {
00561 unsigned int tmp = pi[ j - 1 ];
00562 pi[ j - 1 ] = pi[ j ];
00563 pi[ j ] = tmp;
00564 }
00565 }
00566 }
00567 }
00568
00569
00570 namespace detail
00571 {
00572
00573 template <typename T>
00574 inline Vector3<T> const & axis_x()
00575 {
00576 static Vector3<T> const xa(one<T>(), zero<T>(), zero<T>());
00577 return xa;
00578 }
00579
00580
00581 template <typename T>
00582 inline Vector3<T> const & axis_y()
00583 {
00584 static Vector3<T> const ya(zero<T>(), one<T>(), zero<T>());
00585 return ya;
00586 }
00587
00588
00589 template <typename T>
00590 inline Vector3<T> const & axis_z()
00591 {
00592 static Vector3<T> const za(zero<T>(), zero<T>(), one<T>());
00593 return za;
00594 }
00595
00596 }
00597
00598 }
00599
00600 }
00601
00602
00603 #endif