00001 #include <math.h>
00002 #include <assert.h>
00003 #include "vector3.h"
00004
00005
00006 using namespace Geometry;
00007 using namespace std;
00008
00009
00010
00011
00012 double normalize(double min, double max, double value)
00013 {
00014 double distance = max - min;
00015 if (distance <= 0)
00016 {
00017 cerr << __FILE__ << ": min > max in \"normalize\" function" << endl;
00018 return value;
00019 }
00020
00021 while (value > max)
00022 value -= distance;
00023
00024 while (value < min)
00025 value += distance;
00026
00027 return value;
00028 }
00029
00030
00031
00032
00033 template <class T> Vector3D<T>::Vector3D()
00034 {
00035 for (unsigned i=0 ; i<DIM ; i++)
00036 _data[i] = (T) 0.0;
00037 }
00038
00039
00040 template <class T> Vector3D<T>::Vector3D(const T& x, const T& y, const T& z)
00041 {
00042 _data[0] = x;
00043 _data[1] = y;
00044 _data[2] = z;
00045 }
00046
00047
00048 template <class T> Vector3D<T>::Vector3D(const T data[3])
00049 {
00050 for (unsigned i=0 ; i<DIM ; i++)
00051 _data[i] = data[i];
00052 }
00053
00054
00055 template <class T> Vector3D<T>::Vector3D(const Vector3D<T>& v)
00056 {
00057 for (unsigned i=0 ; i<DIM ; i++)
00058 _data[i] = v._data[i];
00059 }
00060
00061
00062 template <class T> Vector3D<T>::Vector3D(const vector<T>& v)
00063 {
00064 assert(v.size() >= DIM);
00065 for (unsigned i=0 ; i<DIM ; i++)
00066 _data[i] = v[i];
00067 }
00068
00069
00070 template <class T> Vector3D<T>::Vector3D(const Vector3D<T>* v)
00071 {
00072 for (unsigned i=0 ; i<DIM ; i++)
00073 _data[i] = v->_data[i];
00074 }
00075
00076
00077
00078 template <class T> void Vector3D<T>::set(const T&x, const T& y, const T& z)
00079 {
00080 _data[0] = x;
00081 _data[1] = y;
00082 _data[2] = z;
00083 }
00084
00085
00086
00087 template <class T> void Vector3D<T>::set(const T data[3])
00088 {
00089 for (unsigned i=0 ; i<DIM ; i++)
00090 _data[i] = data[i];
00091 }
00092
00093
00094
00095 template <class T> Vector3D<T>& Vector3D<T>::operator=(const Vector3D<T>& src)
00096 {
00097 for (unsigned i=0 ; i<DIM ; i++)
00098 _data[i] = src._data[i];
00099
00100 return *this;
00101 }
00102
00103
00104 template <class T> bool Vector3D<T>::operator==(const Vector3D<T>& src) const
00105 {
00106 for (unsigned i=0 ; i<DIM ; i++)
00107 if (ABS(_data[i] - src._data[i]) > ALMOST_ZERO)
00108 return false;
00109
00110 return true;
00111 }
00112
00113
00114
00115 template <class T> bool Vector3D<T>::operator<(const Vector3D<T>& src) const
00116 {
00117 for (unsigned i=0 ; i<DIM ; i++)
00118 {
00119 if (_data[i] < src._data[i])
00120 return true;
00121 if (_data[i] > src._data[i])
00122 return false;
00123 }
00124
00125 return false;
00126 }
00127
00128
00129 template <class T> void Vector3D<T>::normalize()
00130 {
00131 double mod = module();
00132 *this /= mod;
00133 }
00134
00135
00136 template <class T> void Vector3D<T>::setLength(T len)
00137 {
00138 double mod = module();
00139 *this *= len/mod;
00140 }
00141
00142
00143
00144
00145 template <class T> double Vector3D<T>::squaredModule() const
00146 {
00147 T sum(0);
00148 for (unsigned i=0 ; i<DIM ; i++)
00149 sum += _data[i]*_data[i];
00150
00151 return sum;
00152 }
00153
00154
00155
00156 template <class T> T& Vector3D<T>::operator[](int index)
00157 {
00158 return _data[index];
00159 }
00160
00161
00162 template <class T> const T& Vector3D<T>::operator[](int index) const
00163 {
00164 return _data[index];
00165 }
00166
00167
00168 template <class T> double Vector3D<T>::angle(const Vector3D<T>& v) const
00169 {
00170 Vector3D<T> local(*this);
00171 Vector3D<T> param(v);
00172
00173 double m = module();
00174 assert(!isnan(m));
00175
00176 double mv = v.module();
00177 assert(!isnan(mv));
00178
00179 double mod = m*mv;
00180 assert(!isnan(mod));
00181
00182 if ( mod < ALMOST_ZERO )
00183 return 0.0;
00184
00185 local /= m;
00186 param /= mv;
00187
00188 double dp = local*param;
00189 assert(!isnan(dp));
00190
00191
00192 if (dp > 1.0)
00193 dp = 1.0;
00194 else if (dp < -1.0)
00195 dp = -1.0;
00196
00197 assert(!isnan(acos(dp)));
00198 return acos( dp );
00199 }
00200
00201
00202
00203
00204 template <class T> double Vector3D<T>::squaredDistance(const Vector3D<T>& v) const
00205 {
00206 T sum(0);
00207 for (unsigned i=0 ; i<DIM ; i++)
00208 {
00209 T diff = _data[i] - v._data[i];
00210 sum += diff * diff;
00211 }
00212
00213 return sum;
00214 }
00215
00216
00217 template <class T> double Vector3D<T>::infDistance(const Vector3D<T>& v) const
00218 {
00219 T soFar(0);
00220 for (unsigned i=0 ; i<DIM ; i++)
00221 {
00222 T diff = ABS(_data[i] - v._data[i]);
00223 if (diff > soFar)
00224 soFar = diff;
00225 }
00226
00227 return soFar;
00228 }
00229
00230
00231 template <class T> double Vector3D<T>::manhattanDistance(const Vector3D<T>& v) const
00232 {
00233 T sum(0);
00234 for (unsigned i=0 ; i<DIM ; i++)
00235 sum += ABS(_data[i] - v._data[i]);
00236
00237 return sum;
00238 }
00239
00240
00241
00242
00243 template <class T> double Vector3D<T>::distanceToPlane(const Vector3D<T>& P, const Vector3D<T>& N) const
00244 {
00245 assert( fabs(N.squaredModule() - 1) < ALMOST_ZERO );
00246
00247 return (P-*this) * N;
00248 }
00249
00250
00251
00252
00253 template <class T> void Vector3D<T>::rotateX(double angle)
00254 {
00255 double y = _data[1];
00256 double z = _data[2];
00257 double cosine = cos(angle);
00258 double sine = sin(angle);
00259
00260 _data[1] = (T) (y*cosine - z*sine);
00261 _data[2] = (T) (y*sine + z*cosine);
00262 }
00263
00264
00265
00266 template <class T> void Vector3D<T>::rotateY(double angle)
00267 {
00268 double x = _data[0];
00269 double z = _data[2];
00270 double cosine = cos(angle);
00271 double sine = sin(angle);
00272
00273 _data[2] = (T) (z*cosine - x*sine);
00274 _data[0] = (T) (z*sine + x*cosine);
00275 }
00276
00277
00278 template <class T> void Vector3D<T>::rotateZ(double angle)
00279 {
00280 double x = _data[0];
00281 double y = _data[1];
00282 double cosine = cos(angle);
00283 double sine = sin(angle);
00284
00285 _data[0] = (T) (x*cosine - y*sine);
00286 _data[1] = (T) (x*sine + y*cosine);
00287 }
00288
00289
00290
00291
00292 template <class T> Vector3D<T> Vector3D<T>::rotation(const Vector3D<T>& axis, double angle) const
00293 {
00294 Vector3D<T> Y = axis ^ (*this);
00295 assert(fabs(Y.squaredModule() - 1) < 0.0001);
00296
00297 double cosine = cos(angle);
00298 double sine = sin(angle);
00299
00300 return Y*sine + (*this)*cosine;
00301 }
00302
00303
00304 template <class T> T Vector3D<T>::operator*(const Vector3D<T>& v) const
00305 {
00306 T sum(0);
00307 for (unsigned i=0 ; i<DIM ; i++)
00308 sum += _data[i] * v._data[i];
00309
00310 return sum;
00311 }
00312
00313
00314 template <class T> T Vector3D<T>::operator*(const std::vector<T>& v) const
00315 {
00316 assert(v.size() >= (unsigned) dim());
00317 T sum(0);
00318 for (unsigned i=0 ; i<DIM ; i++)
00319 sum += _data[i] * v[i];
00320
00321 return sum;
00322 }
00323
00324
00325 template <class T> Vector3D<T> Vector3D<T>::operator/(T factor) const
00326 {
00327 return Vector3D<T>(_data[0]/factor, _data[1]/factor, _data[2]/factor);
00328 }
00329
00330
00331 template <class T> const Vector3D<T>& Vector3D<T>::operator/=(T factor)
00332 {
00333 for (unsigned i=0 ; i<DIM ; i++)
00334 _data[i] /= factor;
00335
00336 return *this;
00337 }
00338
00339
00340 template <class T> Vector3D<T> Vector3D<T>::operator*(T factor) const
00341 {
00342 return Vector3D<T>(_data[0]*factor, _data[1]*factor, _data[2]*factor);
00343 }
00344
00345 #if 0
00346
00347 template <class T> Vector3D<T> operator*(T factor, const Vector3D<T>& v)
00348 {
00349 return v*factor;
00350 }
00351 #endif
00352
00353
00354 template <class T> const Vector3D<T>& Vector3D<T>::operator*=(T factor)
00355 {
00356 for (unsigned i=0 ; i<DIM ; i++)
00357 _data[i] *= factor;
00358
00359 return *this;
00360 }
00361
00362
00363 template <class T> Vector3D<T> Vector3D<T>::operator^(const Vector3D<T>& v) const
00364 {
00365 return Vector3D<T>( (_data[1] * v._data[2]) - (v._data[1] * _data[2]),
00366 (_data[2] * v._data[0]) - (v._data[2] * _data[0]),
00367 (_data[0] * v._data[1]) - (v._data[0] * _data[1]) );
00368 }
00369
00370
00371
00372 template <class T> Vector3D<T> Vector3D<T>::operator-(const Vector3D<T>& v) const
00373 {
00374 return Vector3D<T>( _data[0] - v._data[0],
00375 _data[1] - v._data[1],
00376 _data[2] - v._data[2] );
00377 }
00378
00379
00380
00381 template <class T> const Vector3D<T>& Vector3D<T>::operator-=(const Vector3D<T>& v)
00382 {
00383 for (unsigned i=0 ; i<DIM ; i++)
00384 _data[i] -= v._data[i];
00385
00386 return *this;
00387 }
00388
00389
00390
00391 template <class T> Vector3D<T> Vector3D<T>::operator+(const Vector3D<T>& v) const
00392 {
00393 return Vector3D<T>( _data[0] + v._data[0],
00394 _data[1] + v._data[1],
00395 _data[2] + v._data[2] );
00396 }
00397
00398
00399
00400 template <class T> const Vector3D<T>& Vector3D<T>::operator+=(const Vector3D<T>& v)
00401 {
00402 for (unsigned i=0 ; i<DIM ; i++)
00403 _data[i] += v._data[i];
00404
00405 return *this;
00406 }
00407
00408
00409 template <class T> void Vector3D<T>::getSpheric(double& theta, double& phi) const
00410 {
00411 double distance = sqrt( x()*x() + y()*y() + z()*z() );
00412 assert(distance != 0.0);
00413
00414 theta = atan2(y(), x());
00415 phi = acos(z() / distance);
00416
00417
00418
00419 }
00420
00421
00422 template <class T> void Vector3D<T>::getSpheric(double& distance, double& theta, double& phi) const
00423 {
00424 distance = sqrt( x()*x() + y()*y() + z()*z() );
00425 theta = atan2(y(), x());
00426 phi = acos(z() / distance);
00427
00428 assert( (theta >= -M_PI) && (theta <= M_PI) );
00429 assert( (phi >= 0) && (phi <= M_PI) );
00430 }
00431
00432
00433 template <class T> void Vector3D<T>::setSpheric(double distance, double theta, double phi)
00434 {
00435
00436
00437
00438
00439
00440 double sinPhi = sin(phi);
00441
00442 x( (T) (distance * cos(theta) * sinPhi) );
00443 y( (T) (distance * sin(theta) * sinPhi) );
00444 z( (T) (distance * cos(phi)) );
00445 }
00446
00447
00448
00449 template <class T> Vector3D<T> Vector3D<T>::projectX() const
00450 {
00451 return Vector3D<T>(0, _data[1], _data[2]);
00452 }
00453
00454
00455 template <class T> Vector3D<T> Vector3D<T>::projectY() const
00456 {
00457 return Vector3D<T>(_data[0], 0, _data[2]);
00458 }
00459
00460
00461 template <class T> Vector3D<T> Vector3D<T>::projectZ() const
00462 {
00463 return Vector3D<T>(_data[0], _data[1], 0);
00464 }
00465
00466
00467
00468 template <class T> Vector3D<T> Vector3D<T>::project(const Vector3D<T>& n) const
00469 {
00470 return (*this) - n * dotProduct(n);
00471 }
00472
00473
00474
00475
00476
00477
00478 template <class T> Vector3D<T>
00479 Vector3D<T>::intersect(const Vector3D<T>& center, const Vector3D<T>& normal) const
00480 {
00481 return (*this) * ((center*normal) / ((*this)*normal));
00482 }
00483
00484
00485
00486 template <class T> Vector3D<T>
00487 Vector3D<T>::perpendicular() const
00488 {
00489 static const Vector3D<T> X(1, 0, 0);
00490 static const Vector3D<T> Y(0, 1, 0);
00491
00492 const Vector3D<T>& base = (fabs((*this) * X) < fabs((*this) * Y) ? X : Y);
00493 Vector3D<T> result = base ^ (*this);
00494 result.normalize();
00495
00496 return result;
00497 }
00498
00499
00500
00501
00502
00503 template class Vector3D<float>;
00504
00505
00506