00001 /* 00002 Copyright (C) 2010 - 2017 Christoph Haenisch 00003 00004 Chair of Medical Engineering (mediTEC) 00005 RWTH Aachen University 00006 Pauwelsstr. 20 00007 52074 Aachen 00008 Germany 00009 00010 See license.txt for more information. 00011 00012 Version 0.8.2 (2017-12-08) 00013 */ 00014 00020 #ifndef COORDINATE_HPP_1023074891 00021 #define COORDINATE_HPP_1023074891 00022 00023 00024 #include <assert.h> 00025 #include <cmath> 00026 #include <stdexcept> 00027 #include <string> 00028 00029 #include <Eigen/Core> 00030 #include <Eigen/Dense> 00031 00032 #include "Tools.hpp" 00033 #include "ErrorObj.hpp" 00034 00035 #ifdef TRTK_SUPPORT_CVECTOR 00036 #include <Mathbib/Vector.h> 00037 #endif // TRTK_SUPPORT_CVECTOR 00038 00039 00040 namespace TRTK 00041 { 00042 00043 // Forward declarations 00044 00045 namespace Tools 00046 { 00047 template <class T> 00048 bool isZero(const T value); 00049 00050 template <class T> 00051 T rand(); 00052 00053 template <class T> 00054 T rand(T a, T b); 00055 00056 template <class T> 00057 T randn(); 00058 00059 template <class T> 00060 T randn(T mu, T sigma); 00061 } 00062 00154 template <class T> 00155 class Coordinate 00156 { 00157 public: 00158 typedef T value_type; 00159 typedef Eigen::Array<T, Eigen::Dynamic, 1> data_type; 00160 typedef Eigen::Matrix<T, Eigen::Dynamic, 1> matrix_type; 00161 00162 Coordinate(); 00163 Coordinate(T); 00164 Coordinate(T, T); 00165 Coordinate(T, T, T); 00166 Coordinate(T, T, T, T); 00167 00168 Coordinate(const Coordinate &); 00169 00170 template <class U> 00171 Coordinate(const Coordinate<U> & coordinate); 00172 00173 #ifdef TRTK_SUPPORT_CVECTOR 00174 Coordinate(const CVector &); 00175 #endif // TRTK_SUPPORT_CVECTOR 00176 00177 template <typename Derived> 00178 explicit Coordinate(const Eigen::DenseBase<Derived> & vector); 00179 00180 virtual ~Coordinate(); 00181 00182 T & x(); 00183 T & y(); 00184 T & z(); 00185 T & w(); 00186 00187 const T & x() const; 00188 const T & y() const; 00189 const T & z() const; 00190 const T & w() const; 00191 00192 T & operator[](int); 00193 const T & operator[](int) const; 00194 00195 bool operator==(const Coordinate &) const; 00196 00197 Coordinate & operator+=(T); 00198 Coordinate & operator-=(T); 00199 Coordinate & operator*=(T); 00200 Coordinate & operator/=(T); 00201 00202 Coordinate & operator+=(const Coordinate &); 00203 Coordinate & operator-=(const Coordinate &); 00204 Coordinate & operator*=(const Coordinate &); 00205 Coordinate & operator/=(const Coordinate &); 00206 00207 Coordinate operator+(T) const; 00208 Coordinate operator-(T) const; 00209 Coordinate operator*(T) const; 00210 Coordinate operator/(T) const; 00211 00212 Coordinate operator+(const Coordinate &) const; 00213 Coordinate operator-(const Coordinate &) const; 00214 Coordinate operator*(const Coordinate &) const; 00215 Coordinate operator/(const Coordinate &) const; 00216 00217 Coordinate operator,(T) const; 00218 00219 operator data_type(); 00220 operator data_type() const; 00221 00222 #ifdef TRTK_SUPPORT_CVECTOR 00223 operator CVector() const; 00224 #endif // TRTK_SUPPORT_CVECTOR 00225 00226 Coordinate cross(const Coordinate &) const; 00227 double dot(const Coordinate &) const; 00228 Coordinate & fill(T); 00229 double norm() const; 00230 Coordinate & normalize(); 00231 Coordinate normalized() const; 00232 Coordinate orthogonal() const; 00233 Coordinate orthonormal() const; 00234 Coordinate & reserve(unsigned int size); 00235 Coordinate & resize(unsigned int size, T value = T()); 00236 unsigned int size() const; 00237 double squaredNorm() const; 00238 00239 data_type & toArray(); 00240 const data_type & toArray() const; 00241 00242 matrix_type toMatrix() const; 00243 00244 std::string toString() const; 00245 00248 enum Error {DIVISION_BY_ZERO, 00249 UNKNOWN_ERROR 00250 }; 00251 00252 static Coordinate rand(unsigned int size, T a = T(0), T b = T(1)); 00253 static Coordinate randn(unsigned int size, T mu = T(0), T sigma = T(1)); 00254 00255 private: 00256 data_type m_data; 00257 }; 00258 00259 00260 // The subsequent functions allow expressions, where the scalar is in front 00261 // of the coordinate. See Corrdinate.cpp for their implementations 00262 00263 Coordinate<double> operator+(int, const Coordinate<double> &); 00264 00265 00266 Coordinate<double> operator-(int, const Coordinate<double> &); 00267 00268 00269 Coordinate<double> operator*(int, const Coordinate<double> &); 00270 00271 00272 Coordinate<double> operator/(int, const Coordinate<double> &); 00273 00274 00275 Coordinate<int> operator+(double, const Coordinate<int> &); 00276 00277 00278 Coordinate<int> operator-(double, const Coordinate<int> &); 00279 00280 00281 Coordinate<int> operator*(double, const Coordinate<int> &); 00282 00283 00284 Coordinate<int> operator/(double, const Coordinate<int> &); 00285 00286 00287 template <class T> 00288 Coordinate<T> operator+(T, const Coordinate<T> & coordinate); 00289 00290 00291 template <class T> 00292 Coordinate<T> operator-(T, const Coordinate<T> & coordinate); 00293 00294 00295 template <class T> 00296 Coordinate<T> operator*(T, const Coordinate<T> & coordinate); 00297 00298 00299 template <class T> 00300 Coordinate<T> operator/(T, const Coordinate<T> & coordinate); 00301 00302 00303 // Stream operators 00304 00305 template <class T> 00306 std::istream & operator >> (std::istream &, Coordinate<T> &); 00307 00308 00309 template <class T> 00310 std::ostream & operator << (std::ostream &, const Coordinate<T> &); 00311 00312 00313 00314 // Arithmetical functions 00315 00316 template <class T> 00317 TRTK::Coordinate<T> sqrt(const TRTK::Coordinate<T> & coordinate); 00318 00319 00321 00322 00323 template <class T> 00324 Coordinate<T>::Coordinate() 00325 { 00326 } 00327 00328 00334 template <class T> 00335 Coordinate<T>::Coordinate(T x) : m_data(1) 00336 { 00337 m_data(0) = x; 00338 } 00339 00340 00347 template <class T> 00348 Coordinate<T>::Coordinate(T x, T y) : m_data(2) 00349 { 00350 m_data(0) = x; 00351 m_data(1) = y; 00352 } 00353 00354 00362 template <class T> 00363 Coordinate<T>::Coordinate(T x, T y, T z) : m_data(3) 00364 { 00365 m_data(0) = x; 00366 m_data(1) = y; 00367 m_data(2) = z; 00368 } 00369 00370 00379 template <class T> 00380 Coordinate<T>::Coordinate(T x, T y, T z, T w) : m_data(4) 00381 { 00382 m_data(0) = x; 00383 m_data(1) = y; 00384 m_data(2) = z; 00385 m_data(3) = w; 00386 } 00387 00388 00396 template <class T> 00397 Coordinate<T>::Coordinate(const Coordinate & coordinate) 00398 { 00399 m_data = coordinate.m_data; 00400 } 00401 00402 00411 template <class T> 00412 template <class U> 00413 Coordinate<T>::Coordinate(const Coordinate<U> & coordinate) 00414 { 00415 const unsigned int size = coordinate.size(); 00416 00417 m_data.resize(size); 00418 00419 for (unsigned i = 0; i < size; ++i) 00420 { 00421 m_data(i) = static_cast<T>(coordinate[i]); 00422 } 00423 } 00424 00425 00426 #ifdef TRTK_SUPPORT_CVECTOR 00427 00440 template <class T> 00441 Coordinate<T>::Coordinate(const CVector & cVector) 00442 { 00443 const unsigned int size = cVector.GetSize(); 00444 00445 this->resize(size); 00446 00447 for (int i = 0; i < size; ++i) 00448 { 00449 m_data[i] = cVector(i); 00450 } 00451 } 00452 00453 #endif // TRTK_SUPPORT_CVECTOR 00454 00455 00476 template <class T> 00477 template <typename Derived> 00478 Coordinate<T>::Coordinate(const Eigen::DenseBase<Derived> & vector) 00479 { 00480 assert(vector.rows() == 1 || vector.cols() == 1); 00481 m_data = vector; // no conversion from row vector to column vector necessary 00482 } 00483 00484 00490 template <class T> 00491 Coordinate<T>::~Coordinate() 00492 { 00493 } 00494 00495 00498 template <class T> 00499 inline T & Coordinate<T>::x() 00500 { 00501 assert(size() >= 1); 00502 00503 return m_data(0); 00504 } 00505 00506 00509 template <class T> 00510 inline T & Coordinate<T>::y() 00511 { 00512 assert(size() >= 2); 00513 00514 return m_data(1); 00515 } 00516 00517 00520 template <class T> 00521 inline T & Coordinate<T>::z() 00522 { 00523 assert(size() >= 3); 00524 00525 return m_data(2); 00526 } 00527 00528 00531 template <class T> 00532 inline T & Coordinate<T>::w() 00533 { 00534 assert(size() >= 4); 00535 00536 return m_data(3); 00537 } 00538 00539 00542 template <class T> 00543 inline const T & Coordinate<T>::x() const 00544 { 00545 assert(size() >= 1); 00546 00547 return m_data(0); 00548 } 00549 00550 00553 template <class T> 00554 inline const T & Coordinate<T>::y() const 00555 { 00556 assert(size() >= 2); 00557 00558 return m_data(1); 00559 } 00560 00561 00564 template <class T> 00565 inline const T & Coordinate<T>::z() const 00566 { 00567 assert(size() >= 3); 00568 00569 return m_data(2); 00570 } 00571 00572 00575 template <class T> 00576 inline const T & Coordinate<T>::w() const 00577 { 00578 assert(size() >= 4); 00579 00580 return m_data(3); 00581 } 00582 00583 00601 template <class T> 00602 inline T & Coordinate<T>::operator[](int index) 00603 { 00604 assert(0 <= index && index < m_data.size()); 00605 00606 return m_data(index); 00607 } 00608 00609 00627 template <class T> 00628 inline const T & Coordinate<T>::operator[](int index) const 00629 { 00630 assert(0 <= index && index < m_data.size()); 00631 00632 return m_data(index); 00633 } 00634 00635 00644 template <class T> 00645 inline bool Coordinate<T>::operator==(const Coordinate & coordinate) const 00646 { 00647 assert(this->size() == coordinate.size()); 00648 00649 return (m_data == coordinate.m_data).all(); 00650 } 00651 00652 00662 template <class T> 00663 inline Coordinate<T> & Coordinate<T>::operator+=(T value) 00664 { 00665 m_data += value; 00666 return *this; 00667 } 00668 00669 00679 template <class T> 00680 inline Coordinate<T> & Coordinate<T>::operator-=(T value) 00681 { 00682 m_data -= value; 00683 return *this; 00684 } 00685 00686 00696 template <class T> 00697 inline Coordinate<T> & Coordinate<T>::operator*=(T value) 00698 { 00699 m_data *= value; 00700 return *this; 00701 } 00702 00703 00718 template <class T> 00719 Coordinate<T> & Coordinate<T>::operator/=(T value) 00720 { 00721 if (value == 0) 00722 { 00723 ErrorObj error; 00724 error.setClassName("Coordinate"); 00725 error.setFunctionName("operator/="); 00726 error.setErrorMessage("Division by zero."); 00727 error.setErrorCode(DIVISION_BY_ZERO); 00728 throw error; 00729 } 00730 00731 m_data /= value; 00732 return *this; 00733 } 00734 00735 00745 template <class T> 00746 inline Coordinate<T> & Coordinate<T>::operator+=(const Coordinate & coordinate) 00747 { 00748 assert(this->size() == coordinate.size()); 00749 00750 m_data += coordinate.m_data; 00751 return *this; 00752 } 00753 00754 00764 template <class T> 00765 inline Coordinate<T> & Coordinate<T>::operator-=(const Coordinate & coordinate) 00766 { 00767 assert(this->size() == coordinate.size()); 00768 00769 m_data -= coordinate.m_data; 00770 return *this; 00771 } 00772 00773 00783 template <class T> 00784 inline Coordinate<T> & Coordinate<T>::operator*=(const Coordinate & coordinate) 00785 { 00786 assert(this->size() == coordinate.size()); 00787 00788 m_data *= coordinate.m_data; 00789 return *this; 00790 } 00791 00792 00807 template <class T> 00808 Coordinate<T> & Coordinate<T>::operator/=(const Coordinate & coordinate) 00809 { 00810 assert(this->size() == coordinate.size()); 00811 00812 if (!coordinate.m_data.all()) 00813 { 00814 ErrorObj error; 00815 error.setClassName("Coordinate"); 00816 error.setFunctionName("operator/="); 00817 error.setErrorMessage("Division by zero."); 00818 error.setErrorCode(DIVISION_BY_ZERO); 00819 throw error; 00820 } 00821 00822 m_data /= coordinate.m_data; 00823 00824 return *this; 00825 } 00826 00827 00837 template <class T> 00838 Coordinate<T> Coordinate<T>::operator+(T value) const 00839 { 00840 Coordinate<T> coordinate; 00841 coordinate.m_data = m_data + value; 00842 00843 return coordinate; 00844 } 00845 00846 00856 template <class T> 00857 Coordinate<T> Coordinate<T>::operator-(T value) const 00858 { 00859 Coordinate<T> coordinate; 00860 coordinate.m_data = m_data - value; 00861 00862 return coordinate; 00863 } 00864 00865 00875 template <class T> 00876 Coordinate<T> Coordinate<T>::operator*(T value) const 00877 { 00878 Coordinate<T> coordinate; 00879 coordinate.m_data = m_data * value; 00880 00881 return coordinate; 00882 } 00883 00884 00899 template <class T> 00900 Coordinate<T> Coordinate<T>::operator/(T value) const 00901 { 00902 if (value == 0) 00903 { 00904 ErrorObj error; 00905 error.setClassName("Coordinate"); 00906 error.setFunctionName("operator/"); 00907 error.setErrorMessage("Division by zero."); 00908 error.setErrorCode(DIVISION_BY_ZERO); 00909 throw error; 00910 } 00911 00912 Coordinate<T> coordinate; 00913 coordinate.m_data = m_data / value; 00914 00915 return coordinate; 00916 } 00917 00918 00926 template <class T> 00927 Coordinate<T> Coordinate<T>::operator+(const Coordinate & coordinate) const 00928 { 00929 assert(this->size() == coordinate.size()); 00930 00931 Coordinate<T> tmp; 00932 tmp.m_data = m_data + coordinate.m_data; 00933 00934 return tmp; 00935 } 00936 00937 00945 template <class T> 00946 Coordinate<T> Coordinate<T>::operator-(const Coordinate & coordinate) const 00947 { 00948 assert(this->size() == coordinate.size()); 00949 00950 Coordinate<T> tmp; 00951 tmp.m_data = m_data - coordinate.m_data; 00952 00953 return tmp; 00954 } 00955 00956 00964 template <class T> 00965 Coordinate<T> Coordinate<T>::operator*(const Coordinate & coordinate) const 00966 { 00967 assert(this->size() == coordinate.size()); 00968 00969 Coordinate<T> tmp; 00970 tmp.m_data = m_data * coordinate.m_data; 00971 00972 return tmp; 00973 } 00974 00975 00988 template <class T> 00989 Coordinate<T> Coordinate<T>::operator/(const Coordinate & coordinate) const 00990 { 00991 assert(this->size() == coordinate.size()); 00992 00993 if (!coordinate.m_data.all()) 00994 { 00995 ErrorObj error; 00996 error.setClassName("Coordinate"); 00997 error.setFunctionName("operator/"); 00998 error.setErrorMessage("Division by zero."); 00999 error.setErrorCode(DIVISION_BY_ZERO); 01000 throw error; 01001 } 01002 01003 Coordinate<T> tmp; 01004 tmp.m_data = m_data / coordinate.m_data; 01005 01006 return tmp; 01007 } 01008 01009 01046 template <class T> 01047 Coordinate<T> Coordinate<T>::operator,(T value) const 01048 { 01049 const unsigned int size = m_data.size(); 01050 data_type data(size + 1); 01051 data.head(size) = m_data; 01052 data(size) = value; 01053 01054 Coordinate coordinate; 01055 coordinate.m_data = data; 01056 01057 return coordinate; 01058 } 01059 01060 01071 template <class T> 01072 Coordinate<T>::operator data_type() 01073 { 01074 return m_data; 01075 } 01076 01077 01089 template <class T> 01090 Coordinate<T>::operator data_type() const 01091 { 01092 return m_data; 01093 } 01094 01095 01096 #ifdef TRTK_SUPPORT_CVECTOR 01097 01109 template <class T> 01110 Coordinate<T>::operator CVector() const 01111 { 01112 const unsigned int size = m_data.size(); 01113 01114 CVector cVector(size); 01115 01116 for (unsigned int i = 0; i < size; ++i) 01117 { 01118 cVector(i) = m_data(i); 01119 } 01120 01121 return cVector; 01122 } 01123 01124 #endif // TRTK_SUPPORT_CVECTOR 01125 01126 01134 template <class T> 01135 Coordinate<T> Coordinate<T>::cross(const Coordinate & other) const 01136 { 01137 assert((this->size() == 3) && (other.size() == 3)); 01138 01139 const T x1 = m_data(0); 01140 const T x2 = m_data(1); 01141 const T x3 = m_data(2); 01142 01143 const T y1 = other.m_data(0); 01144 const T y2 = other.m_data(1); 01145 const T y3 = other.m_data(2); 01146 01147 return Coordinate<T>(x2 * y3 - x3 * y2, 01148 x3 * y1 - x1 * y3, 01149 x1 * y2 - x2 * y1); 01150 } 01151 01152 01160 template <class T> 01161 double Coordinate<T>::dot(const Coordinate & other) const 01162 { 01163 assert(this->size() == other.size()); 01164 01165 return m_data.matrix().dot(other.m_data.matrix()); 01166 } 01167 01168 01178 template <class T> 01179 inline Coordinate<T> & Coordinate<T>::fill(T value) 01180 { 01181 m_data.setConstant(value); 01182 return *this; 01183 } 01184 01185 01188 template <class T> 01189 inline double Coordinate<T>::norm() const 01190 { 01191 return m_data.matrix().norm(); 01192 } 01193 01194 01202 template <class T> 01203 Coordinate<T> & Coordinate<T>::normalize() 01204 { 01205 m_data.matrix().normalize(); 01206 return *this; 01207 } 01208 01209 01212 template <class T> 01213 Coordinate<T> Coordinate<T>::normalized() const 01214 { 01215 return Coordinate(m_data.matrix().normalized()); 01216 } 01217 01218 01224 template <class T> 01225 Coordinate<T> Coordinate<T>::orthogonal() const 01226 { 01227 assert(this->size() >= 2); 01228 assert(!Tools::isZero(this->norm())); 01229 01230 01231 // Find largest and second largest element of this coordinate 01232 // and their according positions. 01233 01234 T max[2] = {0}; 01235 int pos[2] = {0}; 01236 01237 for (unsigned int i = 0; i < this->size(); ++i) 01238 { 01239 using std::abs; 01240 01241 if (abs(m_data(i)) > abs(max[0])) 01242 { 01243 max[1] = max[0]; 01244 max[0] = m_data(i); 01245 pos[1] = pos[0]; 01246 pos[0] = i; 01247 } 01248 else if (abs(m_data(i)) >= abs(max[1])) 01249 { 01250 max[1] = m_data(i); 01251 pos[1] = i; 01252 } 01253 } 01254 01255 // Construct the orthogonal vector by switching the positions of 01256 // the two largest elements and negating the second largest element. 01257 // All other components are set to zero. 01258 // The dot product of this constructed vector with *this always equals zero. 01259 01260 Coordinate<T> result; 01261 result.resize(this->size(), 0); 01262 result[pos[0]] = - max[1]; 01263 result[pos[1]] = max[0]; 01264 01265 return result; 01266 } 01267 01268 01274 template <class T> 01275 Coordinate<T> Coordinate<T>::orthonormal() const 01276 { 01277 assert(this->size() >= 2); 01278 assert(!Tools::isZero(this->norm())); 01279 01280 // Find largest and second largest element of this coordinate 01281 // and their according positions. 01282 01283 T max[2] = {0}; 01284 int pos[2] = {0}; 01285 01286 for (unsigned int i = 0; i < this->size(); ++i) 01287 { 01288 using std::abs; 01289 01290 if (abs(m_data(i)) > abs(max[0])) 01291 { 01292 max[1] = max[0]; 01293 max[0] = m_data(i); 01294 pos[1] = pos[0]; 01295 pos[0] = i; 01296 } 01297 else if (abs(m_data(i)) >= abs(max[1])) 01298 { 01299 max[1] = m_data(i); 01300 pos[1] = i; 01301 } 01302 } 01303 01304 // Construct the orthonormal vector by switching the positions of 01305 // the two largest elements and negating the second largest element. 01306 // All other components are set to zero. 01307 01308 using std::sqrt; 01309 T norm = sqrt(max[0] * max[0] + max[1] * max[1]); 01310 01311 Coordinate<T> result; 01312 result.resize(this->size(), 0); 01313 result[pos[0]] = - max[1] / norm; 01314 result[pos[1]] = max[0] / norm; 01315 01316 return result; 01317 } 01318 01319 01340 template <class T> 01341 Coordinate<T> Coordinate<T>::rand(unsigned int size, T a, T b) 01342 { 01343 Coordinate<T> coordinate; 01344 coordinate.reserve(size); 01345 01346 for (unsigned i = 0; i < size; ++i) 01347 { 01348 coordinate[i] = Tools::rand(a, b); 01349 } 01350 01351 return coordinate; 01352 } 01353 01354 01372 template <class T> 01373 Coordinate<T> Coordinate<T>::randn(unsigned int size, T mu, T sigma) 01374 { 01375 Coordinate<T> coordinate; 01376 coordinate.reserve(size); 01377 01378 for (unsigned i = 0; i < size; ++i) 01379 { 01380 coordinate[i] = Tools::randn(mu, sigma); 01381 } 01382 01383 return coordinate; 01384 } 01385 01386 01398 template <class T> 01399 Coordinate<T> & Coordinate<T>::reserve(unsigned int size) 01400 { 01401 m_data.resize(size); 01402 return *this; 01403 } 01404 01405 01418 template <class T> 01419 Coordinate<T> & Coordinate<T>::resize(unsigned int size, T value) 01420 { 01421 const int former_size = signed(this->size()); 01422 const int difference_in_size = signed(size) - signed(former_size); 01423 01424 // resizing allocates new memory and thus all data are lost 01425 // --> save data to tempory and restore it afterwards 01426 01427 data_type data = m_data; 01428 01429 m_data.resize(size); 01430 01431 if (difference_in_size <= 0) 01432 { 01433 m_data = data.head(size); 01434 } 01435 else 01436 { 01437 m_data.head(former_size) = data; 01438 m_data.tail(difference_in_size).setConstant(value); 01439 } 01440 01441 return *this; 01442 } 01443 01444 01452 template <class T> 01453 inline unsigned int Coordinate<T>::size() const 01454 { 01455 return static_cast<int>(m_data.size()); 01456 } 01457 01458 01461 template <class T> 01462 inline double Coordinate<T>::squaredNorm() const 01463 { 01464 return m_data.matrix().squaredNorm(); 01465 } 01466 01467 01475 template <class T> 01476 inline typename Coordinate<T>::data_type & Coordinate<T>::toArray() 01477 { 01478 return m_data; 01479 } 01480 01481 01489 template <class T> 01490 inline const typename Coordinate<T>::data_type & Coordinate<T>::toArray() const 01491 { 01492 return m_data; 01493 } 01494 01495 01510 template <class T> 01511 inline typename Coordinate<T>::matrix_type Coordinate<T>::toMatrix() const 01512 { 01513 return m_data; 01514 } 01515 01516 01530 template <class T> 01531 std::string Coordinate<T>::toString() const 01532 { 01533 std::stringstream ss; 01534 01535 // throw an exception if the output operation fails for any reason 01536 01537 ss.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); 01538 01539 // put out formatted coordinate 01540 01541 ss // << std::fixed // or std::scientific 01542 // << std::setprecision(4) 01543 // << std::showpos 01544 // << std::setfill('0') 01545 // << std::internal 01546 << "("; 01547 01548 int i = 0; 01549 01550 while (i < signed(m_data.size()) - 1) 01551 { 01552 ss // << std::setw(10) 01553 << m_data(i++) 01554 << ", "; 01555 } 01556 01557 if (m_data.size() != 0) 01558 { 01559 ss // << std::setw(10) 01560 << m_data(i); 01561 } 01562 01563 ss << ")"; 01564 01565 return ss.str(); 01566 } 01567 01568 01570 01571 01572 // Operators of the form T op Coordinate<class T> 01573 01586 template <class T> 01587 Coordinate<T> operator+(T value, const Coordinate<T> & coordinate) 01588 { 01589 return coordinate + value; 01590 } 01591 01592 01606 template <class T> 01607 Coordinate<T> operator-(T value, const Coordinate<T> & coordinate) 01608 { 01609 return coordinate * (-1) + value; 01610 } 01611 01612 01625 template <class T> 01626 Coordinate<T> operator*(T value, const Coordinate<T> & coordinate) 01627 { 01628 return coordinate * value; 01629 } 01630 01631 01645 template <class T> 01646 Coordinate<T> operator/(T value, const Coordinate<T> & coordinate) 01647 { 01648 Coordinate<T> coordinate2; 01649 coordinate2.resize(coordinate.size(), value); 01650 01651 return coordinate2.operator/(coordinate); 01652 } 01653 01654 01655 // Stream operators 01656 01715 template <class T> 01716 std::istream & operator >> (std::istream & input, Coordinate<T> & coordinate) 01717 { 01718 // The input format is a comma separated list enclosed by round brackets. 01719 // Anything diverging from it, leads to an exception. 01720 // 01721 // Example: (1, 2, 3) 01722 01723 char input_character; 01724 const std::string error_msg("Wrong input format or coordinate size."); 01725 01726 // throw an exception if the input character differs from what was expected 01727 01728 std::ios_base::iostate old_iostate = input.exceptions(); 01729 01730 input.exceptions(std::ios_base::badbit | std::ios_base::failbit); 01731 01732 // read in coordinate 01733 01734 input >> input_character; 01735 if (input_character != '(') throw std::invalid_argument(error_msg); 01736 01737 int i = 0; 01738 01739 while (i < signed(coordinate.size()) - 1) 01740 { 01741 input >> coordinate[i++]; 01742 01743 input >> input_character; 01744 if (input_character != ',') throw std::invalid_argument(error_msg); 01745 } 01746 01747 if (coordinate.size() != 0) // allow empty coordinates like '( )' 01748 { 01749 input >> coordinate[i]; 01750 } 01751 01752 input >> input_character; 01753 if (input_character != ')') throw std::invalid_argument(error_msg); 01754 01755 // restore old io_state 01756 01757 input.exceptions(old_iostate); 01758 01759 return input; 01760 } 01761 01762 01799 template <class T> 01800 std::ostream & operator << (std::ostream & output, const Coordinate<T> & coordinate) 01801 { 01802 // save stream state 01803 01804 std::ios_base::fmtflags saved_flags = output.flags(); 01805 // std::streamsize saved_precision = output.precision(); 01806 01807 // throw an exception if the output operation fails for any reason 01808 01809 output.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit); 01810 01811 // put out formatted coordinate 01812 01813 output.clear(); 01814 01815 output // << std::fixed // or std::scientific 01816 // << std::setprecision(4) 01817 // << std::showpos 01818 // << std::setfill('0') 01819 // << std::internal 01820 << "("; 01821 01822 int i = 0; 01823 01824 while (i < signed(coordinate.size()) - 1) 01825 { 01826 output // << std::setw(10) 01827 << coordinate[i++] 01828 << ", "; 01829 } 01830 01831 if (coordinate.size() != 0) // allow empty coordinates like '( )' 01832 { 01833 output // << std::setw(10) 01834 << coordinate[i]; 01835 } 01836 01837 output << ")"; 01838 01839 // restore old stream state 01840 01841 // output.precision(saved_precision); 01842 output.flags(saved_flags); 01843 01844 return output; 01845 } 01846 01847 01855 template <class T> 01856 TRTK::Coordinate<T> sqrt(const TRTK::Coordinate<T> & coordinate) 01857 { 01858 TRTK::Coordinate<T> result; 01859 result.resize(coordinate.size()); 01860 01861 for (unsigned i = 0; i < coordinate.size(); ++i) 01862 { 01863 using std::sqrt; 01864 result[i] = ::sqrt(coordinate[i]); 01865 } 01866 01867 return result; 01868 } 01869 01870 01871 } // end of namespace TRTK 01872 01873 #endif // COORDINATE_HPP_1023074891
Documentation generated by Doxygen